今天再一次需要用到iptables的port forwarding功能,半年前用过一次,忘得差不多了,今次重新学习,写到博客上来加深记忆。iptables的remote port forwarding即用linux自带的iptables实现NAT功能。当然iptables已实现该功能,我们需要做的只是配置(写iptables的配置文件)。


1.什么时候需要用到该功能


当你需要NAT功能,但此时的NAT功能需要跑在一台linux机器而非路由器上。路由器都有专门的界面让你配置NAT,但是普通的linux没有那么友好的路由管理系统,只有iptables供我们使用。



如果你不知道NAT是什么,基本上就不用往下看了,不过为了有助于理解我还是稍微描述一下场景。今天的情况是公司在外网有一台服务器A,希望使用公司已有的ldap服务。可是跑ldap的服务器B存在于公司内网中,没有公共ip。为了A能联上B,我们希望借助服务器C作为gateway或者说路由或者说跳板。因为C有内网和外网两个网卡,所以它是内网和外网的gateway,或者说纽带。我们希望C能转发来自A的去向C服务器的389号端口(ldap服务的默认端口)的ip包到B服务器的389号端口。


这个转发操作其实可以分为两部分工作:


  1. 当C接收到A发来的tcp连接请求时,更改目标地址C.public_ip为B.ip,并发往内网


  2. 当C接收到B发来的对A的回复时,将源地址B.ip改为C.public_ip,并发往外网



2.如何配置iptables


使用/sbin/iptables往iptables系统里添加或者插入或者删除路由规则。


转发操作只有两步,但是系统管理员的工作要比两步多:


  1. 确认操作系统中的转发功能已开启


$ /sbin/sysctl net.ipv4.ip_forward net.ipv4.ip_forward = 1


/etc/sysctl.conf

文件,找到net.ipv4.ip_forward=0这一行,改为1,然后执行命令


$ /sbin/sysctl -p /etc/sysctl.conf


  2. 使用/sbin/iptables添加路由规则

/sbin/iptables -P FORWARD DROP
/sbin/iptables -P INPUT DROP
/sbin/iptables -A INPUT -p tcp --dport 389 -j ACCEPT
/sbin/iptables -t nat -P PREROUTING ACCEPT
/sbin/iptables -t nat -P POSTROUTING ACCEPT
/sbin/iptables -A FORWARD -o eth0 -i eth1 -s A.ip -d B.ip -j ACCEPT
/sbin/iptables -A FORWARD -o eth1 -i eth0 -s B.ip -d A.ip -j ACCEPT
/sbin/iptables -t nat -A PREROUTING -i eth1 -p tcp -s A.ip --dport 389 -j DNAT --to-destination B.ip:389
/sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE


核心规则在第8行和第九行。第八行执行上文提到的转发第一部分,第九行执行上文提到的转发第二部分。



1行2行指定默认policy,即若任一路由规则都不适用于某个请求,则执行这里的默认行为DROP。


3行指明允许目的端口为389的请求。


4行5行指明允许做NAT的PREROUTING 和POSTROUTING


6行7行指明允许针对A和B之间的转发。即外网往内网转时,源必须是A,目的是B。为什么目的不是C呢?因为FORWARD的规则在PREROUTING之后进行检验,所以那时的目的地址已经改成了B的ip。内网往外网转时,源必须是B,目的是A。为什么源不是C呢?POSTROUTING不是要把源覆盖为C自己的公共ip吗?这是因为POSTROUTING是在FORWARD之后进行的。看了下面这幅图,就能明白iptables的机制

PACKET IN --->---PREROUTING---[ routing ]--->----FORWARD---->---POSTROUTING--->--- PACKET OUT
                         - mangle        |              - mangle        - mangle
                         - nat (dst)     |              - filter        - nat (src)
                                         |                                 |
                                         |                                 |
                                       INPUT                            OUTPUT
                                        - mangle                         - mangle
                                        - filter                         - nat (dst)
                                        |                                - filter
                                        |                                 |
                                        `---->----[ application ]---->----'
 
/etc/init.d/iptables save