Linux 2.4 Packet Filtering HOWTO 用iptables包过滤(转)

由 chinadoudou 在 11-05-2002 11:22 发表:

Linux 2.4 Packet Filtering HOWTO 用iptables包过滤(转)

Linux 2.4 Packet Filtering HOWTO

作者:Rusty Russell, mailing list [email protected]

译者:网中人 [email protected]

v1.0.1 Mon May 1 18:09:31 CST 2000

--------------------------------------------------------------------------------

此文件描述如何在 2.4 Linux kernel 上使用 iptables 对不良封包进行过滤。

--------------------------------------------------------------------------------

--------------------------------------------------------------------------------

1. Introduction

各位看官,欢迎到此一读!

这里,我假设您已经知道什麽是 IP 地址、网路地址、网路遮罩 (netmask)、路由、以及 DNS。否则,我建议您先读一读 Network Concepts HOWTO。

此 HOWTO 文件不止於是一个点到即止的介绍(让您有点发热和发毛,但又肉在砧上的感觉),也不至於是一个抽丝剥茧式的原始大披露(让您必有所获,但不会神经错乱、走火入魔)。

您的网路其实一点也不安全。问题难点是在允许快速而便利通讯之同时,又想确保它只用於良好且非邪恶的意图。其情形等同於在一个拥挤的戏院里面,允许您高谈阔论,但却不能乱喊“著火啦!”一样。这篇 HOWTO 不是用来解决这问题的。

所以,只有您才能决定何处才是折衷所在。我会尝试指引您去使用一些可用工具,也会点出要留意的死穴,当然,同时希望您用於正途之上。又是(与上句)同等的问题。

--------------------------------------------------------------------------------

--------------------------------------------------------------------------------

2. 官方的网站在哪里?有邮件论坛吗?

有三个官方网站非去不可:

感谢 Filewatcher ( http://netfilter.filewatcher.org ).

感谢 The Samba Team and SGI ( http://www.samba.org/netfilter ).

感谢 Jim Pick ( http://netfilter.kernelnotes.org ).

至於官方的 netfilter 邮件论坛,请参阅: Samba's Listserver ( http://lists.samba.org ).

--------------------------------------------------------------------------------

--------------------------------------------------------------------------------

3. 好了,什麽是封包过滤(Packer Filter)呢?

封包过滤就是用一个软体查看所流经封包之表头(header) ,由此决定整个封包的命运。它或许会决定 丢弃(DROP) 这个封包(例如,忽略它就如根本没收到它一样),或是接收(ACCEPT)这个封包(例如,让这个封包通过),或是其它更复杂的动作。

在 Linux 之下,封包过滤功能是内建於核心之内(做为一个核心模组,或者直接内建),同时还有一些技巧我们可以运用於封包之上的,不过最惯用的依然是查看表头以决定封包的命运。

3.1 我为什麽要封包过滤?

简而言之:控制、保安、警戒。

Control:

当您用您的 Linux 主机将您的内部网路连接至其它网路(比方说,ineternet)的时候,您有机会允许特定类型的交通,而禁止其它的。 例如,一个封包的表头会包含封包的目的地地址,所以您可以防止封包流向外部网路的某一部份。再如,我用 Netscape 连线至 Dilbert archives,那网页上有一个来自 doubleclick.net 的广告,这样 Netscape 会浪费我的时间去下载它们。只要让封包过滤机制不允许任何来自doubleclick.net 的封包,我们就可以解决这个问题(当然,有更好的方法来做这件事情啦,请参考 Junkbuster)。

Security:

当您的 Linux 主机是您井然有序的内部网路和外面那个混沌无比的 internet 之间的唯一通道,而您知道可以限制哪些东西才能进入您的门户,诚是不错之举吧。例如,您或许会放行任何从内部网路出去的东西,但又担心来自外面的恶名昭章的‘Ping of Death’。又如,您或许并不希望别人从外面 telnet 上您的 Linux 主机,尽管全部的帐号都有密码保护。或许,您还想(正如大部份人一样)在 internet 上当看客而不愿当伺服器(也可能您是愿意的) ,最简单莫如用封包过滤来拒绝任何意欲连线的封包,不让任何人连进来。

Watchfulness:

有时候,一台设定差劣的机器会从本地网路向外面呕送封包。而好消息是您可以让封包过滤来告诉您是否有变态的事情发生。您或许会对之采取行动,又或许早已见惯不怪了。

3.2 如何在 Linux 下过滤封包?

Linux 的核心自从 1.1 版就已经有封包过滤功能。第一代是 1994 年由 Alan Cox 基於 BSD 的 ipfw 移植过来的,後来在 Linux 2.0 版本再由 Jos Vos 加强,利用 ' ipfwadm ' 这只使用者空间(userspace *)工具来控制核心的过滤规则。在 1998 年年中,我在 Micahel Neuling 的大力帮助下,投注了相当的精力在 Linux 核心 2.2 上面,推出了 ' ipchains ' 这只工具。终於,Linux 核心 2.4 的第四代工具 ' iptables ' 连同其它核心改写也在 1999 年年中进行开发了。这就是目前这个 iptables 的 HOWTO 文件所致力之所在。

(* 译者注:“使用者空间”通常是用来区别系统记忆体的使用□围,主要类型分为核心空间和使用者空间。原作者可能以为大家都是程式高手,故会用如此专门术语。然对一般读者来说,理解上或许有困难,故此多说两句。在往後的阅读中也请留意。)

您需要一个核心有 netfilter 建构於其中:netfilter 是 Linux 核心中一个通用架构,可以让其它东西(例如 iptables 模组) 插入(plug into)。换句话说,您需要核心 2.3.15 或更新的版本,同时在核心编译时以 ' Y ' 回答 CONFIG_NETFILTER 这个选项。

iptables 这只工具会和核心对讲并告诉它什麽封包要过滤。除非您是一个程式人员,或异想天开,那您就是用它来控制封包怎样过滤的了。

iptables

这只 iptables 工具可以插入或移除核心封包过滤表格(packet filtering table) 中的一些规则(rules)。也就是说,无论您设定了什麽,要是重新启动(reboot)系统的话,就会全部丢失;请参阅 制定永久性规则(Making Rules Permanent), 看看如何确保设定在下次 Linux 启动後可以回存。

iptables 是用来取代 ipfwadm 和 ipchains 的:请参阅 使用 ipchains 和 ipfwadm (Using ipchains and ipfwadm), 看看如何无痛的避免使用 iptables,假如您目前正使用它们其中之一。

制定永久性规则

您目前的防火墙设定是储存於核心里面的,也正因如此,设定会在系统重启後丢失。iptables-save 和 iptables-restore * 的撰写目前已经被列入 TODO 列表中了。我保证当它们问世的时候,肯定非常棒。

(* 译者注:在 ipchains 工具中,可以使用 ipchains-save 与 ipchains-restore 来把当前的防火墙设定储存起来,以及将之还原。如果读者没使用过 ipchains 那两个功能的话,或许不知道作者在说什麽。)

目前来说,就把设定规则所需的那些命令写进一个初始命令稿(script)中吧。要确定的是,假如有其中一个命令失败的时候,您能提供一些智能的动作反应 (通常如 ' exec /sbin/sulogin' )。

--------------------------------------------------------------------------------

--------------------------------------------------------------------------------

4. 你算哪根葱啊?为何玩我的核心?

我是 Rusty,是 Linux IP 防火墙的维护者,同时也进行其它的一些编程工作,可以算是天时地利人和的使然吧。我写过 ipchains (请参阅前面的 如何在 Linux 下过滤封包?(How Do I Packet Filter Under Linux?), 看看实际的工作尚得益於哪些同仁),从其中学到足够的东西以匡正今次的封包过滤。我希望如此。

WatchGuard 是一个非常出色防火墙公司,出售真正好用的随插式防火墙设备(plug-in Firebox),且向我免费提供,让我可以全力撰写这些东西,以及维护过往的一些东西。我原本预估 6 个月就可以了,但实际上却花了 12 个月,不过我在最後阶段觉得做得还不错就是了。多翻重写、硬碟毁坏、手提电脑遭窃、数个档案系统的损毁、以及後来的荧幕坏掉,最终,还是做出来了。

在这里,我想澄清一些朋友的错误观念:我并非核心(kenrl)里面的专家。我之所以知道这些,是由於某些核心工作让我接触到他们其中的一些成员: David S. Miller、Alexey Kuznetsov、Andi Kleen、Alan Cox。不过,猪头骨(最难的)都由他们啃了,剩下的豆腐(安全和容易的)才轮到我来收拾啦。

--------------------------------------------------------------------------------

--------------------------------------------------------------------------------

5. 真正的 Rusty 封包过滤快速指南

大部分人都仅用单一的 PPP 拨接上网,同时并不想任何人进入他们的网路、或防火墙:

Insert connection-tracking modules (not needed if built into kernel).

insmod ip_conntrack

insmod ip_conntrack_ftp

Create chain which blocks new connections, except if coming from inside.

iptables -N block

iptables -A block -m state --state ESTABLISHED,RELATED -j ACCEPT

iptables -A block -m state --state NEW -i ! ppp0 -j ACCEPT

iptables -A block -j DROP

Jump to that chain from INPUT and FORWARD chains.

iptables -A INPUT -j block

iptables -A FORWARD -j block

--------------------------------------------------------------------------------

--------------------------------------------------------------------------------

6. 封包如何穿越(traverse)过滤

核心从 'filter' 表格的三个列表(lists) 开始;这三个列表叫做 firewall chains(防火墙链) 或就叫 chains(链)。 这三个链分别为INPUT、OUTPUT 、和 FORWARD 。

这跟 2.0 和 2.2 核心有很大差别哦!

对於 ASCII 艺术迷来说,各链(chains)的布置如下:


Incoming / \ Outgoing

-->[Routing ]--->|FORWARD|------->

[Decision] \_____/ ^

| |

v ____

___ / \

/ \ |OUTPUT|

|INPUT| \____/

\___/ ^

| |

----> Local Process ----

其中三个圈代表著前述的三个链,当一个封包抵达上图中的其中一个圈,相应的链就会接受检验(examined),以决定那个封包的命运。如果链说 DROP 掉这个封包,那麽它就会就地正法,但如果链说 ACCEPT 这个封包,那麽它就继续在图示中穿越。

一个链(chain)其实就是众多规则(rules)中的一个检查清单(checklist)。每一条规则都会说“如果封包表头看起来像这样,就如此这般处置这个封包”。如果规则的设定和封包并不符合(match),那麽就交由链中的下一个规则继续处理。而最终,如果再没有规则可以参考,那麽核心就会看链的policy(原则) 以决定怎麽做。在一个安全至上的系统里,原则(policy)通常都会告诉核心 DROP 掉该封包。

当一个封包进入的时候(假设,通过 Ethernet 网路卡),核心首先看看封包的目的地(destination):这称之为 ' rouging (路由)'。

如果目的地址为本机,这个封包就按图示下行至 INPUT 链。如果它能够通过,那麽等待这个封包的行程(processes)就将之接管下来。

否则,如果核心并没启动转递功能(forwarding),或是它不知道如何转递这个封包,那麽这个封包就会被丢弃(dropped)。如果转递功能已经启动,同时封包指向另一个网路界面(如果您还有另外一张),然後这个封包就按图示右行至 FORWARD 链。如果它被接受(ACCEPT),那麽它就会被送出去。

最後一种情形,一个在本机运行的程式会送出网路封包。封包就直接交给 OUTPUT 链:如果是 ACCEPT,然後这个封包会继续送出至它所指向的界面。

--------------------------------------------------------------------------------

--------------------------------------------------------------------------------

7. 使用 iptables

如果您需要特定的详细了解,iptables 有一个非常详尽的 manual page (man iptables)。假如您熟悉 ipchains 的话,或许可以直接跳到 iptables 与 ipchains 的差异 (Differences Between iptables and ipchains) 去看;它们是非常近似的。

您还可以利用 iptables 做许多不同的事情哦。您所开始的那三个内建(buit-in) 链: INPUT、OUTPUT、和FORWARD ,您是不能删除的。让我们看看整个链的管理运作吧:

建立一个新链 (-N)。

删除一个空链 (-X)。

改变一个内建链的原则 (-P)。

列出一个链中的规则 (-L)。

清除一个链中的所有规则 (-F)。

归零(zero) 一个链中所有规则的封包字节(byte) 记数器 (-Z)。

有好些方法可以统筹一个链中的规则:

延增(append) 一个新规则到一个链 (-A)。

在链内某个位置插入(insert) 一个新规则(-I)。

在链内某个位置替换(replace) 一条规则 (-R)。

在链内某个位置删除(delete) 一条规则 (-D)。

删除(delete) 链内第一条规则 (-D)。

7.1 当您的机器启动时,您所看到的

iptables 可以做成模组(module),叫做 `iptable_filter.o' ,当您第一次跑 iptables 就会被自动载入。它也可以永久性的建置於核心里面。

在跑任何 iptables 命令之前 (小心:有些套件(distributions) 或许会用它们的起始命令稿来跑 iptables),内建链( INPUT'、FORWARD'、和 OUTPUT' )将不带任何规则,所有链都将原则设为 ACCEPT。您可以将 iptable_filter 模组选项设为 forward=0' ,来改变预设的 FORWARD 链原则。

7.2 一个单一规则的运作

下面让我们来熟练一下原则的运用吧,所谓熟能生巧是也。您最常用的或许会是 append (-A) 和 delete (-D) 命令。至於其它如 insert (-I) 和 replace (-R), 只是这些概念的延伸而已。

每一条规则都限定了一组条件(conditions)与特定封包比对,以及当它们符合时要如何处置(指一个target' )。比方说,您或许要丢弃所有来自127.0.0.1 这个 IP 地址的 ICMP 封包,因而我们这里的条件就成为这样:协定必须是 ICMP,而来源地址必须是 127.0.0.1 ,而我们的 target(目标)将会是DROP' 。

我们称 127.0.0.1 为 loopback' 界面,就算您没有真实的网路连接,您也会有这个界面的。您可以用 ping' 这只程式产生这样的封包 (它只是送出一个 type 8(echo request)的 ICMP 封包,而所有乐於回应的合作端(cooperative hosts) 则送回一个 type 0(echo reply)的 ICMP 封包)。用来测试是很好用的。

ping -c 1 127.0.0.1

PING 127.0.0.1 (127.0.0.1): 56 data bytes

64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.2 ms

--- 127.0.0.1 ping statistics ---

1 packets transmitted, 1 packets received, 0% packet loss

round-trip min/avg/max = 0.2/0.2/0.2 ms

iptables -A INPUT -s 127.0.0.1 -p icmp -j DROP

ping -c 1 127.0.0.1

PING 127.0.0.1 (127.0.0.1): 56 data bytes

--- 127.0.0.1 ping statistics ---

1 packets transmitted, 0 packets received, 100% packet loss

这里您可以看到第一个 ping 成功了(这里的 `-c 1' 参数是告诉 ping 只送出一个封包)。

然後,我们为INPUT' 延增(-A)一条规则,将来自 127.0.0.1(-s 127.0.0.1') 的 ICMP 协定 (`-p icmp') 封包送至 DROP 这个目标 (-j DROP)。

然後我们可以用第二个 ping 来测试我们的规则。在程式放弃继续等待那些永不到来的回应之前,将有一段暂停。

我们有两个方法可以移除规则。首先,因为我们目前制定在 input 链中只有唯一一条规则,所以我们可以指定数字来移除,例如:

iptables -D INPUT 1

这样就把第一条规则从 INPUT 链中移除掉。

第二个方法是映射(mirro)上面的 -A 命令,但用 -D 来代替 -A 而已。当您有一个链,里面写有非常复杂的规则,而又不想逐行数出第 37 行就是您要的那条规则,这时候,这方法就非常有用了。

iptables -D INPUT -s 127.0.0.1 -p icmp -j DROP

在命令行中,其语法是 -D 必须和 -A (或 -I、或 -R) 命令的位置一致。如果在同一个链中有数条相同的规则,那麽只有第一条会被移除掉。

7.3 过滤规格

我们已经看过用 -p' 来指定协定,以及用 -s' 来指定来源地址,但还有其它选项我们是可以用来指定出一个封包的特征。底下是一个完整的概述。

指定来源和目的地之 IP 地址

我们可以用四种方法来指定来源(-s'、或--source'、或 --src') 和目的地(-d'、或--destination'、或--dst') IP 地址。最常用的方法是使用完整名称,例如 localhost' 或 www.linuxhq.com ' 。第二种方法是指定其 IP 地址,例如 `127.0.0.1' 。

第三和第四种方法允许指定一组(group) IP地址,例如 199.95.207.0/24' 或 199.95.207.0/255.255.255.0' ,这两个设定都指定了所有从 199.95.207.0 到 199.95.207.255 之间的 IP 地址;而在数字後面的 /' 符号是告诉系统哪部份 IP 才有效。 /32' 或 /255.255.255.255' 为预设值(所有 IP 值都必须吻合)。全部用 /0' 来指定 IP 地址也是可行的,例如:

[ NOTE: `-s 0/0' is redundant here. ]

iptables -A INPUT -s 0/0 -j DROP

不过这非常少用,因为以上的效果和不指定 `-s' 毫无两样。

相反指定

许多旗标(flags),包括 -s' (或 --source')、和 -d' (或 --destination'),可以在它们前面放置一个 !' 符号(发音为not') ,来符合所有非(NOT)其赋予值的地址。比方说,`-s ! localhost' 符合所有非(not) 来自本机的封包。

指定协定

协定可以用 -p' (或 --protocol') 旗标来指定。协定可以为一个号码(假如您知道 IP 协定数值的话),或是一个诸如 TCP'、或UDP'、或ICMP' 这样的名称。大小写没关系,所以 tcp' 和 `TCP' 都可以工作。

协定也可以加上一个 !' 前置符号,使之相反。例如 -p ! TCP' 则指定了所有非 TCP 的封包。

指定界面

我们用 -i' (或 --in-interface') 和 -o' (或 --out-interface') 选项来指定一个符合的界面(interface)。一个界面就是封包进入(-i') ,或传出(-o')之物理设备。您可以用 ifconfig 命令列出哪些界面是跑起来(`up' )的。

穿越 INPUT 链的封包不会有传出(output)界面的,所以,任何在链中使用 -o' 选项的规则都不与之符合。同样的,穿越 OUTPUT 链的封包也不会有传入(input)界面,所以在链中任何带 -i' 选项的规则也是不符合的就是了。

仅仅是穿越 FORWARD 链的封包才会同时有传入和传出界面。

指定一个不存在的界面是完全合法(legal)的;反正在界面还没起来之前,这条规则是不会符合的。这对於 PPP 拨接(通常会是ppp0) 或相类连线,就极之有用了。

例如在一个特殊例子中,界面是用一个 `+' 结尾的话,就泛指所有以此字串开头的界面(不管它们目前是否起来了)。例如,要指定一条规则来符合所有的 PPP 界面的话,-i ppp+ 选项就可以用上了。

界面名称前面可以用一个`!' 符号来符合一个与指定界面 不 符合的封包。

指定封包碎片 (Fragments)

有时候,一个封包会因为太大而不能一次过塞进连线去。当这样的事情发生了,封包会被切割成 碎片(fragments),同时会以多个封包来传送。而另一端则重组这些碎片以还原整个封包。

但碎片的问题是,第一个起始碎片有整个封包表头栏位(IP+TCP、UDP、和 ICMP)可供检查,但後继封包却只包含表头的小部份(不带额外协定栏位的 IP)。这样的话,要检查後继碎片之协定表头(比方由 TCP、UDP、和 ICMP extensions 而成),就不可能了。

如果您要做连线追踪或 NAT,那所有碎片在递给封包过滤码之前都会汇合回一起,所以您无需担心碎片问题。

然而,要弄明白过滤规则如何处理碎片的,就变得非常重要了。任何规则要询问的资料而我们并没有时,将被视为 不 符合。也就是说,第一个碎片封包的处理和其它封包一样。但第二及之後的碎片就不是这样了。这样的话,一条 -p TCP --sport www (指定来源埠口为`www')的规则,将永远不和碎片符合(除第一个碎片外)。相反的规则如-p TCP --sport ! www 也一样就是了。

不过,您可以用 -f' (or --fragment') 旗标特别为第二及以後的碎片指定一条规则。在 -f' 前面加上一个 !' 来指定一条规则 不 适用於第二及以後碎片,也是可行的。

通常,让第二及以後碎片通过是被视为安全的,因为如果过滤会影响第一个碎片的话,那麽也就可以避免在目标主机进行重组;但是,一些已知的臭虫显示,丢送碎片封包可以轻易的让主机当掉。那是阁下要应付的事情了。

网路玩家要留意的是:当进行这样的检测时,不完整的封包(太短的 TCP、UDP、和 ICMP 封包会让火墙程式读不到埠口或 ICMP 码和类型) 会被丢弃。因此, TCP 碎片都由第 8 个位置开始的 *。

(* 译者注:我也不是很明白作者这里所指何物,原文是:‘So are TCP fragments starting at position 8’。因为懒得去翻资料,故不知道 position 8 是指 TCP 表头位置还是其它。假如您找到答案,欢迎写信给我以作澄清。)

举例来说,以下的规则会丢弃任何送给 192.168.1.1 的碎片。

iptables -A OUTPUT -f -d 192.168.1.1 -j DROP

延伸 iptables :新的比对(matches)

iptables 是 可延伸的(extensible),也就是说,核心和 iptables 工具可以进行扩展以提供新的功能。

某些延伸(Extensions)是标准的,但有些则可以说是派生出来的。别的朋友或许会制做出一些延伸,同时散播给合适的用户。

核心的延伸通常居於核心模组目录内,例如 /lib/modules/2.3.15/net 。假如您的核心是用 CONFIG_KMOD 设定来编译的话,它们是应需求载入的,所以您无需手动的插入它们。

然而,iptables 程式的延伸则通常是居於 /usr/local/lib/iptables/ 里面的分享函式库,或者有些散播版本会将它们放进 /lib/iptables 或 /usr/lib/iptables 里去。

延伸有两个种类:新目标(target),和新比对(match);下面我们就讲讲新目标吧。有些协定会自动提供新的测试(tests):目前有 TCP、UDP、和 ICMP,如下述。

在命令後使用 -p' 选项把延伸载入进来,您就可以来指定一个新测试了。当延伸选项允许的时候,使用 -m' 来载入延伸,则可以明确指示一个新测试。

如需某个延伸的求助资料,可以使用选项後接 -h' 或 --help' 将之载入(-p'、 -j'、或 `-m'),例如:

iptables -p tcp --help


由 chinadoudou 在 11-05-2002 11:24 发表:

没完的。

TCP 延伸

如果指定了 `-p tcp' ,TCP 之延伸会自动载入的。它提供如下选项(并不符合 fragments)。

--tcp-flags

後接一个 `!' 选项,则有两个旗标的字串让您能够对指定的 TCP 旗标进行过滤。 第一个字串是遮罩(mask):一个您欲检查的旗标列表。第二个字串是要说哪些东西要设定。例如:

iptables -A INPUT --protocol tcp --tcp-flags ALL SYN,ACK -j DENY

这表示所有旗标都要检查 (ALL' 就是泛指 SYN,ACK,FIN,RST,URG,PSH'),但只有 SNY 和 ACK 被设定而已。另外有一个参数 `NONE' 则是没旗标的意思。

--syn

--tcp-flags SYN,RST,ACK SYN' 的简写,其前面可以备选一个 !' 符号。

--source-port

其後可以备选 !' ,然後是一个单独的 TCP 埠口或一个埠口值域(range)。埠口可以为 /etc/services 所列岛埠口名称,也可以是一个数字。如果是值域的话,可以是一对用:' 符号分隔的埠口名字,或一个埠口後面带 :' (指大於和等於该埠口),又或是一个埠口前面带 :' (指小於和等於该埠口)。

--sport

等同於 `--source-port'。

--destination-port

--dport

与上同,只是它们是用来指定目的地而非来源埠口加以比对。

--tcp-option

其後可以备选 `!' ,然後为一个数字,用来比对一个 TCP 选项等於该数字的封包。假如需要检查 TCP 选项,那些 TCP 表头不完整的封包就会自动的被丢弃。

一个 TCP 旗标的解释

有时候,允许单向而非双向的 TCP 连线会很好用。例如,您或许想允许连线到外部 WWW 伺服器,但却不想来自该伺服器的连线。

最幼稚的举动或许会是挡掉来自该伺服器的 TCP 封包。但不幸的是,TCP 连线根本就要求封包是双向传递的。

解决之道是把那些要求连线的封包挡掉。这些封包被称为 SYN 封包(嗯,技术上讲,它们是带 SYN 设定的封包,而 FIN 和 ACK 标签则是空白,只是我们将之简称为 SYN 封包而已)。要只限制这样的封包的话,我们就可以制止那些外来的连线尝试了。

`--syn' 旗标可以用於这些方面:它仅对那些指定为 TCP 协定的规则有作用。例如,指定来自 192.168.1.1 的 TCP 连线请求:

-p TCP -s 192.168.1.1 --syn

这旗标也可以後接一个 `!' 来反设,意指每一个非该类初始连线的封包。

UDP 延伸

如果 -p udp' 被指定的话,这些延伸就会自动载入。它提供了 --source-port'、 --sport'、--destination-port'、以及 `--dport' 这些选项,一如前述的 TCP 设定。

ICMP 延伸

如果 `-p icmp' 被指定的话,这个延伸就会自动载入。它只提供一个新的选项:

--icmp-type

其後可以备选 !' ,然後是一个 icmp 名称类型(如 host-unreachable' ),或是一个数字类型(如 3' ),或是一对用 /' 分隔的数字类型和编码(如 3/3' )。使用 -p icmp --help' 就可以获得一份可用 icmp 类型名称清单。

其它比对的延伸

在 nerfilter 套件中的其它延伸则是展示性(demonstration)的延伸内容,可以用 `-m' 选项来呼叫(假如已安装了的话)。

mac

此一模组必须要明确的用 -m mac' 或 --match mac' 来指定。它用於比对传入封包的来源 Ethernet (MAC) 地址,因而只对那些穿越 PREROUTING 和 INPUT 链的封包起作用。它只提供一个选项:

--mac-source

其後可以备选 !' ,然後是一个用冒号分隔的十六进制 ethernet 地址,如 --mac-source 00:60:08:91:CC:B7'。

limit

这个模组必须明确的用 -m limit' 或 --match limit'来指定。它用来限制一个比对等级,诸如抑制记录信息等。它只能比对一个每秒次数值(预设是每一个小时 3 个比对,伴随 5 个触发(burst))。它接受两个备选参数:

--limit

後接一个数值;指定可允许的每秒最大平均比对数值。该数值可以用 /second'、/minute'、/hour'、或 /day'、或其中部份 (故 5/second' 和 5/s' 是一样的),来明确指定单位(unit),

--limit-burst

後接一个数值,指示出引起前述限制之前的最大触发次数。

这个比对常用於 LOG 目标,以进行比率限制(rate-limited) 之记录。为了更好了解它是如何工作的,让我们看一看下面的规则,是以预设限制引数来记录封包的:

iptables -A FORWARD -m limit -j LOG

当此规则第一次引用的时候,封包就会被记录下来;事实上,由於预设的触发为 5 ,那为首的 5 个封包就会记录下来。然後,再隔 20 分钟此规则才会再记录封包,而不管期间有多少个封包抵达。而且,每 20 分钟如果没有符合的封包通过,则会恢复 (regained) 一个触发数值;假如 100 分钟内再无这样的封包触及这规则的话,那麽触发次数就会完全复原(recharged);回到我们开始时的状态。

注:您目前不能以大於 59 小时的复原时间来建立一个规则,故此,假如您设定一个平均率为每天一次,那麽,您的触发率则一定要少於 3 。

您也可以用这模组去避免以快速比率提升服务回应的阻断服务攻击(DoS)。

Syn-flood protection:

iptables -A FORWARD -p tcp --syn -m limit --limit 1/s -j ACCEPT

Furtive port scanner:

iptables -A FORWARD -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j ACCEPT

Ping of death:

iptables -A FORWARD -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT

此模组的工作原理有点像“截流阀”一样,请参考下面的图示。

rate (pkt/s)

^ .---.

| / DoS \

| / \

Edge of DoS -|.....:.........\.......................

= (limit * | /: \

limit-burst) | / : \ .-.

| / : \ / \

| / : \ / \

End of DoS -|/....:..............:.../.......\..../.

= limit | : :-' --'

-------------+-----+--------------+------------------> time (s)

LOGIC => Match | Didn't Match | Match

比方说,我们以 5 个封包触发来比对每秒一个封包,但封包从每秒四个开始传入,持续三秒,然後等三秒再重新开始。

<--Flood 1--> <---Flood 2--->

Total ^ Line __-- YNNN

Packets| Rate __-- YNNN

| mum __-- YNNN

10 | Maxi __-- Y

| __-- Y

| __-- Y

| __-- YNNN

|- YNNN

5 | Y

| Y Key: Y -> Matched Rule

| Y N -> Didn't Match Rule

| Y

|Y

0 +--------------------------------------------------> Time (seconds)

0 1 2 3 4 5 6 7 8 9 10 11 12

您会发现头五个封包被允许超过每秒一个封包,然後就引起限制了,如果有一个停歇,其它的触发也将被允许,但就不能通过规则设定的最高比率(在该触发使用後为每秒一个封包)。

owner

此模组为本机产生的封包比对不同特征的封包建立者(creator)。它仅对 OUTPUT 链有用,而且,甚至某些封包(如 ICMP ping responses)或许没有 owner,将被视为不符合哦。

--uid-owner userid

如果封包由一个行程以有效(数字式) user id 建立的,则为符合。

--uid-owner groupid

如果封包由一个行程以有效(数字式) group id 建立的,则为符合。

--pid-owner processid

如果封包由一个行程以 process id 建立的,则为符合。

--sid-owner processid

如果封包由一个行程以 session group 建立的,则为符合。

unclean

此一实验性模组必须以 -m unclean' 或 --match unclean' 来明确指定。它会对封包进行不同的随机判断检测。这模组尚未被稽查过,所以不应该用於安全设备上(它或许会把事情搞砸,因为它本身或许有臭虫的)。它并没提供选项设定。

The State Match

最有用的比对判断标准由 state' 延伸所提供,以诠释 ip_conntrack' 模组的连线追踪分析。这是非常值得鼓励使用的。

指定 -m state' 则允许另一个额外的 --state' 选项,可以为一个豆点分隔的比对陈述列表( `!' 旗标指示 不(not) 符合那些陈述)。这些陈述是:

NEW

一个建立新连线的封包。

ESTABLISHED

一个属於现有连线(如:已经回应封包了)之封包。

RELATED

一个与现有连线相关,但却并不限於其中部份的封包,诸如 ICMP 错误,或是建立 FTP 数据连线的封包(FTP 模组已插入)。

INVALID

一个因某些原因不能被鉴别的封包:这包括记忆体不足和不能回应任何已知连线的 ICMP 错误。通常,这样的封包都会被丢弃掉。

7.4 目标(Target)规格

现在,我们知道可以对封包做什麽样的检查了,我们还需要一个方法来说出对一个符合我们测试的封包要做什麽样动作。这就是所谓的一条规则之目标(target) 啦。

有两个非常相类的内建目标:DROP 和 ACCEPT,我们已经接触过了。如果一条规则符合一个封包,同时目标是其中之一,那麽就再没有规则需要咨询:封包的命运已经定下来了。

除了内建外,也有两种类型的目标:延伸和用户自定链。

用户自定链

iptables 承袭了 ipchains 一个非常厉害的功能,就是让使用者可以创建出新链,附加於三个内建链(INPUT、FORWARD、和 OUTPUT)之外。按惯例,用户自定链用小写以示区别(待会我们会在後面的 在整链上运作(Operations on an Entire Chain) 那里解释如何去建立新的用户自定连)

当一个封包符合一条目标为用户自定链之规则时,封包就会开始穿越用户自定链中的规则。假如该链未能决定出封包的命运,则一旦结束穿越该链後,就会接著当前链中的下一个规则继续穿越下去。

继续玩玩 ASCII 艺术好了。假设有这麽两条(怪)链:INPUT (内建链), 和 test (用户自定链)。

INPUT' test'

---------------------------- ----------------------------

| Rule1: -p ICMP -j DROP | | Rule1: -s 192.168.1.1 |

|--------------------------| |--------------------------|

| Rule2: -p TCP -j test | | Rule2: -d 192.168.1.1 |

|--------------------------| ----------------------------

| Rule3: -p UDP -j DROP |

----------------------------

假设一个来自192.168.1.1 的 TCP 封包,要到 1.2.3.4 那里去。它进入INPUT 链,并受到 Rule1 的测试 - 但不符合。但是符合 Rule2 ,且它的目标是 test,所以下一个要检验的规则将从 test 开始。在 test 中的 Rule1 符合,但并没有指定目标,所以再检验下一条规则,也就是 Rule2 。不过它并不符合,所以我们已经抵达这条链的末端了。然後我们回到 INPUT 链中,也就是我们刚才检验 Rule2 那里,所以我们现在就要检查 Rule3,依然不符合。

这样,该封包的路径是这样子的:

v __________________________

INPUT' | / test' v

------------------------|--/ -----------------------|----

| Rule1 | /| | Rule1 | |

|-----------------------|/-| |----------------------|---|

| Rule2 / | | Rule2 | |

|--------------------------| -----------------------v----

| Rule3 /--+___________________________/

------------------------|---

v

用户自定链也可以再跳到另一个用户自定链去(但不要做成回圈:您的封包如果被发现处於回圈中就会被丢弃)。

iptables 之延伸:新目标

另一类型的目标是一个延伸。一个目标的延伸由核心模组和可选的 iptables 延伸组成,以提供新的命令行选项。在预设的 netfilter 散播版本中有好几个延伸:

LOG

此模组提供核心记录符合的封包。它提供这些额外选项:

--log-level

後接一个层次(level)号码或名称。合法的名称有(大小写有别):debug'、info'、notice'、warning'、err'、crit'、alert'、以及 emerg',相对的号码由 7 到 0 。各层次号码的解释请参考 syslog.conf 的 man page。

--log-prefix

後接一个最多 30 个字母的字串。此一信息由记录信息开始时送出,令其可以个别的被鉴别出来。

此模组常用於一个限制目标後,所以,您不要灌爆您的记录档哦。

REJECT

此模组除了向发送端送出一个 port unreachable' 这样的 ICMP 错误外,和 DROP' 是一样的。注:在下列条件中,ICMP 错误信息将不会送出(请参考 RFC 1122):

被过滤的封包一开始就是一个 ICMP 错误信息,或是其它不明的 ICMP 类型。

被过滤的封包为一个无头 (non-head) 碎片。

我们目前已经送出太多至该目的地的 ICMP 错误信息了。

REJECT 另外还接受一个 `--reject-with' 选项来更改其回应封包:请参考说明文件。

特殊的内建目标

有两种特殊的内建目标:RETURN 和 QUEUE。

Published At
Categories with 服务器类
Tagged with
comments powered by Disqus