隧道就是「把整个包塞进另一个包里」:外层的头负责过路,里层的头原样保留。 代价是每包扣掉一层头,所以隧道入口必须把 MSS 调小,否则大包会默默消失。
5.6.5 的 TURN 中转,底层就是一条隧道,这一节把它单独讲清楚。 4.5.3 的 PMTU 黑洞在隧道里最容易出现,这一节说明为什么。
一、隧道就是套娃
「隧道」这个词很形象:内层的包不知道自己在隧道里,外层的网络也不知道里面装了什么。 规则只有三条:
| 规则 | 含义 | 结果 |
|---|---|---|
| 两端要有端点 | 一头装包、一头拆包 | 端点必须是隧道设备 |
| 中间只看外层 | 内层地址对外不可见 | 内层可以用私有地址 |
| 内层原样保留 | 不改内容、不改头 | 端到端语义不变 |
第二行是隧道的最大好处:内层地址是私有地址也没关系, 因为公网上跑的只是外层那个公网地址。 VPN 能工作,全靠这一条。 第三行是隧道和 NAT 的根本区别: NAT 改内层,隧道不改内层——所以隧道不会破坏端到端,NAT 会。
二、四种典型用途
隧道不是一种协议,是一类做法,用在哪都长得差不多:
| 场景 | 隧道做什么 | 典型协议 |
|---|---|---|
| v6 过渡 | v6 包走 v4 网络 | 6in4、Teredo |
| VPN | 私网包走公网 | IPsec、GRE、WireGuard |
| 多协议承载 | 非 IP 协议走 IP | GRE 里的 IPX |
| 移动 IP | 家乡代理转给外地 | 5.8.5 的三角路由 |
第一行是「过渡期」的用法:两个孤立的 v6 小岛之间,靠一条 v4 隧道连起来。 它的局限是「只能连点,不能连面」——中间那些 v4 路由器始终看不见 v6。 第二行是今天最常见的用法: 员工在家里连公司内网,本质上就是「笔记本发出的包被塞进一个公网包里」。 第四行是「为了让地址不变」而做的隧道,代价我们放到 5.8.5 算。
三、开销要一层一层扣
每套一层就多一个头,从 1500 里直接扣:
| 封装方式 | 额外头(字节) | 剩下给数据的 MTU |
|---|---|---|
| IPv4-in-IPv4 | 20 | 1480 |
| GRE | 24 | 1476 |
| IPsec 传输模式 | 约 50 | 1450 |
| IPsec 隧道模式 | 约 70 | 1430 |
| 6in4 | 20 | 1480 |
注意 IPsec 那两行差别很大:传输模式只保护载荷,隧道模式还要再套一个 IP 头, 所以多付 20 字节。 VPN 里常见的是隧道模式,因为它要连「两个网段」,不只是「两台主机」。 套多层就多扣几次:四层 IPv4 隧道是 80 字节,MTU 从 1500 掉到 1420, 再扣 IP 和 TCP 头 40 字节,MSS 只剩 1380。 所以「隧道入口把 MSS 钳到 1380」是 VPN 配置里最常见的动作。
四、隧道为什么难排查
典型症状是「小包通、大包不通」:ping 得通(默认 32 字节),但网页打不开、SSH 登录卡住。 原因是一连串的误会:内层以为自己能发 1500,外层实际只能过 1420, 而中间设备「过不去就丢」,还不告诉你。 如果内层还设了 DF(不许分片),那就连分片的机会都没有,直接黑洞。 这种「丢包没有任何回音」的情况就是黑洞:4.5.3 讲的 PMTU 黑洞,在隧道场景里发生率高得多, 因为隧道让「路径 MTU」变得比链路 MTU 小,而很多系统只按链路算。 三个对策,从糙到细:一是直接把隧道口的 MTU 配小(最省事,浪费一点); 二是钳 MSS(让 TCP 自己不发大包,最常用); 三是开 PLPMTUD(靠探测自己找上限,最优雅但要看支持)。
五、动手 Demo:隧道要吃掉多少字节
从 1500 里逐层扣,看还剩多少给数据。 最后一行是「套四层」的极端情况。
def usable(base, overhead):
return base - overhead
for name, oh in (('IPv4-in-IPv4', 20), ('GRE', 24),
('IPsec 传输', 50), ('IPsec 隧道', 70),
('6in4', 20)):
print('%-14s %2d %d' % (name, oh, usable(1500, oh)))
print('四层 20 字节头 ->', 1500 - 20 * 4)
实跑输出:
--------------------------------------------------------------------
隧道要吃掉多少字节
--------------------------------------------------------------------
**隧道的本质是「把整个包塞进另一个包里」**:**外面那层头就是「过路费」,从可用空间里扣。**
封装方式 额外头(字节) 剩下给数据的 MTU
--------------------------------------------------------------
**IPv4-in-IPv4** **20** **1480**
**GRE** **24** **1476**
**IPsec(传输模式)** **约 50** **1450**
**IPsec(隧道模式)** **约 70** **1430**
**6in4** **20** **1480**
**第二列是「每包都要付的税」,第三列是「付完之后还剩多少」。**
**注意这还只是一层**——**如果套两层,就再扣一次。**
**算一下四层隧道会怎样**:
**80 字节的头,MTU 从 1500 掉到 1420。**
**这时如果还按 1500 发,包就会被丢**——**因为中间设备过不去。**
**所以要「在隧道入口把 MSS 钳小」**,这是 VPN 配置里最常见的动作。
**隧道带来的不只是开销,还有「故障更难查」**:**ping 大包不通、小包通**,
**而路径上的设备只会「默默丢」**——**这就是 4.5.3 讲的 PMTU 黑洞在隧道场景的高发原因。**
1420 这个数要记住:它意味着「四层隧道之后,一个 1500 字节的包必须被拆成两个」。
而如果内层还按 1500 发,包就会在隧道的某一跳被丢掉。
所以「隧道里 ping 大包不通」不是玄学:
ping 用 -l 1472 能过(1472 加 28 字节头正好 1500),但进了隧道就过不去,
因为隧道只肯给 1420 的 MTU。
这个实验在排查 VPN 时最有用。
最后一个提醒:隧道的开销是「每包」的,不是「每连接」的:
所以它对小包业务(语音、游戏)的相对损失更大——
一个 100 字节的语音包,多 70 字节头,等于多花 70% 的带宽。
这也是「VPN 里语音质量差」的一个常被忽略的原因。
30 秒实验
- 算一下:IPsec 隧道模式 + GRE 两层,MSS 还剩多少?
- 想一下:为什么隧道能承载私有地址,NAT 却要改地址?
- 想一下:为什么「隧道里 ping 大包不通」比普通链路更容易出现?
常见误区
- 以为「隧道是一种协议」。 它是一类做法,IPsec、GRE、6in4 都是它的具体实现。
- 以为「隧道不影响性能只是慢一点」。 它每包扣头,小包业务的相对损失更大。
- 以为「隧道和 NAT 差不多,都是改包」。 隧道不改内层, NAT 改内层——这是端到端能不能保住的差别。
自测三问(点开对答案)
1. 隧道和 NAT 最本质的区别是什么? —— **隧道不改内层的头和地址**,只是外面套一层;**NAT 改内层的地址端口**,所以破坏端到端。 2. 四层 20 字节的隧道,MTU 变成多少? —— **1500 减 80 等于 1420**,再扣 IP 和 TCP 头 40 字节,MSS 只剩 1380。 3. 隧道里为什么要钳 MSS? —— **因为内层以为能发 1500,而隧道只能过 1420**,大包会被中间设备静默丢掉,症状是「小包通、 大包不通」。下一节进入第五章最后一组:多播、任播、QoS、ECN 和 Mobile IP。
- ☐ (本节完,下一节 5.8.1 IP多播相关技术)