分享
 
 
 

iptables技术

王朝other·作者佚名  2008-05-18
窄屏简体版  字體: |||超大  

1. 简介

欢迎,亲爱的读者。

这篇文章假设你知道有关IP地址、网络地址、网络掩码、选路和DNS。如果不知道,我建议你先阅读网络概念的HowTo(Network Concepts HOWTO)。

这篇HOWTO并非一个简要的介绍(会让你发热、发毛,没有安全感),也非一个完全的原始的披露(最吃苦耐劳的人也会被搅晕,不过必定会有所斩获)。

你的网络并不安全。问题在于,必须获取快速、简洁的通讯,但又必须限于良好的、无恶意的行为,就如同在嘈杂的大戏院里,你可以高谈阔论,但是绝不能大喊:着火了!。这篇HOWTO不能解决这种问题。

(译者:所有安全都只是相对的,否则根本不会产生这种东西了)

因此,你只能决定在哪方面妥协。我想帮助你使用一些可用的工具和一些通常需要注意的漏洞,希望你将它们用在好的一面,而不是出于恶意的目的 -- 另一个同样重要的问题。

(C) 2000 Paul `Rusty' Russell. Licenced under the GNU GPL.

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

2、 官方站点及邮件列表位置

这里有三个官方站点:

o Thanks to Filewatcher http://netfilter.filewatcher.org.

o Thanks to The Samba Team and SGI http://netfilter.samba.org.

o Thanks to Harald Welte http://netfilter.gnumonks.org.

你可以通过以下站点访问全部相关站点。

http://www.netfilter.org and http://www.iptables.org

以下是netfilter官方邮件列表

http://www.netfilter.org/contact.html#list.

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

3.那么,什么是包过滤器?

包过滤器是这样一种软件:它检查通过的每个包的头部,然后决定如何处置它们。可以这样对待它们:丢弃(也就是说,如果这个包从未被接受,那么丢弃它),通过(也就是说,让包通过),或者更复杂的(操作)。

Linux下,包过滤内建在内核中(内核模块,或者内建),而且我们还有处理包的一些技巧,不过检查头部和处理包的一般性原则仍在这里。

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

3.1 我为何要包过滤?

控制、安全、警戒。

控制:

当你用你的Linux服务器把你的内部网和另一个网络(就是Internet吧)连起来,你可以决定哪些通信是允许的,哪些不允许。例如,包头部包含了包的目标地址,你可以阻碍包发送到(你)确定的几个外部网络,另一个例子,我用NetScape连接到Dilbert archives。页面上有来自doubleclick.net的广告,然后NetScape浪费了我的时间愉快的下载他们。告诉包过滤器禁止任何来自或者发往doubleclick.net地址的包,问题就解决了。(当然有更好的办法,见Junkbuster)。

安全:

当Linux服务器是混乱的Internet和你良好的、有序的网络之间唯一的东西时,你最好能知道哪些东西可以进入你的大门。例如,你可以允许所有(包)从你的网络 发出,不过你可能会为来自外部的著名的“Ping of Death”而焦急。另一个例子,你不希望 外人telnet到你的Linux服务器,尽管所有账户都有密码。或许你只想(像绝大多数人)成为 Internet的旁观者,而非它的服务器(也可能愿意是吧)。简单的不允许任何人接入,设置 包过滤器拒绝所有进入的包(是不错的办法)。

警戒:

有时,本地网络上错误配置的机器可能会向外部喷射出大量的包。最好是当(网络中)出现任何不正常现象时,让包过滤器告诉你。这样你可能可以做点什么,或者你天生就很好奇。

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

3.2 如何在Linux下进行包过滤?

Linux内核在其1.1系列中就有了包过滤功能。第一代,由Alan Cox 1994年移植于BSD的ipfw。这在Linux 2.0中由Jos Vos和其他人进行了加强;用户空间工具'ipfwadm'可用来控制内核过滤规则。1998年中,我在Michael Neuling的帮助下,为Linux 2.2进行了重写,推出了用户空间工具'ipchains'。最后,1999年中,基于Linux 2.4的第四代工具,'iptables',和其他内核的改写正式推出。这就是这个iptables的HOWTO文档的所在。

译者:userspace根据台湾同胞的说法,是用来区别系统内存中的适用范围的,分为核心空间和使用者空间,不必深究)

你需要包含netfilter架构的内核。netfilter是Linux中的一个通用框架,也可以插入(plug in)其他内容(如iptables模块)。也就是说你需要2.3.15及以后版本,而且在配置内核时对CONFIG_NETFILTER回答'Y'。

iptables这个工具用来和内核交互并告诉它哪些包应该过滤。除非你是程序员或者 特别好奇,否则这就是你用来控制包过滤的了。

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

3.2.1. iptables

iptables工具向内核的包过滤表中插入和删除规则。这就意味着无论怎样设置,启动后信息都会丢失;请参看“制定永久性规则”(Making Rules Permanent)来确定如何保证下次启动这些规则能被恢复。

iptables是ipfwadm和ipchains的替代品。如果你是它们的使用者,请参看 “使用ipchains和ipfwadm”,如何轻松使用iptables。

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

3.2.2 创建永久性规则

你当前的防火墙设置保存在内核中,所以重启后就会丢失。你可以试着用iptables-save和iptables-restore脚本来保存他们,并由一个文件恢复。

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

4. 你算老几,凭什么玩弄我的内核?

我是Rusty Russell。Linux IP防火墙的维护者,也是一个适当的时候出现在适当的地方的coder。我写了ipchains(参见“如何在Linux下进行包过滤?”看看实际的工作其实由哪些人完成),并希望能学到足够的东西修正这次的包过滤。

WatchGuard,一个非常出色的防火墙公司,总之一堆广告,此处省略一千字……

在此,我想澄清一个误解:我不是内核专家,我了解它,是因为我的核心工作让我接触了他们:David S. Miller, Alexey Kuznetsov, Andi Kleen, Alan Cox。无论如何,他们做了最深层的工作,轮到我时,已经非常安全和容易了。

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

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

绝大部分人只有一个PPP连接到Internet,而且不希望有人由此进入他们的网络或者防火墙:

# 插入connection-tracking模块(如国内建在内核中就不需要)

# insmod ip_conntrack

# insmod ip_conntrack_ftp

# 对创建大量新的连接创建一个链,除非这些连接来自内部。

# 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

# 由INPUT和FORWARD链跳往(刚刚创建的)那条链。

# iptables -A INPUT -j block

# iptables -A FORWARD -j block

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

6. 包是如何穿过过滤器的

内核由'filter'表中的以下三个规则开始。这些被称为防火墙链或就叫链。这三个链分别是 INPUT、OUTPUT和FORWARD。

对于ASCII艺术迷来说,链好象这样:(注意:这与2.0和2.2内核非常不同)

译者:ASCII艺术,这里指的是利用纯ASCII文本作图

_____

Incoming / Outgoing

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

[Decision] \_____/ ^

| |

v ____

___ /

/ |OUTPUT|

|INPUT| \____/

\___/ ^

| |

----> Local Process ----

三个圈代表上面说的三个链。当包到达图中的一个圈,那个链就检查并确定包的命运。 如果链决定DROP包,包在那里就被杀死。但是如果链决定让包ACCEPT,包就继续在图中前进。

一个链是规则的列表。每个规则都会说:'如果包头看上去像这个的话,那么就这样处理'。如果规则和包不匹配,由链中的下一个规则处理。最后,如果再也没有要进行处理的规则了,内核就根据链的原则(policy,有时称为默认规则)来决定应当如何做。在一个注重安全的 系统中,原则通常是让内核丢弃这个包。

1. 当一个包进入时(就是由以太网卡),内核首先检查包的目的地。这被称作“选路”。

2. 如果它就是进入本机的,包会向图中的下方移动,到达INPUT链。如果到了这里,任何等待这个包的进程都会收到它。

3. 否则,如果内核未被允许转发,或者不知道该如何转发这个包,它会被丢弃。如果允许转发,而且包的目的地是另一个网络接口(如果你有另一个的话),那么包向我们图中的右边行进,到达FORWARD链。如果允许通过(ACCEPT),它就被送了出去。

4. 最后,服务器上运行的程序可以发送网络包。这些包马上通过OUTPUT链。如果被允(ACCEPT),那么包继续向可以到达它的目的地的网络接口发送。

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

7. 使用iptables

iptables有着非常详尽的使用手册(man iptables),而且如果你需要某个选项更详细的介绍。看看“iptables和ipchains的差别”可能对你非常有用。

使用iptables你可以做很多不同的事。开始的内建的三个链INPUT、OUTPUT和FORWARD是不能被删除的。让我们看看整个链的管理。

1. 创建一个新的链 (-N)。

2. 删除一个空链(-X)。

3.修改内建链的原则(-P)。

4. 显示链中的规则(表)(-L)。

5. 清空一个链(-F)。

6. 将链中所有规则的包和字节计数器清零(-Z)。

有几种办法操作链中的规则:

1. 向链中添加一条新规则(-A)。

2. 在链中某个位置插入一条新规则(-I)。

3. 替换某个位置的规则(-R)。

4. 删除链中某个位置的规则,或者是第一个被匹配的。(-D)。

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

7.1. 当计算机启动后你会看到的

ptables可以作为模块,称为'iptables_filter.o,可以在第一次运行iptables时自动被装载。也可以永久性的编到内核中。

在所有iptables命令执行之前(当心:某些发布版会在初始化脚本中运行iptables),所有内建链中都没有任何规则('INPUT'、 'FORWARD'和'OUTPUT'),所有链的原则都是ACCEPT。你可以在装载iptable_filter模块时,提供'forward=0' 选项来修改FORWARD的默认原则。

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

7.2. 对单个规则的操作

这是基本的包过滤:管理规则,添加(-A)和删除(-D)命令可能是最常用的。其他的(-I插入和-R替换)只是简单的扩展而已。

每个规则都有一组条件来匹配包,和如果匹配了该如何做(target)。例如,你可能希望丢弃所有来自127.0.0.1的ICMP包。这样我们的条件就是协议必须是ICMP,而且源地址必须是127.0.0.1,我们的目标是丢弃(DROP)。127.0.0.1是一个回送接口,即使你没有真正的网络连接它也会存在。你可以用ping程序生成这样的包(它简单的发送ICMP 类型8(echo request),所有愿意响应的主机都会用ICMP 类型0(echo reply)来响应)。这对于测试非常有用。

# 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')包都将被丢弃('-j DROP')。

然后我们测试我们的规则,用第二个ping。在程序放弃等待永远不可能的响应之前,会暂停一下。

我们可以用两种办法中的任一种删除规则。首先,因为知道这是INPUT链中唯一的规则,我们用编号删除:

# iptables -D INPUT 1

删除INPUT链中的编号为1的规则

第二种办法是 -A 命令的映射,不过用-D替换-A。当你的链中规则很复杂,而你不想计算它们的编号的时候这就十分有用了。这样的话,我们可以使用:

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

-D的语法必须和-A(或者-I或者-R)一样精确。如果链中有多个相同的规则,只会删除第一个。

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

7.3 过滤规格

我们已经看了,用'-p'指定协议,用'-s'指定源地址,不过还有其他选项我们可以用来指定包的特征。下面是一个详细的手册。

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

7.3.1 指定源和目的IP地址

源('-s','--source'或'--src')和目的('-d','--destination'或'--dst')IP地址可以用四种办法指定。最常用的方法是使用全名,就像'localhost'或者'www.linuxhq.com'。第二种办法是指定IP地址,如 '127.0.0.1'。

第三和第四种办法允许指定一组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地址,像这样:

# '-s 0/0'在这里是多余的

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

这很少用到,这和上面出现过的不指定'-s'结果完全一样。

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

7.3.2 反向指定

很多标记,包括'-s'(或'--source')和'-d'('--destination')标记可以在前面加上'!'标志(读作'not'),来匹配所有和给出的 NOT 的地址。例如, '-s ! localhost'匹配所有不是来自本机的包。

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

7.3.3 协议指定

可以用'-p'(或'--protocol')指定协议。协议可以是数字(如果你知道IP的协议数值)或者像'TCP'、'UDP'或者'ICMP'这类的名称。大小写无所谓,所以'tcp'和'TCP'一样。

协议名称前可加上'!',以反向解释它,例如'-p ! TCP'将匹配所有不是TCP的包。

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

7.3.4 接口指定

'-i'(或'--in-interface')和'-o'(或'--out-interface')选项指定匹配的接口名。接口可以是包进入的('- i')或者送出('-o')的物理设备。你可以用ifconfig命令列出当前'up'的接口。(也就是说正在工作的)。

通过INPUT链的包不会有送出接口,所以在这个链中'-o'永远不会匹配。同样,通过OUTPUT链的包也没有进入接口,这个链中的'-i'也不会被匹配。

只有通过FORWARD链的包才有进入和送出两个接口。

可以指定一个当前不存在的接口。在这个接口可用之前,规则不能匹配任何东西。这对于拨号PPP连接及类似的非常有用(通常是ppp0接口)。

一个特殊情况,接口名后面是一个'+',那就会匹配以这个字符串开头的所有接口(无论当前是否存在)。例如,指定一个匹配所有ppp接口的规则,要用到-i ppp+选项。

接口名也可以在前面插入 '!',来匹配所有与指定接口不同的包,如-i ! ppp+。

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

7.3.5 分片指定

译者:为帮助大家理解,此处附上IP数据报的格式,摘自《Internetworking with TCP/IP》

0 4 8 16 19 24 31

版本号 首部长度 服务类型 总长度

标志符 标志 分片偏移量

寿命 协议 首部效验和

源IP地址

目的IP地址

IP选项 填充

数据

……

有时一个包太大,不可能适合所有线路。这样的话,包会被分成片,然后当作多个包发送。最终重组这些分片来重建整个包。

分片的问题是,被检查的初始片含有整个头部字段(IP+TCP,UDP和ICMP),但随后的包只有一部分头(没有附加协议字段的IP),因此,检查后面的分片的头部(就像有TCP、UDP和ICMP一样)是不可能的。

如果你在做NAT或连接追踪,那么所有分片在包过滤代码处理以前都会合并,所以你不需要为分片担心。

还请注意,到filter表中的INPUT链(或者任何由NF_IP_LOCAL_IN钩子程序钩入的表)的包实际上由核心IP栈片重组后到达。

否则,理解分片是如何被过滤规则处理的就非常重要了。任何过滤规则要求我们没有的信息,将被认为不匹配。这意味着(分片的)第一片像普通的包一样被处理。第二及后面的片则不会。因此,规则 -p TCP --sport www(指定源端口为'www')永远不会匹配一个分片(的包)(除了第一片),相反的规则 -p TCP --sport ! www也不会。

无论如何,你可以用'-f'(或'--fragment')标记指定专门处理第二及以后的分片的规则。当然也可以指定一个规则,让它不去匹配第二及以后的分片,在'-f'前加上'!'。

通常,让第二及以后的分片通过被认为是安全的,因为如果过滤处理了第一片,那么就无法在目标主机上进行重组。不过,已知的Bug是发送分片可能会轻易的让主机崩溃。你自己看着办吧。

网络高手注意:当这类检查进行时,畸形的包(防火墙读取的ICMP代码和类型过短的TCP、UDP和ICMP包)都将被丢弃。所以TCP分片从位置8开始。(译者:什么意思?大概是指IP包中的首部字段位置)

例如,下面的规则会丢弃任何发往192.168.1.1的分片。

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

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

7.3.6 iptables扩展:新的匹配

iptables是可扩展的,也就是包括内核和iptables工具都可以扩充新的特性。

下列部分扩展是标准的,其他的则是派生的。其他人可以做出扩展并发布给合适的人。

内核扩展一般位于内核模块子目录,诸如/lib/modules/2.4.0-test10/kernel/net/ipv4/netfilter。如果你使用了CONFIG_KMOD设置来编译内核,那么它们要求被装载,所以你不需要手工插入。

iptables程序扩展通常是位于/usr/local/lib/iptables/下的共享库,当然也可能在/lib/iptables或者/usr/lib/iptables,具体的要根据不同的发行版本来确定。

扩展有两种:新的目标,新的匹配(我们马上会谈到新的目标)。有些协议自动给出新的测试:如下所示,现有的包括TCP、UDP和ICMP。

这样,你可以在命令行中在 '-p'选项后指定新的测试,就可以载入扩展(模块)了。当允许扩展时,可以用'-m'选项装入扩展。

在选项后面('-p','-j'或者'-m')加上 '-h'或'--help'来获取扩展的帮助。

# iptables -p tcp --help

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

7.3.6.1. TCP 扩展

如果指定了'-p tcp',那么TCP扩展将自动加载,并提供下列选项(不匹配分片)。

--tcp-flags

可附加一个'!'。有两个标志字串可以通过TCP标记来过滤。第一个标志字符串是mask:你想要测验的标志列表。第二个指出哪些将要被设置。例如:

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

意思是所有标志都将被测试('ALL'和'SYN, ACK,FIN,RST,URG,PSH'同义),不过只设置SYN和ACK。当然也可以用'NONE'表示无标志。

--syn

前面的'!'是可选的,是'--tcp-flags SYN, RST, ACK, SYN'的缩写

--source-port

后面可以跟一个'!',可以是单个TCP端口,或一段端口。可以是/etc/services中的端口名或者数字。端口范围格式是低端口名 : 高端口名,或者(指定大于或等于给出的端口)是端口名 + :,或者(指定小于或等于给出的端口)是: + 端口名。

--sport

就是 '--source-port'。

--destination-port

--dport

和上面类似,不过是指定匹配的目的端口(范围)。

--tcp-option

可以跟一个'!'和一个数字,匹配的是TCP选项和数字相等的包。如果试图用 这个TCP选项匹配一个没有完整的TCP包头的包,那么这个包会被自动丢弃。

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

7.3.6.1.1. TCP标志的解释

有时只允许单向的TCP连接会很有用。例如,你可能会允许连接到外部WWW服务器,但不会允许来自那个服务器的连接。

最简单的举动可能是阻止来自那个服务器的包,可惜,TCP连接需要包双向传送(才能正常工作)。

解决办法是,只阻挡那些用来请求连接的包。这些包称为SYN包(OK,从技术上说,它们的SYN标志被设置,而没有设置RST和ACK标志,不过我们简单的称为SYN包)。通过只阻止这种包,我们就可以阻止来自那些地方的连接企图。

'--syn'标志是这样用的:只对指定了TCP协议的规则有效。例如,指定来自192.168.1.1的连接请求。

-p TCP -s 192.168.1.1 --syn

当然也可以在前面加上'!',意即所有不是初始连接的包。

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

7.3.6.2 UDP 扩展

这些扩展在指定'-p udp'时自动加载。可以提供 '--source-port'、'--sport'、'--destination-port'和'--dport'等和TCP类似的选项。

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

7.3.6.3 ICMP扩展

这些扩展在指定'-p icmp'时自动加载。只提供一个新的选项:

--icmp-type

可以跟'!',icmp类型名称(如'host-unreachable')或者数值(如'3'),或者数值类型/代码(如'3/3')。用'-p icmp --help'可以列出可用的icmp类型名。

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

7.3.6.4 其他匹配的扩展

这些netfilter包中的其他扩展尚属于演示阶段,(如果安装了的话)可以用'-m'来启用。

mac

--mac-source

可以跟一个'!',后面是以太网地址,用冒号分隔的16近制表示,如`--mac-source 00:60:08:91:CC:B7'。

limit

此模块必须明确指定'-m limit'或'--match limit'。用来限制匹配的速率。就像抑制记录信息。只会匹配给定的数字/每秒(默认是每小时3个匹配,和5个触发)。可以有两个参数:

--limit

后面跟数字:指定每秒钟允许的匹配最大平均数。这个数字可以指定 明确的单位,使用'/second'、`/minute'、`/hour' 或者 `/day',或者 只写一部分(如'5/second'和'5/s'一样)。

--limit-burst

后面跟一个数字,指明在上面的limit起作用前最大的触发值。

这个匹配(项)通常和LOG目标结合起来使用,以对速率限制进行记录。 为了理解它是如何工作的,我们来看看下面这条规则,它使用默认限制参数 记录包。

# iptables -A FORWARD -m limit -j LOG

当这条规则第一次启用时,包开始被记录。实际上,由于默认触发是5,前五个包会被记录。然后,每隔20分钟再记录一次包,无论这期间有多少包到达。而且,每个不匹配包的20分钟间隔里,会恢复一个触发(值)。如果100分钟都没有包到达这个规则,那么所有触发都会恢复,回到起点。

提示:你目前不能以大于59小时的时间来创建这种规则,所以如果你设置一个平均率为一天,那么你的触发率必须小于3。

你也可以将此模块用于避免使用快速响应速率的各类拒绝服务攻击(DoS,Denial of Server)。

(译者:以下是较著名的攻击)

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 -|.....:................................ DoS的边界 =

= (limit * | /:

limit-burst) | / : .-.

| / : /

| / : /

End of DoS -|/....:..............:.../.........../. DoS结束

= limit | : :`-' `--'

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

LOGIC => Match | Didn't Match | Match

我们匹配由五个包触发的每秒一个包,不过每秒钟第四个包才开始进入(这个规则),进行三秒钟,然后重新开始。

<--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

--uid-owner userid

根据给出的有效的(数值)user id来匹配包的创建进程。

--gid-owner groupid

根据给出的有效的(数值)group id 来匹配包的创建进程。

--pid-owner processid

根据给出的process id 来匹配包的创建进程。

--sid-owner sessionid

根据给出的 session group 来匹配包的创建进程。

unclean

这是试验性模块,必须明确指定'-m unclean'或者'--match unclean'。 它对包进行各种随机判断。此模块还未通过审核,所以不要用在安全设施上。 (可能造成更糟糕的结果,它自己可能还有Bug)。没有提供选项。

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

7.3.6.5 状态匹配

最有用的匹配标准是'state'扩展。它负责解释'ip_conntrack'模块的connection-tracking分析。 这是推荐使用的(好东东)。

通过指定'-m state'来允许附加的'--state'选项,匹配用逗号分割的状态列表('!'标志表明不符合那些状态(的状态))。

NEW

由新连接创建的包

ESTABLISHED

属于已存在连接的包(也就是说,响应的包)

RELATED

和一个已存在连接有关,但不是它的一部分的包。如ICMP错误,或者(已加载FTP模块)一个建立FTP数据连接的包。

INVALID

由于以下原因而不能被识别的包:包括内存不足和不是相应当前任何连接的ICMP错误。通常这些包会被丢弃。

这个强大的匹配扩展的一个例子:

# iptables -A FORWARD -i ppp0 -m state ! --state NEW -j DROP

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

7.4 目标规格

现在,我们知道了如何对包进行测试,但是我们还需要告诉那些匹配的包应该如何做。这被称作规则的目标。

有两个很简单的内建目标:DROP和ACCEPT。我们已经看过了。如果包匹配的规则,其目标是这二者中的一个,那么不再考虑更多的规则了:包的命运已经决定。

除此之外有两种目标:扩展的和用户定义的链。

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

7.4.1 用户定义链

iptables一个强大的特点是由ipchains继承来的可以让用户创建新的链,附加在三个内建的链上(INPUT、FORWARD和 OUTPUT)。按照惯例,用户定义链使用小写以区分他们。(我们会在“Operations on an Entire Chains”中描述如何创建新的用户定义链)。

当包匹配的链的目标是一个用户定义链时,包就转移到用户定义链中的规则。如果 没有决定包的命运,那么包在(用户定义链)中的移动就结束了,并回到当前链的下一个规则。

搞搞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到1.2.3.4的TCP包。它进入INPUT链,由Rule1检查 - 不匹配。 Rule2匹配,那么它的目标就是test,所以下一个检查由test开始。test中的第一个规则 Rule1是匹配的,但是没有指定目标,所以由第二个规则Rule2检查。结果是不匹配,而我们到达了链的尾部。于是回到INPUT链,因为刚刚被Rule2检查,所以现在由Rule3来检查,仍然 不匹配。

所以这个包的路线是:

v __________________________

`INPUT' | / `test' v

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

| Rule1 | /| | Rule1 | |

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

| Rule2 / | | Rule2 | |

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

| Rule3 /--+___________________________/

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

v

用户定义链可以跳转到另一个用户定义链(不过不能循环:如果发现循环,包就会被丢弃)。

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

7.4.2 iptables扩展:新目标

其他类型的扩展是目标。目标扩展由内核模块组成,而且iptables的一个可选扩展提供了新的命令行选项。有几个扩展是包含在默认netfilter发布中的。

LOG

--log-level

跟一个级别名称或数字。合适的名字是(忽略大小写)'debug'、'info'、'notice'、'warning'、'err'、'crit'、 'alert'和'emerg',相当于数字7到0。请参考syslog.conf的手册获取这些级别的说明。默认是'warning'。

--log-prefix

跟一个最多29个字符的字符串,它被写入到log信息的开始处,这样可以区别出来。

这个模块最有用的就是跟在limit match后面,这样你就不会被你的log淹没了。

REJECT

此模块和'DROP'效果一样,除了会发送一个'port unreachable'的ICMP错误报文。注意如果属于以下情况,ICMP错误报文不会发送:

o 包一开始就是ICMP错误报文,或者是未知的ICMP类型。

o 包被作为无头的分片过滤了。

o 我们已经向那里发送了太多的ICMP错误报文(参见/proc/sys/net/ipv4/icmp ratelimit)。

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

7.4.3 特殊的内建目标

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

RETURN如同到达这个链的尾部:如果是内建的链的规则,那么这个链的默认规则将被执行。如果是用户定义链,当跳至这个链中的这条规则(包含RETURN)时,回到前面的链继续匹配。

QUEUE是一个特别的目标,会为用户空间进程队列这个包。要这样使用,需要两个部件:

o 一个"queue handler",处理用户空间与内核之间的机制。

o 和一个用户空间用来接收的应用程序,可能是操作,以及对包进行裁决。

IPv4 iptables的标准queue handler是 ip_queue 模块,跟随内核发布并标记为实验中。

下面是一个如何用iptables为用户空间进程队列包的快速例子:

# modprobe iptable_filter

# modprobe ip_queue

# iptables -A OUTPUT -p icmp -j QUEUE

在这个例子中,本地生成的送出ICMP包(如由ping产生)到达ip_queue模块,然后包被试图送往用户空间应用。如果没有用户空间应用在(那儿)等着,包就被丢弃了。

要写一个用户空间应用,需要libipq API。和iptables一起发布。在CVS的testsuite tools(如redirect.c)中可以找到相关例子。

可以通过这里检查ip_queue的状态:

/proc/net/ip_queue

队列的最大长度(也就是不包含返回包的送往用户空间包的数量)可以通过这里控制:

/proc/sys/net/ipv4/ip_queue_maxlen

默认队列长度是1024。一旦达到这个长度,新的包就会被丢弃,直到队列长度小于这个值。好的协议如TCP,会对丢弃的包作出拥挤的解释,而且在队列满了后会很理想的将它挡回。无论如何,如果默认值太小的话,最好是多实验以决定队列的最大长度。

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

7.5 对整个链进行操作

iptables一个非常有用的特性是可以将链中相关的规则成组。你可以随意给链取名,不过我建议使用小写字母以避免与内建的链和目标产生冲突。链的名称最长为31个字母。

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

7.5.1 创建新链

让我们创建一个新链。因为我是个充满想象的家伙,我叫它test。使用'-N'或'--new-chain'选项:

# iptables -N test

如此简单,现在你可以像上面说的那样放入规则了。

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

7.5.2 删除链

删除一个链同样简单,使用 '-X'或'--delete-chain'选项。为什么是'-X'?嗯,因为所有合适的字母都已经被使用了。

# iptables -X test

有几个删除链的限制:他们必须是空的(见下面的"Flushing a Chain")而且他们不能是任何规则的目标。你也不能删除任何一个内建的链。

如果你不指定链名的话,所有可以被删除的用户定义链都将被删除。

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

7.5.3 清空一个链

这是清除一个链中所有规则的简单方法,使用'-F' 或 '--flush'命令。

# iptables -F FORWARD

如果不指定链的话,所有链都将被清空。

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

7.5.4 对链进行列表

用'-L'或'--list'命令,你可以列出一个链中的所有规则。

用户定义链中的'refcnt'是有多少链的规则指向了它。这个值必须为0,然后才可以删除这个链。

如果链名被忽略,所有链都将被列出,即便是空的。

'-L'可以有三个选项。'-n'(数字)选项对于阻止iptables试图查找IP地址时非常有用,因为(如果你像大多数人一样使用DNS)如果你的DNS设置不太合适的话,可能会造成长时间的停顿,或者你滤掉了DNS请求。它还会让TCP或UDP端口以数字显示。

'-v'选项显示所有规则的细节,包括饱和字节计数器,TOS比较,以及接口。否则这些值是被忽略的。

注意,报和字节计数器可以分别使用'K'、'M'或者'G'来代替1000、1,000,000 和1,000,000,000。使用'-x'(扩展数字)标志来打印整个值,不管它有多大。

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

7.5.5 重置(清零)计数器

可以重置计数器非常有用。可以用'-Z'或'--zero'来完成。

考虑下面的:

# iptables -L FORWARD

# iptables -Z FORWARD

在上述例子中,有些包在'-L'和'-Z'命令之间通过。因此,你可以把'-L'和'-Z'一起使用,读取时就清空计数器。

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

7.5.6 设置原则(默认规则)

我们在前面讨论包是如何通过链的时候,已经解释了当包到达内建链的尾部时会发生什么。这时,链的原则就决定包的命运。只有内建的链(INPUT、OUTPUT和FORWARD)有原则,因为如果包到达用户定义链的尾部会返回到前面的链。

原则可以是ACCEPT或DROP,例如:

# iptables -P FORWARD DROP

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

8. 使用ipchains和ipfwadm

netflter发布中有ipchains.o和ipfwadm.o模块。把其中一个加载到你的内核(注意:他们和ip_tables.o不兼容)。然后你就可以像以前那样使用ipchains和ipfwadm了。

这在一段时间内仍然被支持。我认为合理的计算方式是 2*(替代发布 - 初始的稳定版本),超过了这个时间,就应当使用替代的稳定版本了。这意味着在Linux 2.6或2.8中对它们的支持很可能被放弃。

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

9. NAT和包过滤的混合使用

想要做网络地址转换(参见NAT HowTo)和包过滤的已很常见。好消息是他们可以混合起来使用的,而且工作得非常好。

你可以完全忽略你的NAT,来定义你的包过滤。包过滤看见的包的源及目标是“真正”的源和目标。例如,如果你将任何发往1.2.3.4 80端口的包DNAT到10.1.1.1的8080端口。包过滤器看见的是包发往10.1.1.1的8080端口(真正的目的地),而非1.2.3.4 的80端口。同样,你可以忽略伪装:看到的是包的真实外部IP地址(如10.1.1.1),而响应的则返回到那里。

你可以使用'state'匹配扩展,使包过滤器不需要做任何额外的工作,因为无论如何,NAT都会要求连接跟踪。扩展NAT HowTo中简单的伪装例子,以禁止任何来自ppp0接口的新的连接,你可以这样:

#对送至ppp0的包进行伪装

iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE

# 禁止由ppp0进入的新的或不合适的包

iptables -A INPUT -i ppp0 -m state --state NEW,INVALID -j DROP

iptables -A FORWARD -i ppp0 -m state --state NEW,INVALID -j DROP

# 开启IP转发

echo 1 > /proc/sys/net/ipv4/ip_forward

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

10. iptables和ipchains之间的差别

o 首先,内建链的名称从小写改成了大写,因为现在的INPUT和OUTPUT链只获取指向本地和本地生成的包。他们用来检查所有进入和发送的包。

o '-i'标志现在表示进入接口的意思,而且只适用于INPUT和FORWORD链。FORWORD或OUTPUT链中的规则应该将'-i'改为'-o'。

o TCP和UDP端口现在必须用--source-port或--sport(或者--destination-port/--dport)拼写,而且必须放在'-p tcp'或'-p udp'选项之后,因为TCP或UDP扩展是分别加载的。

o TCP -y 标志现在是 --syn,而且必须在'-p tcp'之后。

o DENY目标现在是DROP.

o 对单个链,可以在列出其工作同时清零。

o 清空内建链同时清除了原则计数器。

o 列出链给出的是一个计数器的微型的快照。

o REJECT和LOG现在是扩展目标,意思是他们是独立的内核模块。

o 链的名称最多可以是31个字符。

o MASQ现在是MASQUERADE而且使用不同的语法。REDRIRECT,在保留相同的名字时,也经历了语法的改变。参见NAT-HOWTO以获取配置它们的更多信息。

o -o选项不再用于将包传递给用户空间设备了(见上面的-i)。现在通过 QUEUE目标传递到用户空间。

o 很可能还有一些我也忘了。

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

11. 对制定包过滤器的建议

在计算机安全领域中,最明智的办法是阻挡所有东西,然后对需要的开启。这通常称为“凡是没有明确允许的都是禁止的”。我建议这样做如果安全是你最关心的。

不要运行任何你不需要的服务,即使你认为你已经阻碍了对它们的访问。

如果你创建专用防火墙,开始时不运行任何东西,并阻止所有包,然后添加服务并让需要的包通过。

我强调安全:结合tcp-wrappers(对于包过滤器本身的连接),代理(通过包过滤器的连接),路由验证和包过滤。路由验证是如果包来自未预期的接口那么将被删除:例如,如果你的内部网络地址是10.1.1.0/24,而一个包的源地址是你的外部接口,那么它将被丢弃。对一个接口如ppp0来说可以这样:

# echo 1 > /proc/sys/net/ipv4/conf/ppp0/rp_filter

或者对所有已有的或将有的接口:

# for f in /proc/sys/net/ipv4/conf/*/rp_filter; do

# echo 1 > $f

# done

Debian在可能的范围了将这些设为默认。如果你使用非对称路由(如你期望包来自一个其他的方向),你可能需要在这些接口上禁止这一过滤。

记录对于当工作不正常时设置防火墙非常有用,但是在一个作为产品的防火墙上,总是应当将它与'limit'匹配结合,以防止有人充斥你的记录。

我极力推荐对安全系统使用连接追踪:它虽然会造成负担,因为所有连接都被追踪。但是对于控制对你的网络的访问非常有用。如果你的内核没有自动加载而且没有内建,你需要加载'ip_conntrack.o'这个模块。如果想要精确追踪复杂的协议,你需要加载合适的相关模块(如 'ip_conntrack_ftp.o')。

# iptables -N no-conns-from-ppp0

# iptables -A no-conns-from-ppp0 -m state --state ESTABLISHED,RELATED -j ACCEPT

# iptables -A no-conns-from-ppp0 -m state --state NEW -i ! ppp0 -j ACCEPT

# iptables -A no-conns-from-ppp0 -i ppp0 -m limit -j LOG --log-prefix "Bad packet from ppp0:"

# iptables -A no-conns-from-ppp0 -i ! ppp0 -m limit -j LOG --log-prefix "Bad packet not from ppp0:"

# iptables -A no-conns-from-ppp0 -j DROP

# iptables -A INPUT -j no-conns-from-ppp0

# iptables -A FORWARD -j no-conns-from-ppp0

建造一个好的防火墙超越了这个HOWTO的范围,不过我的建议是“一切从严”。请参见Security HOWTO获取更多信息,来测试和探索你的服务器。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有