Docker端口映射本质是nat表中PREROUTING、OUTPUT、DOCKER和POSTROUTING四链协同的DNAT/SNAT转换:PREROUTING捕获入站流量并跳转DOCKER链,OUTPUT处理本机发起请求,DOCKER链执行具体DNAT至容器IP:端口,POSTROUTING对响应包做SNAT确保回程可达。

要深度审计 Docker 容器端口映射背后的 NAT 转换行为,核心是理清 iptables 中 nat 表各链的协作逻辑,并逐层验证规则是否生效、路径是否完整、流量是否被正确重写。这不是单纯“看规则”,而是结合容器网络拓扑、数据包流向与状态跟踪机制做闭环验证。
定位并解析关键 nat 表链路
Docker 端口映射依赖 nat 表中四条链协同工作,缺一不可:
-
PREROUTING:捕获所有入站流量(含外部访问宿主机端口的请求),执行 DNAT(目的地址转换),把
host_ip:host_port改写为container_ip:container_port - OUTPUT:处理宿主机自身发起的、目标为映射端口的请求(如 curl localhost:8080),同样需 DNAT,否则会走本地回环而非容器网络
-
DOCKER:Docker 自建的自定义链,位于 PREROUTING 和 OUTPUT 的跳转目标处,存放具体容器级 DNAT 规则,例如:
-j DNAT --to-destination 172.17.0.2:80 - POSTROUTING:对从容器发出的响应包做 SNAT/MASQUERADE,将源 IP 替换为宿主机 IP,确保返回路径可达
逐链检查规则有效性与顺序
使用带详细选项的命令查看每条链的实际规则及匹配计数,重点关注 pkts 和 bytes 是否随测试流量增长:
- 查 PREROUTING:`iptables -t nat -L PREROUTING -n --line-numbers`,确认有指向 DOCKER 链的规则(如
-j DOCKER)且位置靠前 - 查 DOCKER 链:`iptables -t nat -L DOCKER -n --line-numbers`,核对 DNAT 目标 IP 是否与
docker inspect 容器名 | jq '.NetworkSettings.IPAddress'一致 - 查 OUTPUT:`iptables -t nat -L OUTPUT -n --line-numbers`,确认存在针对本机发往映射端口的 DNAT 规则(常被忽略但影响 curl 测试)
- 查 POSTROUTING:`iptables -t nat -L POSTROUTING -n --line-numbers`,确认存在 MASQUERADE 或 SNAT 规则,作用于容器子网(如
172.17.0.0/16)
验证数据包实际流转路径
仅看规则不够,要确认流量真实经过这些链:
- 启用 iptables 日志:在 PREROUTING 和 DOCKER 链中插入 LOG 规则(如
-j LOG --log-prefix "DOCKER-DNAT: "),再用dmesg -w实时观察日志输出 - 用
tcpdump抓包比对:在宿主机 eth0 抓外部请求,在 docker0 抓转发后流量,确认目的 IP 和端口已变更 - 检查 conntrack 状态:运行
conntrack -L | grep :宿主机端口,应看到 ESTABLISHED 状态且原始目的 IP 已替换为容器 IP
排查常见断裂点
审计失败往往源于以下隐性断点:
- ip_forward 未开启:`sysctl net.ipv4.ip_forward` 必须返回 1;否则 FORWARD 链不生效,容器无法收发跨网段流量
- filter 表拦截:即使 nat 表完成 DNAT,若 filter 表 INPUT 或 FORWARD 链默认策略为 DROP,且无 ACCEPT 规则放行容器 IP 或 docker0 接口,连接仍被拒绝
-
DOCKER 链缺失或顺序错位:某些手动添加规则可能插在 DOCKER 链之前,导致跳转未触发;可用
iptables -t nat -S查看原始规则顺序 - 容器防火墙干扰:容器内若运行 iptables 或 ufw,可能丢弃已 DNAT 的包;建议容器内禁用防火墙或显式放行目标端口


















