--------------------------------------------------------------------------------
Linux 的封包过滤机制:iptables
上面谈了这麼多,主要还是希望您能瞭解到防火墙是什麼这个议题!而且也希望您知道防火墙并非万能的。 好了,那麼底下我们终於可以来瞧一瞧,那目前我们的 2.6 版这个 Linux 核心到底使用什麼核心功能来进行防火墙设定?
--------------------------------------------------------------------------------
不同 Linux 核心版本的防火墙软体
Linux 的防火墙為什麼功能这麼好?这是因為他本身就是由 Linux kernel 所提供, 由於直接经过核心来处理,因此效能非常好!不过,不同核心版本所使用的防火墙软体是不一样的! 因為核心支援的防火墙是逐渐演进来的嘛!
Version 2.0:使用 ipfwadm 这个防火墙机制;
Version 2.2:使用的是 ipchains 这个防火墙机制;
Version 2.4 与 2.6 :主要是使用 iptables 这个防火墙机制,不过在某些早期的 Version 2.4 版本的 distributions 当中,亦同时支援 ipchains (编译成為模组),好让使用者仍然可以使用来自 2.2 版的 ipchains 的防火墙规划。不过,不建议在 2.4 以上的核心版本使用 ipchains 喔!
因為不同的核心使用的防火墙机制不同,且支援的软体指令与语法也不相同, 所以在 Linux 上头设定属於你自己的防火墙规则时,要注意啊,先用 uname -r 追踪一下你的核心版本再说! 如果你是安装 2004 年以后推出的 distributions ,那就不需要担心了,因為这些 distributions 几乎都使用 kernel 2.6 版的核心啊! ^_^
--------------------------------------------------------------------------------
iptables 的表格与封包进入流程
前面的几个小节裡面我们一直谈到:『防火墙规则』,咦!啥是规则啊?因為 iptables 是利用封包过滤的机制, 所以他会分析封包的表头资料。根据表头资料与定义的『规则』来决定该封包是否可以进入主机或者是被丢弃。 意思就是说:『根据封包的分析资料 "比对" 你预先定义的规则内容, 若封包资料与规则内容相同则进行动作,否则就继续下一条规则的比对!』 重点在那个『比对与分析顺序』上。
举个简单的例子,假设我预先定义 10 条防火墙规则好了,那麼当 Internet 来了一个封包想要进入我的主机, 那麼防火墙是如何分析这个封包的呢?我们以底下的图示来说明好了:
图五、封包过滤的规则动作及分析流程

当一个网路封包要进入到主机之前,会先经由 NetFilter 进行检查,那就是 iptables 的规则了。 检查通过则接受 (ACCEPT) 进入本机取得资源,如果检查不通过,则可能予以丢弃 (DROP) ! 上图五主要的目的在告知您:『规则是有顺序的』!例如当网路封包进入 Rule 1 的比对时, 如果比对结果符合 Rule 1 ,此时这个网路封包就会进行 Action 1 的动作,而不会理会后续的 Rule 2, Rule 3.... 等规则的分析了。
而如果这个封包并不符合 Rule 1 的比对,那就会进入 Rule 2 的比对了!如此一个一个规则去进行比对就是了。 那如果所有的规则都不符合怎办?此时就会透过预设动作 (封包政策, Policy) 来决定这个封包的去向。 所以啦,当您的规则顺序排列错误时,就会產生很严重的错误了。 怎麼说呢?让我们看看底下这个例子:
假设您的 Linux 主机提供了 WWW 的服务,那麼自然就要针对 port 80 来啟用通过的封包规则,但是您发现 IP 来源為 192.168.100.100 老是恶意的尝试入侵您的系统,所以您想要将该 IP 拒绝往来,最后,所有的非 WWW 的封包都给他丢弃,就这三个规则来说,您要如何设定防火墙检验顺序呢?
Rule 1 先抵挡 192.168.100.100 ;
Rule 2 再让要求 WWW 服务的封包通过;
Rule 3 将所有的封包丢弃。
这样的排列顺序就能符合您的需求,不过,万一您的顺序排错了,变成:
Rule 1 先让要求 WWW 服务的封包通过;
Rule 2 再抵挡 192.168.100.100 ;
Rule 3 将所有的封包丢弃。
此时,那个 192.168.100.100 『可以使用您的 WWW 服务』喔!因為只要他对您的主机送出 WWW 要求封包,就可以使用您的 WWW 主机功能了,因為您的规则顺序定义第一条就会让他通过, 而不去考虑第二条规则!这样可以理解规则顺序的意义了吗!现在再来想一想,如果 Rule 1 变成了『将所有的封包丢弃』,Rule 2 才设定『WWW 服务封包通过』,请问,我的 client 可以使用我的 WWW 服务吗?呵呵!答案是『否~』想通了吗? ^_^
--------------------------------------------------------------------------------
iptables 的表格与链 (chain)
事实上,那个图五所列出的规则仅是 iptables 眾多表格当中的一个链 (chain) 而已。 什麼是链呢?这得由 iptables 的名称说起。為什麼称為 ip"tables" 呢? 因為这个防火墙软体裡面有多个表格 (table) ,每个表格都定义出自己的预设政策与规则, 且每个表格都用途都不相同。我们可以使用底下这张图来稍微瞭解一下:
图六、iptables 的表格示意图

刚刚图五的规则内容仅只是图六内的某个 chain 而已! 而预设的情况下,咱们 Linux 的 iptables 至少就有三个表格,包括管理本机进出的 filter 、管理后端主机 (防火墙内部的其他电脑) 的 nat 、 管理特殊旗标使用的 mangle (较少使用) 。更有甚者,我们还可以自订额外的链呢! 真是很神奇吧!每个表格与其中链的用途分别是这样的:
filter:主要跟 Linux 本机有关,这个是预设的 table 喔!
INPUT:主要与封包想要进入我们 Linux 本机有关;
OUTPUT:主要与我们 Linux 本机所要送出的封包有关;
FORWARD:这个咚咚与 Linux 本机比较没有关係,他可以封包『转递』到后端的电脑中,与 nat 这个 table 相关性很高。
nat:这个表格主要在用作来源与目的之 IP 或 port 的转换, 与 Linux 本机较无关,主要与 Linux 主机后的区域网路内的电脑较有相关。
PREROUTING:在进行路由判断之前所要进行的规则(DNAT/REDIRECT)
POSTROUTING:在进行路由判断之后所要进行的规则(SNAT/MASQUERADE)
OUTPUT:与发送出去的封包有关
mangle:这个表格主要是与特殊的封包的路由旗标有关, 早期仅有 PREROUTING 及 OUTPUT 链,不过从 kernel 2.4.18 之后加入了 INPUT 及 FORWARD 链。 由於这个表格与特殊旗标相关性较高,所以像咱们这种单纯的环境当中,较少使用 mangle 这个表格。
那麼各个表格与链的相关性可以使用下图来表示:
图七、iptables 内建各表格与链的相关性

上面的图示很复杂喔!不过基本上你依旧可以看出来,我们的 iptables 可以控制两种封包的流向:
如上图的 A ,封包主要是要读取我们 Linux 本机内的资料,会经过 filter 的 INPUT 链, 而资料的输出则是经过 filter 的 OUTPUT 链;
如上图的 B ,封包主要是要透过防火墙而去后端,也就是说,该封包的目标并非我们的 Linux 本机。 主要经过的链是 filter 的 FORWARD 以及 nat 的 POSTROUTING, PREROUTING。
由於 mangle 这个表格很少被使用,如果将图七的 mangle 拿掉的话,那就容易看的多了:
图八、iptables 内建各表格与链的相关性(简图)

透过图八你就可以更轻鬆的瞭解到,事实上与本机最有关的其实是 filter 这个表格内的 INPUT 与 OUTPUT 这两条链,如果你的 iptables 只是用来防备 Linux 主机本身的话,那 nat 的规则根本就不需要理他,直接设定為开放即可。
不过,如果你的防火墙事实上是用来管制 LAN 内的其他主机的话,那麼你就必须要再针对 filter 的 FORWARD 这条链,还有 nat 的 PREROUTING, POSTROUTING 以及 OUTPUT 进行额外的规则订定才行。 nat 表格的使用需要很清晰的路由概念才能够设定的好,建议新手先不要碰! 最多就是先玩一玩最阳春的 nat 功能『IP 分享器的功能』就好了! ^_^! 这部份我们在本章的最后一小节会介绍的啦!
--------------------------------------------------------------------------------
本机的 iptables 语法
理论上,当你安装好 Linux 之后,系统应该会主动的帮你啟动一个阳春的防火墙规则才是。 不过如果您是依照鸟哥的建议来安装 Linux 时,那麼安装完毕后,你的系统应该是没有防火墙的啦。 另外,某些早期的版本 (例如 Red Hat 9) 本身同时提供 iptables 及 ipchains 这两个防火墙模组, 不过这两个模组是无法同时存在的!所以你仅能啟动其中一个,那当然是啟动 iptables 才对啊! 如果不小心啟动了 ipchains 的话 (新版的 Linux 都不会有这个困扰) ,那请使用 rmmod 来移除吧!
不过,在开始进行底下的练习之前,鸟哥这裡有个很重要的事情要告知一下。 因為 iptables 的指令会将网路封包进行过滤及抵挡的动作,所以 请不要在远端主机上进行防火墙的练习,因為您很有可能一不小心将自己关在家门外! 尽量在本机前面登入 tty1-tty6 终端机进行练习,否则常常会发生悲剧啊! 鸟哥以前刚刚在玩 iptables 时,就常常因為不小心规则设定错误,导致常常要请远端的朋友帮忙重新开机...
刚刚提到咱们的 iptables 至少有三个预设的 table (filter, nat, mangle),较常用的是本机的 filter 表格, 这也是预设表格啦。另一个则是后端主机的 nat 表格,至於 mangle 较少使用,所以这个章节我们并不会讨论 mangle。 由於不同的 table 他们的链不一样,导致使用的指令语法或多或少都有点差异。 在这个小节当中,我们主要将针对 filter 这个预设表格的三条链来做介绍。底下就来玩一玩吧!
Tips:
防火墙的设定主要使用的就是 iptables 这个指令而已。而防火墙是系统管理员的主要任务之一, 且对於系统的影响相当的大,因此『只能让 root 使用 iptables 』,不论是设定还是观察防火墙规则喔!
--------------------------------------------------------------------------------
规则的清除与观察
如果你在安装的时候选择没有防火墙的话,那麼 iptables 在一开始的时候应该是没有规则的,不过, 可能因為你在安装的时候就有选择系统自动帮您建立防火墙机制,那系统就会有预设的防火墙规则了! 无论如何,我们先来看看目前本机的防火墙规则是如何吧!
[root@linux ~]# iptables [-t tables] [-L] [-nv]
参数:
-t :后面接 table ,例如 nat 或 filter ,若省略此项目,则使用预设的 filter
-L :列出目前的 table 的规则
-n :不进行 IP 与 HOSTNAME 的反查,显示讯息的速度会快很多!
-v :列出更多的资讯,包括通过该规则的封包总位元数、相关的网路介面等
范例:列出 filter table 三条链的规则
[root@linux ~]# iptables -L -n
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
范例:列出更多的资讯
[root@linux ~]# iptables -L -nv
Chain INPUT (policy ACCEPT 5748 packets, 746K bytes)
pkts bytes target prot opt in out source destination
....底下省略....
仔细看到上面表格的输出,因為没有加上 -t 的参数,所以预设就是 filter 这个表格内的 INPUT, OUTPUT, FORWARD 三条链的规则囉。由於没有规则嘛!所以每个链内部的规则都是空的。 同时注意一下,在每个 chain 后面括号内的 policy 项目,那就是『预设动作(政策)』咯!以上面来看, 虽然我们啟动了 iptables ,但是我们没有设定规则,然后政策又是 ACCEPT, 所以是『任何封包都会接受』的意思喔!至於如果加上 -v 的参数时, 则连同该规则所通过的封包总位元数也会被列出来啊。底下则是 nat 表格的规则项目:
[root@linux ~]# iptables -t nat -L -n
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
瞧!与 fiter 表格一模一样吧!只是三条链的内容不同囉!要注意啊! ^_^! 以后当你设定每一条防火墙的规则时,记得瞧一瞧设定先!好,那如何清除规则?这样做就对了:
[root@linux ~]# iptables [-t tables] [-FXZ]
参数:
-F :清除所有的已订定的规则;
-X :杀掉所有使用者 "自订" 的 chain (应该说的是 tables )囉;
-Z :将所有的 chain 的计数与流量统计都归零
范例:清除本机防火墙 (filter) 的所有规则
[root@linux ~]# iptables -F
[root@linux ~]# iptables -X
[root@linux ~]# iptables -Z
由於这三个指令会将本机防火墙的所有规则都清除,但却不会改变预设政策 (policy) , 所以如果你不是在本机下达这三行指令时,很可能你会被自己挡在家门外 (若 INPUT 设定為 DROP 时)! 要小心啊!
一般来说,我们在重新定义防火墙的时候,都会先将规则给他清除掉。还记得我们前面谈到的, 防火墙的『规则顺序』是有特殊意义的,所以囉, 当然先清除掉规则,然后一条一条来设定会比较容易一点啦。底下就来谈谈定义预设政策吧!
--------------------------------------------------------------------------------
定义预设政策 (policy)
清除规则之后,再接下来就是要设定规则的政策啦!还记得政策指的是什麼吗?『 当您的封包不在您设定的规则之内时,则该封包的通过与否,以 Policy 的设定為準』,在本机方面的预设政策中,假设您对於内部的使用用者有信心的话, 那麼 filter 内的 INPUT 链方面可以定义的比较严格一点,而 FORWARD 与 OUTPUT 则可以订定的鬆一些!通常鸟哥都是将 INPUT 的 policy 定义為 DROP 啦,其他两个则定义為 ACCEPT。 至於 nat table 则暂时不理会他。
[root@linux ~]# iptables [-t nat] -P [INPUT,OUTPUT,FORWARD] [ACCEPT,DROP]
参数:
-P :定义政策( Policy )。注意,这个 P 為大写啊!
ACCEPT :该封包可接受
DROP :该封包直接丢弃,不会让 client 端知道為何被丢弃。
范例:将本机的 INPUT 设定為 DROP ,其他设定為 ACCEPT
[root@linux ~]# iptables -P INPUT DROP
[root@linux ~]# iptables -P OUTPUT ACCEPT
[root@linux ~]# iptables -P FORWARD ACCEPT
[root@linux ~]# iptables -L -n
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain INPUT (policy DROP)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
# 由於 INPUT 设定為 DROP 而又尚未有任何规则,所以上面的输出结果显示:
# 所有的封包都无法进入你的主机!是不通的防火墙设定!(网路连线是双向的)
看到输出的结果了吧?INPUT 被修改设定了喔!其他的 nat table 三条链的设定也是一样的,例如:『 iptables -t nat -P PREROUTING ACCEPT 』就设定了 nat table 的 PREROUTING 链為可接受的意思!预设政策设定完毕后,来谈一谈关於封包的基础比对设定吧。
--------------------------------------------------------------------------------
封包的基础比对 IP/netmask I/O 装置
开始来进行封包的比对设定吧!我们先由最基础的 IP 与网域的特徵谈起,再谈装置 (网路卡) 的限制等等。
[root@linux ~]# iptables [-AI 链] [-io 网路介面] [-p 协定] \
> [-s 来源IP/网域] [-d 目标IP/网域] -j [ACCEPT|DROP]
参数:
-AI 链:针对某的链进行规则的 "插入" 或 "累加"
-A :新增加一条规则,该规则增加在原本规则的最后面。例如原本已经有四条规则,
使用 -A 就可以加上第五条规则!
-I :插入一条规则。如果没有指定此规则的顺序,预设是插入变成第一条规则。
例如原本有四条规则,使用 -I 则该规则变成第一条,而原本四条变成 2~5 号
链 :有 INPUT, OUTPUT, FORWARD 等,此链名称又与 -io 有关,请看底下。
-io 网路介面:设定封包进出的介面规范
-i :封包所进入的那个网路介面,例如 eth0, lo 等介面。需与 INPUT 链配合;
-o :封包所传出的那个网路介面,需与 OUTPUT 链配合;
-p 协定:设定此规则适用於哪种封包格式
主要的封包格式有: tcp, udp, icmp 及 all 。
-s 来源 IP/网域:设定此规则之封包的来源项目,可指定单纯的 IP 或包括网域,例如:
IP :192.168.0.100
网域:192.168.0.0/24, 192.168.0.0/255.255.255.0 均可。
若规范為『不许』时,则加上 ! 即可,例如:
-s ! 192.168.100.0/24 表示不许 192.168.100.0/24 之封包来源;
-d 目标 IP/网域:同 -s ,只不过这裡指的是目标的 IP 或网域。
-j :后面接动作,主要的动作有接受 (ACCEPT)、丢弃 (DROP) 及记录 (LOG)
iptables 的基本参数就如同上面所示的,仅只谈到 IP 、网域与装置等等的资讯, 至於 TCP, UDP 封包特有的埠口 (port number) 与状态 (如 SYN 旗标) 则在下小节才会谈到。 好,先让我们来看看最基础的几个规则,例如开放 lo 这个本机的介面以及某个 IP 来源吧!
范例一:所有的来自 lo 这个介面的封包,都予以接受
[root@linux ~]# iptables -A INPUT -i lo -j ACCEPT
# 仔细看上面并没有列出 -s, -d 等等的规则,这表示:不论封包来自何处或去到哪裡,
# 只要是来自 lo 这个介面,就予以接受!这个观念挺重要的,就是
#『没有设定的规定,则表示该规定完全接受』的意思!例如这个案例当中,
# 关於 -s, -d...等等的参数没有规定时
范例二:目标来自 192.168.0.1 这个 IP 的封包都予以接受
[root@linux ~]# iptables -A INPUT -i eth0 -s 192.168.0.1 -j ACCEPT
# 不管什麼封包格式,只要来自 192.168.0.1 就予以接受。
范例三:目标来自 192.168.1.0/24 可接受,但 192.168.1.10 丢弃
[root@linux ~]# iptables -A INPUT -i eth0 -s 192.168.1.10 -j DROP
[root@linux ~]# iptables -A INPUT -i eth0 -s 192.168.1.0/24 -j ACCEPT
# 上述这两个范例很重要啊!因為有点关係!要先丢弃 192.168.1.10 才能接受该网域。
[root@linux ~]# iptables -L -n
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 192.168.0.1 0.0.0.0/0
DROP all -- 192.168.1.100 0.0.0.0/0
ACCEPT all -- 192.168.1.0/24 0.0.0.0/0
# 瞧!刚刚的设定在这裡已经生效囉!
这就是最单纯、简单的防火墙规则的设定与观察方式。你在设定完毕后,都可以利用 iptables -L -n 或 iptables -L -v 来简单的查阅一下。而如果你想要记录某个规则的纪录怎麼办?可以这样做:
[root@linux ~]# iptables -A INPUT -s 192.168.2.200 -j LOG
[root@linux ~]# iptables -L -n
target prot opt source destination
LOG all -- 192.168.2.200 0.0.0.0/0 LOG flags 0 level 4
看到输出结果的最左边,会出现的是 LOG 喔!只要有封包来自 192.168.2.200 这个 IP 时, 那麼该封包的相关资讯就会被写入到核心讯息,亦即是 /var/log/messages 这个档案当中。 然后该封包会继续进行后续的规则比对。所以说, LOG 这个动作仅在进行记录而已,并不会影响到这个封包的其他规则比对的。 好了,接下来我们分别来看看 TCP,UDP 以及 ICMP 封包的其他规则比对吧!
[ 本帖最后由 superchen 于 2006-9-21 13:15 编辑 ]