iptables + tproxy 实现透明代理
type
status
date
slug
summary
tags
category
icon
password
先看一下iptables,正经图
路由设置
不同场景
内网机器访问国内服务
A的请求到达路由器的PREROUTING链,根据链上规则
直接返回原来的PREROUTING连,走FORWARD以及后续的操作
内网机器访问国外服务
A的请求到达路由器的PREROUTING链,根据链上规则
给TCP请求加上mark,然后重定向到1081,根据前面的路由设置,会直接到本地回环,请求会到达Transparent Proxy
- 判断需要走Proxy,那接下来的流程就是,包装原请求并发出,带上了0xff(即255)的mark
按照OUTPUT链上的规则
直接返回OUTPUT链,走POSTROUTING链出去
- 判断为直连,直接原封不动的请求真实服务器,也是带上0xff的mark,后面和情况1一样
路由器访问国内服务
路由器的请求会从OUTPUT开始,会匹配上OUTPUT链上规则
直接返回OUTPUT链,走POSTROUTING链出去
路由器访问国外服务
路由器的请求会匹配上OUTPUT链上最后一条规则
给这个请求打上mark,然后打上mark的请求会重新走PREROUTING链,会匹配上如下规则
也就是说,流量会绕一圈,重新进入Transparent Proxy
一个坑来了
当通过tproxy进入Transparent Proxy的时候,这个包的的remoteAddr是请求发起方的地址(即路由器IP),localAddr则是真实需要到达的服务器地址(比如Google.com),响应该请求的时候,DST会变成请求发起方的地址(正是路由器的地址)
如果我们不在OUTPUT对这个包做操作的话,这个包会再次被设置mark,都无法完成握手
最终成品:Github
其他小插曲
TProxy在代理UDP流量的时候,比如,代理从192.168.2.100:1234到8.8.8.8:53的流量,会在本地监听(bind)8.8.8.8:53的流量,正常情况下是不允许这样bind的,但是如果设置了
syscall.IP_TRANSPARENT
就能正常bind,但有个特例,如果本地已经有服务绑定了0.0.0.0:53的监听,那就会报错EADDRINUSE (address already in use)
Loading...