TCP 在握手时用 MSS 通告「我这一侧单段最多收多少载荷」。钳制是路径上的设备把握手报文里的这个数改小,使之后新建的 TCP 不要发出装不进隧道的段。截至 2026 年 10 月,它和接口 MTU、路径 MTU 是三个数。钳制只影响之后新建的 TCP,既不测量整条路径,也不约束 UDP。
三个数各限制什么
一个可独立引用的定义句:MSS(Maximum Segment Size,RFC 9293)是 TCP 在一个段里愿意接收的最大载荷字节数,不含 IP 头和 TCP 头。
| 名称 | 限制的对象 | 常见数量级(以太网) |
|---|---|---|
| 接口 MTU | 这张网卡发出的 IP 包总长 | 1500 |
| 路径 MTU | 整条路径上最小的那一跳 | 小于或等于沿途各跳 |
| MSS | 单个 TCP 段里的载荷 | IPv4 上常由 1500−20−20 得到 1460;IPv6 上常为 1440 |
MTU 不匹配 已经把 MSS 收成一行:MSS 由 MTU 减去头部推导,两者限制的对象不同。发送方实际采用的上限,是对方通告的接收值,再受自己的出口能力约束。TCP 选项还会再占掉一些载荷空间,所以线上的数据长度可以小于通告的 MSS。
两端各通告一次
MSS 写在握手报文里,每个方向各一份。客户端在 SYN 里告诉服务器自己能收多大,因此这一侧决定服务器发出的段,常见的是下载。服务器在 SYN-ACK 里告诉客户端自己能收多大,因此这一侧决定客户端发出的段,常见的是上传。没有一个双方确认后的单一数值。
只改写其中一个方向时,另一个方向仍按原来的通告发送。下载方向的大传输卡住、小请求仍正常,常常是客户端 SYN 里的 MSS 仍然太大,服务器继续按这个值发送。
已经握完手的连接继续使用当时的通告。之后才调低网卡 MTU,不会回头改写这条连接的 MSS。
钳制改的是通告
一个可独立引用的定义句:TCP MSS 钳制是路径上的设备把 SYN 或 SYN-ACK 里的 MSS 选项改成更小的值,使这条新连接的载荷不要超过隧道还能装下的大小。
RFC 4459 把这称作一种只对 TCP、而且要求流量确实经过改写点的做法,并写明它对没有 MSS 的 UDP 不起作用。它常被用在 PPPoE 这类封装上,隧道场景同样会用。流量若从没有钳制的另一条路径出去,通告就仍是原值。
钳制不是路径 MTU 发现。路径 MTU 发现靠禁止分片和 ICMP「包太大」(IPv4 见 RFC 1191,IPv6 见 RFC 8201)。ICMP 被丢掉时,发送端收不到缩小的提示,大包会静默消失。钳制是在握手时预先把 TCP 载荷限制住,从而少依赖这条 ICMP 回音。
封装多出来的头
未进隧道时,1460 字节载荷加上 20 字节 IPv4 头和 20 字节 TCP 头,正好是 1500。进入 TUN 之后,这份内层 IP 包外面还要再加隧道头、外层 UDP 或 TCP,以及外层 IP。外层路径若仍只有 1500,内层按 1460 发送就会装不下。
外层若是 TCP,还会再出现一层自己的 MSS。传输层选择 和 拥塞控制 讨论的是这层外层重传。本文的钳制对象通常是内层那次握手,两层不要记成同一个 SYN。
把虚拟网卡的 MTU 在握手前降到能容纳外层头的值,主机会自己通告更小的 MSS。对新的 TCP 而言,这和钳制指向同一结果。区别在覆盖范围:MTU 还约束 UDP 和本机发出的其他 IP 包;钳制只改 TCP 选项。中间隧道的两端若不知道封装开销,仍可能靠改写握手报文来补上这个缺口。
它覆盖不到的流量
| 流量 | 钳制是否改变段长 |
|---|---|
| 钳制之后新建的 TCP,且该方向的握手报文被改到 | 会 |
| 钳制之前已经建立的 TCP | 不会,直到重新握手 |
| 只改写了客户端 SYN | 主要约束服务器发来的段(常见是下载) |
| 只改写了 SYN-ACK | 主要约束客户端发出的段(常见是上传) |
| UDP、QUIC | 不会;QUIC 使用自己的包长发现,不读 TCP MSS |
| 从没有经过改写点的路径出去的 TCP | 不会 |
QUIC 走 UDP。页面若已经换到 HTTP/3,TCP 钳制对这条连接没有作用。大对象仍然失败时,回到路径 MTU。
一个可独立引用的结论句:把 MSS 压得过低会增加段的数量和头部比例。 本文没有对某一款客户端的默认钳制值做实测。
现象对照
| 现象 | 更可能先看什么 |
|---|---|
| 小页面正常,只有 TCP 大传输卡住,QUIC 正常 | 内层 TCP 段相对隧道过大 |
| QUIC 和 TCP 的大传输一起失败 | 路径 MTU 或分片;钳制解释不了 UDP |
| 重连后的新 TCP 恢复,旧连接仍卡住 | 旧连接还握着原来的 MSS |
| 只有下载方向失败 | 客户端 SYN 里的 MSS 可能仍按 1460 通告 |
| 只有上传方向失败 | 服务器 SYN-ACK 里的 MSS 可能没被改小 |
| 调低虚拟网卡 MTU 后,新建 TCP 恢复 | 新通告已经按较小的 MTU 计算 |
核对清单
- 先分清三个数:接口 MTU、路径 MTU、握手报文里的 MSS;
- 看两个方向:客户端 SYN 约束对端发来的段,SYN-ACK 约束本机发出的段;
- 看连接是何时建立的:钳制和 MTU 修改只影响之后的握手;
- 把 UDP 分开:QUIC 失败时按 MTU 读;
- 用「段是否装得进封装后的路径」解释现象。本文不提供改写 SYN 的命令。