摘要:Iptables 指南 1.1.19(4)
Iptables 指南 1.1.19
6.5. Targets/Jumps
target/jump决定符合条件的包到何处去,语法是--jump target或-j target。(译者注:本文中,原作者把target细分为两类,即Target和Jump。它们唯一的区别是jump的目标是一个在同一个表内的链,而target的目标是具体的操作。)我们会先接触到两个基本的target,就是ACCEPT和DROP。
前面提到过用户自定义链要用到-N命令。下面我们在filter表中建一个名为tcp_packets的链:
iptables -N tcp_packets
然后再把它作为jump的目标:
iptables -A INPUT -p tcp -j tcp_packets
这样我们就会从INPUT链跳入tcp_packets链,开始在tcp_packets中的旅行。如果到达了tcp_packets链的结尾(也就是未被链中的任何规则匹配),则会退到INPUT链的下一条规则继续它的旅行。如果在子链中被ACCEPT了,也就相当于在父链中被ACCEPT了,那么它不会再经过父链中的其他规则。但要注意这个包能被其他表的链匹配,过程可查看章节 表和链。
target指定我们要对包做的操作,比如DROP和ACCEPT,还有很多,我们后面会介绍。不同的target有不同的结果。一些target会使包停止前景,也就是不再继续比较当前链中的其他规则或父链中的其他规则,最好的例子就是DROP和ACCEPT。而另外一些target在对包做完操作之后,包还会继续和其他的规则比较,如LOG,ULOG和TOS。它们会对包进行记录、mangle,然后让包通过,以便匹配这条链中的其他规则。有了这样的target,我们就可以对同一个包既改变它的TTL又改变它的TOS。有些target必须要有准确的参数(如TOS需要确定的数值),有些就不是必须的,但如果我们想指定也可以(如日志的前缀,伪装使用的端口,等等)。本节我们会尽可能全面地介绍每一个target。现在我们就来看看有哪几种target。
6.5.1. ACCEPT target
这个target没有任何选项和参数,使用也很简单,指定-j ACCEPT即可。一旦包满足了指定的匹配条件,就会被ACCEPT,并且不会再去匹配当前链中的其他规则或同一个表内的其他规则,但它还要通过其他表中的链,而且在那儿可能会百DROP也说不准哦。
6.5.2. DNAT target
这个target是用来做目的网络地址转换的,就是重写包的目的IP地址。如果一个包被匹配了,那么和它属于同一个流的所有的包都会被自动转换,然后就可以被路由到正确的主机或网络。DNAT target是非常有用的。比如,你的Web服务器在LAN内部,而且没有可在Internet上使用的真实IP地址,那就可以使用这个 target让防火墙把所有到它自己HTTP端口的包转发给LAN内部真正的Web服务器。目的地址也可以是一个范围,这样的话,DNAT会为每一个流随机分配一个地址。因此,我们可以用这个target做某种类型地负载平衡。
注意,DANT target只能用在nat表的PREROUTING和OUTPUT链中,或者是被这两条链调用的链里。但还要注意的是,包含DANT target的链不能被除此之外的其他链调用,如POSTROUTING。
Table 6-16. DNAT target
Option
--to-destination
Example
iptables -t nat -A PREROUTING -p tcp -d 15.45.23.67 --dport 80 -j DNAT --to-destination 192.168.1.1-192.168.1.10
Explanation
指定要写入IP头的地址,这也是包要被转发到的地方。上面的例子就是把所有发往地址15.45.23.67的包都转发到一段LAN使用的私有地址中,即192.168.1.1到 192.168.1.10。如前所述,在这种情况下,每个流都会被随机分配一个要转发到的地址,但同一个流总是使用同一个地址。我们也可以只指定一个IP地址作为参数,这样所有的包都被转发到同一台机子。我们还可以在地址后指定一个或一个范围的端口。比如:--to-destination 192.168.1.1:80或 --to-destination 192.168.1.1:80-100。SNAT的语法和这个target的一样,只是目的不同罢了。要注意,只有先用--protocol指定了TCP或 UDP协议,才能使用端口。
因为DNAT要做很多工作,所以我要再罗嗦一点。我们通过一个例子来大致理解一下它是如何工作的。比如,我想通过Internet连接发布我们的网站,但是HTTP server在我们的内网里,而且我们对外只有一个合法的IP,就是防火墙那个对外的IP——$INET_IP。防火墙还有一个内网的IP——$LAN_IP,HTTP server的IP是$HTTP_IP (这当然是内网的了)。为了完成我们的设想,要做的第一件事就是把下面的这个简单的规则加入到nat表的PREROUTING链中:
iptables -t nat -A PREROUTING --dst $INET_IP -p tcp --dport 80 -j DNAT \ --to-destination $HTTP_IP
现在,所有从Internet来的、到防火墙的80端口去的包都会被转发(或称做被DNAT )到在内网的HTTP服务器上。如果你在Internet上试验一下,一切正常吧。再从内网里试验一下,完全不能用吧。这其实是路由的问题。下面我们来好好分析这个问题。为了容易阅读,我们把在外网上访问我们服务器的那台机子的IP地址记为$EXT_BOX。
包从地址为$EXT_BOX的机子出发,去往地址为$INET_IP 的机子。
包到达防火墙。
防火墙DNAT(也就是转发)这个包,而且包会经过很多其他的链检验及处理。
包离开防火墙向$HTTP_IP前进。
包到达HTTP服务器,服务器就会通过防火墙给以回应,当然,这要求把防火墙作为HTTP到达$EXT_BOX的网关。一般情况下,防火墙就是HTTP服务器的缺省网关。
防火墙再对返回包做Un-DNAT(就是照着DNAT的步骤反过来做一遍),这样就好像是防火墙自己回复了那个来自外网的请求包。
返回包好象没经过这么复杂的处理、没事一样回到$EXT_BOX。
现在,我们来考虑和HTTP服务器在同一个内网(这里是指所有机子不需要经过路由器而可以直接互相访问的网络,不是那种把服务器和客户机又分在不同子网的情况)的客户访问它时会发生什么。我们假设客户机的IP为$LAN_BOX,其他设置同上。
包离开$LAN_BOX,去往$INET_IP。
包到达防火墙。
包被DNAT,而且还会经过其他的处理。但是包没有经过SNAT 的处理,所以包还是使用它自己的源地址,就是$LAN_BOX(译者注:这就是IP 传输包的特点,只根据目的地的不同改变目的地址,但不因传输过程中要经过很多路由器而随着路由器改变其源地址,除非你单独进行源地址的改变。其实这一步的处理和对外来包的处理是一样的,只不过内网包的问题就在于此,所以这里交待一下原因)。
包离开防火墙,到达HTTP服务器。
HTTP服务器试图回复这个包。它在路由数据库中看到包是来自同一个网络的一台机子,因此它会把回复包直接发送到请求包的源地址(现在是回复包的目的地址),也就是$LAN_BOX。
回复包到达客户机,但它会很困惑,因为这个包不是来自它访问的那台机子。这样,它就会把这个包扔掉而去等待“真正”的回复包。
针对这个问题有个简单的解决办法,因为这些包都要进入防火墙,而且它们都去往需要做DNAT才能到达的那个地址,所以我们只要对这些包做SNAT操作即可。比如,我们来考虑上面的例子,如果对那些进入防火墙而且是去往地址为$HTTP_IP、端口为80的包做SNAT操作,那么这些包就好象是从$LAN_IP来的了,也就是说,这些包的源地址被改为$LAN_IP了。这样,HTTP服务器就会把回复包发给防火墙,而防火墙会再对包做 Un-DNAT操作,并把包发送到客户机。解决问题的规则如下:
iptables -t nat -A POSTROUTING -p tcp --dst $HTTP_IP --dport 80 -j SNAT \ --to-source $LAN_IP
要记住,按运行的顺序POSTROUTING链是所有链中最后一个,因此包到达这条链时,已经被做过DNAT操作了,所以我们在规则里要基于内网的地址$HTTP_IP(包的目的地)来匹配包。

警告:我们刚才写的这条规则会对日志产生很大影响,这种影响应该说是很不好的。因为来自 Internet包在防火墙内先后经过了DNAT和SNAT处理,才能到达HTTP服务器(上面的例子),所以HTTP服务器就认为包是防火墙发来的,而不知道真正的源头是其他的IP。这样,当它记录服务情况时,所有访问记录的源地址都是防火墙的IP而不是真正的访问源。我们如果想根据这些记录来了解访问情况就不可能了。因此上面提供的“简单办法”并不是一个明智的选择,但它确实可以解决“能够访问”的问题,只是没有考虑到日志而已。
其他的服务也有类似的问题。比如,你在LAN内建立了SMTP服务器,那你就要设置防火墙以便能转发SMTP的数据流。这样你就创建了一个开放的SMTP中继服务器,随之而来的就是日志的问题了。
一定要注意,这里所说的问题只是针对没有建立DMZ或类似结构的网络,并且内网的用户访问的是服务器的外网地址而言的。(译者注:因为如果建立了DMZ,或者服务器和客户机又被分在不同的子网里,那就不需要这么麻烦了。因为所有访问的源头都不在服务器所在的网里,所以就没必要做SNAT去改变包的源地址了,从而记录也就不是问题了。如果内网客户是直接访问服务器的内网地址那就更没事了)
较好的解决办法是为你的LAN在内网建立一台单独的DNS服务器(译者注:这样,内网的客户使用网站名访问HTTP服务器时,DNS就可以把它解析成内网地址。客户机就可以直接去访问HTTP服务器的内网地址了,从而避免了通过防火墙的操作,而且包的源地址也可以被HTTP服务器的日志使用,也就没有上面说的日志问题了。),或者干脆建立DMZ得了(这是最好的办法,但你要有钱哦,因为用的设备多啊)。
对上面的例子应该考虑再全面些,现在还有一个问题没解决,就是防火墙自己要访问HTTP服务器时会发生什么,能正常访问吗?你觉得呢:)很可惜,现在的配置还是不行,仔细想想就明白了。我们这里讨论的基础都是假设机子访问的是HTTP服务器的外网地址,但这个外网地址其实就是防火墙对外的地址,所以当防火墙访问这个外网地址时,就是访问它自己。防火墙上如果有HTTP服务,那客户机就会看到页面内容,不过这不是它想看到的(它想要的在DNAT上了),如果没有HTTP服务,客户就只能收到错误信息了。前面给出的规则之所以不起作用是因为从防火墙发出的请求包不会经过那两条链。还记得防火墙自己发出的包经过哪些链吧:)我们要在nat表的OUTPUT链中添加下面的规则:
iptables -t nat -A OUTPUT --dst $INET_IP -p tcp --dport 80 -j DNAT \ --to-destination $HTTP_IP
有了最后这条规则,一切都正常了。和HTTP服务器不在同一个网的机子能正常访问服务了,和它在一个网内的机子也可以正常访问服务了,防火墙本身也能正常访问服务了,没有什么问题了。这种心情,套用《大话西游》里的一句话,就是“世界又清净了”。(不要说你不知道什么是《大话西游》)

我想大家应该能明白这些规则只说明了数据包是如何恰当地被DNAT和SNAT的。除此之外,在 filter表中还需要其他的规则(在FORWARD链里),以允许特定的包也能经过前面写的(在POSTROUTING链和 OUTPUT链里的)规则。千万不要忘了,那些包在到达FORWARD链之前已经在PREROUTING链里被DNAT过了,也就是说它们的目的地址已被改写,在写规则时要注意这一点。
6.5.3. DROP target
顾名思义,如果包符合条件,这个target就会把它丢掉,也就是说包的生命到此结束,不会再向前走一步,效果就是包被阻塞了。在某些情况下,这个target会引起意外的结果,因为它不会向发送者返回任何信息,也不会向路由器返回信息,这就可能会使连接的另一方的sockets因苦等回音而亡:) 解决这个问题的较好的办法是使用REJECT target,(译者注:因为它在丢弃包的同时还会向发送者返回一个错误信息,这样另一方就能正常结束),尤其是在阻止端口扫描工具获得更多的信息时,可以隐蔽被过滤掉的端口等等(译者注:因为扫描工具扫描一个端口时,如果没有返回信息,一般会认为端口未打开或被防火墙等设备过滤掉了)。还要注意如果包在子链中被DROP了,那么它在主链里也不会再继续前进,不管是在当前的表还是在其他表里。总之,包死翘翘了。
6.5.4. LOG target
这个target是专门用来记录包地有关信息的。这些信息可能是非法的,那就可以用来除错。LOG会返回包的有关细节,如IP头的大部分和其他有趣的信息。这个功能是通过内核的日志工具完成的,一般是syslogd。返回的信息可用dmesg阅读,或者可以直接查看syslogd的日志文件,也可以用其他的什么程序来看。LOG对调试规则有很大的帮助,你可以看到包去了哪里、经过了什么规则的处理,什么样的规则处理什么样的包,等等。当你在生产服务器上调试一个不敢保证100%正常的规则集时,用LOG代替DROP是比较好的(有详细的信息可看,错误就容易定位、解决了),因为一个小小的语法错误就可能引起严重的连接问题,用户可不喜欢这样哦。如果你想使用真正地扩展日志地话,可能会对ULOG target有些兴趣,因为它可以把日志直接记录到MySQL databases或类似的数据库中。

注意,如果在控制台得到的信息不是你想要的,那不是iptables或Netfilter的问题,而是 syslogd 配置文件的事,这个文件一般都是/etc/syslog.conf。有关这个问题的更多信息请查通过man syslog.conf查看。
LOG现在有5个选项,你可以用它们指定需要的信息类型或针对不同的信息设定一些值以便在记录中使用。选项如下:
Table 6-17. LOG target options
Option
--log-level
Example
iptables -A FORWARD -p tcp -j LOG --log-level debug
Explanation
告诉iptables和 syslog使用哪个记录等级。记录等级的详细信息可以查看文件syslog.conf,一般来说有以下几种,它们的级别依次是:debug,info,notice,warning,warn,err,error,crit,alert, emerg,panic。其中,error和err、warn和warning、panic和emerg分别是同义词,也就是说作用完全一样的。注意这三种级别是不被赞成使用的,换句话说,就是不要使用它们(因为信息量太大)。信息级别说明了被记录信息所反映的问题的严重程度。所有信息都是通过内核的功能被记录的,也就是说,先在文件 syslog.conf里设置kern.=info /var/log/iptables,然后再让所有关于iptables的LOG信息使用级别info,就可以把所有的信息存入文件/var/log/iptables内。注意,其中也可能会有其他的信息,它们是内核中使用info 这个等级的其他部分产生的。有关日志的详细信息,我建议你看看syslog和syslog.conf的帮助,还有HOWTO,等等。
Option
--log-prefix
Example
iptables -A INPUT -p tcp -j LOG --log-prefix "INPUT packets"
Explanation
告诉iptables在记录的信息之前加上指定的前缀。这样和grep或其他工具一起使用时就容易追踪特定的问题,而且也方便从不同的规则输出。前缀最多能有29个英文字符,这已经是包括空白字符和其他特殊符号的总长度了。
Option
--log-tcp-sequence
Example
iptables -A INPUT -p tcp -j LOG --log-tcp-sequence
Explanation
把包的TCP序列号和其他日志信息一起记录下来。TCP序列号可以唯一标识一个包,在重组时也是用它来确定每个分组在包里的位置。注意,这个选项可能会带来危险,因为这些记录被未授权的用户看到的话,可能会使他们更容易地破坏系统。其实,任何iptables的输出信息都增加了这种危险。(译者注:现在,我深刻理解了什么是“言多必失”,什么是“沉默是金”)
Option
--log-tcp-options
Example
iptables -A FORWARD -p tcp -j LOG --log-tcp-options
Explanation
记录TCP包头中的字段大小不变的选项。这对一些除错是很有价值的,通过它提供的信息,可以知道哪里可能出错,或者哪里已经出了错。
Option
--log-ip-options
Example
iptables -A FORWARD -p tcp -j LOG --log-ip-options
Explanation
记录IP包头中的字段大小不变的选项。这对一些除错是很有价值的,还可以用来跟踪特定地址的包。
6.5.5. MARK target
用来设置mark值,这个值只能在本地的mangle表里使用,不能用在其他任何地方,就更不用说路由器或另一台机子了。因为mark比较特殊,它不是包本身的一部分,而是在包穿越计算机的过程中由内核分配的和它相关联的一个字段。它可以和本地的高级路由功能联用,以使不同的包能使用不同的队列要求,等等。如果你想在传输过程中也有这种功能,还是用TOS target吧。有关高级路由的更多信息,可以查看Linux Advanced Routing and Traffic Control HOW-TO。
Table 6-18. MARK target options
Option
--set-mark
Example
iptables -t mangle -A PREROUTING -p tcp --dport 22 -j MARK --set-mark 2
Explanation
设置mark值,这个值是一个无符号的整数。比如,我们对一个流或从某台机子发出的所有的包设置了mark值,就可以利用高级路由功能来对它们进行流量控制等操作了。
6.5.6. MASQUERADE target
这个target和SNAT target的作用是一样的,区别就是它不需要指定--to-source 。MASQUERADE是被专门设计用于那些动态获取IP地址的连接的,比如,拨号上网、DHCP连接等。如果你有固定的IP地址,还是用SNAT target吧。
伪装一个连接意味着,我们自动获取网络接口的IP地址,而不使用--to-source 。当接口停用时,MASQUERADE不会记住任何连接,这在我们kill掉接口时是有很大好处的。如果我们使用SNAT target,连接跟踪的数据是被保留下来的,而且时间要好几天哦,这可是要占用很多连接跟踪的内存的。一般情况下,这种处理方式对于拨号上网来说是较好的(这有利于已有那连接继续使用)。如果我们被分配给了一个不同于前一次的IP,不管怎样已有的连接都要丢失,但或多或少地还是有一些连接记录被保留了(真是白痴,是吧)。
即使你有静态的IP,也可以使用MASQUERADE,而不用SNAT 。不过,这不是被赞成的,因为它会带来额外的开销,而且以后还可能引起矛盾,比如它也许会影响你的脚本,使它们不能用。
注意,MASQUERADE和SNAT一样,只能用于nat表的 POSTROUTING链,而且它只有一个选项(不是必需的):
Table 6-19. MASQUERADE target
Option
--to-ports
Example
iptables -t nat -A POSTROUTING -p TCP -j MASQUERADE --to-ports 1024-31000
Explanation
在指定TCP或UDP的前提下,设置外出包能使用的端口,方式是单个端口,如--to-ports 1025,或者是端口范围,如--to- ports 1024-3000。注意,在指定范围时要使用连字号。这改变了SNAT中缺省的端口选择,详情请查看 SNAT target。
6.5.7. MIRROR target
这个target是实验性的,它只是一个演示而已,不建议你使用它,因为它可能引起循环,除此之外,还可能引起严重的DoS。这个target的作用是颠倒IP头中的源目地址,然后再转发包。这会引起很有趣的事,一个骇客最后攻破的可能就是他自己的机子。看来,使用这个target至少可以使我们的机子更强壮:) 我们如果对机子A的80端口使用了MIRROR,会发生什么呢?假设有来自yahoo.com的机子B 想要访问A的HTTP服务,那他得到的将是yahoo的主页,因为请求是来自yahoo的。
注意,MIRROR只能用在INPUT、 FORWARD、 PREROUTING链和被它们调用的自定义链中。还要注意,如果外出的包是因 MIRROR target发出的,则它们是不会被filter、nat或mangle表内的链处理的,这可能引起循环或其他问题。比如,一台机子向另一台配置了MIRROR且TTL值为255的机子发送一个会被认为是欺骗的数据包,同时这台机子也欺骗自己的数据包,以使它被认为好像是来自第三个使用了MIRROR 的机子。这样,那个包就会不间断地往来很多次,直到TTL为0。如果两台机子之间只有一个路由器,这个包就会往返240-255次。对骇客来说,这是不坏的情况,因为他只要发送一个1500字节的数据(也就是一个包),就可以消耗你的连接的380K字节。对于骇客或者叫做脚本小子(不管我们把他们称作什么)来说,这可是很理想的情况。
6.5.8. QUEUE target
这个target为用户空间的程序或应用软件管理包队列。它是和iptables之外的程序或工具协同使用的,包括网络计数工具,高级的数据包代理或过滤应用,等等。讨论程序的编码已超出了本文的范围。即使讨论,也要花很多时间,而且在这样一篇文章之内也无法说清有关Netfilter和iptables的编程。具体的信息请查看Netfilter Hacking HOW-TO。
6.5.9. REDIRECT target
在防火墙所在的机子内部转发包或流到另一个端口。比如,我们可以把所有去往端口HTTP的包REDIRECT到HTTP proxy(例如squid),当然这都发生在我们自己的主机内部。本地生成的包都会被映射到127.0.0.1。换句话说,这个target把要转发的包的目的地址改写为我们自己机子的IP。我们在做透明代理(LAN内的机子根本不需要知道代理的存在就可以正常上网)时,这个target可是起了很大作用的。
注意,它只能用在nat表的PREROUTING、OUTPUT链和被它们调用的自定义链里。 REDIRECT只有一个选项:
Table 6-20. REDIRECT target
Option
--to-ports
Example
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080
Explanation
在指定TCP或UDP协议的前提下,定义目的端口,方式如下:
1、不使用这个选项,目的端口不会被改变。
2、指定一个端口,如--to-ports 8080
3、指定端口范围,如--to-ports 8080-8090
6.5.10. REJECT target
REJECT和DROP基本一样,区别在于它除了阻塞包之外,还向发送者返回错误信息。现在,此target还只能用在INPUT、FORWARD、OUTPUT和它们的子链里,而且包含 REJECT的链也只能被它们调用,否则不能发挥作用。它只有一个选项,是用来控制返回的错误信息的种类的。虽然有很多种类,但如果你有TCP/IP方面的基础知识,就很容易理解它们。
Table 6-21. REJECT target
Option
--reject-with
Example
iptables -A FORWARD -p TCP --dport 22 -j REJECT --reject-with tcp-reset
Explanation
告诉REJECT target应向发送者返回什么样的信息。一旦包满足了设定的条件,就要发送相应的信息,然后再象DROP一样无情地抛弃那些包。可用的信息类型有:1、icmp-net-unreachable 2、icmp-host-unreachable 3、 icmp-port-unreachable 4、icmp-proto-unreachable 5、icmp-net-prohibited 6、icmp-host-prohibited 。其中缺省的是port-unreachable。你可以在附录ICMP类型中看到更多的信息。还有一个类型——echo-reply,它只能和匹配 ICMP ping包的规则联用。最后一个类型是tcp-reset,(显然,只能用于TCP协议)它的作用是告诉REJECT返回一个TCP RST包(这个包以文雅的方式关闭TCP连接,有关它的详细信息在RFC 793 - Transmission Control Protocol里)给发送者。正如iptables的 man page中说的,tcp-reset主要用来阻塞身份识别探针(即113/tcp,当向被破坏的邮件主机发送邮件时,探针常被用到,否则它不会接受你的信)。
6.5.11. RETURN target
顾名思义,它使包返回上一层,顺序是:子链——>父链——>缺省的策略。具体地说,就是若包在子链中遇到了RETURN,则返回父链的下一条规则继续进行条件的比较,若是在父链(或称主链,比如INPUT)中遇到了RETURN,就要被缺省的策略(一般是ACCEPT或DROP)操作了。(译者注:这很象C语言中函数返回值的情况)
我们来举个例子说明一下,假设一个包进入了INPUT链,匹配了某条target为--jump EXAMPLE_CHAIN规则,然后进入了子链EXAMPLE_CHAIN。在子链中又匹配了某条规则,恰巧target是--jump RETURN,那包就返回INPUT链了。如果在INPUT链里又遇到了--jump RETURN,那这个包就要交由缺省的策略来处理了。
6.5.12. SNAT target
这个target是用来做源网络地址转换的,就是重写包的源IP地址。当我们有几个机子共享一个Internet 连接时,就能用到它了。先在内核里打开ip转发功能,然后再写一个SNAT规则,就可以把所有从本地网络出去的包的源地址改为Internet连接的地址了。如果我们不这样做而是直接转发本地网的包的话,Internet上的机子就不知道往哪儿发送应答了,因为在本地网里我们一般使用的是IANA组织专门指定的一段地址,它们是不能在Internet上使用的。SNAT target的作用就是让所有从本地网出发的包看起来都是从一台机子发出的,这台机子一般就是防火墙。
SNAT只能用在nat表的POSTROUTING链里。只要连接的第一个符合条件的包被SNAT了,那么这个连接的其他所有的包都会自动地被SNAT,而且这个规则还会应用于这个连接所在流的所有数据包。
Table 6-22. SNAT target
Option
--to-source
Example
iptables -t nat -A POSTROUTING -p tcp -o eth0 -j SNAT --to-source 194.236.50.155-194.236.50.160:1024-32000
Explanation
指定源地址和端口,有以下几种方式:
1、单独的地址。
2、一段连续的地址,用连字符分隔,如194.236.50.155-194.236.50.160,这样可以实现负载平衡。每个流会被随机分配一个IP,但对于同一个流使用的是同一个IP。
3、在指定-p tcp 或 -p udp的前提下,可以指定源端口的范围,如194.236.50.155:1024-32000,这样包的源端口就被限制在1024-32000了。
注意,如果可能,iptables总是想避免任何的端口变更,换句话说,它总是尽力使用建立连接时所用的端口。但是如果两台机子使用相同的源端口,iptables 将会把他们的其中之一映射到另外的一个端口。如果没有指定端口范围, 所有的在512以内的源端口会被映射到512以内的另一个端口,512和1023之间的将会被映射到 1024内,其他的将会被映射到大于或对于1024的端口,也就是说是同范围映射。还要注意,这种映射和目的端口无关。因此,如果客户想和防火墙外的HTTP服务器联系,它是不会被映射到FTP control所用的端口的。
6.5.13. TOS target
TOS是用来设置IP头中的Type of Service字段的。这个字段长一个字节,可以控制包的路由情况。它也是iproute2及其子系统可以直接使用的字段之一。值得注意的是,如果你有几个独立的防火墙和路由器,而且还想在他们之间利用包的头部来传递路由信息,TOS是唯一的办法。前面说过,MARK是不能用来传递这种信息的。如果你需要为某个包或流传递路由信息,就要使用TOS字段,它也正是为这个而被开发的。
Internet上有很多路由器在这一方面并没有做好工作,因此,在发送包之前改变其TOS没有什么大用处。最好的情况是路由器根本不理它,最坏的情况是路由器会根据TOS处理,但都是错误的。然而,如果你是在一个很大的WAN或LAN里,而且有很多路由器,TOS还是能有很好的作为的。总的来说,基于TOS的值给包以不同的路由和参数还是可能的,即使在网络里是受限制的(译者注:大不了不起作用就是了)。

TOS只能用来设置具体的或者说是特定的值(这些预定义的值在内核源码的include文件——Linux/ip.h中),原因是很多的,但不管怎么说,你不要使用其他的值就是了。当然,我们也有办法突破这个限制,就是使用一个名为FTOS的patch,你可在由Matthew G. Marsh维护的站点 Paksecured Linux Kernel patches得到它,但要小心使用哦。除了非常特殊、极端的情况,我们是不应该使用预定义以外的值的。

注意,这个target只能在mangle表内使用。

还要注意,在一些老版(1.2.2或更低)的iptables中包含的这个target在设置了TOS之后,不会调整包的校验和,这样包会被认为是错误的并要求重发。而且,这很可能会导致更多的mangle操作,从而使整个连接无法工作。(译者注:好在我们现在不会再用这么老的版本了:) )
TOS target只有一个选项:
Table 6-23. TOS target
Option
--set-tos
Example
iptables -t mangle -A PREROUTING -p TCP --dport 22 -j TOS --set-tos 0x10
Explanation
设置TOS的值,值的形式可以是名字或者使相应的数值(十进制或16进制的)。一般情况下,建议你使用名字而不使用数值形式,因为以后这些数值可能会有所改变,而名字一般是固定的。TOS字段有8个二进制位,所以可能的值是0-255(十进制)或0x00-0xFF(16进制)。如前所述,你最好使用预定义的值,它们是:
1、Minimize-Delay 16 (0x10),要求找一条路径使延时最小,一些标准服务如telnet、SSH、FTP- control 就需要这个选项。
2、Maximize-Throughput 8 (0x08),要求找一条路径能使吞吐量最大,标准服务FTP-data能用到这个。
3、Maximize-Reliability 4 (0x04),要求找一条路径能使可靠性最高,使用它的有BOOTP和TFTP。
4、Minimize-Cost 2 (0x02),要求找一条路径能使费用最低,一般情况下使用这个选项的是一些视频音频流协议,如RTSP(Real Time Stream Control Protocol)。
5、Normal-Service 0 (0x00),一般服务,没有什么特殊要求。这个值也是大部分包的缺省值。
完整的列表可以通过命令iptables -j TOS -h
得到。在1.2.5版时,这个列表就已经是完整的了,而且会保持很长一段时间。
6.5.14. TTL target

这个target需要patch-o-matic里的名为TTL的patch,可从 http://www.netfilter.org获得。此站点的FAQ是开始学习iptables和Netfilter的好地方。
TTL可以修改IP头中Time To Live字段的值。它有很大的作用,我们可以把所有外出包的Time To Live值都改为一样的,比如64,这是Linux的默认值。有些ISP不允许我们共享连接(他们可以通过TTL的值来区分是不是有多个机子使用同一个连接),如果我们把TTL都改为一样的值,他们就不能再根据TTL来判断了。
关于任何设置Linux的TTL默认值,请参阅附录其他资源和链接 内的ip-sysctl.txt。
TTL只能在mangle表内使用,它有3个选项:
Table 6-24. TTL target
Option
--ttl-set
Example
iptables -t mangle -A PREROUTING -i eth0 -j TTL --ttl-set 64
Explanation
设置TTL的值。这个值不要太大,也不要太小,大约64就很好。值太大会影响网络,而且有点不道德,为什么这样说呢?如果有些路由器的配置不太正确,包的TTL又非常大,那它们就会在这些路由器之间往返很多次,值越大,占用的带宽越多。这个target就可以被用来限制包能走多远,一个比较恰当的距离是刚好能到达DNS服务器。
Option
--ttl-dec
Example
iptables -t mangle -A PREROUTING -i eth0 -j TTL --ttl-dec 1
Explanation
设定TTL要被减掉的值,比如--ttl-dec 3。假设一个进来的包的TTL是53,那么当它离开我们这台机子时,TTL就变为49了。为什么不是50呢?因为经过我们这台机子,TTL本身就要减1,还要被TTL target再减3,当然总共就是减去4了。使用这个 target可以限制“使用我们的服务的用户”离我们有多远。比如,用户总是使用比较近的DNS,那我们就可以对我们的DNS服务器发出的包进行几个--ttl-dec。(译者注:意思是,我们只想让距离DNS服务器近一些的用户访问我们的服务)当然,用--set-ttl控制更方便些。
Option
--ttl-inc
Example
iptables -t mangle -A PREROUTING -i eth0 -j TTL --ttl-inc 1
Explanation
设定TTL要被增加的值,比如--ttl-inc 4。假设一个进来的包的TTL是53,那么当它离开我们这台机子时,TTL应是多少呢?答案是56,原因同--ttl-dec。使用这个选项可以使我们的防火墙更加隐蔽,而不被trace-routes发现,方法就是设置--ttl-inc 1。原因应该很简单了,包每经过一个设备,TTL就要自动减1,但在我们的防火墙里这个1又被补上了,也就是说,TTL的值没变,那么trace-routes就会认为我们的防火墙是不存在的。Trace-routes让人又爱又恨,爱它是因为在连接出问题时,它可以给我们提供极有用的信息,告诉我们哪里有毛病;恨它是由于它也可以被黑客或骇客用来收集目标机器的资料。怎么使用它呢?这里有个很好的例子,请看脚本Ttl-inc.txt。
6.5.15. ULOG target
ULOG可以在用户空间记录被匹配的包的信息,这些信息和整个包都会通过netlink socket被多播。然后,一个或多个用户空间的进程就会接受它们。换句话说,ULOG是至今iptables和Netfilter下最成熟、最完善的日志工具,它包含了很多更好的工具用于包的记录。这个target可以是我们把信息记录到MySQL或其他数据库中。这样,搜索特定的包或把记录分组就很方便了。你可以在ULOGD project page里找到ULOGD用户空间的软件。
Table 6-25. ULOG target
Option
--ulog-nlgroup
Example
iptables -A INPUT -p TCP --dport 22 -j ULOG --ulog-nlgroup 2
Explanation
指定向哪个netlink组发送包,比如-- ulog-nlgroup 5。一个有32个netlink组,它们被简单地编号位1-32。默认值是1。
Option
--ulog-prefix
Example
iptables -A INPUT -p TCP --dport 22 -j ULOG --ulog-prefix "SSH connection attempt: "
Explanation
指定记录信息的前缀,以便于区分不同的信息。使用方法和 LOG的prefix一样,只是长度可以达到32个字符。
Option
--ulog-cprange
Example
iptables -A INPUT -p TCP --dport 22 -j ULOG --ulog-cprange 100
Explanation
指定每个包要向“ULOG在用户空间的代理”发送的字节数,如--ulog-cprange 100,表示把整个包的前100个字节拷贝到用户空间记录下来,其中包含了这个包头,还有一些包的引导数据。默认值是0,表示拷贝整个包,不管它有多大。
Option
--ulog-qthreshold
Example
iptables -A INPUT -p TCP --dport 22 -j ULOG --ulog-qthreshold 10
Explanation
告诉ULOG在向用户空间发送数据以供记录之前,要在内核里收集的包的数量(译者注:就像集装箱),如--ulog-qthreshold 10。这表示先在内核里积聚10个包,再把它们发送到用户空间里,它们会被看作同一个netlink的信息,只是由好几部分组成罢了。默认值是1,这是为了向后兼容,因为以前的版本不能处理分段的信息。