Appearance
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 NOTRACKmangle 表
用于修改数据包的元信息(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 100nat 表
用于网络地址转换(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 容器网络正常工作而手动配置的桥接网络可能不通的原因。
四表对比
| 表名 | 优先级 | 包含的链 | 核心功能 | 主要目标 |
|---|---|---|---|---|
| raw | 1(最高) | PREROUTING, OUTPUT | 关闭连接追踪 | NOTRACK |
| mangle | 2 | 全部五链 | 修改包元信息 | MARK, TOS, TTL |
| nat | 3 | PREROUTING, OUTPUT, POSTROUTING | 地址转换 | SNAT, DNAT, MASQUERADE |
| filter | 4(最低) | 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查看完整规则。