Skip to content

iptables 四表五链 ​

iptables 是 Linux 内核级防火墙,通过规则链(Chain)对数据包进行过滤和处理,规则链按功能分组为规则表(Table)。

整体架构 ​

text
数据包进入
    │
    ▼
┌─────────────────────────────────────────┐
│              raw 表                      │
│  PREROUTING → OUTPUT                    │
├─────────────────────────────────────────┤
│            mangle 表                     │
│  PREROUTING → INPUT → FORWARD →        │
│  OUTPUT → POSTROUTING                  │
├─────────────────────────────────────────┤
│              nat 表                      │
│  PREROUTING → OUTPUT → POSTROUTING     │
├─────────────────────────────────────────┤
│            filter 表                     │
│  INPUT → FORWARD → OUTPUT              │
└─────────────────────────────────────────┘

💡 提示:数据包处理时,表的处理优先级为 raw → mangle → nat → filter。

五链(Five Chains) ​

五链对应数据包在内核协议栈中的五个挂载点,决定规则在什么时机被匹配。

链名触发时机数据包方向
PREROUTING路由判断之前刚进入网卡的数据包
INPUT路由判断后,发往本机目的地是本机的数据包
FORWARD路由判断后,转发经本机转发的数据包
OUTPUT本机进程发出本机产生的数据包
POSTROUTING路由判断之后,发出网卡即将离开网卡的数据包
text
           数据包进入
               │
          PREROUTING
               │
           路由判断
          ╱        ╲
     本机           转发
     │               │
   INPUT           FORWARD
     │               │
  本机进程            │
     │               │
   OUTPUT            │
     │               │
   路由判断           │
  ╱      ╲           │
本机    外发          │
│        │           │
│        ╲         ╱
│      POSTROUTING
│           │
│      数据包发出
│
└──→ 本地投递(不经过 POSTROUTING)

四表(Four Tables) ​

raw 表 ​

最高优先级表,主要用于关闭连接追踪(conntrack),提升性能。

  • 仅含 PREROUTING 和 OUTPUT 两条链
  • 核心目标:NOTRACK,标记数据包不走连接追踪
  • 适用场景:高流量服务无需追踪连接状态时

Docker 用例:Docker 默认不对容器间通信做连接追踪,可在 raw 表设置 NOTRACK 减少开销:

bash
# 对容器间通信关闭连接追踪,提升性能
iptables -t raw -A PREROUTING -s 172.17.0.0/16 -d 172.17.0.0/16 -j NOTRACK
iptables -t raw -A OUTPUT -s 172.17.0.0/16 -d 172.17.0.0/16 -j NOTRACK

mangle 表 ​

用于修改数据包的元信息(TOS、TTL、Mark 等),不负责过滤或地址转换。

  • 包含全部五条链:PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING
  • 核心目标:TOS、TTL、MARK、SECMARK 等
  • 适用场景:QoS 策略标记、路由策略、TTL 修改

Docker 用例:Docker 使用 mangle 表的 MARK 目标为数据包打标记,配合策略路由实现容器流量走特定网络路径:

bash
# 为来自 Docker 容器的数据包打标记
iptables -t mangle -A PREROUTING -s 172.17.0.0/16 -j MARK --set-mark 1

# 配合策略路由,让标记为 1 的包走特定路由表
ip rule add fwmark 1 table 100
ip route add default via 10.0.0.1 table 100

nat 表 ​

用于网络地址转换(NAT),修改数据包的源地址或目的地址。

  • 仅含 PREROUTING、OUTPUT、POSTROUTING 三条链
  • 核心目标:SNAT、DNAT、MASQUERADE、REDIRECT
  • PREROUTING:DNAT(目的地址转换),用于端口映射/端口转发
  • POSTROUTING:SNAT(源地址转换),用于让内网访问外网
  • OUTPUT:对本机发出的包做 DNAT

Docker 用例:Docker 大量使用 nat 表实现容器网络通信:

bash
# Docker 容器访问外网:源地址转换(SNAT/MASQUERADE)
# 将容器源 IP 172.17.0.2 转换为宿主机 IP
iptables -t nat -A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE

# Docker 端口映射:目的地址转换(DNAT)
# 将宿主机 8080 端口转发到容器 172.17.0.2:80
iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 172.17.0.2:80

💡 提示:执行 docker run -p 8080:80 nginx 时,Docker 自动在 nat 表的 PREROUTING 链添加 DNAT 规则,在 POSTROUTING 链添加 MASQUERADE 规则。

filter 表 ​

默认表,用于过滤数据包,决定是否放行。

  • 仅含 INPUT、FORWARD、OUTPUT 三条链
  • 核心目标:ACCEPT、DROP、REJECT
  • INPUT:过滤进入本机的包
  • FORWARD:过滤经本机转发的包
  • OUTPUT:过滤本机发出的包

Docker 用例:Docker 使用 filter 表控制容器网络访问:

bash
# Docker 默认允许 FORWARD 链中 docker0 接口的流量转发
iptables -A FORWARD -i docker0 -j ACCEPT
iptables -A FORWARD -o docker0 -j ACCEPT

# 限制某容器不可访问外网
iptables -A FORWARD -s 172.17.0.3 -o eth0 -j DROP

# 允许外部访问容器暴露的端口
iptables -A INPUT -p tcp --dport 8080 -j ACCEPT

💡 提示:Docker 启动时会设置 filter 表 FORWARD 链的默认策略为 DROP,然后逐条添加允许规则,这就是为什么 Docker 容器网络正常工作而手动配置的桥接网络可能不通的原因。

四表对比 ​

表名优先级包含的链核心功能主要目标
raw1(最高)PREROUTING, OUTPUT关闭连接追踪NOTRACK
mangle2全部五链修改包元信息MARK, TOS, TTL
nat3PREROUTING, OUTPUT, POSTROUTING地址转换SNAT, DNAT, MASQUERADE
filter4(最低)INPUT, FORWARD, OUTPUT包过滤ACCEPT, DROP, REJECT

数据包处理流程 ​

以 Docker 容器访问外网为例,完整流程如下:

text
容器 172.17.0.2 → 外部服务器
    │
    ▼
[PREROUTING]  raw → mangle → nat(DNAT)
    │
    ▼
  路由判断(目标是外网,需转发)
    │
    ▼
[FORWARD]  mangle → filter
    │
    ▼
[POSTROUTING]  mangle → nat(SNAT/MASQUERADE)
    │
    ▼
  宿主机物理网卡发出

以外部访问 Docker 容器端口为例:

text
外部客户端 → 宿主机:8080 → 容器:80
    │
    ▼
[PREROUTING]  raw → mangle → nat(DNAT: 8080→172.17.0.2:80)
    │
    ▼
  路由判断(目标是容器,需转发)
    │
    ▼
[FORWARD]  mangle → filter(ACCEPT)
    │
    ▼
[POSTROUTING]  mangle → nat
    │
    ▼
  docker0 网桥 → 容器

常用命令 ​

bash
# 查看所有规则(默认 filter 表)
iptables -L -n -v

# 查看指定表
iptables -t nat -L -n -v
iptables -t mangle -L -n -v
iptables -t raw -L -n -v

# 查看 Docker 设置的 NAT 规则
iptables -t nat -L DOCKER -n -v

# 添加规则
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT

# 删除规则
iptables -D INPUT -p tcp --dport 80 -j ACCEPT
iptables -t nat -D PREROUTING 1

# 保存规则(CentOS)
iptables-save > /etc/sysconfig/iptables

# 恢复规则
iptables-restore < /etc/sysconfig/iptables

💡 提示:使用 iptables-save 和 iptables-restore 可以完整导出/导入所有表的所有规则,排查 Docker 网络问题时建议先用 iptables-save 查看完整规则。