使用iptables实现透明代理

最近有这么个需求,即从某台机器(A)无法访问到服务器B的p0端口,因此需要从另一台机器C的p1端口中转一下。
当然网上有很多代理的方法,包括代理软件、ssh隧道等,但是应用程序不支持代理,因此必须使用透明代理,即在A的应用中将C设置为服务器,C将所有到达其p1端口的包转发给B的p0端口,然后B的所有回复都由C转发回A。当然,C必须做地址转换,使得A认为自己在与C通信,B也认为自己在与C通信。
这么看来这个需求其实和NAT很类似,唯一不同的是这里的A、B和C的地址都是global地址。
研究了一下,其实可以使用类似NAT的方法来做,即在C上配置2个SNAT和1个DNAT,A和B都不用配置。
其中A发往C的包使用DNAT转换,C发往A和B的包使用SNAT转换。具体配置如下:

-A PREROUTING -s ! b.ip -d c.ip -p tcp -m tcp –dport p1 -j DNAT –to b.ip:p0

-A POSTROUTING -s ! b.ip -d b.ip -p tcp -m tcp –dport p0 -j SNAT –to c.ip

-A POSTROUTING -s b.ip -d !b.ip -p tcp -m tcp –sport p0 -j SNAT –to c.ip

可以发现,如果将C看成是NAT Box,B看成是内网机器,A看成是外网机器的话,以上配置与加了端口转发的NAT的唯一区别就是多了第二条规则。这是因为B的IP是Global的,它访问A的时候路由不经过C,所以A到B仅作DNAT是不够的,还必须用SNAT把源地址换成C的地址。

btw,别忘了启用ip_forward