netfilter/iptables IP 信息包过滤系统是一种功能强大的工具,可用于添加、编辑和除去规则,这些规则是在做信息包过滤决定时,防火墙所遵循和组成的规则。这些规则存储在专用的信息包过滤表中,而这些表集成在 Linux 内核中。在信息包过滤表中,规则被分组放在我们所谓的链(chain)中。我马上会详细讨论这些规则以及如何建立这些规则并将它们分组在链中。
虽然 netfilter/iptables IP 信息包过滤系统被称为单个实体,但它实际上由两个组件netfilter和 iptables 组成。
netfilter 组件也称为 内核空间(kernelspace),是内核的一部分,由一些信息包过滤表组成,这些表包含内核用来控制信息包过滤处理的规则集。
iptables 组件是一种工具,也称为 用户空间(userspace),它使插入、修改和除去信息包过滤表中的规则变得容易。除非您正在使用 Red Hat Linux 7.1 或更高版本,否则需要从 netfilter.org 下载该工具并安装使用它。
通过使用用户空间,可以构建自己的定制规则,这些规则存储在内核空间的信息包过滤表中。这些规则具有 目标,它们告诉内核对来自某些源、前往某些目的地或具有某些协议类型的信息包做些什么。如果某个信息包与规则匹配,那么使用目标 ACCEPT
允许该信息包通过。还可以使用目标DROP
或 REJECT
来阻塞并杀死信息包。对于可对信息包执行的其它操作,还有许多其它目标。
根据规则所处理的信息包的类型,可以将规则分组在链中。处理入站信息包的规则被添加到 INPUT
链中。处理出站信息包的规则被添加到OUTPUT
链中。处理正在转发的信息包的规则被添加到 FORWARD
链中。这三个链是基本信息包过滤表中内置的缺省主链。另外,还有其它许多可用的链的类型(如PREROUTING
和 POSTROUTING
),以及提供用户定义的链。每个链都可以有一个 策略,它定义“缺省目标”,也就是要执行的缺省操作,当信息包与链中的任何规则都不匹配时,执行此操作。
建立规则并将链放在适当的位置之后,就可以开始进行真正的信息包过滤工作了。这时内核空间从用户空间接管工作。当信息包到达防火墙时,内核先检查信息包的头信息,尤其是信息包的目的地。我们将这个过程称为路由。
如果信息包源自外界并前往系统,而且防火墙是打开的,那么内核将它传递到内核空间信息包过滤表的 INPUT
链。如果信息包源自系统内部或系统所连接的内部网上的其它源,并且此信息包要前往另一个外部系统,那么信息包被传递到 OUTPUT
链。类似的,源自外部系统并前往外部系统的信息包被传递到FORWARD
链。
接下来,将信息包的头信息与它所传递到的链中的每条规则进行比较,看它是否与某条规则完全匹配。如果信息包与某条规则匹配,那么内核就对该信息包执行由该规则的目标指定的操作。但是,如果信息包与这条规则不匹配,那么它将与链中的下一条规则进行比较。最后,如果信息包与链中的任何规则都不匹配,那么内核将参考该链的策略来决定如何处理该信息包。理想的策略应该告诉内核DROP
该信息包。 图 1 用图形说明了这个信息包过滤过程。
原文链接
iptables防火墙可以用于创建过滤(filter)与NAT规则。所有Linux发行版都能使用iptables,因此理解如何配置iptables将会帮助你更有效地管理Linux防火墙。如果你是第一次接触iptables,你会觉得它很复杂,但是一旦你理解iptables的工作原理,你会发现其实它很简单。
首先介绍iptables的结构:iptables -> Tables -> Chains -> Rules. 简单地讲,tables由chains组成,而chains又由rules组成。如下图所示。
图: IPTables Table, Chain, and Rule Structure
iptables具有Filter, NAT, Mangle, Raw四种内建表:
Filter表示iptables的默认表,因此如果你没有自定义表,那么就默认使用filter表,它具有以下三种内建链:
NAT表有三种内建链:
Mangle表用于指定如何处理数据包。它能改变TCP头中的QoS位。Mangle表具有5个内建链:
Raw表用于处理异常,它具有2个内建链:
下图展示了iptables的三个内建表:
图: IPTables 内建表
牢记以下三点式理解iptables规则的关键:
下面是你可以在target里指定的特殊值:
如果你执行iptables --list
你将看到防火墙上的可用规则。下例说明当前系统没有定义防火墙,你可以看到,它显示了默认的filter表,以及表内默认的input链, forward链, output链。
# iptables -t filter --list 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
查看mangle表:
# iptables -t mangle --list
查看NAT表:
# iptables -t nat --list
查看RAW表:
# iptables -t raw --list
/!\注意:如果不指定-t选项,就只会显示默认的filter表。因此,以下两种命令形式是一个意思:
# iptables -t filter --list (or) # iptables --list
以下例子表明在filter表的input链, forward链, output链中存在规则:
# iptables --list Chain INPUT (policy ACCEPT) num target prot opt source destination 1 RH-Firewall-1-INPUT all -- 0.0.0.0/0 0.0.0.0/0 Chain FORWARD (policy ACCEPT) num target prot opt source destination 1 RH-Firewall-1-INPUT all -- 0.0.0.0/0 0.0.0.0/0 Chain OUTPUT (policy ACCEPT) num target prot opt source destination Chain RH-Firewall-1-INPUT (2 references) num target prot opt source destination 1 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 2 ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmp type 255 3 ACCEPT esp -- 0.0.0.0/0 0.0.0.0/0 4 ACCEPT ah -- 0.0.0.0/0 0.0.0.0/0 5 ACCEPT udp -- 0.0.0.0/0 224.0.0.251 udp dpt:5353 6 ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:631 7 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:631 8 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED 9 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22 10 REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
以上输出包含下列字段:
在配置iptables之前,你通常需要用iptables --list
命令或者iptables-save
命令查看有无现存规则,因为有时需要删除现有的iptables规则:
iptables --flush 或者 iptables -F
这两条命令是等效的。但是并非执行后就万事大吉了。你仍然需要检查规则是不是真的清空了,因为有的linux发行版上这个命令不会清除NAT表中的规则,此时只能手动清除:
iptables -t NAT -F
当你删除、添加规则后,这些更改并不能永久生效,这些规则很有可能在系统重启后恢复原样。为了让配置永久生效,根据平台的不同,具体操作也不同。下面进行简单介绍:
首先,保存现有的规则:
iptables-save > /etc/iptables.rules
然后新建一个bash脚本,并保存到/etc/network/if-pre-up.d/目录下:
#!/bin/bash iptables-restore < /etc/iptables.rules
这样,每次系统重启后iptables规则都会被自动加载。
/!\注意:不要尝试在.bashrc或者.profile中执行以上命令,因为用户通常不是root,而且这只能在登录时加载iptables规则。
# 保存iptables规则 service iptables save # 重启iptables服务 service iptables stop service iptables start
查看当前规则:
cat /etc/sysconfig/iptables
可以使用iptables -A
命令追加新规则,其中-A表示Append。因此,新的规则将追加到链尾。
一般而言,最后一条规则用于丢弃(DROP)所有数据包。如果你已经有这样的规则了,并且使用-A参数添加新规则,那么就是无用功。
iptables -A chain firewall-rule
以下这些规则参数用于描述数据包的协议、源地址、目的地址、允许经过的网络接口,以及如何处理这些数据包。这些描述是对规则的基本描述。
对规则有了一个基本描述之后,有时候我们还希望指定端口、TCP标志、ICMP类型等内容。
本例实现的规则将仅允许SSH数据包通过本地计算机,其他一切连接(包括ping)都将被拒绝。
# 1.清空所有iptables规则 iptables -F # 2.接收目标端口为22的数据包 iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT # 3.拒绝所有其他数据包 iptables -A INPUT -j DROP
上例的例子仅对接收的数据包过滤,而对于要发送出去的数据包却没有任何限制。本节主要介绍如何更改链策略,以改变链的行为。
/!\警告:请勿在远程连接的服务器、虚拟机上测试!
当我们使用-L选项验证当前规则是发现,所有的链旁边都有policy ACCEPT标注,这表明当前链的默认策略为ACCEPT:
# iptables -L Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT tcp -- anywhere anywhere tcp dpt:ssh DROP all -- anywhere anywhere Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination
这种情况下,如果没有明确添加DROP规则,那么默认情况下将采用ACCEPT策略进行过滤。除非:
a)为以上三个链单独添加DROP规则:
iptables -A INPUT -j DROP iptables -A OUTPUT -j DROP iptables -A FORWARD -j DROP
b)更改默认策略:
iptables -P INPUT DROP iptables -P OUTPUT DROP iptables -P FORWARD DROP
糟糕!!如果你严格按照上一节的例子配置了iptables,并且现在使用的是SSH进行连接的,那么会话恐怕已经被迫终止了!
为什么呢?因为我们已经把OUTPUT链策略更改为DROP了。此时虽然服务器能接收数据,但是无法发送数据:
# iptables -L Chain INPUT (policy DROP) target prot opt source destination ACCEPT tcp -- anywhere anywhere tcp dpt:ssh DROP all -- anywhere anywhere Chain FORWARD (policy DROP) target prot opt source destination Chain OUTPUT (policy DROP) target prot opt source destination
尽管5.4节已经介绍了如何初步限制除SSH以外的其他连接,但是那是在链默认策略为ACCEPT的情况下实现的,并且没有对输出数据包进行限制。本节在上一节基础上,以SSH和HTTP所使用的端口为例,教大家如何在默认链策略为DROP的情况下,进行防火墙设置。在这里,我们将引进一种新的参数-m state,并检查数据包的状态字段。
# 1.允许接收远程主机的SSH请求 iptables -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT # 2.允许发送本地主机的SSH响应 iptables -A OUTPUT -o eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
如果服务器也需要使用SSH连接其他远程主机,则还需要增加以下配置:
# 1.送出的数据包目的端口为22 iptables -A OUTPUT -o eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT # 2.接收的数据包源端口为22 iptables -A INPUT -i eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
HTTP的配置与SSH类似:
# 1.允许接收远程主机的HTTP请求 iptables -A INPUT -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT # 1.允许发送本地主机的HTTP响应 iptables -A OUTPUT -o eth0 -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT
# 1.删除现有规则 iptables -F # 2.配置默认链策略 iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT DROP # 3.允许远程主机进行SSH连接 iptables -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT # 4.允许本地主机进行SSH连接 iptables -A OUTPUT -o eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A INPUT -i eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT # 5.允许HTTP请求 iptables -A INPUT -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT
[1] Linux Firewall Tutorial: IPTables Tables, Chains, Rules Fundamentals
[2] IPTables Flush: Delete / Remove All Rules On RedHat and CentOS Linux
[3] Linux IPTables: How to Add Firewall Rules (With Allow SSH Example)
[4] Linux IPTables: Incoming and Outgoing Rule Examples (SSH and HTTP)
[5] 25 Most Frequently Used Linux IPTables Rules Examples
[6] man 8 iptables
附录1:
mangle表中的PREROUTING要先于nat 表中的PREROUTING 和 filter表中的FORWARD
enum nf_ip_hook_priorities {
NF_IP_PRI_FIRST = INT_MIN,
NF_IP_PRI_CONNTRACK_DEFRAG = -400,
NF_IP_PRI_RAW = -300,
NF_IP_PRI_SELINUX_FIRST = -225,
NF_IP_PRI_CONNTRACK = -200,
NF_IP_PRI_MANGLE = -150,
NF_IP_PRI_NAT_DST = -100,
NF_IP_PRI_FILTER = 0,
NF_IP_PRI_NAT_SRC = 100,
NF_IP_PRI_SELINUX_LAST = 225,
NF_IP_PRI_CONNTRACK_CONFIRM = INT_MAX,
NF_IP_PRI_LAST = INT_MAX,
};
nat 在 mangle 之后,而 nat 中又有 NAT_DST(PREROUTING)和 NAT_SRC(POSTROUTING)
附录2 netfilter框架(来自百度百科) :
技术分析