zzxworld

Linux iptables 命令详解和选项参考

iptables 常被解释为 Linux 服务器上的防火墙软件,事实上它只是被用来创建和维护 IP 包的过滤规则,然后这些规则会交给 Linux 系统上的 Netfilter 框架来读取,从而实现防火墙的功能。

iptables 的使用规则很复杂,比如下面这条配置规则:

iptables -A INPUT -i eth0 -p tcp \
    --dport 22 \
    -m state --state NEW,ESTABLISHED -j ACCEPT

是不是如同看天书一般?看不懂也没关系,相信看完本文的介绍,示例以及选项参考后,就能理解上面这行配置的意思。

基础概念

在理解 iptables 命令规则之前,需要先了解它的「五链三表」。所谓的五链分别为:

  1. PREROUTING: 路由之前的规则处理。
  2. INPUT: 处理进来的数据包。
  3. OUTPUT: 处理本地生成后要发出去的数据包。
  4. FORWARD: 处理转发的数据包。
  5. POSTROUTING: 路由之后的规则处理。

三表为:

  1. filter:这是默认的表,主要用来根据规则接受或丢弃数据包。可操作 INPUTFORWORDOUTPUT 链。
  2. nat:用于地址转换。可操作 PREROUTINGOUTPUTPOSTROUTING 链。
  3. mangle:用来对指定的包进行修改并重新封装。可操作 PREROUTINGINPUTOUTPUTFORWARDPOSTROUTING 链。

关于这五个链的流程和表的关系可参照下面这张图来理解:

iptables-chain 图片来自网络

除了五链三表,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 规则或者包检查(待检查包)的协议。指定协议可以是 tcpudpicmp 中的一个或者全部,也可以是数值,代表这些协议中的某一个。当然也可以使用在 /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-unreachableicmp-host-unreachableicmp-port-nreachableicmp-proto-unreachableicmp-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 的规则。