1.8.4 target和jump
从字面的意思来理解,target表示目标,jump表示跳转,两个结合起来表示被匹配到的数据包将跳转的哪个目标去,并执行那个目标相应的动作,DROP、ACCEPT或其他。还是举个例子有助于我们理解target和jump。
#iptables –N power_users
#iptables –A power_users –p all –j ACCEPT
#iptables –A FORWARD –s 192.168.1.0 –j power_users
上面的例子中,第一句表示新建一条chain,名称叫做power_users,第二句是对power_users链定义策略,该策略表明接受所有协议的数据包,确实如此,否则我们也不会将这条链成为power_users了,第三条语句定义了一个转发策略,将原地址为192.168.1.0/24网段的用户产生的数据包被跳转至power_users链处理。
在本节中,我们将对比较常用的几个targets进行详细的描述,他们分别是DROP、ACCEPT、SNAT、DNAT、MASQUERADE、LOG。
DROP: DROP target表示被匹配的数据包将要被执行的动作是丢弃,也就是说,在这里,包的生命走到了终点,在这种情况下,iptables对包的处理只是将包丢弃,它不会对包的发送者返回任何信息,也不会向路由器发送任何错误信息,这在某些情况下会造成一些问题,比如发送者还在苦苦等待回包的到来,而发送出去的包早就在半路上夭折了,可以通过REJECT target来避免这个问题,REJECT和DROP的差别在于它不仅仅丢弃包,而且还礼节性的告诉发送者,这样就不至于发送者苦苦等待了。其实对于一般的应用,我们并不建议使用REJECT,既然包总是要被DROP的,那就让发送者去等吧,这和我们有什么关系呢?
ACCEPT:这个target没有任何选项和参数,使用也很简单,指定-j ACCEPT即可。一旦包满足了指定的匹配条件,就会被ACCEPT,并且不会再去匹配当前链中的其他规则或同一个表内的其他规则。
SNAT:这个target是用来做源网络地址转换的,就是重写包的源IP地址。当我们有若干台计算机共享一个Internet 连接时,就能用到它了,而且这也是绝大多数企业用户所采用的Internet互联方案。先在内核里打开ip转发功能,然后再写一个SNAT规则,就可以把所有从本地网络出去的包的源地址改为Internet连接的地址了。如果我们不这样做而是直接转发本地网的数据包的话,Internet上的机子就不知道往哪儿发送应答了,因为在本地网里我们一般使用的是IANA组织专门指定的一段地址,它们是不能在Internet上使用的,还记得那些地址范围吗?让我们来回忆一下:
10.0.0.0 - 10.255.255.255 (10/8 prefix)
172.16.0.0 - 172.31.255.255 (172.16/12 prefix)
192.168.0.0 - 192.168.255.255 (192.168/16 prefix)
SNAT target的作用就是让所有从本地网出发的包看起来都是从一台机子发出的,这台机子一般就是防火墙或路由器之类的三层设备。
SNAT只能用在nat表的POSTROUTING链里。只要连接的第一个符合条件的包被SNAT了,那么这个连接的其他所有的包都会自动地被SNAT,而且这个规则还会应用于这个连接所在流的所有数据包。
既然提到了ip包转发的问题,我们也不妨费一些文字做一些简要的说明,当iptables被用来安装在一个提供WWW或E_mail服务的主机上以期为主机提供保护时是不涉及包转发的,但当iptables被用在网络的边界节点充当一个安全网关时,就涉及到包转发的问题了,这时,iptables需要通过不同的网卡来转发数据包,在linux系统中,控制是否允许转发数据包是有一个开关的,0表示不转发,1表示转发,只要更改 /etc/sysct.confl文件中的如下内容:
#Controls IP Packets Forwarding
net.ipv4.ip_forward = 1
然后重启系统,这时系统就能够进行包转发了,还有一种方法是在内核空间内直接更改,通过改下列文件的参数:
#echo 1 > /proc/sys/net/ipv4/ip_forward
注意,这个文件一旦更改,立即生效,但如果重启系统,将回到默认设置,所以/etc/sysctl.conf文件无论如何都应该将转发开关置位为“1”。
看看下面的范例,一般一个SNAT的命令是这样完成的:
#iptables –t nat –A POSTROUTING –s 192.168.1.0 –j SNAT --to-source 1.1.1.1
这条命令表示将内部网络的192.168.1.0/24网段的地址翻译成1.1.1.1,这样内部地址就可以使用一个公有IP(Public IP address)地址共享上网了,当然,还要有额外的策略允许内部用户上网才行哦,别忘了。
SNAT只有一个参数,--to-source,它有几种使用方法:
1、单独的地址,就象上面的例子所示。
2、一段连续的地址,用连字符分隔,如1.1.1.1-1.1.1.10,这样可以实现负载平衡。每个流会被随机分配一个IP,但对于同一个流使用的是同一个IP。当然,前提是你要有这么多的公有ip才行啊!
3、在指定-p tcp 或 -p udp的前提下,可以指定源端口的范围,如1.1.1.1:1024-32000,这样包的源端口就被限制在1024-32000了。
DNAT:这个target是用来做目的网络地址转换的,意思是重写包的目的IP地址。如果一个包被匹配了,那么和它属于同一个流的所有的包都会被自动转换,然后就可以被路由到正确的主机或网络。DNAT target是非常有用的。比如,你的Web服务器在LAN内部,而且没有可在Internet上使用的真实IP地址,那就可以使用这个 target让防火墙把所有到它自己HTTP端口的包转发给LAN内部真正的Web服务器。目的地址也可以是一个范围,这样的话,DNAT会为每一个流随机分配一个地址。因此,我们可以用这个target做某种类型的负载平衡。
DNAT也和SNAT一样只有一个参数,--to-destination,看看下面的例子:
#iptables –t nat –A PREROUTING –d 1.1.1.1 –j DNAT --to-destination 192.168.1.24
上面的例子说明凡是访问1.1.1.1的数据包都转给内网的192.168.1.24,这样内部的服务器就可以发布出去了。现在问题来了,如果仅仅这样配置还是存在一点问题的,假设内部网络的其他用户也访问这个经过映射后的地址会怎样?当然他们完全可以直接访问服务器的真实地址,但在一些具体的情况下,比如 dns的解析就是指向了映射后的地址。可以加一条这样的语句:
#iptables –t nat –A POSTROUTING –d 1.1.1.1 –j SNAT –to-source 192.168.1.254
在这里,假设防火墙的内网地址是192.168.1.254,通过这样的配置,问题解决了,想一想为什么会这样?看看下面的示意图:也许你就明白了:

知道问题出在哪里了吗?很明显,当客户机192.168.1.23发起一个访问请求给映射后的地址1.1.1.1,防火墙收到这个请求后根据策略表匹配发现是一个对内部服务器192.168.1.24的映射,如果不加上面的那一行语句,防火墙会通过纯路由的方式将数据包转发给服务器 192.168.1.24,服务器收到请求后,发现源地址为192.168.1.23的客户机发来了一个请求,并且这台主机与自己在同一个网段内,于是直接将回应包SYN+ACK发送给主机192.168.1.23,主机收到这个包后会感觉很奇怪,因为它从来就没有给192.168.1.24发送过连接请求报文,所以就会将回应报文丢弃,现在,我们对内网主机通过映射后地址访问内网服务器的需求进行一些修改,如上面的哪条命令,我们对所有到1.1.1.1 的连接都做一个原地址路由,将连接的原地址改变成防火墙的内网接口地址,于是问题解决了。
当然,问题总有两面性,对于服务器而言,所有访问者这时都变成了防火墙内网的接口地址,这对于服务器的审计是有影响的,在具体的配置过程中,使用者需要权衡利弊,在做配置决定。
MASQUERADE:这个链与SNAT的差别不大,回忆一下在进行SNAT的配置时需要指明一个固定的映射地址,但如果用户的网络使用的是ADSL这种动态获取IP地址的方式,SNAT就不适用了,这时只能使用MASQUERADE(地址伪装),在具体的处理过程中,系统需要读取当前的动态地址,然后用当前的地址对数据包进行重新封装:
#iptables –A POSTROUTING –o eth1 –s 192.168.1.0/24 –j MASQUERADE
MASQUERADE可以添加参数--to-ports 1024-30000,可以通过这个参数指定映射后的源端口范围。