VPN 的原理是「把整个包再装进一个新包里」,每套一层就加一层头。 一层层扣下来,MTU 从 1500 掉到 1360——这就是「在家连公司内网打不开系统」的根源。
3.5.4 讲 PPPoE 时扣掉过 8 个字节,VPN 是同一件事的更狠版本。 这一节把「层层封装」的账一次算清,以后遇到 MTU 问题就有章法。
一、一层层加起来
IPsec 隧道模式下,一个包外面要套这些东西:
| 部分 | 字节 | 作用 |
|---|---|---|
| 外层 IP 头 | 20 | 隧道两端地址 |
| ESP 头 | 8 | 安全参数索引、序号 |
| IV 加密向量 | 8 到 16 | AES-CBC 要 16,GCM 只要 8 |
| 内层 IP 头 | 20 | 原始包的 |
| ESP 尾 | 2 到 11 | 块对齐用的填充 |
| ICV 校验 | 12 到 16 | SHA-1 是 12,SHA-256 是 16 |
加起来最少 50、最多 91 字节: 所以「IPsec 隧道的典型 MTU 是 1400」这个数,是留了余量之后的经验值。 「IV 是 8 到 16」这一行说明一件事:同样的加密强度,不同的工作模式开销不同。 GCM 是「认证加密一体」,所以向量只要 8 字节;CBC 要单独做完整性校验,向量就要 16。 选算法的时候,这个差别会直接影响 MTU。
二、MTU 一路缩下来
每过一层隧道,能装的数据就少一截:
| 链路 | MTU | TCP 的 MSS |
|---|---|---|
| 以太网 | 1500 | 1460 |
| PPPoE | 1492 | 1452 |
| IPsec | 1400 | 1360 |
| GRE over IPsec | 1376 | 1336 |
| PPPoE+GRE+IPsec | 1360 | 1320 |
最后一行的 1360 是「最坏情况」的常见配置: 家庭宽带(PPPoE)里再连公司 VPN(GRE + IPsec),一层层扣下来就剩这么多。 所以「在家连公司内网,某些系统就是打不开」的老问题,根源全在这张表里。 第三列是「MSS」,等于 MTU 减 40(20 字节 IP 头加 20 字节 TCP 头)。 这两个数是联动的:MTU 变,MSS 跟着变。 而「谁来决定 MSS」是有讲究的: TCP 建连时会协商 MSS,但如果中间有个隧道把它压小了而两端不知道,就会出问题。 所以工程上有一种做法叫「MSS 钳制」:在隧道口把 MSS 改小,主动通知两端「别发那么大」。
三、小包能过、大包过不去
这个故障有个很讨厌的特点:症状是「部分能用」:
| 操作 | 包大小 | 结果 |
|---|---|---|
| ping | 小包 | 通 |
| 网页首页 | 小包 | 能开 |
| 传文件/登录 | 大包 | 卡死 |
第一行通、第三行不通,人就会怀疑「是不是服务器挂了」——
其实服务器好好的,是「大包被丢在了路上」。
机制是这样的:包超过路径 MTU 时,要么被分片,要么被丢弃并回一个「需要分片」的 ICMP。
而很多防火墙把 ICMP 全屏蔽了,
于是发送方永远收不到「你发太大了」这个通知,就一直重发、一直失败。
这叫「PMTU 黑洞」,是 VPN 排障里最常见的坑。
排障办法很土但有效:用「不分片」的 ping 一点点加大包长,试到不通为止,
那个值加上 28(IP 头 20 加 ICMP 头 8)就是路径 MTU。
在 Windows 上就是 ping -f -l 1400 目标——这个命令值得背下来,它比任何图形工具都快。
四、动手 Demo:VPN 每套一层,就少一截 MTU
把 IPsec 的六段头加起来,再把五条链路的 MTU 与 MSS 一起算出来。 注意最后一行:PPPoE 加 GRE 加 IPsec,只剩 1360。
lo = 20 + 8 + 8 + 2 + 12
hi = 20 + 8 + 16 + 20 + 11 + 16
print('IPsec 一层:最少 %d 字节,最多 %d 字节' % (lo, hi))
for name, mtu in (('以太网', 1500), ('PPPoE', 1492), ('IPsec', 1400),
('GRE over IPsec', 1376), ('PPPoE+GRE+IPsec', 1360)):
print('%-16s MTU %4d MSS %4d' % (name, mtu, mtu - 40))
实跑输出:
--------------------------------------------------------------------
VPN 每套一层,就少一截 MTU
--------------------------------------------------------------------
**VPN 的原理是「把整个包再装进一个新包里」。**
**每套一层就要加一层头,于是「能装的数据」又少一截**——这和 PPPoE 那 8 个字节是同一回事,
只是这次更狠。
部分 字节 说明
--------------------------------------------------------------------------
外层 IP 头 20 隧道两端的地址
ESP 头 8 SPI + 序号
**IV(加密向量)** **8~16** **AES-CBC 需要,GCM 只要 8**
内层 IP 头 20 原始包的
ESP 尾(填充 + 下一头) 2~11 **块对齐用的填充**
**ICV(完整性校验)** **12~16** **SHA-1 是 12,SHA-256 是 16**
**加起来最少 50、最多 91 字节**:
**所以「IPsec 隧道的典型 MTU 是 1400」这个数,是留了余量之后的经验值。**
链路 MTU TCP 的 MSS
--------------------------------------------
以太网 1500 1460
PPPoE 1492 1452
IPsec 1400 1360
GRE over IPsec 1376 1336
PPPoE + GRE + IPsec 1360 1320
**最后一行的 1360 是「最坏情况」的常见配置**:
**家庭宽带(PPPoE)里再连公司 VPN(GRE + IPsec),一层层扣下来就剩这么多。**
**所以「在家连公司内网,某些系统就是打不开」的老问题,根源全在这张表里。**
**而且这个问题有个讨厌的特点**:
**小包(ping)能过,大包(网页、文件)过不去**——**因为分片就发生在「超过 MTU」的那一刻。**
**排障办法是「ping 大包 + 不分片」,逐步试到不通为止,那个值就是路径 MTU。**
「最少 50」这个数是这么来的:外层 IP 20、ESP 头 8、IV 8、ESP 尾 2、ICV 12,合计 50。 它不含「内层 IP 头」,因为那 20 字节是你原本就要付的。 而「最多 91」把内层也算进去了, 所以这两个数严格说不是同一口径,看厂商文档时要注意它算的是哪一层。 为什么 MTU 取 1400 而不是 1450:因为「取整」比「取紧」好维护。 1400 减 40 得 1360,是个好记的数;而 1450 在某些算法组合下会不够用(IV 和 ICV 都可能变大)。 工程上「留一点余量」几乎总是对的——因为出了问题的排查成本,远高于那 50 字节的带宽。 还有一个更彻底的解法:MSS 钳制。 在隧道路由器上把所有经过的 TCP SYN 里的 MSS 改成「MTU 减 40」, 这样两端一开始就按小包发,永远不会触发分片。 代价是「所有连接都要改 SYN」,路由器要处理每一个连接建立—— 所以它一般只在接入侧开,不在骨干上开。
30 秒实验
- 算一下:MTU 1360 时,传一个 100 KB 的文件最少要多少个包?
- 想一下:为什么防火墙屏蔽 ICMP 会导致「PMTU 黑洞」?
- 在你电脑上试一次
ping -f -l 1400加一个常用网站,看能不能通。
常见误区
- 以为「VPN 连上就应该全通」。 MTU 不够时会「部分通」,小包过、大包丢。
- 以为「MTU 是端到端协商出来的」。 实际靠 ICMP 通知,ICMP 被屏蔽就协商不了。
- 以为「隧道越多越安全」。 每多一层就少一截 MTU,超过某个点就要靠分片,性能反而更差。
自测三问(点开对答案)
1. IPsec 一层最少吃掉多少字节? —— **约 50 字节**(外层 IP 20、ESP 头 8、IV 8、ESP 尾 2、ICV 12)。 2. MSS 和 MTU 什么关系? —— **MSS 等于 MTU 减 40**,减掉的是 20 字节 IP 头和 20 字节 TCP 头。 3. 「PMTU 黑洞」是什么? —— **包太大被丢,但「需要分片」的 ICMP 被防火墙挡了**,发送方一直重发、一直失败。下一节看公共无线 LAN:为什么咖啡馆的 WiFi 总是慢。
- ☐ (本节完,下一节 3.7.8 公共无线LAN)