docker和mss
下面给出一个较为完整的裸 Docker 网络中,结合 iptables(mangle 表)以及路由转发流程的图示,涵盖了外部流量进入、容器间通信以及容器出站的全部流程。下图以外部服务器到容器为例,同时标注了各个 iptables 链和路由的转发路径。你可以根据下面图示理解数据包如何在 Docker 网络中经过 NAT、mangle 链以及路由表的处理。
1. 外部服务器 → Docker 容器(入站流量)的 iptables 和路由流程
[外部服务器]
│
│ (数据包进入宿主机外网接口,例如 eth0)
│
▼
┌─────────────────┐
│ PREROUTING │ <---(mangle 表:修改 TOS、TTL、MSS 等;DNAT也可在nat表中处理)
│ (mangle/ │
│ nat) │
└─────────────────┘
│
│ 经过 DNAT(目的地址转换:将外部目的地址改为目标容器 IP)
│
▼
┌─────────────────┐
│ FORWARD │ <---(mangle 表:调整 MSS、其他包标记;filter 表:防火墙规则检查)
│ (mangle/ │
│ filter) │
└─────────────────┘
│
│ 路由查表,确定出接口为 docker bridge(通常是 docker0 或 veth 组合)
│
▼
┌─────────────────────────┐
│ veth → 桥接(bridge) │ <---(容器内部虚拟接口,承载容器通信)
└─────────────────────────┘
│
▼
[Docker 容器]
说明
数据包在进入宿主机时首先由 PREROUTING 链处理,此时 NAT(DNAT)将外部目的地址转换为容器 IP;同时 mangle 表可以对包进行 MSS 调整、标记等处理。
经过 PREROUTING 后,数据包进入 FORWARD 链,此处完成进一步的包处理(例如 TCPMSS 调整,确保经过 Docker 桥接后数据包大小符合 MTU 限制)。
路由模块查找路由表,根据转换后的目标 IP 将数据包送入 docker bridge(veth 对),到达容器网络命名空间。
2. Docker 容器 → 外部服务器(出站流量)的 iptables 和路由流程
[Docker 容器]
│
│ 数据包通过容器内 veth 发出
▼
┌─────────────────────────┐
│ veth → 桥接(bridge) │ <---(容器到宿主机)
└─────────────────────────┘
│
│ 数据包经过宿主机 FORWARD 链(mangle/filter),检查允许转发
▼
┌─────────────────┐
│ FORWARD │ <---(在 mangle 表中,TCP MSS规则生效)
│ (mangle/filter)│
└─────────────────┘
│
│ 路由查表,确定下一跳为宿主机外网接口(例如 eth0)
▼
┌─────────────────┐
│ POSTROUTING │ <---(mangle 表 / nat表,进行 SNAT ,同时 TCPMSS 调整)
│ (mangle/nat) │
└─────────────────┘
│
│ 经过 SNAT(源地址转换为宿主机外网IP)
▼
[外部服务器]
说明
容器内部发出的数据包通过 veth / docker bridge 到达宿主机,进入 FORWARD 链(同时如果容器本地数据包从宿主机发出则走 OUTPUT 链,但这里以转发出的流量为主)。
在 POSTROUTING 链上,会进行 SNAT(把源地址改为宿主机外网地址),同时可通过 mangle 表中的 TCPMSS 规则(如
--clamp-mss-to-pmtu)调整 TCP 数据包的 MSS,确保不会超过实际路径 MTU,避免因 VXLAN 或其它封装导致包过大而丢包或碎片化。最后路由表确定后,数据包发送至外部服务器。iptables -t mangle -A FORWARD -o eth0 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
3. 重点:为什么在 POSTROUTING 链上加 TCPMSS 调整
-
场景背景:
在 Docker 网络中,出站流量(以及跨节点的情况,如使用 VXLAN、Flannel 等隧道技术)容易遇到 MTU 不匹配问题。隧道封装会增加额外的报头(例如 VXLAN 通常增加约 50 字节),如果数据包尺寸超过物理链路的 MTU,会导致需要碎片化甚至丢包。 -
POSTROUTING 链的优势:
在数据包离开宿主机前,所有修改已经完成,选择在此阶段进行 TCP MSS 调整可以确保最终发出的 TCP SYN 包中的 MSS 值已经根据实际路径的 MTU(PMTU)进行了限制。
使用如下规则:iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN \ -j TCPMSS --clamp-mss-to-pmtu此规则会自动将 TCP MSS 限制为当前出接口的 MTU 减去 IP/TCP 头部,从而避免由于隧道封装等原因导致的数据包过大。
-
总结:
在 POSTROUTING 阶段调 MSS,确保:-
数据包经过所有 NAT 修改后,出接口仍然符合物理链路 MTU 限制;
-
隧道技术(如 VXLAN)带来的额外头部被考虑在内;
-
整个出站流程中,TCP连接的建立不会因 MSS 设置不当而引起后续数据包传输失败。
-
4. 参考完整的裸 Docker 网络流程(包含 iptables 链和路由查找)
┌─────────────────────────────┐
│ 外部服务器 │
└─────────────▲───────────────┘
│
(入站数据包通过宿主机外网接口)
│
│
┌───────▼────────┐
│ PREROUTING │
│ (mangle / nat) │
└───────▼────────┘
│ DNAT(目的地址转换)
│
┌───────▼────────┐
│ FORWARD │
│ (mangle/filter)│
└───────▼────────┘
│
┌───────▼────────┐
│ veth → 桥接 │
│ (docker0) │
└───────▼────────┘
│
┌───────▼────────┐
│ Docker容器 │
└────────────────┘
│
(容器出站→经过docker0/veth→进入宿主机网络)
│
┌───────▼────────┐
│ FORWARD │
│ (mangle/filter)│
└───────▼────────┘
│ 路由查表:选择宿主机外网接口
┌───────▼────────┐
│ POSTROUTING │
│ (mangle/nat) │
│ (SNAT & TCPMSS)│
└───────▼────────┘
│
┌───────▼────────┐
│ 宿主机外网接口│
└───────▼────────┘
│
┌─────────────▼───────────────┐
│ 外部服务器 │
└─────────────────────────────┘
说明:
图中展示的流程涵盖了数据包从外部进入到 Docker 容器,以及容器出站到外部的全流程。
在 PREROUTING 阶段进行 DNAT,以确保外部数据包能找到目标容器。
FORWARD 阶段处理转发规则和包过滤。
POSTROUTING 阶段不仅负责 SNAT(将容器源地址改为宿主机的外网地址),还在 mangle 表中通过 TCPMSS 规则确保数据包 MSS 限制,防止因 MTU 问题产生碎片或丢包。
该流程图详细说明了裸 Docker 网络中 iptables(mangle/nat/filter表)与宿主机路由表配合,确保数据包在进入、转发、离开宿主机时均满足网络的 MTU 和安全要求。如果有其它细节需求,可以进一步展开讨论。
浙公网安备 33010602011771号