流量解析
开启ip包转发
sysctl net.ipv4.ip_forward=1
开启之后目的地的数据包才能进入 FORWARD 链,可以作为网关。
策略路由
ip rule add fwmark 1 table 100
# 将打标签的流量用 table 100 中的规则处理
ip route add local 0.0.0.0/0 dev lo table 100
# 在 table 100 中添加规则:将所有(0.0.0.0/0)包重定向到 loopback 中(从而进入 INPUT)
作为透明代理,需要代理两块流量:
- 非本机的包通过 PREROUTING 链之后,会走 FORWARD 链出去,但是流量需要通过 INPUT 链进入到达 v2ray 进程,所以要将经过 PREROUTING 链的流量通过策略路由转发到 INPUT 链。
如果是本机的数据包,由于本机的进程流量直接通过 OUTPUT 以及 POSTROUTING 链出去,没有经过 tproxy 的处理,所以:
iptables -t mangle -N V2RAY_MASK
iptables -t mangle -A V2RAY_MASK -p udp -j MARK --set-mark 1 # 给 UDP 打标记,重路由
iptables -t mangle -A V2RAY_MASK -p tcp -j MARK --set-mark 1 # 给 TCP 打标记,重路由
iptables -t mangle -A OUTPUT -j V2RAY_MASK # 应用规则
结合策略路由,将 OUTPUT 链中的 tcp 和 udp 流量打标记,然后重新由 loopback 处理,这样流量就会经过 PREROUTING 链,也就是会被发送到 v2ray 的进程。
同样,对于目标是局域网的包不需要处理:
iptables -t mangle -A V2RAY_MASK -d 224.0.0.0/4 -j RETURN
iptables -t mangle -A V2RAY_MASK -d 255.255.255.255/32 -j RETURN
iptables -t mangle -A V2RAY_MASK -d 192.168.0.0/16 -p tcp -j RETURN
DNS请求
根据上面的规则,DNS 使用的 udp 协议也会通过代理来查询,我们的目的也是需要让 v2ray 来帮我们做 dns 查询,但是如果本地的某些客户端配置了局域网的 dns 服务器,那么 dns 请求还是没有经过代理,所以对于这种情况,我们也要劫持 dns 请求:
iptables -t mangle -A V2RAY -d 192.168.0.0/16 -p udp ! --dport 53 -j RETURN
iptables -t mangle -A V2RAY_MASK -d 192.168.0.0/16 -p udp ! --dport 53 -j RETURN
这样局域网内目的端口是 53 的 udp 包也会通过 v2ray 进程来处理。
最后还要注意一点,如果是 v2ray 进程发出的包,就不需要处理了,再处理就会发生回环了:
iptables -t mangle -A V2RAY_MASK -j RETURN -m mark --mark 0xff
这个规则配合 v2ray 的配置(0xff就是255):
"streamSettings": {
"sockopt": {
"mark": 255
}
}
所有最后的规则就是:
# 设置策略路由
ip rule add fwmark 1 table 100
ip route add local 0.0.0.0/0 dev lo table 100
# 代理局域网设备
iptables -t mangle -N V2RAY
iptables -t mangle -A V2RAY -d 127.0.0.1/32 -j RETURN
iptables -t mangle -A V2RAY -d 224.0.0.0/4 -j RETURN
iptables -t mangle -A V2RAY -d 255.255.255.255/32 -j RETURN
iptables -t mangle -A V2RAY -d 192.168.0.0/16 -p tcp -j RETURN
iptables -t mangle -A V2RAY -d 192.168.0.0/16 -p udp ! --dport 53 -j RETURN
iptables -t mangle -A V2RAY -j RETURN -m mark --mark 0xff # 直连 SO_MARK 为 0xff 的流量(0xff 是 16 进制数,数值上等同与上面V2Ray 配置的 255),此规则目的是解决v2ray占用大量CPU(https://github.com/v2ray/v2ray-core/issues/2621)
iptables -t mangle -A V2RAY -p udp -j TPROXY --on-ip 127.0.0.1 --on-port 12345 --tproxy-mark 1
iptables -t mangle -A V2RAY -p tcp -j TPROXY --on-ip 127.0.0.1 --on-port 12345 --tproxy-mark 1
iptables -t mangle -A PREROUTING -j V2RAY
# 代理网关本机
iptables -t mangle -N V2RAY_MASK
iptables -t mangle -A V2RAY_MASK -d 224.0.0.0/4 -j RETURN
iptables -t mangle -A V2RAY_MASK -d 255.255.255.255/32 -j RETURN
iptables -t mangle -A V2RAY_MASK -d 192.168.0.0/16 -p tcp -j RETURN
iptables -t mangle -A V2RAY_MASK -d 192.168.0.0/16 -p udp ! --dport 53 -j RETURN
iptables -t mangle -A V2RAY_MASK -j RETURN -m mark --mark 0xff
iptables -t mangle -A V2RAY_MASK -p udp -j MARK --set-mark 1
iptables -t mangle -A V2RAY_MASK -p tcp -j MARK --set-mark 1
iptables -t mangle -A OUTPUT -j V2RAY_MASK
最后,关于 TPROXY:
TProxy 是 iptables 中的一种目标,用于实现透明代理功能。它允许在代理服务器上拦截和处理通过网络流经的数据,而不需要客户端进行任何额外的配置。这对于实现网络代理、内容过滤、访问控制等方面非常有用,但需要小心配置以确保正确和安全地运行。