📚 第五章 IP协议相关技术
📄 一句话概括

隧道就是「把整个包塞进另一个包里」:外层的头负责过路,里层的头原样保留。 代价是每包扣掉一层头,所以隧道入口必须把 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 秒实验

  1. 算一下:IPsec 隧道模式 + GRE 两层,MSS 还剩多少?
  2. 想一下:为什么隧道能承载私有地址,NAT 却要改地址?
  3. 想一下:为什么「隧道里 ping 大包不通」比普通链路更容易出现?

常见误区

  1. 以为「隧道是一种协议」。 它是一类做法,IPsec、GRE、6in4 都是它的具体实现。
  2. 以为「隧道不影响性能只是慢一点」。 它每包扣头,小包业务的相对损失更大。
  3. 以为「隧道和 NAT 差不多,都是改包」。 隧道不改内层, NAT 改内层——这是端到端能不能保住的差别。
自测三问(点开对答案) 1. 隧道和 NAT 最本质的区别是什么? —— **隧道不改内层的头和地址**,只是外面套一层;**NAT 改内层的地址端口**,所以破坏端到端。 2. 四层 20 字节的隧道,MTU 变成多少? —— **1500 减 80 等于 1420**,再扣 IP 和 TCP 头 40 字节,MSS 只剩 1380。 3. 隧道里为什么要钳 MSS? —— **因为内层以为能发 1500,而隧道只能过 1420**,大包会被中间设备静默丢掉,症状是「小包通、 大包不通」。

下一节进入第五章最后一组:多播、任播、QoS、ECN 和 Mobile IP。

相关笔记