当前位置: > Linux服务器 > iptables >

Iptables 指南 1.1.19(9)

时间:2014-12-10 23:35来源:www.it.net.cn 作者:IT
Chapter 8. 例子简介
本章的目的是对指南提到的每个脚本都给以简单明了的说明,以及提供一个关于这些脚本的框架,描述它 们提供的服务。这些脚本不是任何情况都能用的,它们可能并不符合你的意图。也就是说,为了能满足你的 需要,还是要取决于你自己。在这方面,下面的内容可能会给你很大的帮助。第一小节介绍了这些脚本的结 构,你会发现我们在这些脚本里使用的处理方式还是比较容易的。
 
8.1. rc.firewall.txt脚本的结构
本指南所有的脚本都是依据一个特定的结构来写的。理由嘛,就是这样可以使它们彼此相似,便于我们查 找不同之处。本章将要对这个结构做一个很好的说明,而且还会简单地阐述这些脚本为什么会按照现在这种 样子来写,以及我为什么选择一直使用这种结构。
 
 
 
Note
注意,即使我选择了这种结构,你也不一定非要用它,对你来说,它可能并不是最好的。我选择它 只是因为它易读,而且能很好地符合我的逻辑。
 
8.1.1. 脚本结构
这就是本指南所有脚本遵循的脚本结构。如果有不同于此的地方,可能就是我出错了,除非我特意说明为 什么要打破这种结构。
 
 
 
Configuration —— 首先是一个配置选项区,里面的变量在脚本中会用到。 几乎任何脚本(shell-script)的第一部分都是配置选项区。
 
 
 
Internet —— 有关Internet连接的配置。如果我们没有任何Internet连 接,这一部分就可以跳过去。注意,相比我们列出来的,这一部分可能会包含更多小节,虽然我们这里只有 了了几个,但足够应对我们已有的各种Internet连接了。
 
 
 
DHCP —— 如果脚本用到了DHCP,我们就要在此添加相应的配置。
 
PPPoE —— 如果想把脚本用于PPPoE连接,就要在此添加相应的配置。
 
LAN —— 如果防火墙后有局域网,就要使用这里的配置了。大部分情况下 都会用到这儿,因为局域网几乎总是存在的。
 
DMZ —— 对非军事区(DMZ zone)的配置。大部分脚本不会用到这个设 置,因为这些脚本针对的主要是一些普通的家庭网络,或小企业的网络。
 
Localhost —— 本地(local-host)的有关设置。虽然我把它们写成变量 的形式,但一般不会被改变,也不应该有什么理由要改变它们。
 
iptables —— 有关iptables的设置。大部分情况下,这里只设置一个变 量,用来指向iptables程序的位置。
 
Other —— 如果还有什么信息,首先应该把它们放在相应的小节里,实在 没有相应的小节,就放这儿吧。
 
Module loading —— 脚本应该维护一个模块列表。它分为两部分,第一部分 包含必需的模块,同时第二部分要包含不必要的模块的列表。
 
 
 
Note
注意,这些模块可能会提高安全性,或为管理者、客户添加某些服务,还有一些模块不是必需 的,但它们可能也被加入了列表。不过,在本例中,我已经注意了这个问题。
 
 
 
Required modules —— 这里装载的是必要的模块,它们可能会提高安全性 或为管理者、客户增加某些服务。
 
Non-required modules —— 这里列出的是不必要的模块,所以它们都被注 释掉了。如果你用到了它们提供的功能,就可以启用它们。
 
proc configuration —— 这儿关心的是有关proc系统的设置。如果一些选项 是必须的,我们就启用它,如果不是,就把它注释掉。大部分有用的proc配置都列在这儿了,但远远不是全 部的。
 
 
 
Required proc configuration —— 包含了使脚本能正常工作的所有必需 的proc配置,它也可以包含一些能提高安全性或为管理者、客户增加特定服务的选项。
 
Non-required proc configuration —— 这里提到的选项不是必需的,虽 然它们可能很有用。因此,我把它们都注释掉了。当然,这里并没有包括所有这样的选项。
 
rules set up —— 现在,应该添加规则了。我把所有的规则都明确地分配到 了与表、链相应的小节里。所有自定义的规则都写在系统内建的链之前(译者注:当然要写在前面了,因为 后面要调用它们哦)。另外,我是按照命令iptables -L输出的顺序来安排此脚本里 表与链的出现顺序的(译者注:这样,便于我们查看哦)。
 
 
 
Filter table —— 首先是filter表,而且我们先要设置策略。
 
 
 
Set policies —— 为所有系统内建的链设置策略。通常,我会设置 DROP,对于允许使用的服务或流会在后面明确地给以ACCEPT。这样,我们就可以方便地排除所有我们不想让 人们使用的端口。
 
Create user specified chains —— 在这里创建所有以后会用到的自定 义链。如果没有事先建立好,后面是不能使用它们的,所以我们要尽早地建立这些链。
 
Create content in user specified chains —— 建立自定义链里使用 的规则。其实你也可以在后面的某个地方写这些规则,之所以写在这儿,唯一的原因是这样做规则和链会离 得近些,便于我们查看。
 
INPUT chain —— 创建INPUT链的规则。
 
 
 
Note
从这里开始,我就是遵循iptables -L的输出格式来创建规则的,这 样做的唯一原因就是为了便于阅读,避免混淆。
 
FORWARD chain —— 为FORWARD链创建规则。
 
OUTPUT chain —— 为OUTPUT链创建规则。其实,在这里要建的规则很 少。
 
nat table —— 在处理完filter表之后,该设置nat表了。我们这样做是有 一定原因的。首先,我们不想太早地打开转发机制(译者注:注意,filter表设定的是过滤机制,而不是转 发)和NAT功能,因为它们可能导致数据会在错误的时间(也就是这样的时刻:我们打开了NAT,但过滤规则 还没有运行)通过防火墙。还有,我把nat表看作是围绕filter表的一个层。也就是说,filter表是核心, nat表是它外部的一个层,mangle表是第二层。从某些观点来看,这可能有点不对,但也八九不离十了。
 
 
 
Set policies —— 与filter一样,我们先来设置策略。一般说来,缺省 的策略,即ACCEPT,就很好。这个表不应该被用来做任何过滤,而且我们也不应该在这儿丢弃任何包,因为 对我们假设的网络情况来说,可能会发生一些难以应付的事情。我把策略设为ACCEPT,因为没有什么原因不 这样做。
 
Create user specified chains —— 在这儿创建nat表会用到的自定义 链。一般情况下,我没有任何规则要在这儿建立,但我还是保留了这个小节,以防万一罢了。注意,在被系 统内建链调用之前一定要建好相应的自定义链。
 
Create content in user specified chains —— 建立自定义链的规 则。
 
PREROUTING chain —— 要对包做DNAT操作的话,就要用到此链了。大部 分脚本不会用到这条链,或者是把里面的规则注释掉了,因为我们不想在不了解它的情况下就在防火墙上撕 开一个大口子,这会对我们的局域网造成威胁。当然,也有一些脚本默认使用了这条链,因为那些脚本的目 的就是提供这样的服务。
 
POSTROUTING chain —— 如果使用SNAT操作,就要在此建立规则。你可 能有一个或多个局域网需要防火墙的保护,而我就是依据这样的情况来写此脚本的,所以这个脚本中使用的 POSTROUTING链是相当实用的。大部分情况下,我们会使用SNAT target,但有些情况,如PPPoE,我们不得不 使用MASQUERADE target。
 
OUTPUT chain —— 不管什么脚本都几乎不会用到这个链。迄今为止,我 还没有任何好的理由使用它,如果你有什么理由用它了的话,麻烦你把相应的规则也给我一份,我会把它加 到本指南里的。
 
mangle table —— 最后要做的就是处理mangle表了。通常,我不会使用这 个表,因为一般情况下,它不会被任何人要到,除非他们有什么特殊的需要,比如为了隐藏一条连接后的多 台机子,我们要统一设置TTL或TOS等。在这个脚本里,此表是空白的。但在此指南中还是有个小小的例子说 明了mangle表的用处。
 
 
 
Set policies —— 设置策略。这里的情形和nat表几乎完全相同。这里 不应该做过滤,也不应该丢弃任何包。在任何脚本里我都不会把mangle表的策略设为其他的值,也不鼓励你 这样做。
 
Create user specified chains —— 建立自定义链。我几乎不会用到这 个链,所以没有建立任何规则。保留此小节,只是已备后用。
 
Create content in user specified chains —— 建立自定义链的规 则。
 
PREROUTING —— 本指南的所有脚本都未在此链建立规则。
 
INPUT chain —— 本指南的所有脚本都未在此链建立规则。
 
FORWARD chain —— 本指南的所有脚本都未在此链建立规则。
 
OUTPUT chain —— 本指南的所有脚本都未在此链建立规则。
 
POSTROUTING chain —— 本指南的所有脚本都未在此链建立规则。
 
这应该可以较详细地解释每个脚本的结构是怎样的以及它们为什么要使用这个结构了。
 
 
 
Caution
注意,上面的描述其实还是非常简单的,应该被看作一个摘要,它简要地解释了脚本为什么要按照 这种松散的结构来写。千万注意,我可没有说过这种结构是唯一的、最好的。
 
8.2. rc.firewall.txt
 
 
 
 
 
 
脚本rc.firewall.txt是核心,第七章防火墙配置实例 rc.firewall对它已经做了很详细的解释,其他的脚 本都是以它为基础得到的。这个脚本主要是针对具有两个连接的家庭网络而设计的,如一个局域网连接,一 个Internet连接。我们假设的情况是你有一个静态IP地址,不需要DHCP,PPP, SLIP或其他什么协议为你动态分配IP。如果你想要的恰恰是使用这些协议的脚本,就到rc.DHCP.firewall.txt看看吧。
 
脚本rc.firewall.txt要完全发挥作用,系统必需要有下面列出的功能,你可 以把它们编译进内核,也可以编译成模块。如果你改变了脚本,就要加入相应的功能模块或把它们编进内 核。
 
 
 
CONFIG_NETFILTER
 
CONFIG_IP_NF_CONNTRACK
 
CONFIG_IP_NF_IPTABLES
 
CONFIG_IP_NF_MATCH_LIMIT
 
CONFIG_IP_NF_MATCH_STATE
 
CONFIG_IP_NF_FILTER
 
CONFIG_IP_NF_NAT
 
CONFIG_IP_NF_TARGET_LOG
 
8.3. rc.DMZ.firewall.txt
 
 
 
 
 
 
脚本rc.DMZ.firewall.txt所针对的情况 是这样的:有一个可信任的内网,一个DMZ,还有一个Internet连接。这里的DMZ是通过设置一对一的NAT 操作得到的,它需要IP别名(就是在一块网卡上设置多个IP地址)的支持。我们还有其他的方法来实现 DMZ:如果你有一个整个的网段,可划分子网,然后把某个子网分给DMZ,再为防火墙配置相应的内网与外网 IP地址(译者注:第一种方法是针对有多个网段的情况,即内网一个网段,DMZ一个网段,第二种方法是把一 个网段划分成几个子网,这样就和第一种情况一样了)。注意,这种方法会多消耗两个IP,一个是网络地 址,一个是广播地址(译者注:具体细节请上网搜索子网划分的相关信息,这个指南并不包含此类信息)。 以上两种方法用哪一个就要你自己决定了。本指南会给你实现防火墙与NAT的手段或叫做技术,但具体如何去 做,没有完全的说明,因为这已经超出本文的范围了。
 
这个脚本需要以下模块,也可能它们已被编译进内核了。
 
 
 
CONFIG_NETFILTER
 
CONFIG_IP_NF_CONNTRACK
 
CONFIG_IP_NF_IPTABLES
 
CONFIG_IP_NF_MATCH_LIMIT
 
CONFIG_IP_NF_MATCH_STATE
 
CONFIG_IP_NF_FILTER
 
CONFIG_IP_NF_NAT
 
CONFIG_IP_NF_TARGET_LOG
 
从图中可以看出,此脚本假设你有两个内网,一个是可信任的内网,使用地址192.168.0.0/24,另一个是 DMZ(我们正是对它做一对一的NAT),使用地址192.168.1.0/24。如果有人从Internet向我们的DNS_IP发送一个包,我们就要对它使用DNAT,之后,此包的目的地址就指向DMZ 里的DNS服务器了,它也就可以到达真正的DNS服务器。否则,DNS服务器不会看到这个包,也就没有应答之说 了。下面是实现上述DNAT功能的语句:
 
$IPTABLES -t nat -A PREROUTING -p TCP -i $INET_IFACE -d 
$DNS_IP /
--dport 53 -j DNAT --to-destination $DMZ_DNS_IP
    
我们可以看出,这个规则要放在nat表的PREROUTING链中,包要满足的条件是:使用 TCP协议且使用53号端口,从接口$INET_IFACE进入,而且要以$DNS_IP为目的。被匹配的包要交给DNAT target来处理,它会把包的目的地址 改为由--to-destination指定的地址$DMZ_DNS_IP。这就是 DNAT的工作流程。当相应的应答包被发送到防火墙时,会自动地被un-DNAT。
 
现在,你应该完全可以读懂这个脚本了。如果有什么你不明白的东西在脚本的其他部分没有被用到,那可 能就是我的错误了,要告诉我哦。
 
8.4. rc.DHCP.firewall.txt
 
 
 
 
 
 
脚本rc.DHCP.firewall.txt适用于那些 使用DHCP、PPP或SLIP连接Internet的情况,它和原始的脚本rc.firewall.txt几乎一样,主要的区别在于这里不再使用变量STATIC_IP。原因很简单了,就是它不能和动态的IP一起使用。此脚本相对于原始脚本的 改变是很少的,但还是有一些人发信问我做了什么改变。经过大家的考验,这个脚本应该是一个很好的解决 方案了。
 
它需要如下功能模块。
 
 
 
CONFIG_NETFILTER
 
CONFIG_IP_NF_CONNTRACK
 
CONFIG_IP_NF_IPTABLES
 
CONFIG_IP_NF_MATCH_LIMIT
 
CONFIG_IP_NF_MATCH_STATE
 
CONFIG_IP_NF_FILTER
 
CONFIG_IP_NF_NAT
 
CONFIG_IP_NF_TARGET_MASQUERADE
 
CONFIG_IP_NF_TARGET_LOG
 
我做的改变主要是删除了变量STATIC_IP以及和它相关的所有东西。以前,主要 的过滤工作是基于变量STATIC_IP的,现在是INET_IFACE 了。也就是说,在这个脚本里,我们不再把-d $STATIC_IP作为过滤的条件,而是用 -i $INET_IFACE。这几乎是唯一的改变,也是必需的改变。
 
可还是有一些问题要考虑。现在,我们不能再在INPUT链依据某些条件,比如--in-interface $LAN_IFACE --dst $INET_IP来进行过滤(译者注:因为这时已无固定 的INET_IP)。这强迫我们只能基于Internet接口进行包的过滤,在这种情况下,内网必须访问那个可变的 Internet的IP。这会出现一些问题,有个例子可以说明这一点,就是我们在防火墙上运行HTTP服务。如果我 们访问这个网站(其中,主页包含了一个指向HTTP服务器的静态连接,这可能是某个动态的DNS解决方案), 问题就暴露了。经过NAT操作的机子会向DNS查询HTTP服务器的IP,然后再试着访问这 个IP。万一我们是基于接口和IP做的过滤,这台机子就不能访问到HTTP了,因为INPUT链会 DROP掉这个包(译者注:还是因为Internet接口的IP不固定)。在某种情况下,这也会发生在你有静态IP的 时候,但在那种情况下,我们可以增加一条规则,以检查LAN接口的包是否是发往INET_IP的,若是,则ACCEPT。
 
如果你看过以前的内容,得到或写一个可以获取动态IP的脚本可能会是个解决问题的好办法。比如,我们 可以写一个脚本,它紧随着Internet连接的启动而运行,而且它能从命令ifconfig的 输出中提取IP,再把这个IP赋给某个变量。较好的办法是使用一些程序自带的脚本,如 pppd带的脚本ip-up。也有一些网站,如linuxguruz.org,提供了很多有用的 脚本,你可以在附录其他资源和链接找到它的链接。
 
 
 
Note
这个脚本比rc.firewall.txt的安全性要差一点。我明确地建议你尽可 能使用后者,因为前者的开放性大了点,所以外部攻击的威胁就大了。
 
还有一种方法可获得IP,就是在脚本里加上类似这样的语句:
 
INET_IP=`ifconfig $INET_IFACE | grep inet | cut -d : -f 2 | 
/
cut -d ' ' -f 1`
    
上面这句话的作用是从ifconfig的输出里提取接口$INET_IFACE的IP,再赋给$INET_IP。更好的办法是使用脚本 retreiveip.txt。但要注意,这个方法可能会引起一些不正常的情况,比如使防火墙和内网之间已有的 连接停止。下面就说明一下最常见的问题。
 
 
 
如果这个脚本的代码是在另一个脚本内运行的,而那个脚本又是由PPP daemon启动的,就会因 为NEW not SYN rules(具体信息查看未设置SYN的NEW状态包)的原因而 挂起所以当前活动的连接。如果你删掉那个规则,可能会没有事,但还是不保险。
 
如果你不想改动已有的规则,而又要添加或删除规则,还要不损害已有的规则,这就没法做了。比如, 你又想阻塞所有局域网里的机子访问防火墙,又想让它们能控制防火墙上的PPP daemon,如果不删除 那个用来阻塞的规则,怎么能完成这样的事?
 
事情可能也不必这么复杂,就像上面说的,这会导致一些安全问题。但如果这个脚本能保持简单,维 持规则的顺序与发现问题都是很容易的。
 
 
8.5. rc.UTIN.firewall.txt
 
 
 
 
 
 
脚本rc.UTIN.firewall.txt适用于这样 的情况:我们不信任任何与防火墙连接的网络,包括内网。我们只允许内网使用POP3、HTTP 和FTP。至于从Internet来的连接,权限和其他脚本一样。
 
此脚本需要以下功能模块。
 
 
 
CONFIG_NETFILTER
 
CONFIG_IP_NF_CONNTRACK
 
CONFIG_IP_NF_IPTABLES
 
CONFIG_IP_NF_MATCH_LIMIT
 
CONFIG_IP_NF_MATCH_STATE
 
CONFIG_IP_NF_FILTER
 
CONFIG_IP_NF_NAT
 
CONFIG_IP_NF_TARGET_LOG
 
这个脚本遵循的原则是不要相信任何人,包括我们自己的员工。这是个令人悲痛的现实,大部分破坏和攻 击确实是来自我们内部的。这个脚本只是在加强防火墙方面给了你一个例子。它和 rc.firewall.txt并没有太多的不同,只是少了一些允许通行的规则。
 
8.6. rc.test-iptables.txt
这个脚本用来测试iptables里所有的链。当然,这要根据你的配置情况做些操作,如打开ip_forwarding或是设置masquerading,等等。只要你的安装了基本的 iptables,就可以使用它。其实这个脚本只使用了LOG,以便能记录所有的ping请求 与应答。通过这种方式,我们就可以了解哪些链被穿越了以及被穿越的顺序。使用方法如下,先运行这个脚 本,再发布一个ping命令,如:
 
ping -c 1 host.on.the.internet
 
    
然后用命令tail -n 0 -f /var/log/messages就可看到用了哪些链以及是什么顺 序,除非记录因某些原因被替换了。
 
 
 
Note
此脚本仅仅是为测试而写的。也就是说,不要使用类似这样的规则,它记录某一类包的所有信息, 这会很快地占满你的日志分区,而且它会成为一个有效的DoS攻击。它还可能导致在最初的DoS攻击之后,无 法记录真正的攻击信息。
 
8.7. rc.flush-iptables.txt
rc.flush-iptables.txt不应该被称作 脚本,它只是重置并清空所有的表、链。它先把filter表的INPUT、OUTPUT和 FORWARD链的策略设为缺省的ACCEPT,然后是nat表的PREROUTING 、POSTROUTING和OUTPUT链。我们这样做就不必为被关闭的连接和没有通过的包而操心。 这个脚本就是为防火墙设置和除错用的,因此我们只关心打开所有的东西并恢复它们的缺省值就行了。
 
之后,我们清空filter表里所有的链,紧接着是NAT表的。这样,就不会有什么不应该存 在的规则了。这个做完后就该删除filter表和NAT表里的自定义链了。这时,脚本的工作就应 该完成了。当然,如果你用到了mangle表,可以在这个脚本里添加相应的清空规则。(译者注:其实 作者已经这样做了)
 
 
 
Note
最后再说明一下,有些人写信建议我把这个脚本放到rc.firewall脚本里面,而且是用Red Hat Linux脚本的语法,这样当rc.firewall启动时,这个脚本也可以启动。但我不会这样做的,因为这是一个指 南,主要是用来学习iptables的使用方法的,不应该有过多的shell脚本特有的语法。加入shell脚本特有的 语法会使阅读的难度大大增加,这就远离了我的初衷。这个指南是按照易读的标准来写的,以后我会继续这 样做。
 
8.8. Limit-match.txt
这个脚本是用来测试limit match的,也会让你明白limit match是如何工作的。装入这个脚本,再用不同 的时间间隔发送ping数据包,可以看出哪个包可以通过,这些包又是以什么频率通过的。你应该可以看出, 在limit的burst值再次到达之前,所有的echo replies都会被阻塞。
 
8.9. Pid-owner.txt
这个脚本说明了如何使用PID owner match。它其实什么都没做,但你可以运行一下,命令iptables -L -v的输出会说明它确实匹配了些东西。
 
8.10. Sid-owner.txt
说明SID owner match如何使用的一个例子。同样,它也是什么都没做,但你可以运行一下,命令iptables -L -v的输出会说明它确实匹配了些东西。
 
8.11. Ttl-inc.txt
一个小小的例子,说明了如何隐藏我们的防火墙或路由器,以使跟踪路由程序看不到,这样就可以对可能 的攻击者隐藏很多信息。
 
8.12. Iptables-save ruleset
这只是一个输出的例子,它在规则的保存与恢复里被用来说明 iptables-save命令是如何使用的。所以,它没有任何用处,只是一个参考而已。
 
附录 A. 常用命令详解
A.1. 查看当前规则集的命令
查看当前正在使用的规则集是一个十分常用的操作,使用iptables的什么命令还 记得吗?我们可是在规则是如何练成的这一章里介绍过啊,虽然 到时说得简单了点。再复习一下吧,命令语法如下:
 
iptables -L
 
这个命令会尽可能地以易读的形式显示当前正在使用的规则集。比如,它会尽量用文件/etc/services里相应的名字表示端口号,用相应的DNS记录表示IP地址。但后者可能 会导致一些问题,例如,它想尽力把LAN的IP地址(如192.168.1.1)解析 成相应的名字。但192.168.0.0/16这个网段是私有的,也就是说,它只能 用在局域网里,而不能在Internet里使用,所以它不会被Internet上的DNS服务器解析。因此,当解析这个地 址时,命令就好像停在那儿了。为了避免这种情况的发生,我们就要使用选项:
 
iptables -L -n
 
如果你想看看每个策略或每条规则、每条链的简单流量统计,可以在上面的命令后再加一个verbose标 志,如下:
 
iptables -L -n -v
 
不要忘了,iptables -L命令还可以查看nat表和mangle表的内容哦(更不要忘 了,默认的表是filter),只需要使用-t选项,比如我们只想看nat表的规则,就用下面的命令:
 
iptables -L -t nat
 
在/proc里,可能还有一些文件你会感兴趣。比如,你可以在连接跟踪记录表 里看到当前有哪些连接。这个表包含了当前的所有连接,你还可以通过它了解到每个连接处于什么状态。要 注意,这个表是不能编辑的,即使可以,也不应该更改它。可以用下面的命令查看这个表:
 
cat /proc/net/ip_conntrack | less
 
此命令会显示当前所有被跟踪的连接,但要读懂那些记录可是有些难度哦。
 
A.2. 修正和清空iptables的命令
即使你把iptables弄的一塌糊涂,我们也有非常有效的命令来处理,而不必重新启动计算机。我接到过很 多关于这个问题的询问,所以我想最好在这儿回答一下。如果你增加的规则有问题,要想删掉它,只要把命 令中的-A改为-D即可。这样,iptables就会找到那个错误的 规则并删掉它,但如果在你的规则里有好几条同样的规则,它只能删掉找到的第一条。如果你不想这样的事 情发生,那就试试用序号来删除。如,你想删除INPUT链的第10条规则,可以使用 iptables -D INPUT 10。
 
还有一种情况,就是要清空整个链,这就要使用选项-F。比如,我们要清空整个 INPUT链,使用的命令就是iptables -F INPUT。但是要注意,选项-F并不改变链的缺省策 略。所以,如果被我们清空的那条INPUT链的策略是DROP,它还是会阻塞所有的包。那怎么才能重置策略呢? 还记得策略DROP是如何设置的吧,还是用那个方法啊。比如,我们把INPUT链的策略改为ACCEPT,就用iptables -P INPUT ACCEPT。
 
我已经写了一个用来清空并重置iptables的脚本,叫做rc.flush- iptables.txt(附录里有它的代码),在你写自己的防火 墙脚本时,很可能会用到。但如果你在mangle表里乱试乱改而导致问题的话,这个脚本就帮不上忙了。因为 在脚本rc.firewall.txt里,我没有用到mangle表,所以在 rc.flush-iptables.txt里也就没有添加相应的恢复功能。
 
附录 B. 常见问题与解答
B.1. 模块装载问题
装载模块时,你可能会遇到几个问题,比如,有错误提示说明没有你指定名字的那种模块:
 
insmod: iptable_filter: no module by 
that name found
这个提示是无关紧要的,因为那些模块很有可能已经被静态地编译进内核了。当你遇到这个信息时,这是 你应该首先想到的。至于是否真的如我们所想,最简单的测试方就是敲一个用到那个模块功能的命令试试。 对于上面的情况,可能是filter表没有装入,从而就没有相应的功能,当然不能使用filter表了。为了检查 filter表是否装入,可以用下面的命令来试试:
 
iptables -t filter -L
   
这个命令会输出filter表里所有的链,或者是运行失败,给出错误提示信息。如果一切正常,输出结果类 似下面的情况,当然,这还要看你是否已经在filter表里加入了规则(译者注:在这个例子里,表是空 的)。
 
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
 
Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
 
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
    
如果你确实没有装载filter表,得到的就是如下信息:
 
iptables 
v1.2.5: can't initialize iptables table `filter': Table /
     does not exist (do you need to insmod?)
Perhaps iptables or your kernel needs to be upgraded.
    
这个问题就有些严重了,从此提示中我们能得到两个信息:第一,我们确实没有把相应的功能编译进内核 里;第二,在模块一般应在的目录中没有找到这个模块。这意味着问题是,你或者忘记了装载想用的模块, 或者没有用depmod -a命令更新模块数据库,或者没有把相应的功能编译进内核(不 论是静态的还是作为模块)。当然还可能是其他原因,但这些是主要的,不管怎样,大部分原因是很容易解 决的。比如,第一个问题可以简单地通过在内核源码目录里运行make modules_install 命令来解决,这当然是有前提的,就是源码已经编译(compile)而且模块已经构建(build)。第二个 问题的解决办法也很简单,只要运行一下depmod -a命令,之后再看看能否正常工作即可。第三个问题有点超出我们的范围了,而 且这个问题或多或少会让你感到发晕。更多的信息可以在Linux文档计划里找 到。
 
在运行iptables时,你还可能得到另外一个错误信息:
 
iptables: No chain/target/match by that name
   
这说明你要用的链或target、或match不存在,原因有很多,但最普遍的是你拼错了名字。当你想使用一 个不可用的模块时也会产生这种错误。模块之所以不可用,可能是因为你没有装载正确的模块,或者内核里 不包含那个模块,或者是iptables自动装载模块时失败了。通常,你不止应该考虑上面提到的所有解决办 法,还要考虑规则中target的拼写错误,或者其他的原因。
 
B.2. 未设置SYN的NEW状态包
iptables有个“特点”没有被很好地给以说明,所以很多人(当然,也包括我)都忽视了它。这个“特 点”就是:如果你使用状态NEW,那么未设置SYN的包也会通过防火墙。之所以有这个特点,是因为在某些情况下, 我们想把那样的包看作某个(比如是和另一个防火墙有关的)已处于ESTABLISHED状 态的连接的一部分。这个特点使拥有两个或更多的防火墙协同工作成为可能,而且可使数据在服务器间无丢 失的传输,如辅助防火墙可以接受子网的防火墙的操作。但它也会导致这样的事情:状态 NEW会允许几乎所有的TCP连接进入,而不管是否有3次握手。为了处理这个问题,我们需要在防火墙的 INPUT链、OUTPUT链和FORWARD链加入如下规则(译者注:此规则作者称为“NEW not SYN rules”,下一小节 还会提到):
 
$IPTABLES -A 
INPUT -p tcp ! --syn -m state --state NEW -j LOG /
     --log-prefix "New not syn:"
$IPTABLES -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
    
 
 
Caution
警告,在Netfilter/iptables项目中,这个特点所 拥有的行为缺少文档说明,更明确的说,在你的防火墙上,它是一个很不安全的因素。
 
注意,这个规则用于microsoft的TCP/IP(微软实现的TCP/IP就是不行,至少现在不行)产生的包时还是 有些问题。如果包是由microsoft的产品生成的,且被标为状态NEW,那么就会被此规 则记录然后丢弃。看起来规则工作很正常啊,是吧。但问题就出在这儿了,因为连接无法中断了。这个问题 出现在关闭连接时,在最后一个包即FIN/ACK包发出后,Netfilter的状态机制就会关 闭连接、删除连接跟踪表里的相应记录。但就在这时,Microsoft那不完善的程序会发送另外一个包,这个包 就是那种未设置SYN且被认为是NEW状态的包,因此它就会被上面的规则匹配。换句话说,就是对这个规则不 需要过于关注,如果你很在意它,就在规则里加入选项--log-headers吧。这样,你 就可以把包头记录下来,从而可以更好地了解相应的包。
 
对于这个规则,还有一些已知的问题。比如,某个连接(比如是从LAN发出的)已经连接到防火墙,而且 有个脚本要在启动PPP时激活。当你启动PPP连接时,刚才提到的那个连接可能就会被干掉(be killed)。当 然,这只会在特定的情况下才能发生,就是你把conntrack和nat作为模块运行,并且每次运行那个脚本时这 两个模块都要被装入和卸载。如果你在防火墙之外的机子上运行telnet,而且又通过这个telnet连接运行脚 本rc.firewall.txt,也会导致上面的问题。为了能简单地表达这个问题,你先准 备一个telnet连接,或其他的流连接,再运行连接跟踪模块,然后装入上面的规则,最后,试着用telnet client或daemon发送一些数据。效果应该出来了,连接 跟踪代码会认为这个连接是非法的,因为在此之前,它没有看到任何方向有包发出,更为严重的是现在连接 上有了未设置SYN的包,因为刚才由telnet client或daemon发出的包肯定不是这个连接的第一个包。因此, 上面的规则就起作用了,也就是说,这个包会被记录下来,然后被无情地扔掉,从而连接就会中断。
 
B.3. NEW状态的SYN/ACK包
某些,TCP欺骗攻击所用的技术叫做序列号预测(Sequence Number Prediction)。在这类攻击中,攻击 者利用另一台机子的IP访问攻击对象(译者注:这就是为什么叫欺骗的原因了,攻击者是想假冒另一台被攻 击对象信任的机子,以达到欺骗攻击对象的目的),然后再试着预测攻击对象使用什么序列号。
 
我们来看看典型的使用序列号预测技术的欺骗是如何实现的,参与者:攻击者[A](attacker)试图假装 另一台机子[O](other host)向受害者[V](victim)发送数据。
 
 
 
[A]以[O]的IP为源地址向[V]发SYN。
 
[V]向[O]回应SYN/ACK。
 
现在,若[O]以RST回应这个未知的SYN/ACK,攻击就失败了,但如果[O]已经没有这个能力了呢?比如它 早已被另外的攻击(如SYN flood)降服,或者被关闭,或者它的RST包被防火墙拒绝。
 
如果[O]没能破坏这条连接,而且[A]猜对了序列号,那它就能以[O]的身份和[V]交谈了。
 
只要我们没能在第三步以RST回应那个未知的SYN/ACK包,[V]就会被攻击,而且我们还会被连累(译者 注:因为我们本身也被攻击了,而且还可能会成为攻击者的替罪羊被起诉,呜呜,好惨)。所以,为安全起 见,我们应该以正确的方式向[V]发送一个RST包。如果我们使用类似“NEW not SYN rules”(译者注:在上 一小节中)的规则,SYN/ACK包就可以被丢弃了。因此,我们在bad_tcp_packets链中加入了如下规则:
 
iptables -A 
bad_tcp_packets -p tcp --tcp-flags SYN,ACK SYN,ACK /
-m state --state NEW -j REJECT --reject-with tcp-reset
   
这样,你想成为上面那个[O]的机会就很少了(译者注:作者好幽默啊,我们可不想成为被别人利用的对 象),而且这条规则在绝大部分情况下是安全的,不会有什么副作用,但多个防火墙要协同工作的情况要除 外。那种情况下,防火墙之间会经常传递、接受包或流,有了这条规则,有些连接可能会被阻塞,即使是合 法的连接。这条规则的存在还产生了另外一问题,就是有几个portscan(端口扫描器)会看到我们的防火 墙,但好在仅此而已。
 
B.4. 使用私有IP地址的ISP
我的一位朋友告诉我说有些事我完全忘记了,从那时起,我就把这一节加上了。你刚上网时连接的网络是 ISP提供的,但某些愚蠢的ISP在那个网络里使用的是私有地址,而那是IANA专门分 配给局域网使用的。Swedish Internet Service Provider和电话垄断企业Telia就是这样做的,例如在DNS服 务器上,他们使用的IP地址段就是10.x.x.x。我们最容易遇到的问题是,在这个脚本里,为了防止被欺骗, 不允许从10.x.x.x发出的连接来访问我们。不幸的是,对于上面的例子,为了DNS能正常地被访问,我们不得 不把规则的放宽松一些。也就是说,我们或者在刚才提到的那条防止欺骗的规则上面增加一条规则(如 下),或者是把那条规则注释掉:
 
/usr/local/sbin/iptables -t nat -I PREROUTING -i 
eth1 -s /
     10.0.0.1/32 -j ACCEPT
   
我愿意对这些ISP再多费些唇舌。这些IP地址不是为了让你象这样愚蠢的使用而分配给你的,至少我知道 不是这样的。对于一个大集团的站点或者是我们自己的家庭网络来说,这样用是很合适的,但你不能只因为 你们的一些原因就强迫我们把自己公示于天下。
 
B.5. 放行DHCP数据
一旦你了解DHCP是如何工作的,就会知道这其实是一个很简单的任务。但你必须小心处理到底让谁进入、 不让谁进入。首先,我们要明白DHCP是工作在UDP协议之上的,所以,UDP协议是我们期望的第一个条件。其 次,我们应该检查是从那个接口接收和发送请求的。例如,如果我们设置了DHCP使用接口eth0,那就要阻塞 eth1上的DHCP请求。为了让规则再详细些,我们只需打开(allow)DHCP实际使用的UDP端口,一般都是67和 68。这两个端口是标准定义,我们就用它们来匹配被允许的包。现在,规则应该是这个样子的:
 
$IPTABLES  -I INPUT -i $LAN_IFACE -p udp --dport 67:68 --sport /
     67:68 -j ACCEPT
   
注意,现在我们能够接受所有来自和发往UDP端口67、68的数据,好像不太安全,但这并不是多大的问 题,因为这条规则只允许从67或68端口连接的主机才能访问。当然,此规则还可以更严谨一些,但也应该足 够接受所有的DHCP请求和更新,而不至于需要在防火墙上开一个大洞。如果你很在意现在的规则是否很宽 松,你当然可以写一个限制条件更紧的。
 
B.6. 关于mIRC DCC的问题
mIRC使用一个特殊的设定,它可以使mIRC连接穿过防火墙,也可以使DCC连接能在防火墙不了解它的情况 下正常工作。如果此选项和iptables还有ip_conntrack_irc模块与ip_nat_irc模块一起使用,那mIRC就不能 工作了。问题在于mIRC会自动对包进行NAT操作,这样当包到达防火墙后,防火墙就完全不知道该对包做什么 了,也不知道该怎么做。如果是防火墙来处理,它只是简单地用自己的IP去询问IRC服务器,然后用那个地址 发送DCC请求。mIRC不希望防火墙自作聪明地以这种方式代替自己来处理这个包。
 
打开“I am behind a firewall”(我在防火墙后)这个配置选项并且使用ip_conntrack_irc和 ip_nat_irc模块,会导致Netfilter建立包含“Forged DCC send packet”的记录。
 
最简单的解决办法是不要选中mIRC的那个选项而让iptables来做这些工作。意思就是要明确地告诉mIRC, 它不是在防火墙后面的。
 
附录 C. ICMP类型
这是一个完整的ICMP类型的列表:
 
Table C-1. ICMP类型
 
TYPE CODE Description Query Error
0 0 Echo Reply——回显应答(Ping应答) x
3 0 Network Unreachable——网络不可达 x
3 1 Host Unreachable——主机不可达 x
3 2 Protocol Unreachable——协议不可达 x
3 3 Port Unreachable——端口不可达 x
3 4 Fragmentation needed but no frag. bit set——需要进行分片但设置不分片比特 x
3 5 Source routing failed——源站选路失败 x
3 6 Destination network unknown——目的网络未知 x
3 7 Destination host unknown——目的主机未知 x
3 8 Source host isolated (obsolete)——源主机被隔离(作废 不用) x
3 9 Destination network administratively prohibited——目的网络被强制禁止 x
3 10 Destination host administratively prohibited——目的主机被强制禁止 x
3 11 Network unreachable for TOS——由于服务类型TOS,网络 不可达 x
3 12 Host unreachable for TOS——由于服务类型TOS,主机不可 达 x
3 13 Communication administratively prohibited by filtering——由于过滤,通信被强制禁止 x
3 14 Host precedence violation——主机越权 x
3 15 Precedence cutoff in effect——优先中止生效 x
4 0 Source quench——源端被关闭(基本流控制)
5 0 Redirect for network——对网络重定向
5 1 Redirect for host——对主机重定向
5 2 Redirect for TOS and network——对服务类型和网络重定 向
5 3 Redirect for TOS and host——对服务类型和主机重定向
8 0 Echo request——回显请求(Ping请求) x
9 0 Router advertisement——路由器通告
10 0 Route solicitation——路由器请求
11 0 TTL equals 0 during transit——传输期间生存时间为0 x
11 1 TTL equals 0 during reassembly——在数据报组装期间生 存时间为0 x
12 0 IP header bad (catchall error)——坏的IP首部(包括各 种差错) x
12 1 Required options missing——缺少必需的选项 x
13 0 Timestamp request (obsolete)——时间戳请求(作废不 用) x
14 Timestamp reply (obsolete)——时间戳应答(作废不用) x
15 0 Information request (obsolete)——信息请求(作废不 用) x
16 0 Information reply (obsolete)——信息应答(作废不用) x
17 0 Address mask request——地址掩码请求 x
18 0 Address mask reply——地址掩码应答 x

(责任编辑:IT)
------分隔线----------------------------