iptables
{Back to Index}  

Table of Contents

1 概述

1.1 命令格式

iptables [ -t 表名] 命令选项 [链名] [匹配] [-j 目标动作或跳转]

1.1.1 表 (操作维度)

在 iptables 中,每种表对应不同的功能(操作),由相应的内核模块提供支持:

  1. filter (iptables_filter)

    负责过滤功能,防火墙。

  2. nat (iptable_nat)

    提供网络地址转换,端口映射功能。

  3. mangle (iptable_mangle)

    拆解报文,做出修改,并重新封装。

  4. raw (iptable_raw)

    优先级最高的表 ,设置 raw 时一般是为了不再做数据包的链接跟踪处理,以提高性能。

    因为优先级最高,从而可以对收到的数据包在连接跟踪前进行处理,即数据包在某个链上由 raw 表处理完后, 就意味着跳过了 nat 表(和 iptables_nat 模块中对 ip_conntrack 的处理,相当于不再做地址转换和数据包的链接跟踪处理了)

    可以应用在那些 不需要做 nat 的情况下 ,以提高性能。如大量访问的 web 服务器,可以让 80 端口不再做数据包的链接跟踪处理, 以提高用户的访问速度。

1.1.2 链 (执行维度)

PREROUTING
raw, mangle, nat
INPUT
mangle, filter
FORWARD
mangle, filter
OUTPUT
raw, mangle, nat, filter
POSTROUTING
mangle, nat

数据包经过一个链的时候,会将当前链的所有规则都匹配一遍,但是 匹配是有顺序的 ,当 4 张表处于同一条链时,执行的优先级如下:

raw -> mangle -> nat -> filter

拥有 过滤功能 的链只有 3 条:INPUT, OUTPUT, FORWARD 。

1.1.3 命令选项

1.1.3.1 rule 管理
-A: 在指定链的末尾添加( --append )一条新的规则
-D: 删除( --delete )指定链中的某一条规则,按规则序号或内容确定要删除的规则
-I: 在指定链中插入( --insert )一条新的规则,默认在链的开头插入
-R: 修 改、替换( --replace )指定链中的一条规则,按规则序号或内容确定
1.1.3.2 链管理
-F: 清空( --flush )指定链中的所有规则,默认清空表中所有链的内容
-N: 新建( --new-chain )一条用户自己定义的规则链
-X: 删除指定表中用户自定义的规则链( --delete-chain )
-P: 设置指定链的默认策略( --policy )
-z: 置零计数器
-r [CHAIN]: 清空指定规则链,如果省略 CHAIN,则删除对应表中的所有链
1.1.3.3 查看信息
-L: 列出( --list )指定链中的所有的规则进行查看,默认列出表中所有链的内容
-n: 用数字形式( --numeric )显示输出结果,若显示主机的 IP 地址而不是主机名
-v: 查看规则列表时显示详细( --verbose )的信息
-x: 计数器取消近似
-line-numbers: 查看规则列表时,同时显示规则在链中的顺序号

1.1.4 匹配

1.1.4.1 通用匹配
-p {tcp|udp|icmp}: 指定隐含扩展,其余扩展(如 state)必须由 -m 指定
-s, --src:         指定源地址
-d, --dst:         指定目标地址
-i <INTERFACE>:    指定报文流入接口,仅适用于 PREROUTING,INPUT,FORWARD
-o <INTERFACE>:    指定报文流出接口,仅适用于 OUTPUT,POSTROUTING,FORWARD
1.1.4.2 隐含匹配
-p tcp:
  --sport PORT|STARTPORT-ENDPORT: 源端口
  --dport PORT|STARTPORT-ENDPORT: 目标端口
  --tcp-flags <mask> <comp>: 检查<mask>中列出的标志位, <comp>中指明的必须为1,其余必须为零
                             如:--tcp-flags SYN,FIN,ACK,RST SYN,ACK
  --syn: 等效于 --tcp-flags SYN,FIN,ACK,RST SYN,ACK

-p icmp:
  --icmp-type: 0(echo-reply), 8(echo-request)

-p udp:
  --sport
  --dport
1.1.4.3 显式匹配
-m state:
  --state NEW|ESTABLISHED|RELATED|INVALID

-m multiport:
  --source-ports
  --destination-ports

-m iprange:
  --src-range
  --dst-range

-m connlimit:
  --connlimit-above

-m limit:
  --limit
  --limit-burst

-m time:
  --datestart
  --datestop
  --timestart
  --timestop

-m string:
  --algo: 用于指定匹配算法,可选的算法有 bm 与 kmp
  --string: 指定要匹配的字符串,如果报文中包含对应的字符串,则符合匹配条件

1.1.5 目标动作

  • ACCEPT

    允许数据包通过。

  • DROP

    直接丢弃数据包,不给任何回应信息。

  • REJECT

    拒绝数据包通过,客户端刚请求会收到拒绝的信息。

  • SNAT

    源地址转换,解决内网用户用同一个公网地址上网的问题。

  • MASQUERADE

    是 SNAT 的一种特殊形式适用于网关 NAT 的情况 ,例如:

    iptables -t nat -A POSTROUTING -s 192.168.56.0/24 -o eth1 -j MASQUERADE

    在网关上仅针对由内网到 Internet 的流量进行 NAT 转换:【10.0.0.0/8 为公司内部网段】

  • DNAT

    目标地址转换。

  • REDIRECT

    在本机做端口映射。

  • LOG

    /var/log/messages 文件中记录日志信息,然后将数据包传递给下一条规则(除了记录以外不对数据包做任何其他操作,仍然让下一条规则去匹配)。

1.2 四表五链

overview.png

Figure 1: 链与表的分布

overview_update.png

Figure 2: iptables/netfilter 整体架构

通过以下命令设置主机支持转发功能:

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

2 应用场景 1

2.1 NAT

nat.png

Figure 3: 网络地址映射

使用 NAT 技术一定会发生两次 IP 地址的转换(下面以内网访问外网为例):

  1. 内部网络的报文发送出去时,报文的源 IP 会被修改,也就是源地址转换(SNAT)
  2. 外部网络的报文响应时,响应报文的目标 IP 会再次被修改,也就是目标地址转换(DNAT)

上述过程被称为 SNAT ,是因为先发生了 SNAT。如果先使用 DNAT (比如外网穿透内网的场景,下面会讲到),则整个过程被称为 DNAT 。

也就是说,NAT 属于 SNAT 还是 DNAT ,取决于整个过程的最先使用了 SNAT 还是 DNAT 。

2.1.1 SNAT

snat.png

Figure 4: SNAT 网络拓扑

只是配置 SNAT 的话,并不用手动配置 DNAT ,iptables 会自动维护 NAT 表,自动执行 DNAT 将响应报文的目标地址转换回来。

2.1.2 DNAT

dnat.png

Figure 5: DNAT 网络拓扑

只是配置 DNAT 的话,并不用手动配置 SNAT ,iptables 会自动维护 NAT 表,自动执行 SNAT 将响应报文的源地址转换回来。

2.1.3 本地端口转发

iptables -t nat -A PREROUTING -d 1.2.3.4 -p tcp --dport 80 -j REDIRECT --to-port 8080
# 若 8080 监听于 localhost,则可能需要执行:sysctl -w net.ipv4.conf.all.route_localnet=1

2.2 封堵端口

iptables -I INPUT -p tcp --dport <port> -j REJECT
iptables -I OUTPUT -p tcp --sport <port> -j REJECT

2.3 禁止 SYN floods

# Limit the number of incoming tcp connections
# Incoming syn-flood protection
iptables -N syn_flood
iptables -A INPUT -p tcp --syn -j syn_flood
iptables -A syn_flood -m limit --limit 1/s --limit-burst 3 -j RETURN
iptables -A syn_flood -j REJECT
# --limit 1/s: Maximum average matching rate in seconds
# --limit-burst 3: Maximum initial number of packets to match

2.4 限制连接数

iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 3 -j DROP # 超过 3 个连接则拒绝

2.5 防止 DoS

利用 recent 和 state 模块限制单个 IP 在 300 秒内只能与本机建立 3 个新连接,被限制 5 分钟周恢复访问。

iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 300 --hitcount 3 --name SSH -j DROP

# --name:     指定记录名称
# --set:      记录数据包的来源 IP,若已存在,则更新
# --update:   每次建立连接都要更新记录
# --seconds:  必须与 --rcheck 或 --update 同时使用
# --hitcount: 必须与 --rcheck 或 --update 同时使用

# 记录保存于:/proc/net/ipt_recent/SSH

2.6 LOG

for c in PREROUTING OUTPUT; do
    iptables -t nat -I $c -d <dest-ip> -j LOG --log-prefix "DBG@$c: " --log-level 4
    # log level: 0 - 7 [emerg,alert,crit,error,warning,notice,info,debug]
    # 4: standard syslog level (warning)
done

Footnotes:

Author: Hao Ruan (ruanhao1116@gmail.com)

Created: 2021-01-08 Fri 12:08

Updated: 2022-04-27 Wed 21:55

Emacs 27.2 (Org mode 9.4.4)