PPPoE 就是在以太网里套一层 PPP:多 8 个字节,MTU 从 1500 掉到 1492。 这 8 个字节会一路上传到 TCP 的 MSS,变成 1452——很多「打不开网页」的根源。
3.5.3 讲的是 PPP 帧本身,这一节讲它怎么跑在今天的宽带上。 关键数字是 8 与 1492,以及它带来的 MSS 问题。
一、8 个字节怎么来的
六个字段,加起来 8 字节:
| 字段 | 字节 | 作用 |
|---|---|---|
| VER/TYPE | 1 | 固定 0x11 |
| CODE | 1 | 0x00 会话数据、0x09 拨号请求 |
| SESSION_ID | 2 | 区分同一条线上的多个会话 |
| LENGTH | 2 | 后面的 PPP 帧有多长 |
PPPoE 头 6 字节,加上 PPP 自己的协议字段 2 字节,正好 8 字节。 所以「以太网 MTU 1500 减 8 等于 1492」, 这个 1492 就是 PPPoE 环境下「一个 IP 包最多能多大」。 第三行那个 SESSION_ID 是 PPPoE 的关键设计: 以太网上可能同时有多个 PPPoE 会话(比如一栋楼共用一条线路),靠这个 ID 区分。 所以 PPPoE 分成「发现阶段」和「会话阶段」: 先用 0x09 的 PADI/PADO 找到对端、分配 ID,再进入正式传输。
二、一路传导到 MSS
8 个字节会一直传到应用层:
| 链路 | MTU | TCP 的 MSS |
|---|---|---|
| 以太网 | 1500 | 1460 |
| PPPoE | 1492 | 1452 |
| PPPoE + VPN | 1400 | 1360 |
第二列少 8 字节,第三列也少 8 字节:因为 MSS = MTU − IP 头 20 − TCP 头 20,是个固定减法。 所以「MTU 少一点」会一路放大——一亿个包就少 800 MB 的载荷。 这就是「PPPoE 环境下有些网站打不开」的老问题根源: 路径上有一台设备坚持发 1500 字节的包,而 PPPoE 这边只能接 1492, 那个包会被静默丢弃,表现为「能 ping 通、网页卡住」。 解决办法有两个:一是「MSS 钳制」(在网关把 TCP 握手里的 MSS 改成 1452); 二是「让对端正确分片」(发 ICMP「需要分片」消息)。前者更可靠,因为很多服务器会屏蔽 ICMP。
三、为什么要套这一层
直接在以太网上跑 PPP 好像很绕,但它解决了实际问题:
| 需求 | PPPoE 怎么满足 |
|---|---|
| 按用户认证 | PPP 的 PAP/CHAP 直接复用 |
| 按会话分配地址 | IPCP 直接复用 |
| 按会话限速/计费 | SESSION_ID 就是计费单位 |
三行都是「复用」:运营商不需要重新发明一套认证和地址分配, 把拨号时代那套 PPP 直接搬过来就行。 所以 PPPoE 的本质是「用最小的改动,把拨号时代的运营体系搬到宽带上」。 这也解释了「为什么不能直接用 DHCP」:DHCP 没有认证,谁插上都能要地址,运营商没法管控。 而 PPPoE 的「账号密码」是硬门槛。 今天有些运营商改用「IPoE」(用 DHCP + 网页认证或绑定端口), 好处是「不用拨号、开机就有网」,坏处是「认证更弱、更容易被盗用」。 所以「要不要 PPPoE」本质是「管控强度」和「用户体验」的取舍。
四、动手 Demo:PPPoE 为什么要扣掉 8 个字节
先把 PPPoE 头的字段列出来,再算 MTU 一路减到 MSS 的链。 重点看最后那张表:1500 → 1492 → 1452。
hdr = [('VER/TYPE', 1, '固定 0x11'), ('CODE', 1, '0x00 会话、0x09 拨号'),
('SESSION_ID', 2, '区分多个会话'), ('LENGTH', 2, '后面的 PPP 帧长度')]
for name, n, note in hdr:
print('%-12s %d 字节 %s' % (name, n, note))
print('PPPoE 头 %d 字节 + PPP 协议字段 2 字节 = 8' % sum(h[1] for h in hdr))
for name, mtu in (('以太网', 1500), ('PPPoE', 1492), ('PPPoE + VPN', 1400)):
print('%-12s MTU %4d MSS %4d' % (name, mtu, mtu - 40))
实跑输出:
--------------------------------------------------------------------
PPPoE 为什么要扣掉 8 个字节
--------------------------------------------------------------------
**家里的宽带拨号,跑的是「以太网里套 PPP」。**
**套这一层要走 8 个字节,于是 MTU 从 1500 掉到 1492**——这个 8 不是随便来的,
可以一个字节一个字节数出来。
PPPoE 头字段 字节 作用
-------------------------------------------------------------------
VER/TYPE 1 固定 0x11(版本 1、类型 1)
CODE 1 0x00 是会话数据,0x09 是拨号请求
SESSION_ID 2 **会话号,用来区分同一条线上的多个用户**
LENGTH 2 后面的 PPP 帧有多长
**PPPoE 头 6 字节,加上 PPP 自己的协议字段 2 字节,正好 8 字节。**
项目 字节 说明
-------------------------------------------------------------
以太网 MTU 1500 载荷上限
减 PPPoE 头 −6 VER/CODE/SESSION/LENGTH
减 PPP 协议字段 −2 0x0021 表示 IPv4
**PPPoE 的 MTU** **1492** **上层能用的最大值**
**这 8 个字节会一路传导到 TCP**:
链路 MTU TCP 的 MSS
------------------------------------
以太网 1500 1460
PPPoE 1492 1452
PPPoE + VPN 1400 1360
**第三列就是「一个 TCP 段最多能装多少应用数据」**:
**以太网 1460、PPPoE 1452、再套一层 VPN 只剩 1360。**
**MTU 少 8 字节,MSS 也少 8 字节,一亿个包就少 800 MB 的载荷。**
**这也是「PPPoE 环境下有些网站打不开」的老问题根源**:
**路径上有一台设备坚持发 1500 字节的包,而 PPPoE 这边只能接 1492**,
**那个包会被静默丢弃,表现为「能 ping 通、网页卡住」。**
**解决办法是把 MSS 钳到 1452(叫 MSS clamping),或者让对端正确分片。**
**所以那 8 个字节的教训不是「8 很小」**:**而是「任何一层加头,都会把上层的可用空间往下压」**,
**而「谁都不肯少发」这件事,最后会以「莫名其妙打不开」的形式出现。**
sum(h[1] for h in hdr) 算出来是 6:加上 PPP 的协议字段 2 字节,正好 8。
所以「1492」这个数不是标准拍脑袋定的,是「1500 减 6 减 2」算出来的。
MSS 那一列是「MTU 减 40」:IP 头 20 + TCP 头 20。
所以 PPPoE 的 MSS 是 1452,
这个数在路由器配置里叫「MSS clamping 1452」——家宽打不开某些网站时,改的就是这个。
第三行「PPPoE + VPN」是很多人的真实处境:
在家连公司 VPN,MTU 再减 92 到 1400,MSS 只剩 1360。
所以「在家办公时某些系统打不开」不是公司系统的问题,是「包太大,路上被丢了」。
30 秒实验
- 算一下:MTU 1400 时,一个 10 MB 的文件要比 MTU 1500 多发多少个包?
- 查一下你路由器 WAN 设置里的 MTU 值是多少。
- 想一下:为什么「MSS 钳制」比「让对端分片」更可靠?
常见误区
- 以为 PPPoE 只是「多一层头,无所谓」。 8 个字节会一路传到 MSS,引发「打不开网页」。
- 以为「PPPoE 拨号只是为了计费」。 主要是认证,DHCP 没有认证能力。
- 以为「MTU 只要两端一致就行」。 路径上任何一台设备都可能丢大包。
自测三问(点开对答案)
1. PPPoE 多出来的 8 个字节是哪几部分? —— **PPPoE 头 6 字节(VER/TYPE、CODE、SESSION_ID、LENGTH)+ PPP 协议字段 2 字节。** 2. PPPoE 环境下 MTU 和 MSS 各是多少? —— **MTU 1492、MSS 1452**(1492 − 20 − 20)。 3. 为什么运营商不直接用 DHCP? —— **DHCP 没有认证。** PPPoE 复用 PPP 的 PAP/CHAP,账号密码是硬门槛。下一节换一种完全不同的链路:ATM 的 53 字节信元。
- ☐ (本节完,下一节 3.6.1 ATM)