MSS 收敛是怎么发生的
MSS 是 TCP 声明的单个报文段能承载的最大数据量,由两端在握手时通过选项互相告知。隧道、PPPoE 这类封装会额外占用字节,使实际可用载荷小于端到端路径能通过的尺寸,于是出口设备常主动把 MSS 改小(MSS clamping)。抓包对比改写前后的握手选项,就能确认策略是否真的落地,而不是只在配置里写了。
基本信息
| 抓包字段 | tcp.options.mss_val,过滤表达式为 tcp.options.mss |
|---|---|
| 出现位置 | SYN 与 SYN-ACK 中各出现一次,方向不同值可能不同 |
| 验证方法 | 在改写设备前后各抓一份,对比同一连接的 MSS 值 |
| 合理取值 | 按封装开销核算,常见是在标准值基础上减去封装头长度 |
| 影响范围 | 只作用于 TCP;UDP 大包问题需按路径 MTU 单独处理 |
| 关注重点 | 两端与路径各段口径是否一致,避免大包进入后被丢弃 |
典型使用场景
- 隧道接入验证:确认 VPN 或 GRE 出口确实改写了 MSS,避免大包被静默丢弃
- 上线核对:新链路启用后对比两端 MSS,确认改写方向与数值符合设计
- 故障复现:确认小包正常、大包失败的场景是否与 MSS 未被收敛有关
- 策略回归:变更防火墙或负载均衡配置后,验证是否又引入了新的改写
- 跨厂商对接:不同厂商对 MSS 的处理策略不同,用抓包对齐双方实际行为
对比与核对
对比与核对
# 改写设备前(发端)看到的 MSS
tshark -r before.pcap -Y 'tcp.flags.syn == 1 && tcp.flags.ack == 0' -T fields -e ip.src -e tcp.options.mss_val
# 改写设备后(隧道出口或对端)看到的同一个 SYN
tshark -r after.pcap -Y 'tcp.flags.syn == 1 && tcp.flags.ack == 0' -T fields -e ip.src -e tcp.options.mss_val
# 两侧数值不同即为存在改写, 结合拓扑确认是哪台设备做的
# 顺带核对 SYN-ACK 中服务端声明的 MSS 是否也被改写
tshark -r after.pcap -Y 'tcp.flags.syn == 1 && tcp.flags.ack == 1' -T fields -e ip.src -e tcp.options.mss_valMSS 取值参考
| 场景 | 常见 MSS 量级 | 说明 |
|---|---|---|
| 标准以太网 | 1460 左右 | 1500 减去 IP 与 TCP 头长度 |
| PPPoE 接入 | 1452 左右 | 接入层额外封装导致的缩减 |
| IP 隧道封装 | 按开销核算,常见 1400 上下 | 封装头越长, 可用载荷越小 |
| 仅 IP 头带选项 | 比标准值再小若干字节 | 选项占用也计入头部长度 |
| 两端不一致 | SYN 与 SYN-ACK 数值不同 | 方向不同属正常, 需按方向分别核对 |
MSS 只约束 TCP,而且只约束对端发送的报文段尺寸;UDP 或 ICMP 大包被丢弃属于路径 MTU 问题,改 MSS 不会有任何效果。
改写方向写错时,会出现一端声明的 MSS 很小而另一端很大的情况,表面看连接正常,实际大包仍会在路径上被丢弃;对照时按每一段逐项核对,而不是只看最终值。