iptables 常被解释为 Linux 服务器上的防火墙软件,事实上它只是被用来创建和维护 IP 包的过滤规则,然后这些规则会交给 Linux 系统上的 Netfilter 框架来读取,从而实现防火墙的功能。
iptables 的使用规则很复杂,比如下面这条配置规则:
iptables -A INPUT -i eth0 -p tcp \
--dport 22 \
-m state --state NEW,ESTABLISHED -j ACCEPT
是不是如同看天书一般?看不懂也没关系,相信看完本文的介绍,示例以及选项参考后,就能理解上面这行配置的意思。
基础概念
在理解 iptables 命令规则之前,需要先了解它的「五链三表」。所谓的五链分别为:
PREROUTING
: 路由之前的规则处理。INPUT
: 处理进来的数据包。OUTPUT
: 处理本地生成后要发出去的数据包。FORWARD
: 处理转发的数据包。POSTROUTING
: 路由之后的规则处理。
三表为:
filter
:这是默认的表,主要用来根据规则接受或丢弃数据包。可操作INPUT
,FORWORD
和OUTPUT
链。nat
:用于地址转换。可操作PREROUTING
、OUTPUT
和POSTROUTING
链。mangle
:用来对指定的包进行修改并重新封装。可操作PREROUTING
、INPUT
、OUTPUT
、FORWARD
和POSTROUTING
链。
关于这五个链的流程和表的关系可参照下面这张图来理解:
图片来自网络
除了五链三表,iptables 还有一个值得了解的概念是目标(Targets)。对于匹配到规则的数据包,可以指定处理的方式,这个处理方式可以是一个自定义的链名,也可以是指定的目标值。下面是几个常用的目标值:
- ACCEPT: 表示让匹配的数据包通过。
- DROP: 表示丢弃匹配的数据包。
- QUEUE: 表示把匹配的数据包传递到用户空间排队等待处理。
- RETURN: 表示停止这条链的匹配,到前一个链的规则重新开始。
基础概念就是上面这些。是不是已经迫不及待了?我们接下来将直接从例子开始入手,来更加深入的理解 iptables 命令的用法。
命令示例
iptables
命令提供的参数众多,对于接下来示例中的选项如果有不理解的,请参照本文最后的命令选项列表来了解具体用法。
首先来看个最简单的例子,查看当前所有规则:
iptables -L
不允许访问本机的 80 端口:
iptables -I INPUT -p tcp --dport 80 -j REJECT
上面的命令稍微多了几个命令选项,别怕,以 -
开头的参数可以在下面的选项表中去找,看说明就能理解。INPUT
上面已经介绍过,是处理进来数据包的链,DROP
也介绍过,表示丢弃数据包。结合起来看就很容易理解了,只要是 80 端口进来的 TCP 数据包,就丢弃掉。相当于是禁止了 80 端口 TCP 协议的访问。
使用 -I
选项插入规则时可以在链名后指定插入位置:
iptables -I INPUT 1 -p tcp –-dport 80 -j REJECT
在来个更复杂一点的,对 80 端口的请求数量进行限制,指定每分钟匀速请求为 10,瞬时最大请求不能超过 30:
iptables -A INPUT -p tcp --dport 80 -m limit \
--limit 10/minute --limit-burst 30 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j DROP
上面用到了 iptables 的 limit 扩展,关于扩展的用法,同样请查阅后面的选项模块扩展表。
继续例子,只指定的 MAC 地址通过:
iptables -A INPUT -m mac --mac-source 00:0A:38:22:32:A3 -j ACCEPT
只允许已建立链接和关联链接通过:
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
将来自 80 端口的 TCP 请求数据记录到系统日志中(/var/log/message):
iptables -A INPUT -p tcp --dport 80 -j LOG
将 80 端口的请求重新定位到 8080 端口:
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080
禁止指定的 IP 连接:
iptables -I INPUT -s 10.0.28.15 -j REJECT
禁止所有来源连接:
iptables -A INPUT -j REJECT
如果发现设置的规则有问题,可以通过 -F
选项来清空:
iptables -F
如果存在一些创建的自定义链,可以用下面的命令来清空:
iptables -X
这样就 iptables 就恢复成了默认状态。所以随便折腾吧,有问题了大不了清空一下再来。如果对当前规则很满意,可以把它们备份为文件:
iptables-save > iptables.bak
然后在需要的时候直接还原:
iptables-restore < iptables.bak
iptables 命令选项
iptables 命令选项有多种类型,有用来执行明确动作的选项命令,还有扩展命令用的选项参数。除此之外,还有扩展模块提供的相关选项,具体内容请参阅下面按选项类型汇总的表格。
选项命令
缩写 | 完整名称 | 说明 |
---|---|---|
-A |
-append |
在所选择的链末添加一条或更多规则。 |
-D |
-delete |
从所选链中删除一条或更多规则。 |
-R |
-replace |
从选中的链中取代一条规则。 |
-I |
-insert |
根据给出的规则序号向所选链中插入一条或更多规则。 |
-L |
-list |
显示所选链的所有规则。如果没有选择链,所有链将被显示。 |
-F |
-flush |
清空所选链。这等于把所有规则一个个的删除。 |
--Z |
-zero |
把所有链的包及字节的计数器清空。 |
-N |
-new-chain |
根据给出的名称建立一个新的用户定义链。这必须保证没有同名的链存在。 |
-X |
-delete-chain |
删除指定的用户自定义链。 |
-P |
-policy |
设置链的目标规则。 |
-E |
-rename-chain |
根据用户给出的名字对指定链进行重命名。 |
-h |
输出命令帮助。 |
选项参数
缩写 | 完整名称 | 说明 |
---|---|---|
-p |
-protocal [!]protocol |
规则或者包检查(待检查包)的协议。指定协议可以是 tcp 、udp 、icmp 中的一个或者全部,也可以是数值,代表这些协议中的某一个。当然也可以使用在 /etc/protocols 中定义的协议名。在协议名前加上 ! 表示相反的规则。数字 0 相当于所有 all 。Protocol all 会匹配所有协议,而且这是缺省时的选项。在和 check 命令结合时,all 可以不被使用。 |
-s |
-source [!] address[/mask] |
指定源地址,可以是主机名、网络名和清楚的 IP 地址。mask 说明可以是网络掩码或清楚的数字,在网络掩码的左边指定网络掩码左边 1 的个数,因此,mask 值为 24 等于255.255.255.0。在指定地址前加上 ! 说明指定了相反的地址段。标志 --src 是这个选项的简写。 |
-d |
--destination [!] address[/mask] |
指定目标地址,要获取详细说明请参见 -s 标志的说明。标志 --dst 是这个选项的简写。 |
-j |
--jump target |
指定规则的跳转目标。指定包匹配后应当做的操作。目标可以是用户自定义链,某个专用内建目标,或者一个扩展。如果忽略这个选项,匹配的过程不会对包产生影响,不过规则的计数器会增加。 |
-i |
-in-interface [!] [name] |
指定接收包的入口名称。当在名称前使用 ! 符号表示相反的名称。如果接口名后面加上 + ,则表示所有以此接口名开头的名称。 |
-o |
--out-interface [!][name] |
指定送出包的出口名称。使用规则上与 -i 类似。 |
[!] -f |
--fragment |
在分片的包中,规则只询问第二及以后的片。 |
辅助选项
缩写 | 完整名称 | 说明 |
---|---|---|
-v |
--verbose |
输出命令详细信息。这个选项让 list 命令显示接口地址、规则选项和 TOS(Type of Service)掩码。包和字节计数器也将被显示,分别用 K、M、G 表示 1000、1,000,000 和1,000,000,000 倍。对于添加, 插入, 删除和替换命令,会输出一个或多个规则的相关详细信息。 |
-n |
--numeric |
以数字输出 IP 地址和端口。默认情况下,程序试显示主机名、网络名或者服务名。 |
-x |
-exact |
显示包和字节计数器的精确值,代替用 K, M, G 表示的约数。这个选项仅适用于 -L 选项命令。 |
--line-numbers |
当列表显示规则时,在每个规则的前面加上行号,与该规则在链中的位置相对应。 |
选项模块扩展
iptables 能够使用一些与模块匹配的扩展包。以下就是含于基本包内的扩展包,它们大多数都可以通过在前面加上 !
来表示相反的意思。
模块名称 | 选项 | 说明 |
---|---|---|
tcp |
--source-port [!] [port[:port]] |
源端口或端口范围指定。 |
tcp |
--destionation-port [!] [port:[port]] |
目标端口或端口范围指定。这个选项可以使用 --dport 别名来代替。 |
tcp |
--tcp-flags [!] mask comp |
匹配指定的 TCP 标记。第一个参数是我们要检查的标记,一个用逗号分开的列表,第二个参数是用逗号分开的标记表,是必须被设置的。标记如下:SYN ACK FIN RST URG PSH ALL NONE 。举个例子:iptables -A FORWARD -p tcp --tcp-flags SYN, ACK, FIN, RST SYN 只匹配那些SYN 标记被设置而 ACK、FIN 和 RST 标记没有设置的包。 |
tcp |
[!] --syn |
只匹配那些设置了 SYN 位而清除了 ACK 和 FIN 位的 TCP 包。这些包用于 TCP 连接初始化时发出请求;例如,大量的这种包进入一个接口发生堵塞时会阻止进入的 TCP 连接,而出去的 TCP 连接不会受到影响。这等于 --tcp-flags SYN, RST, ACK SYN 。如果 --syn 前面有 ! 标记,表示相反的意思。 |
tcp |
--tcp-option [!] number |
匹配设置的 TCP 选项。 |
udp |
--source-port [!] [port:[port]] |
源端口或端口范围指定。详见 TCP 扩展的 --source-port 选项说明。 |
udp |
--destination-port [!] [port:[port]] |
目标端口或端口范围指定。详见 TCP 扩展的 --destination-port 选项说明。 |
icmp |
--icmp-type [!] typename |
指定 ICMP 类型,使用 iptables -p icmp -h 命令可以查看可用的 ICMP 类型名。 |
mac |
--mac-source [!] address |
匹配物理地址。必须是 XX:XX:XX:XX:XX 这样的格式。它只对来自以太设备并进入 PREROUTING,FORWORD 和 INPUT 链的包有效。 |
limit |
--limit rate |
设置最大平均匹配速率。可赋的值有 /second , /minute , /hour , 或 /day 这样的单位,默认是 3/hour 。 |
limit |
--limit-burst number |
待匹配包初始个数的最大值。若前面指定的极限还没达到这个数值,则数字加 1,默认值为 5。 |
limit |
multiport |
这个模块匹配一组源端口或目标端口,最多可以指定 15 个端口。只能和 -p tcp 或者 -p udp 连着使用。 |
limit |
--source-port [port[, port]] |
如果源端口是其中一个给定端口则匹配。 |
limit |
--destination-port [port[, port]] |
如果目标端口是其中一个给定端口则匹配。 |
limit |
--port [port[, port]] |
若源端口和目的端口相等并与某个给定端口相等则匹配。 |
mark |
--mark value [/mask] |
匹配无符号标记值的包。 |
owner |
--uid-owner userid |
如果给出有效的user id,那么匹配它的进程产生的包。 |
owner |
--gid-owner groupid |
如果给出有效的group id,那么匹配它的进程产生的包。 |
owner |
--sid-owner seessionid |
根据给出的会话组匹配该进程产生的包。 |
state |
--state state |
这里 state 是一个逗号分割的匹配连接状态列表。可能的状态有: INVALID 表示包是未知连接,ESTABLISHED 表示是双向传送的连接,NEW 表示包为新的连接,否则是非双向传送的,而 RELATED 表示包由新连接开始,但是和一个已存在的连接在一起,如 FTP 数据传送,或者一个ICMP 错误。 |
unclean |
此模块没有可选项,不过它试着匹配那些奇怪的、不常见的包。处在实验中。 | |
tos |
--tos tos |
匹配 IP 包首部的 8 位服务类型字段。这个参数可以是一个标准名称,用 iptables -m tos -h 可查看可用的名称和值。 |
目标模块扩展
iptables 标准版默认有以下目标模块:
LOG
: 为匹配的包开启内核记录。MARK
: 用来设置包的 netfilter 标记值。REJECT
: 作为对匹配的包的响应,返回一个错误的包,其他情况下和 DROP 相同。TOS
: 用来设置IP包的首部八位tos。只能用于mangle表。MIRROR
: 用于转换 IP 首部字段中的源地址和目标地址,再传送该包。只适用于 INPUT、FORWARD 和 OUTPUT 链,以及只调用它们的用户自定义链。SNAT
: 修改包的源地址。只适用于 nat 表的 POSTROUTING 链。MASQUERADE
: 用于动态获取 IP 连接,只用于 nat 表的 POSTROUTING 链。REDIRECT
: 修改包的目标 IP 地址来发送包到机器自身,只适用于 nat 表的 PREROUTING 和 OUTPUT 链。
这些模块的选项如下:
模块名称 | 选项 | 说明 |
---|---|---|
LOG |
--log-level level |
记录级别。 |
LOG |
--log-prefix prefix |
在纪录信息前加上特定的前缀。 |
LOG |
--log-tcp-sequence |
记录 TCP 序列号。 |
LOG |
--log-tcp-options |
记录来自 TCP 包头部的选项。 |
LOG |
--log-ip-options |
记录来自 IP 包头部的选项。 |
MARK |
--set-mark mark |
设置包的 netfilter 标记值。 |
REJECT |
--reject-with type |
type 可以是 icmp-net-unreachable 、icmp-host-unreachable 、icmp-port-nreachable 、icmp-prot 、o-unreachable 、icmp-net-prohibited 或者 icmp-host-prohibited ,该类型会返回相应的 ICMP 错误信息(默认是 port-unreachable )。 |
TOS |
--set-tos tos |
你可以使用一个数值型的 TOS 值,或者用 iptables -j TOS -h 来查看有效 TOS 名称。 |
SNAT |
--to-source <ipaddr>[-<ipaddr>][:port-port] |
可以指定一个单一的新的 IP 地址,一个 IP 地址范围,也可以附加一个端口范围(只能在指定 -p tcp 或者 -p udp 的规则里)。 |
SNAT |
--to-destiontion <ipaddr>[-<ipaddr>][:port-port] |
可以指定一个单一的新的 IP 地址,一个 IP 地址范围,也可以附加一个端口范围(只能在指定 -p tcp 或者 -p udp 的规则里)。如果未指定端口范围,目标端口不会被修改。 |
MASQUERADE |
--to-ports <port>[-port>] |
指定使用的源端口范围,覆盖默认的 SNAT 源地址选择。这个选项只适用于指定了 -p tcp 或者 -p udp 的规则。 |
REDIRECT |
--to-ports <port>[<port>] |
指定使用的目的端口或端口范围。不指定的话,目标端口不会被修改。只能用于指定了 -p tcp 或 -p udp 的规则。 |