记一次OpenWrt TPROXY透明代理踩坑之旅
v2ray + OpenWrt + TPROXY 实现透明代理纪实。
之前文章写过了,我有两台软路由,都装了OpenWrt系统,自然要在上面跑v2ray,也自然要配个透明代理。最开始是配REDIRECT透明代理,但是随后发现,REDIRECT只能代理TCP流量,无法转发UDP流量,然后可以使用TPROXY透明代理,就可以转发UDP流量了,虽然我暂时没有转发UDP流量的需求,但是TPROXY看起来更优,我自然要选择更优的方案了。
TPROXY透明代理说明
v2ray配置
1 | { |
这块的配置网上很多,没啥多说的,但是在后续调试中,没办法通过v2ray得知12345是否接收到链接,所以我用python实现了tproxy
监听:
1 | import socket |
iptables 配置
1 | // 局域网透明代理 |
路由表配置
1 | # ip rule add fwmark 1 table 100 |
问题说明
讲道理,完成了上述的配置以后,透明代理就能配置成功。
我两台路由器A和B,完成了上述配置后,其中A的确是成功了,但是B却失败了。这是之前遇到的问题,一直没能解决,我也就暂时搁置了,随后让A继续用TPROXY透明代理,让B使用REDIRECT透明代理。
但是这几天,路由器A又不行了,所以我又一次开始研究这个TPROXY透明代理。
透明代理流程
通过我的研究,我发现透明代理的步骤大致如下:
- 局域网设备C请求网站,发送SYN包,到达路由器A
- 路由器A的iptables mangle表的PREROUTING,匹配到这个SYN包,打上了0x1的mark,然后要发送给127.0.0.1:10000
- 因为SYN包有mark=1的标记,所以匹配到路由表100的规则,流量在lo网卡上进行本地回环
- 然后应该就能到127.0.0.1:10000的应用上了
如果是路由器本地进行透明代理则是:
- 路由器A请求网站,发送SYN包
- 路由器A的iptables mangle表的OUTPUT,匹配到这个SYN包,给其打上0x1的mark
- 路由器A的iptables mangle表的PREROUTING,匹配到,打上0x1的mark,然后转发给127.0.0.1:10000
- 因为SYN包有mark=1的标记,所以匹配到路由表100的规则,流量在lo网卡上进行本地回环
- 然后应该就能到127.0.0.1:10000的应用上了
调试思路
在本地进行透明代理是没问题的,问题只出在局域网的透明代理上。
iptalbes可以使用如下命令进行调试:iptables -t mangle -I PREROUTING -p tcp -j LOG
或者使用iptables -t mangle -vL
可用查看规则是否命中。
然后根据上图中的流程进行调试,查看包流到了哪。
但是路由表的处理却不知道如何调试,tcpdump也抓不到包。
通过调试,发现能成功流经filter表的INPUT规则,但是后续却不知道数据包应该去哪了,也不知道该如何调试了。
随后思考,也有可能是sysctl的问题,或者内核驱动的问题。
所以找了一个同事,他家的设备TPROXY的透明代理能正确运行。和他设备的/proc/sys/net/ipv4
目录下的怀疑的一些配置进行对比,但是失败了。
随后,我同事说他之前在docker环境下配置也失败了,但是不知道为啥。这让我突然想到,我的路由器B是装了docker环境的,路由器A最近也装了,而且好像透明代理失败也是在我装了docker之后。
所以我把怀疑点放在了docker上,首先是iptables的规则,把路由器B的docker卸载了,然后重启,使用iptables-save > 1.firewall
保存规则,然后再把docker装上,再应用规则iptables-restore < 1.firewall
。
但是失败了,所以问题应该不在docker的iptables规则上。
随后又对比了有docker和没有docker环境下lsmod
的信息,也没有得到啥有用的信息。
随后,我按照的我安装命令:opkg install dockerd luci-app-dockerman docker-compose luci-lib-docker
我去查找这些包的信息,随后在dockerd
包中发现了:https://github.com/openwrt/packages/blob/openwrt-21.02/utils/dockerd/files/etc/sysctl.d/sysctl-br-netfilter-ip.conf
这个文件,然后我尝试sysctl net.bridge.bridge-nf-call-iptables=0
这回透明代理成功了,然后就确定了,的确是docker的问题,让我的TPROXY透明代理失效了。
随后也查找了一些信息:https://feisky.gitbooks.io/sdn/content/linux/params.html#bridge-nf
得知该配置的作用,但是还是没搞清楚该配置为啥会让透明代理失效,因为我查找了iptables所有表的FORWARD规则,并没有命中的。然后使用NOTRACK
,也没用。
又搜了半天,但是还是没找到该配置会导致TPROXY透明失效的根本原因,不过至少解决了TPROXY透明代理的问题。也测试了,在这个配置设置为0的情况下,也并没有影响docker网络的正常运行。
记一次OpenWrt TPROXY透明代理踩坑之旅