这两天闲着没事简单研究了下关于透明代理的方面的东西,有一些感想来记录下。
先来简单说下透明代理的大体流程:
1.用户将流量发送的网关服务器
2.网关通过设置iptables、ip路由策略方式将感兴趣的流量截获并重定向代理应用程序
3.代理应用程序通过某些方式获取原始目标的IP地址和port等信息 最后根据需求来定制实现不同的协议代理(如socks5)
...
一、第一步没什么好说 直接跳过 。
二、 流量转发
主要有两种方案来重定向流量:
1.iptables+redirect
2.iptables+tproxy
因为这两种方式的原理不同,会影响第三步的代理应用的实现方式。首先方法一是采用的DNAT的方式来转发流量的,这意味着代理程序监听到的是目标连接地址是本地地址。而方案二中确实不改变目标源地址,但是其实目标端口还是变了。
先贴一下常用的iptables的设置规则,以redsocks为例:
#全局TCP代理规则 iptables+REDIRECT
sudo iptables -t nat -N SSTCP
sudo iptables -t nat -A SSTCP -d x.x.x.x -j RETURN #SS Server tcp via
sudo iptables -t nat -A SSTCP -d 0.0.0.0/8 -j RETURN
sudo iptables -t nat -A SSTCP -d 10.0.0.0/8 -j RETURN
sudo iptables -t nat -A SSTCP -d 127.0.0.0/8 -j RETURN
sudo iptables -t nat -A SSTCP -d 169.254.0.0/16 -j RETURN
sudo iptables -t nat -A SSTCP -d 172.16.0.0/12 -j RETURN
sudo iptables -t nat -A SSTCP -d 192.168.0.0/16 -j RETURN
sudo iptables -t nat -A SSTCP -d 224.0.0.0/4 -j RETURN
sudo iptables -t nat -A SSTCP -d 240.0.0.0/4 -j RETURN
sudo iptables -t nat -A SSTCP -p tcp -j REDIRECT –to-ports 12345
sudo iptables -t nat -A PREROUTING -p tcp -j SSTCP
#局部UDP代理规则 手动指定IP端口 可解决DNS污染
#sudo iptables -t nat -N SSDNS,
#sudo iptables -t nat -A SSDNS -p udp –dport 53 -j REDIRECT –to-ports 10053
#sudo iptables -t nat -A PREROUTING -p udp -j SSDNS
#全局UDP代理规则 iptables+TPROXY
sudo ip route add local 0.0.0.0/0 dev lo table 100
sudo ip rule add fwmark 1 table 100
sudo iptables -t mangle -N SSUDP
sudo iptables -t mangle -A SSUDP -d 0.0.0.0/8 -j RETURN
sudo iptables -t mangle -A SSUDP -d 10.0.0.0/8 -j RETURN
sudo iptables -t mangle -A SSUDP -d 127.0.0.0/8 -j RETURN
sudo iptables -t mangle -A SSUDP -d 169.254.0.0/16 -j RETURN
sudo iptables -t mangle -A SSUDP -d 172.16.0.0/12 -j RETURN
sudo iptables -t mangle -A SSUDP -d 192.168.0.0/16 -j RETURN
sudo iptables -t mangle -A SSUDP -d 224.0.0.0/4 -j RETURN
sudo iptables -t mangle -A SSUDP -d 240.0.0.0/4 -j RETURN
sudo iptables -t mangle -A SSUDP -p udp -j TPROXY –on-port 10053 –tproxy-mark 0x01/0x01
sudo iptables -t mangle -A PREROUTING -p udp -j SSUDP
三. 应用实现(以redsocks为例)
先说说第一种:iptables+redirect
iptables+redirect 这种一般是用来重定向TCP数据的 所以代理程序可以通过getsockopt (s, SOL_IP, SO_ORIGINAL_DST, &dstaddr, &n)函数来获取原始目标地址和端口信息,大概的原理应该是通过查询系统ip_conntrack结构来获得原始目标地址和端口信息。但这个SO_ORIGINAL_DST参数并不适用于UDP协议,所以才有了的tproxy的用武之地。不过这种方式还是可以用在某些特定的UDP协议上如DNS,因为可以手动设置一个IP和端口作为原始目标DNS服务器地址,这样就可以解决DNS污染的问题。在redsocks的配置文件中可以这样设置:
redudp {
//`ip' and `port' for redsocks to listen
local_ip = 0.0.0.0;