iptables 端口映射入门到放弃

TCP很好实现,但是UDP怎么搞都没搞好,总结下。首先要打开kernel的转发

vi /etc/sysctl.conf
#去掉net.ipv4.ip_forward = 1的注释
sysctl -p #激活配置

配置TCP转发

iptables -t nat -A PREROUTING -i <in> -p tcp --dport <port> -j DNAT --to <target>:<tport>

“PREROUTING”靠近流量入口,从<in>进来的目标端口为<port>的流量使用DNAT修改包的目的地地址,让包转到<target>:<tport>上。<in>一般为其他机器看见的端口,如公网网卡等。修改后这个包会从修改后的地址对应的端口出去(即下面的<out>)。

iptables -t nat -A POSTROUTING -o <out> -p tcp --dport <tport> -j SNAT --to <out_ip>

“POSTROUTING”靠近流量出口,要从<out>出去的目标端口为<tport>的流量,使用SNAT修改包的源地址为<out_ip>,<out>一般为内网网卡,连接到<target>, <out_ip> 是指转发机器<out>上的地址。这里修改源地址是为了让 <target> 上的机器回复包的时候能正在使包回到中转机器上,而不是<in>上的机器,另外TCP是有连接的所以这些操作应该都是在建立连接时进行的。连接后就不需要这两条处理。

iptables -A FORWARD -i <out> -o <in> -p tcp --sport <tport> -m state --state ESTABLISHED -j ACCEPT
iptables -A FORWARD -i <in> -o <out> -p tcp --dport <port> -j ACCEPT

连接建立之后靠上面两条进行转发,这时候不需要修改地址。

网上很多的UDP转发都是直接修改上面的“tcp”为“udp”,事实上是不行的,为什么?因为UDP根本就没有连接器的概念,全部都是一个个的小包。

上面的规则修改成UDP后用户从 <in> 进来的包是可以从<out>到达 <target> 的,但是<target>回复的包却没办法从<out>到<in>再给用户,因为进来的时候转发的所有包的源地址已经修改成<out_ip>,所以回复的时候目标地址是 <out_ip> 。这个包进到我们的转发机器,问题就来了,转发的机器根本不知道这个包是要回复给<in>上哪个用户的。所以这个方法行不通。

解决的方法也有,就是像路由器一样,所有要转发的用户包从<in>上的一个端口进来,转发的时候通过<out>上不同的端口发给 <target>,当<target>返回的包回复到对应的端口时,转发的机器再根据收到数据的端口号找到<in>上对应的用户地址和端口,再修改包目标地址端口及源地址端口,并通过<in>扔回给对应的用户。理论应该就是这样,UDP转发的过程,其实就是UDP路由过程的反向。因为UDP没有连接概念路由上开的端口是有一定时间的,所以才有NAT穿透一说。但是本人学艺不精不知道用iptables该怎么实现。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注