透明代理实现

参考资料

https://guide.v2fly.org/app/tproxy.html

https://xtls.github.io/document/level-2/transparent_proxy/transparent_proxy.html

开启IP转发

  1. echo net.ipv4.ip_forward=1 >> /etc/sysctl.conf

    • echo net.ipv4.ip_forward=1:这部分的作用是输出net.ipv4.ip_forward=1这个字符串。net.ipv4.ip_forward=1是一个设置项,表示启用IPv4的IP转发。IP转发是指系统接收到一个网络接口上的数据包,并将其转发到另一个网络接口的能力,这对于路由器和网关设备来说是必要的功能。
    • >> /etc/sysctl.conf:这部分的作用是将前面echo命令的输出追加到/etc/sysctl.conf文件的末尾。/etc/sysctl.conf是一个系统配置文件,用于在系统启动时设置内核参数。通过将net.ipv4.ip_forward=1添加到这个文件,你可以确保每次系统启动时IP转发都会被启用。
  2. &&:这是一个逻辑运算符,用于连接两个命令。它的作用是如果前一个命令(即echo net.ipv4.ip_forward=1 >> /etc/sysctl.conf)执行成功(即返回状态为0),则执行后一个命令(即sysctl -p)。

  3. sysctl -p

    • sysctl是一个用于运行时修改内核参数的工具。
    • -p参数表示加载/etc/sysctl.conf文件中的设置。这意味着在/etc/sysctl.conf文件被修改后,通过执行sysctl -p可以立即应用这些更改,而无需重启系统。

综上所述,这条命令的整体作用是将IP转发的设置添加到系统配置中,并立即应用这一更改,从而启用系统的IP转发功能。这对于设置路由器、防火墙或执行网络地址转换(NAT)等网络相关任务非常重要。

nftables 配置

lsmod | grep nft 的目的是在Linux系统中查找已加载的模块(Kernel modules),特别是那些与nft(即nftables)相关的模块。lsmod命令用于显示当前已加载的内核模块列表,而grep nft用于从这个列表中过滤出包含字符串“nft”的行。这可以帮助你确认是否已经加载了nftables相关的内核模块。

如果nftables已经在系统上被使用,你可能会看到一些像是nft_counter、nft_chain_nat_ipv4等与nftables功能相关的模块名字。

nft_compat:提供了对旧iptables/xtables规则的兼容性支持。

nft_tproxy、nf_tproxy_ipv4、nf_tproxy_ipv6:用于透明代理功能的支持,允许nftables重定向流量到本地的代理服务器。

nft_fib_inet、nft_fib_ipv4、nft_fib_ipv6:用于实现基于FIB(Forwarding Information Base)的路由决策。

nft_fib:提供了FIB查找功能。

nft_reject_ipv4、nft_reject:用于生成拒绝流量的规则,例如ICMP回应。

nf_reject_ipv4:为IPv4提供拒绝流量的能力。

nft_ct:允许使用连接跟踪信息进行规则匹配。

nft_masq:提供了NAT的MASQUERADE(伪装)功能,常用于共享上网。

nft_chain_nat:用于定义NAT规则的链。

nf_tables:nftables的核心模块,提供了框架和基础功能。

nfnetlink:为nftables提供了与用户空间通信的能力。

nf_nat:提供了网络地址转换的核心功能。

nf_conntrack:提供了连接跟踪的核心功能,是实现NAT和防火墙规则的基础。

nf_defrag_ipv6、nf_defrag_ipv4:处理IPv4和IPv6数据包碎片重组的功能。

x_tables:提供了iptables使用的基础架构,nft_compat模块通过它提供对旧iptables规则的兼容性支持。

测试以下命令,如果可以达成,则加入开机自动执行。

'''shell

#设置策略路由

ip rule add fwmark 1 table 100

ip route add local 0.0.0.0/0 dev lo table 100

#代理局域网设备

nft add table v2ray

nft add chain v2ray prerouting { type filter hook prerouting priority 0 ; }

nft add rule v2ray prerouting ip daddr {127.0.0.1/32, 224.0.0.0/4, 255.255.255.255/32} return

nft add rule v2ray prerouting meta l4proto tcp ip daddr 192.168.0.0/16 return

nft add rule v2ray prerouting ip daddr 192.168.0.0/16 udp dport != 53 return

nft add rule v2ray prerouting mark 0xff return # 直连 0xff 流量

nft add rule v2ray prerouting meta l4proto {tcp, udp} mark set 1 tproxy to 127.0.0.1:12345 accept # 转发至 V2Ray 12345 端口

#代理网关本机

nft add chain v2ray output { type route hook output priority 0 ; }

nft add rule v2ray output ip daddr {127.0.0.1/32, 224.0.0.0/4, 255.255.255.255/32} return

nft add rule v2ray output meta l4proto tcp ip daddr 192.168.0.0/16 return

nft add rule v2ray output ip daddr 192.168.0.0/16 udp dport != 53 return

nft add rule v2ray output mark 0xff return # 直连 0xff 流量

nft add rule v2ray output meta l4proto {tcp, udp} mark set 1 accept # 重路由至 prerouting

#DIVERT 规则

nft add table filter

nft add chain filter divert { type filter hook prerouting priority -150 ; }

nft add rule filter divert meta l4proto tcp socket transparent 1 meta mark set 1 accept

'''

这组命令配置了策略路由、代理局域网设备以及代理网关本机的网络流量,并使用nftables设置了DIVERT规则。这里分步骤解释每个命令的作用:

设置策略路由

  1. ip rule add fwmark 1 table 100

    • 这条命令添加一条策略路由规则,指定所有标记为1(fwmark 1)的数据包使用路由表100。
  2. ip route add local 0.0.0.0/0 dev lo table 100

    • 将所有目标地址为0.0.0.0/0(即任意地址)的数据包路由到本地回环接口(dev lo),并指定这条路由规则在表100中。这通常用于TProxy(透明代理)配置,使得标记的流量可以被本地捕获和处理。

代理局域网设备

以下命令创建一个名为v2ray的nftables表,并在其中设置规则以处理局域网设备的流量:

  1. nft add table v2ray

    • 创建一个新的nftables表v2ray
  2. nft add chain v2ray prerouting { type filter hook prerouting priority 0 \; }

    • v2ray表中添加一个名为prerouting的链,这个链在预路由阶段被触发,用于处理进入的流量。
  3. nft add rule v2ray prerouting ip daddr {...} return

    • 添加几条规则,指定某些目的地址的流量直接返回,不经过代理。这包括本地回环地址、多播地址和广播地址,以及局域网地址(192.168.0.0/16)和非DNS(端口53)UDP流量。
  4. nft add rule v2ray prerouting mark 0xff return

    • 对于已经标记为0xff的流量(通常表示直连流量),直接返回,不做处理。
  5. nft add rule v2ray prerouting meta l4proto {tcp, udp} mark set 1 tproxy to 127.0.0.1:12345 accept

    • 对于TCP和UDP流量,设置标记为1,并通过TProxy转发到本地的12345端口(假设这是V2Ray等代理软件监听的端口)。

代理网关本机

以下命令设置规则以处理网关本机的流量:

  1. nft add chain v2ray output { type route hook output priority 0 \; }

    • v2ray表中添加一个名为output的链,这个链在输出阶段被触发,用于处理从本机发出的流量。
  2. nft add rule v2ray output ...

    • 类似于prerouting链的规则,这里设置了一系列规则来处理输出流量。特别是,将TCP和UDP流量的标记设置为1,允许它们通过prerouting链重新路由。

DIVERT 规则

  1. nft add table filter

    • 创建一个新的nftables表filter
  2. nft add chain filter divert { type filter hook prerouting priority -150 \; }

    • filter表中添加一个名为divert的链,这个链在预路由阶段被触发,优先级为-150,用于处理特定的转发逻辑。
  3. nft add rule filter divert meta l4proto tcp socket transparent 1 meta mark set 1 accept

    • 对于TCP流量,如果是透明套接字的一部分,则设置标记为1并接受。这条规则用于DIVERT链,配合TProxy使用,允许透明地拦截和重定向TCP流量。

开机自动运行透明代理规则

由于策略路由以及 iptables/nftables 有重启会失效的特性,所以当测试配置没有问题之后,需要再弄个服务在开机时自动配置策略路由和 iptables,否则每次开机的时候就要手动执行一遍。

1、由于 iptables 命令有点多,所以先将 iptables 规则保存到 /etc/iptables/rules.v4 中:

mkdir -p /etc/nftables && nft list ruleset > /etc/nftables/rules.v4

2、在 /etc/systemd/system/ 目录下创建一个名为 tproxyrule.service 的文件,然后添加以下内容并保存。

'''shell

[Unit]

Description=Tproxy rule

After=network.target

Wants=network.target

[Service]

Type=oneshot

RemainAfterExit=yes

#注意分号前后要有空格

ExecStart=/sbin/ip rule add fwmark 1 table 100 ; /sbin/ip route add local 0.0.0.0/0 dev lo table 100 ; /sbin/nft -f /etc/nftables/rules.v4

ExecStop=/sbin/ip rule del fwmark 1 table 100 ; /sbin/ip route del local 0.0.0.0/0 dev lo table 100 ; /sbin/nft flush ruleset

[Install]

WantedBy=multi-user.target

'''

3、最后执行 systemctl enable tproxyrule

如果使用V2raya

已经自动帮忙配好透明代理上网

执行 nft list ruleset ,得到:

'''config

table inet v2raya {

set whitelist {

type ipv4_addr

flags interval

auto-merge

elements = { 0.0.0.0, 10.0.0.0/8,

100.64.0.0/10, 127.0.0.0/8,

169.254.0.0/16, 172.16.0.0/12,

192.0.0.0/24, 192.0.2.0/24,

192.88.99.0/24, 192.168.0.0/16,

198.51.100.0/24, 203.0.113.0/24,

224.0.0.0/3 }

}

set whitelist6 {
type ipv6_addr
flags interval
auto-merge
elements = { ::/127,
64:ff9b::/96,
100::/64,
2001::/32,
2001:20::/28,
fe80::/10,
ff00::/8 }
}

set interface {
type ipv4_addr
flags interval
auto-merge
elements = { 127.0.0.0/8, 172.17.0.0/16,
192.168.0.0/16 }
}

set interface6 {
type ipv6_addr
flags interval
auto-merge
elements = { ::1,
fe80::/64 }
}

chain tp_out {
meta mark & 0x00000080 == 0x00000080 return
meta l4proto { tcp, udp } fib saddr type local fib daddr type != local jump tp_rule
}

chain tp_pre {
iifname "lo" meta mark & 0x000000c0 != 0x00000040 return
meta l4proto { tcp, udp } fib saddr type != local fib daddr type != local jump tp_rule
meta l4proto { tcp, udp } meta mark & 0x000000c0 == 0x00000040 tproxy ip to 127.0.0.1:52345
meta l4proto { tcp, udp } meta mark & 0x000000c0 == 0x00000040 tproxy ip6 to [::1]:52345
}

chain output {
type route hook output priority mangle - 5; policy accept;
meta nfproto { ipv4, ipv6 } jump tp_out
}

chain prerouting {
type filter hook prerouting priority mangle - 5; policy accept;
meta nfproto { ipv4, ipv6 } jump tp_pre
}

chain tp_rule {
meta mark set ct mark
meta mark & 0x000000c0 == 0x00000040 return
iifname "br-" return
iifname "docker
" return
iifname "veth*" return
iifname "wg*" return
iifname "ppp*" return
meta l4proto { tcp, udp } th dport 53 jump tp_mark
meta mark & 0x000000c0 == 0x00000040 return
ip daddr @interface return
ip daddr @whitelist return
ip6 daddr @interface6 return
ip6 daddr @whitelist6 return
jump tp_mark
}

chain tp_mark {
tcp flags syn / fin,syn,rst,ack meta mark set meta mark | 0x00000040
meta l4proto udp ct state new meta mark set meta mark | 0x00000040
ct mark set meta mark
}

}

'''

V2RayA 通过 nftables 为你自动设置的规则主要是为了实现透明代理,使得局域网内的设备(包括旁路由自身)可以通过V2RayA代理上网。这些规则包括了对流量的拦截、标记、以及重定向到V2RayA监听的端口(在这里是127.0.0.1:52345)。下面是对这些规则的简要分析:

设置和集合

透明代理的实现

结论

基于以上规则,你的V2RayA设置已经可以作为旁路由代理上网了。这套规则通过拦截、标记和重定向流量到V2RayA,使得局域网内的设备无需单独配置代理就可以通过V2RayA访问互联网,同时避免了对特定地址和服务的干扰(例如DNS查询和局域网通信)。注意,还需要启动 nftables 服务。

确认以下几点:

确保 nftables 服务正在运行:可以通过 sudo systemctl status nftables 来检查服务状态。

确保内核支持:透明代理(特别是 TProxy 功能)需要内核支持。请确保你的内核配置(通常是 /boot/config-$(uname -r) 文件)包含了对 TProxy 的支持(例如,配置项 CONFIG_NETFILTER_XT_TARGET_TPROXY)。

确保 V2RayA 或其他代理软件正确配置:代理软件需要监听上述 nftables 规则中指定的端口(如 127.0.0.1:52345),并正确配置以处理透明代理的流量。

检查防火墙规则冲突:确保没有其他防火墙规则(无论是 nftables 还是 iptables 的)阻止了代理流量的正确处理。

目前查到的内核配置:CONFIG_NETFILTER_XT_TARGET_TPROXY=m

是被当成TProxy模块了,没有进内核:

如果内核配置项 CONFIG_NETFILTER_XT_TARGET_TPROXY 设置为 m,这意味着 TProxy(透明代理目标)支持被编译为模块,而不是直接编入内核。这种设置允许你按需加载或卸载 TProxy 功能,而不需要在每次启动时都启用它。

要确保 TProxy 功能正常工作,你需要确保相应的内核模块已经被加载到系统中。你可以使用 modprobe 命令手动加载模块,例如:

sudo modprobe xt_TPROXY

加载模块后,你应该能够使用 nftables 配置的 TProxy 规则进行透明代理。

自动加载模块

如果你希望在系统启动时自动加载 xt_TPROXY 模块,可以将模块名称添加到 /etc/modules 文件中。这样,每次系统启动时,xt_TPROXY 模块就会被自动加载。只需执行以下命令:

echo "xt_TPROXY" | sudo tee -a /etc/modules

验证模块是否加载

加载模块后,你可以使用 lsmod 命令来检查模块是否已经被加载:

lsmod | grep xt_TPROXY

如果输出中显示了 xt_TPROXY,这意味着模块已成功加载。

总结

在你的设置中,由于 CONFIG_NETFILTER_XT_TARGET_TPROXY 被设置为模块,你需要确保在尝试设置或使用 TProxy 功能之前,相应的模块已被加载到系统中。这是实现旁路由透明代理功能的先决条件之一。