原 iptables 设置
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 -p udp -j TPROXY --on-port 12345 --tproxy-mark 1
iptables -t mangle -A V2RAY -p tcp -j TPROXY --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
问题定位
容器中非本地网段 tcp/udp 均无法访问
开启 iptables 响应日志后,用以下命令记录路由信息
iptables -t <table> -A <chain> -j LOG --log-prefix "<table>:<chain>"
发现数据包在进入 mangle:OUTPUT 后被丢弃,SRC 是 172.17.0.0/16 网段
因为 docker0 使用了 nat 作为网桥,并且规则在 nat:POSTROUTING 中定义,而 nat:POSTROUTING 是 iptables 最后一条链,因此只有在网卡发出前才会进行 IP 地址的转换
所以在进入 mangle:PREROUTING 后,实际上 SRC 仍是 172.17.0.0/16,由于不知名的原因无法被代理
解决方案
其实,作为容器的 docker 本就不应该被代理,因此只需要在 mangle:PREROUTING 中将 SRC = 172.17.0.0/16 网段的数据包直接 RETURN
iptables -t mangle -A V2RAY -s 172.17.0.0/16 -j RETURN
注意事项
docker 网段可能有所不同,可以通过 ifconfig 查看