PPP 帧结构 (PPP Frame Format)
PPP (Point-to-Point Protocol) 帧格式基于 HDLC,支持多种 NCP 协议
标志字段 (Flag)
1 字节 (0x7E = 01111110): 标识帧的开始和结束。
PPP 使用字节填充 (Byte Stuffing) 技术来避免数据中出现与 Flag 相同的比特模式:
- 发送方:如果数据中出现 0x7E,则转换为 0x7D 0x5E 序列
- 发送方:如果数据中出现 0x7D,则转换为 0x7D 0x5D 序列
- 接收方:将 0x7D 0x5E 恢复为 0x7E,0x7D 0x5D 恢复为 0x7D
这种机制确保 Flag 模式不会在数据字段中意外出现。
地址字段 (Address)
1 字节 (0xFF): PPP 的地址控制字段。
在 PPP 中,地址字段固定为 0xFF(全 1),表示"所有站点都接收"(广播地址)。
- 与 HDLC 不同,PPP 不需要指定单个目标地址
- 因为 PPP 是点对点链路,只有两个端点
- 这个字段主要是为了兼容 HDLC 格式
控制字段 (Control)
1 字节 (0x03): PPP 的控制字段。
固定为 0x03,表示"无编号信息帧"(Unnumbered Information Frame)。
- 在 HDLC 中,控制字段用于流量控制和序号
- PPP 简化了这个字段,因为点对点链路本身不需要复杂的流量控制
- 0x03 表示这是一个无连接的、无确认的信息帧
协议字段 (Protocol)
2 字节: 标识 Data 字段中封装的上层协议类型。
这是 PPP 多协议支持的核心字段。常见协议值:
| 协议值 (十六进制) | 协议名称 | 说明 |
|---|---|---|
0x0021 |
IP | IPv4 数据包 |
0x0023 |
OSCP | OSI 连接less 网络协议 |
0x002b |
NS | Novell IPX |
0x002d |
AppleTalk | Apple 协议 |
0xc021 |
LCP | 链路控制协议 |
0xc023 |
PAP | 密码认证协议 |
0xc223 |
CHAP | 挑战握手认证协议 |
0x8021 |
IPCP | IP 控制协议(用于 IPv4) |
0x8057 |
IPv6CP | IPv6 控制协议 |
注意: 协议值小于 0x0200 的是网络层协议,0x0200-0x0FFF 保留,0x1000-0x7FFF 是实验性协议,0x8000-0xFFFF 是控制协议(LCP/NCP)。
数据字段 (Data / Payload)
可变长度 (0-1500 字节,通常): 封装的上层协议数据。
Data 字段包含:
- 如果是
0x0021协议,则是 IPv4 数据包 - 如果是
0xc021协议,则是 LCP 报文 - 如果是
0xc023协议,则是 PAP 报文 - 如果是
0x8021协议,则是 IPCP 配置报文
最大长度受 MTU 限制,通常为 1500 字节(以太网 PPPoE 环境下为 1492 字节)。
帧校验序列 (FCS - Frame Check Sequence)
2 字节或 4 字节: 用于错误检测的 CRC 校验码。
PPP 默认使用 16 位 CRC-CCITT (CRC-16-IBM),也可以协商使用 32 位 CRC。
- FCS 覆盖从 Address 到 Data 的所有字段
- 接收方重新计算 FCS,如果结果不为 0,则丢弃该帧
- 提供比奇偶校验更强的错误检测能力
计算方式: 使用 CRC-CCITT 多项式 x^16 + x^12 + x^5 + 1 (0x1021)。
结束标志 (Flag)
1 字节 (0x7E): 标识帧的结束。
与起始 Flag 相同,都是 0x7E (01111110)。
- 接收方检测到 Flag 时,知道帧已经结束
- 两个 Flag 之间的所有内容都是帧的有效载荷
- 如果链路空闲,会连续发送 Flag 作为填充
💡 PPP 帧结构总结
- 最小帧长: 7 字节(Flag + Address + Control + Protocol + FCS + Flag,无 Data)
- 典型帧长: 20-1500 字节(包含 Data)
- 最大帧长: 取决于 MTU,通常 1544 字节(1500 数据 + 44 头部/FCS)
- 编码方式: 异步链路使用字节填充,同步链路使用比特填充(HDLC 风格)
- 多协议支持: Protocol 字段允许在同一链路上传输多种网络层协议
LCP 报文格式 (Link Control Protocol)
LCP 用于建立、配置、测试和维护 PPP 链路
代码 (Code)
1 字节: LCP 报文类型。
常见 LCP 报文类型:
| Code | 名称 | 方向 | 说明 |
|---|---|---|---|
1 |
Configure-Request | 发送 → 接收 | 请求配置链路参数 |
2 |
Configure-Ack | 接收 → 发送 | 确认配置请求 |
3 |
Configure-Nak | 接收 → 发送 | 拒绝配置,建议修改 |
4 |
Configure-Reject | 接收 → 发送 | 拒绝配置,不理解该选项 |
5 |
Terminate-Request | 任意 → 任意 | 请求终止链路 |
6 |
Terminate-Ack | 任意 → 任意 | 确认终止请求 |
7 |
Code-Reject | 接收 → 发送 | 拒绝未知的 Code |
8 |
Protocol-Reject | 接收 → 发送 | 拒绝不支持的协议 |
9 |
Echo-Request | 任意 → 任意 | 链路探测请求(ping) |
10 |
Echo-Reply | 任意 → 任意 | 链路探测回复 |
11 |
Discard-Request | 任意 → 任意 | 请求丢弃后续报文 |
标识符 (Identifier)
1 字节: 用于匹配请求和响应。
发送方在发送 Configure-Request 时设置一个唯一的 ID(通常从 1 开始递增)。
- 接收方在回复 Configure-Ack/Nak/Reject 时,必须使用相同的 Identifier
- 这允许发送方同时发送多个配置请求,并正确匹配响应
- Identifier 循环使用(达到 255 后回到 1)
长度 (Length)
2 字节: LCP 报文的总长度(从 Code 到 Data 末尾)。
- 最小长度为 4(只有 Code、ID、Length,无 Data)
- Data 字段的长度 = Length - 4
- 接收方验证长度,如果长度小于 4 或超出预期,则丢弃报文
数据字段 (Options)
可变长度: LCP 配置选项列表。
每个选项的格式:
- Type (1 字节): 选项类型
- Length (1 字节): 选项总长度(包括 Type 和 Length)
- Data (可变): 选项具体数据
常见 LCP 选项:
| Type | 名称 | 说明 |
|---|---|---|
1 |
Maximum-Receive-Unit (MRU) | 最大接收单元,默认 1500 |
2 |
Async-Control-Character-Map (ACCM) | 异步控制字符映射 |
3 |
Authentication-Protocol | 认证协议(PAP/CHAP) |
4 |
Quality-Protocol | 质量检测协议 |
5 |
Magic-Number | 魔术数,用于检测环路 |
7 |
Protocol-Field-Compression | 协议字段压缩 |
8 |
Address-and-Control-Field-Compression | 地址控制字段压缩 |
💡 LCP 协商流程
- Configure-Request: 发送方发送配置请求,包含希望使用的选项(如 MRU、认证协议)
- Configure-Ack: 接收方完全接受请求,链路参数确定
- Configure-Nak: 接收方部分拒绝,建议修改值(如 MRU 太大)
- Configure-Reject: 接收方不理解该选项,要求移除
- 发送方根据 Ack/Nak/Reject 重新发送 Configure-Request
- 协商完成后,进入 Opened 状态,可以开始传输数据
PAP 报文格式 (Password Authentication Protocol)
PAP 是两次握手的明文认证协议,安全性较低
代码 (Code)
1 字节: PAP 报文类型。
| Code | 名称 | 说明 |
|---|---|---|
1 |
Authenticate-Request | 客户端发送认证请求(用户名/密码) |
2 |
Authenticate-Ack | 服务器确认认证成功 |
3 |
Authenticate-Nak | 服务器拒绝认证(密码错误等) |
标识符 (Identifier)
1 字节: 匹配请求和响应。
客户端在 Authenticate-Request 中设置 ID,服务器在 Ack/Nak 中回复相同 ID。
长度 (Length)
2 字节: 整个 PAP 报文的长度(从 Code 到 Message 末尾)。
- 最小长度:4(只有 Code、ID、Length,无 Message)
- 实际长度 = 4 + 用户名长度 + 密码长度 + 2(两个分隔符)
消息字段 (Message)
可变长度: 包含用户名和密码,格式为:
用户名长度(1字节) + 用户名(ASCII) + 密码长度(1字节) + 密码(ASCII)
⚠️ 安全性警告:
- PAP 以明文传输密码,容易被窃听
- 不推荐在生产环境中使用
- 仅用于测试环境或内部可信网络
- CHAP 是更安全的选择
💡 PAP 认证流程
- 客户端 → 服务器: 发送 Authenticate-Request,包含明文用户名和密码
- 服务器: 检查用户名和密码是否与本地数据库或 RADIUS 服务器匹配
- 服务器 → 客户端: 如果匹配,返回 Authenticate-Ack;否则返回 Authenticate-Nak
- 客户端: 收到 Ack 后继续链路建立;收到 Nak 或超时则终止链路
注意: PAP 是两次握手,没有加密,也没有防重放攻击机制。
CHAP 报文格式 (Challenge Handshake Authentication Protocol)
CHAP 是三次握手的挑战-响应认证协议,使用 MD5 哈希,安全性更高
代码 (Code)
1 字节: CHAP 报文类型。
| Code | 名称 | 说明 |
|---|---|---|
1 |
Challenge | 服务器发送挑战(随机数) |
2 |
Response | 客户端发送响应(MD5 哈希) |
3 |
Success | 认证成功 |
4 |
Failure | 认证失败 |
标识符 (Identifier)
1 字节: 用于匹配 Challenge 和 Response。
- 服务器在 Challenge 中设置随机 ID
- 客户端在 Response 中必须使用相同的 ID
- Success/Failure 报文也使用相同的 ID
- 每次认证使用不同的 ID,防止重放攻击
长度 (Length)
2 字节: CHAP 报文的总长度。
- Challenge/Response 报文:最小长度 5(Code+ID+Length+1字节数据长度)
- Success/Failure 报文:最小长度 4(Code+ID+Length+1字节消息长度)
挑战/响应值 (Value)
可变长度: 根据 Code 类型不同,内容不同。
- Challenge: 包含随机挑战字符串(通常 8-16 字节)
- Response: 包含 MD5 哈希值(16 字节)
- Success/Failure: 包含可选的服务器消息
CHAP 计算过程:
MD5(Identifier + 密码 + 随机挑战)
- 客户端收到 Challenge 后,用本地存储的密码与挑战值计算 MD5 哈希
- 客户端发送 Response,包含 MD5 结果
- 服务器用相同的密码和挑战计算 MD5,与客户端响应比较
- 如果匹配,发送 Success;否则发送 Failure
名称字段 (Name)
可变长度: 可选字段,标识对端身份。
- Challenge 报文可以包含服务器名称
- Response 报文可以包含客户端用户名
- Success/Failure 报文可以包含服务器名称
- 如果不需要,可以省略此字段
💡 CHAP 认证流程(三次握手)
- 服务器 → 客户端: 发送 Challenge,包含随机数(Challenge Value)和 ID
- 客户端: 计算
MD5(ID + 密码 + Challenge),发送 Response,包含哈希值和用户名 - 服务器: 用本地密码库中的密码计算相同哈希,与 Response 比较
- 服务器 → 客户端: 如果匹配,发送 Success;否则发送 Failure
CHAP 优势:
- 密码不通过网络传输(只传输哈希)
- 使用随机挑战,防止重放攻击
- 支持周期性重新认证(链路建立后定期 Challenge)
- 比 PAP 安全得多
IPCP 报文格式 (IP Control Protocol)
IPCP 用于 PPP 链路上协商 IPv4 地址参数,是 NCP 的一种
代码 (Code)
1 字节: IPCP 报文类型(与 LCP 类似)。
| Code | 名称 | 说明 |
|---|---|---|
1 |
Configure-Request | 请求配置 IP 参数 |
2 |
Configure-Ack | 确认配置 |
3 |
Configure-Nak | 拒绝,建议修改 |
4 |
Configure-Reject | 拒绝,不理解该选项 |
5 |
Terminate-Request | 请求终止 IPCP |
6 |
Terminate-Ack | 确认终止 |
标识符 (Identifier)
1 字节: 匹配请求和响应,与 LCP 相同。
- 发送 Configure-Request 时递增 ID
- 响应报文使用相同的 ID
- 用于匹配并发请求
长度 (Length)
2 字节: IPCP 报文总长度。
- 最小长度 4(无选项)
- 实际长度 = 4 + 所有选项长度之和
选项字段 (Options)
可变长度: IPCP 配置选项列表,每个选项格式:
Type (1字节) + Length (1字节) + Data (可变)
常见 IPCP 选项:
| Type | 名称 | 说明 | Data 格式 |
|---|---|---|---|
1 |
IP-Address | 指定/协商 IP 地址 | 4 字节 IPv4 地址 |
2 |
Primary-DNS-Server | 主 DNS 服务器 | 4 字节 IPv4 地址 |
3 |
Secondary-DNS-Server | 备用 DNS 服务器 | 4 字节 IPv4 地址 |
4 |
Primary-NBNS-Server | 主 WINS 服务器 | 4 字节 IPv4 地址 |
5 |
Secondary-NBNS-Server | 备用 WINS 服务器 | 4 字节 IPv4 地址 |
129 |
DNS-Server-List | DNS 服务器列表 | 多个 4 字节地址 |
IP-Address 选项:
- 客户端可以请求特定 IP 地址(发送 Configure-Request,Data 为 0.0.0.0 表示请求服务器分配)
- 服务器可以分配 IP 地址(回复 Configure-Nak 或 Ack,Data 为具体 IP)
- 如果客户端请求的 IP 不可用,服务器会 Nak 并建议其他 IP
💡 IPCP 协商流程
- LCP 链路建立: 首先完成 LCP 协商,链路进入 Opened 状态
- 认证(可选): 如果配置了 PAP/CHAP,完成认证
- IPCP 协商: 双方交换 Configure-Request,协商 IP 地址、DNS 等参数
- IP 通信: IPCP 完成后,可以开始 IPv4 数据传输
典型场景: PPPoE 拨号上网时,IPCP 负责为客户端分配公网或私有 IP 地址。