IPv6 头部格式:结构、字段和扩展头部
理解 IPv6 数据包头部结构、其 8 个字段以及扩展头部的工作原理。与 IPv4 进行比较,并了解简化设计如何改进路由。
为什么 IPv6 改变了头部#
IPv4 的头部是几十年来有机增长的。添加了选项,字段被重新利用,最后你得到了一个可变长度的头部,有 14 个不同的字段(有些是可选的)和一个复杂的结构,路由器必须在每一跳仔细解析。
IPv6 采取了不同的方法:固定长度、简化和优化以实现快速转发。基本头部始终恰好是 40 字节,有 8 个明确定义的字段。没有可变长度选项,没有头部校验和,主头部中没有分片字段。
结果是路由器可以更快地处理头部,更容易在硬件中实现,并支持扩展而不会破坏向后兼容性。理解 IPv6 头部意味着理解为什么要这样构建以及设计者做出了哪些权衡。
40 字节基本头部#
每个 IPv6 数据包都以这种格式的恰好 40 字节开始:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| Traffic Class | Flow Label |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Payload Length | Next Header | Hop Limit |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ +
| |
+ Source Address +
| |
+ +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ +
| |
+ Destination Address +
| |
+ +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+固定大小。基本头部中没有选项。每个路由器都确切知道每个字段的位置,无需解析。
八个字段#
让我们按照路由器通常处理它们的顺序检查每个字段。
1. 版本(4 位)#
对于 IPv6 数据包始终为 6。对于 IPv4 数据包始终为 4。这就是设备如何区分线路上的 IPv6 和 IPv4。
实际含义:双栈系统首先查看这 4 位以确定如何解析数据包的其余部分。
Version = 6 (二进制: 0110)简单、不变且对于协议识别至关重要。
2. 流量类别(8 位)#
在早期的 IPv6 规范中称为「优先级」,此字段标记数据包以进行服务质量(QoS)处理。它的用途与 IPv4 的服务类型(ToS)或差异化服务代码点(DSCP)相同。
结构:
- 位 0-5:DSCP(差异化服务代码点)
- 位 6-7:ECN(显式拥塞通知)
常见 DSCP 值:
| 值 | 名称 | 二进制 | 用例 |
|---|---|---|---|
| 0 | 尽力而为 | 000000 | 正常流量 |
| 46 | EF(加速转发) | 101110 | VoIP、实时 |
| 34 | AF41 | 100010 | 高优先级数据 |
| 26 | AF31 | 011010 | 中等优先级数据 |
| 10 | AF11 | 001010 | 低优先级数据 |
ECN 允许路由器在不丢弃数据包的情况下发出拥塞信号。现代 TCP 实现使用它来更好地控制拥塞。
示例:
Traffic Class = 46 (EF) = 0b10111000
DSCP = 46 (加速转发)
ECN = 0 (不支持 ECN)支持 QoS 的路由器检查此字段以确定数据包的优先级。VoIP 获得比文件下载更高的优先级。实时视频比电子邮件获得更好的处理。
3. 流标签(20 位)#
IPv6 最有趣但未充分利用的功能之一。流标签标识属于同一流并应接收相同路由处理的数据包。
目的:
- 允许路由器在不检查上层头部的情况下识别相关数据包
- 支持已知流的快速路径转发
- 为每个流的 QoS 提供句柄
规范(RFC 6437):
- 值 0:数据包不是需要特殊处理的流的一部分
- 值 1-0xFFFFF:流标识符(由源随机选择)
- 对于流中的所有数据包必须一致
- 应该是伪随机的,以允许路由器哈希
什么构成流:
- 源 + 目的地 + 流标签唯一标识它
- TCP 连接中的所有数据包可能使用相同的流标签
- 或者每个视频流可能获得唯一的标签
实际用法:
许多实现将流标签设置为 0,因为:
- 基于流标签进行哈希/转发所需的硬件并非普遍存在
- 应用程序支持有限
- 它是可选的,零工作正常
但是当正确使用时,流标签可以实现:
- 跨 ECMP(等成本多路径)路由的负载均衡
- 每个流的流量工程
- 硬件快速路径转发
设置流标签的示例(Linux):
# 启用自动流标签
sysctl -w net.ipv6.auto_flowlabels=1
# 流标签将根据 5 元组哈希设置启用时,Linux 为 TCP 连接自动生成流标签,使用源/目标地址和端口的哈希。
4. 有效载荷长度(16 位)#
数据包有效载荷的长度(以字节为单位),不包括 40 字节基本头部。
范围:0 到 65,535 字节
重要细节:
- 包括扩展头部(如果有)加上层数据
- 不包括基本 40 字节 IPv6 头部
- 最大值 65,535 意味着最大数据包大小为 65,575 字节(65,535 + 40)
特殊情况:超大数据包
对于大于 65,535 字节的数据包,有效载荷长度设置为 0,逐跳扩展头部带有超大数据包选项携带实际长度(最多 4,294,967,295 字节)。
超大数据包很罕见。它们用于具有超大帧支持的专用高性能网络,通常在 10 Gbps+ 链路上。
示例:
Payload Length = 1440 字节
40 字节 IPv6 头部(不计算)
1440 字节有效载荷(TCP 头部 + 数据)
总数据包 = 1480 字节5. 下一个头部(8 位)#
标识紧跟在 IPv6 头部之后的头部类型。这就是指定扩展头部和上层协议的方式。
常见值:
| 值 | 协议/扩展 | 描述 |
|---|---|---|
| 6 | TCP | 传输控制协议 |
| 17 | UDP | 用户数据报协议 |
| 58 | ICMPv6 | IPv6 的互联网控制消息协议 |
| 0 | 逐跳选项 | 扩展头部,必须是第一个 |
| 43 | 路由 | 路由扩展头部 |
| 44 | 分片 | 分片扩展头部 |
| 60 | 目标选项 | 目标选项扩展头部 |
| 51 | AH | 认证头部(IPsec) |
| 50 | ESP | 封装安全有效载荷(IPsec) |
| 59 | 无下一个头部 | 后面没有更多数据 |
链接如何工作:
每个扩展头部都包含自己的下一个头部字段,形成一条链:
IPv6 Header (Next Header = 0)
-> Hop-by-Hop Options (Next Header = 43)
-> Routing Header (Next Header = 6)
-> TCP Header
-> Data接收主机按顺序处理头部,直到到达传输协议(TCP/UDP)或数据。
没有扩展头部的示例:
Next Header = 6 (TCP)
IPv6 头部直接后跟 TCP 头部有扩展头部的示例:
Next Header = 44 (Fragment)
IPv6 头部后跟分片头部 (Next Header = 6)
分片头部后跟 TCP 头部6. 跳数限制(8 位)#
数据包被丢弃之前剩余的路由器跳数。每个路由器将其减 1。当它达到 0 时,路由器丢弃数据包并发送 ICMPv6 超时消息。
范围:0-255
这是 IPv6 等效于 IPv4 的 TTL(生存时间)字段,但名称更准确——它计算跳数,而不是时间。
常见初始值:
| 操作系统/协议栈 | 默认跳数限制 | 原因 |
|---|---|---|
| Linux | 64 | RFC 4861 建议 |
| Windows | 128 | 历史默认值 |
| Cisco IOS | 64 | 标准合规性 |
| BSD | 64 | KAME 协议栈默认值 |
为什么不同的值对于指纹识别很重要:
你可以通过查看接收数据包中的跳数限制来猜测源操作系统:
接收到的跳数限制: 56
56 + 8 跳 = 64 (可能是 Linux/BSD)
接收到的跳数限制: 117
117 + 11 跳 = 128 (可能是 Windows)Traceroute 使用跳数限制:
Traceroute 通过发送具有递增跳数限制值的数据包来工作:
- 跳数限制 1:第一个路由器响应超时
- 跳数限制 2:第二个路由器响应超时
- 跳数限制 3:第三个路由器响应超时
- ...直到到达目的地
安全考虑:
一些攻击使用低跳数限制使数据包在到达 IDS/IPS 系统之前过期。防火墙有时会对入站流量强制执行最小跳数限制值。
示例:
Hop Limit = 64
路由器 1 接收,减至 63,转发
路由器 2 接收,减至 62,转发
...
路由器 64 接收,减至 0,丢弃并发送 ICMPv6 类型 37. 源地址(128 位)#
数据包发送者的 IPv6 地址。始终 128 位,没有例外。
格式:标准 IPv6 地址表示法
2001:db8:1234:5678:9abc:def0:1234:5678特殊考虑:
**未指定地址(::)**仅在特定情况下有效:
- 重复地址检测(DAD)
- 地址分配前的 DHCP 请求
- 某些 ICMPv6 消息
**链路本地地址(fe80::/10)**是有效的源地址,但仅在本地链路上。路由器不转发具有链路本地源的数据包。
多播地址永远不是有效的源地址。具有多播源的数据包应立即丢弃。
实际问题:源地址选择
当主机具有多个 IPv6 地址(使用 SLAAC、DHCPv6 和隐私扩展很常见)时,它必须选择用作源的地址。RFC 6724 定义了选择算法,优先选择:
- 与目标地址范围相同的地址
- 具有更长匹配前缀的地址
- 非弃用地址
- 具有更高偏好的地址
8. 目标地址(128 位)#
数据包预期接收者的 IPv6 地址。与源地址一样,始终 128 位。
格式:标准 IPv6 地址表示法
2001:4860:4860::8888路由决策:
路由器检查此字段以确定将数据包转发到何处。与 IPv4 中 NAT 可能重写地址不同,IPv6 目标地址通常保持端到端不变。
特殊地址:
**环回(::1)**永远不能出现在线路上的数据包中。到 ::1 的数据包在内部处理。
**多播地址(ff00::/8)**表示数据包应传递给多个接收者:
- ff02::1 - 本地链路上的所有节点
- ff02::2 - 本地链路上的所有路由器
- ff02::1:ff00:0/104 - 请求节点多播(用于邻居发现)
路由头部修改:
当存在路由扩展头部时,中间节点可能会以不同方式处理目标地址,但由于安全问题,这在现代网络中并不常见。
IPv6 vs IPv4 头部比较#
理解什么改变了有助于欣赏设计决策。
| 功能 | IPv4 | IPv6 | 为什么改变 |
|---|---|---|---|
| 头部大小 | 20-60 字节(可变) | 40 字节(固定) | 更快的处理,更简单的硬件 |
| 总字段 | 14+ 字段 | 8 字段 | 简化解析 |
| 地址 | 每个 32 位 | 每个 128 位 | 解决地址耗尽 |
| 校验和 | 是 | 否 | 卸载到 L2/L4,更快的转发 |
| 分片 | 由路由器 | 仅源 | 强制 PMTUD,更好的性能 |
| 选项 | 在主头部中 | 扩展头部 | 更清洁的基本头部 |
| TTL/跳数限制 | TTL(8 位) | 跳数限制(8 位) | 重命名以提高准确性 |
| 协议/下一个头部 | 协议(8 位) | 下一个头部(8 位) | 可通过链接扩展 |
| 服务类型 | ToS/DSCP(8 位) | 流量类别(8 位) | 相同功能 |
| 标志 | DF、MF、保留 | (在分片头部中) | 移至扩展头部 |
| 分片偏移 | 13 位 | (在分片头部中) | 移至扩展头部 |
| 头部长度 | IHL(4 位) | 不需要 | 固定 40 字节 |
| 标识 | 16 位 | (在分片头部中) | 移至扩展头部 |
| 流标签 | 无 | 20 位 | QoS/路由的新功能 |
删除了什么以及为什么#
头部校验和:IPv4 路由器在每一跳重新计算校验和,因为 TTL 会改变。这增加了处理开销。IPv6 消除了它,因为:
- 链路层(以太网)有自己的校验和
- 传输层(TCP/UDP)有自己的校验和
- 路由器不需要验证数据包完整性——端点需要
头部长度字段:IPv4 需要这个,因为选项使头部可变长度。IPv6 的固定 40 字节头部使此字段不必要。
分片字段:IPv4 允许任何路由器对数据包进行分片。IPv6 要求源使用路径 MTU 发现执行分片。这将复杂性移至端点并提高路由器性能。
选项:IPv4 选项很少使用,但强制路由器解析可变长度头部。IPv6 将选项移至扩展头部,保持基本头部简单。
扩展头部解释#
扩展头部是 IPv6 在不使基本头部复杂化的情况下添加功能的方式。它们出现在 IPv6 头部和传输层(TCP/UDP)之间,形成一条链。
扩展头部如何工作#
每个扩展头部都包含一个指向链中下一个头部的下一个头部字段:
+--------+-------+--------+-------+--------+-------+-----+
| IPv6 | NH=0 | Hop-by | NH=43 | Routing| NH=6 | TCP |
| Header | | -Hop | | Header | | |
+--------+-------+--------+-------+--------+-------+-----+主机按顺序处理扩展头部。路由器通常仅处理逐跳选项;其他头部仅由目标检查。
标准扩展头部#
RFC 8200 定义了存在多个扩展头部时的推荐顺序:
- 逐跳选项(0)
- 目标选项(当存在路由头部时用于中间目标)
- 路由(43)
- 分片(44)
- 认证头部(51)
- 封装安全有效载荷(50)
- 目标选项(60)(用于最终目标)
- 上层(TCP=6、UDP=17、ICMPv6=58)
逐跳选项头部(类型 0)#
携带路径上每个路由器都必须检查的选项。
格式:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Next Header | Hdr Ext Len | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
| |
. Options .
. .
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+常见选项:
Pad1 和 PadN:用于对齐的填充
路由器警报(类型 5):告诉路由器更仔细地检查数据包。由 MLD(多播侦听器发现)等协议使用。
超大数据包(类型 194):用于大于 65,535 字节的数据包。
必须是第一个:如果存在,逐跳选项必须紧跟在 IPv6 头部之后。RFC 8200 要求这种严格的顺序。
安全问题:许多路由器丢弃带有它们不识别的逐跳头部的数据包,或者严格限制它们的速率。实际上,除了特定协议(MLD、超大数据包)之外,此扩展头部并不常见。
路由头部(类型 43)#
指定数据包在到达最终目标之前应访问的中间节点。
格式:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Next Header | Hdr Ext Len | Routing Type | Segments Left |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
. Type-specific data .
. .
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+路由类型:
类型 0(已弃用):原始松散源路由。由于安全问题(放大攻击)被 RFC 5095 弃用。
类型 2:由移动 IPv6 用于路由到移动节点。有限用例。
类型 3:SRv6 的段路由头部(SRH)。用于运营商网络中流量工程和服务链的现代用例。
安全:类型 0 路由头部允许攻击者通过任意节点路由数据包,创建放大攻击。大多数网络丢弃类型 0。类型 3(SRv6)设计得更仔细,但在公共互联网上仍然引起安全问题。
分片头部(类型 44)#
当源对路径 MTU 来说太大的数据包进行分片时使用。
格式:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Next Header | Reserved | Fragment Offset |Res|M|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identification |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+字段:
- 下一个头部:分片数据的协议(TCP、UDP 等)
- 分片偏移:此分片在原始数据包中的偏移量(以 8 字节为单位)
- M 标志:更多分片(1 = 更多,0 = 最后一个分片)
- 标识:用于重组的唯一 ID(一个数据包的所有分片相同)
分片如何工作:
- 源尝试发送大数据包
- 接收 ICMPv6 数据包太大消息
- 将数据包分片成较小的片段
- 为每个片段添加分片头部
- 目标根据标识字段重组
示例:
原始 2000 字节数据包,MTU 1280:
分片 1:
IPv6 Header (40 字节)
Fragment Header (8 字节) [M=1, Offset=0, ID=12345]
Data (1232 字节)
总计: 1280 字节
分片 2:
IPv6 Header (40 字节)
Fragment Header (8 字节) [M=0, Offset=154, ID=12345]
Data (768 字节)
总计: 816 字节最小 MTU:IPv6 要求所有链路至少支持 1280 字节。源可以在任何兼容的 IPv6 网络上发送 1280 字节的数据包而无需分片。
安全问题:分片使攻击成为可能:
- 重叠分片(从 IDS 混淆有效载荷)
- 分片洪水(耗尽重组资源)
- 微小分片(浪费处理时间)
许多防火墙丢弃分片数据包或在检查之前重组它们。
目标选项头部(类型 60)#
仅为目标节点携带选项。中间路由器不处理它。
格式:与逐跳选项相同,但仅在目标处检查。
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Next Header | Hdr Ext Len | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
| |
. Options .
. .
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+用例:
- 对齐填充
- 应用程序特定选项
- 未来扩展而不更改基本头部
可以在头部链中出现两次:
- 在路由头部之前(由中间目标处理)
- 在 ESP/AH 头部之后(由最终目标处理)
认证头部(类型 51)和 ESP(类型 50)#
提供认证和加密的 IPsec 头部。
AH(51):提供认证和完整性,但不提供机密性。很少使用,因为 ESP 可以做同样的事情加上加密。
ESP(50):提供机密性、认证和完整性。VPN 和加密通信的标准。
IPsec 是超出头部结构的大主题。关键点:这些头部从一开始就是 IPv6 设计的一部分,不像 IPv4 中 IPsec 是后来添加的。
处理扩展头部#
主机必须:
- 按顺序处理所有扩展头部
- 支持所有标准扩展头部
- 根据下一个头部值处理未知头部
路由器通常:
- 仅检查逐跳选项
- 转发其他扩展头部而不处理
- 出于安全考虑,可能会限制速率或丢弃带有某些头部的数据包
防火墙考虑:
扩展头部使防火墙复杂化,因为:
- 传输头部(TCP/UDP)可能在数据包深处
- 必须解析整个链以找到用于过滤的端口
- 攻击者可以使用复杂的头部链混淆有效载荷
最佳实践:
- 限制扩展头部链长度
- 丢弃带有弃用头部的数据包(类型 0 路由)
- 在检查之前重组分片
- 限制带有逐跳选项的数据包的速率
为什么没有校验和?#
IPv4 包含一个头部校验和,路由器必须在每一跳重新计算(因为 TTL 改变)。IPv6 故意省略了这个。
原因:
-
链路层已经有校验和:以太网有 CRC32。Wi-Fi 有校验和。现代链路层是可靠的。
-
传输层校验和:TCP 和 UDP 包括覆盖数据和头部的校验和。端到端验证无论如何都会发生。
-
路由器性能:在每一跳重新计算校验和浪费 CPU 周期。高速路由器每秒转发数十亿个数据包——消除校验和计算有帮助。
-
错误很少见:现代网络具有低比特错误率。校验和捕获的错误比 1980 年代设计 IPv4 时少。
如果 IPv6 头部中的位翻转会怎样?
如果 IPv6 头部中的位翻转:
- 错误的目标地址:数据包到达错误的地方或被丢弃,TCP 重传
- 错误的跳数限制:数据包可能过早或过晚死亡,影响很小
- 错误的下一个头部:目标无法解析它,TCP 检测到丢失的数据并重传
端到端原则说端点应该检测和处理错误。中间路由器只是快速转发数据包。
UDP 在 IPv6 中必须校验和
在 IPv4 中,UDP 校验和是可选的(通常为了性能而禁用)。IPv6 使 UDP 校验和成为强制性的。没有 IP 层校验和,UDP 必须提供完整性检查。这是权衡:更简单/更快的路由,但 UDP 实现必须计算校验和。
实际影响#
对于网络工程师#
防火墙配置:
- 必须解析扩展头部链以找到传输头部
- 应该限制链深度以防止滥用
- 丢弃弃用的头部(类型 0 路由)
性能调优:
- 没有头部校验和意味着硬件中更快的转发
- 固定头部大小在路由器中实现更好的流水线
- 扩展头部可能触发慢速路径处理
故障排除:
- tcpdump 显示所有头部:
tcpdump -i eth0 -vv ip6 - Wireshark 清楚地解析扩展头部
- 检查导致丢弃的意外扩展头部
对于开发人员#
套接字编程:
- IPv6 套接字可以通过辅助数据接收扩展头部
- 应用程序很少需要手动构造扩展头部
- 操作系统自动处理分片
数据包构造:
- 为 QoS 敏感应用程序(VoIP、视频)设置流量类别
- 启用自动流标签生成以实现更好的 ECMP 负载均衡
- 不要假设你可以分片——正确使用 PMTUD
安全:
- 验证源地址(拒绝多播源等)
- 小心处理分片数据包或拒绝它们
- 注意中间盒可能会丢弃扩展头部
对于系统管理员#
MTU 配置:
- 确保所有链路上的 MTU 至少为 1280 字节
- 更大的 MTU 提高性能(1500 标准,9000 用于超大帧)
- 允许 ICMPv6 数据包太大通过防火墙
QoS 设置:
- 配置路由器以遵守流量类别标记
- 将应用程序流量映射到适当的 DSCP 值
- 监控 QoS 策略是否正常工作
IPsec/VPN:
- AH 和 ESP 是扩展头部——防火墙必须允许它们
- IPsec 增加开销——在 MTU 计算中考虑这一点
- 考虑传输模式与隧道模式对头部的影响
使用工具检查头部#
tcpdump#
捕获并显示 IPv6 头部:
# 基本 IPv6 数据包捕获
sudo tcpdump -i eth0 -n ip6
# 显示所有头部字段的详细输出
sudo tcpdump -i eth0 -vv ip6
# 仅显示带有扩展头部的数据包
sudo tcpdump -i eth0 -vv 'ip6 and ip6[6] != 6 and ip6[6] != 17 and ip6[6] != 58'
# 捕获分片数据包
sudo tcpdump -i eth0 -n 'ip6 and ip6[6] = 44'示例输出:
12:34:56.789012 IP6 2001:db8::10 > 2001:db8::20: DSTOPT (TCP)
2001:db8::10.54321 > 2001:db8::20.80: Flags [S], seq 123456789, win 65535
分析:
- 源: 2001:db8::10, 端口 54321
- 目标: 2001:db8::20, 端口 80
- 扩展头部: 目标选项 (DSTOPT)
- 传输: TCP SYNWireshark#
Wireshark 提供详细的头部分析:
过滤器:
# 所有 IPv6 流量
ipv6
# 带有特定扩展头部的数据包
ipv6.nxt == 0 # 逐跳
ipv6.nxt == 43 # 路由
ipv6.nxt == 44 # 分片
ipv6.nxt == 60 # 目标选项
# 分片数据包
ipv6.fragment
# 特定流量类别
ipv6.tclass == 46 # 加速转发头部检查:
- 在数据包详细信息中展开「Internet Protocol Version 6」
- 查看所有 8 个字段清楚标记
- 扩展头部显示为单独的层
- 右键单击字段进行过滤
Scapy(Python)#
以编程方式构建和分析 IPv6 数据包:
from scapy.all import *
# 创建 IPv6 数据包
pkt = IPv6(src="2001:db8::10", dst="2001:db8::20", tc=46, fl=12345)
pkt = pkt/TCP(sport=54321, dport=80, flags="S")
# 显示数据包结构
pkt.show()
# 输出:
# ###[ IPv6 ]###
# version= 6
# tc= 46
# fl= 12345
# plen= None
# nh= TCP
# hlim= 64
# src= 2001:db8::10
# dst= 2001:db8::20
# ###[ TCP ]###
# sport= 54321
# dport= http
# 添加扩展头部
pkt = IPv6(dst="2001:db8::20")/IPv6ExtHdrDestOpt()/TCP(dport=80)
pkt.show()常见错误配置#
完全阻止扩展头部#
问题:防火墙丢弃所有带有扩展头部的数据包。
影响:
- 分片不工作(类型 44 被阻止)
- IPsec VPN 失败(类型 50/51 被阻止)
- 某些合法流量丢弃
解决方案:允许必要的头部(分片、AH、ESP),阻止弃用的头部(类型 0 路由)。
# iptables: 允许分片,丢弃类型 0 路由
ip6tables -A FORWARD -m rt --rt-type 0 -j DROP
ip6tables -A FORWARD -p ipv6-icmp --icmpv6-type packet-too-big -j ACCEPT忽略流量类别#
问题:没有 QoS 的路由器配置,所有数据包都获得尽力而为的处理。
影响:
- VoIP 质量受损
- 视频流缓冲
- 时间敏感流量与批量传输竞争
解决方案:根据流量类别/DSCP 配置 QoS 策略。
! Cisco IOS 示例
class-map match-any VOICE
match dscp ef
!
policy-map WAN-QOS
class VOICE
priority percent 20
class class-default
fair-queue
!
interface GigabitEthernet0/1
service-policy output WAN-QOSMTU 不匹配#
问题:MTU < 1280 的链路或阻止 ICMPv6 数据包太大的防火墙。
影响:
- 连接挂起
- 大型传输失败
- PMTUD 不工作
解决方案:确保每个地方的最小 MTU 为 1280,允许 ICMPv6 类型 2。
# 设置 MTU
ip link set dev eth0 mtu 1500
# 验证
ip -6 link show eth0
# 允许数据包太大
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type packet-too-big -j ACCEPT相关文章#
- IPv6 基础知识 - 在深入研究头部之前了解基本的 IPv6 地址和概念。
- ICMPv6 解释 - 了解使用下一个头部值 58 且对 IPv6 至关重要的 ICMPv6。
- IPv6 防火墙配置 - 配置防火墙以正确处理 IPv6 头部和扩展头部。
常见问题#
为什么 IPv6 头部恰好是 40 字节?
固定大小可实现更快的处理。路由器在不解析的情况下确切知道每个字段的位置。硬件可以更有效地流水线数据包处理。40 字节大小容纳两个 128 位地址(32 字节)加上其他字段的 8 字节(版本、流量类别、流标签、有效载荷长度、下一个头部、跳数限制)。可变长度头部需要在转发之前进行解析,从而减慢路由器速度。
我可以像 IPv4 一样对 IPv6 数据包进行分片吗?
不可以。只有源可以对 IPv6 数据包进行分片。路由器不进行分片。如果数据包对于链路来说太大,路由器会丢弃它并将 ICMPv6 数据包太大消息发送回源。然后源减小其数据包大小。这称为路径 MTU 发现(PMTUD)。它将分片复杂性移至端点并提高路由器性能。所有 IPv6 链路必须至少支持 1280 字节 MTU。
如果我将流标签设置为 0 会怎样?
没有任何东西会坏。流标签 0 意味着数据包不是需要特殊处理的流的一部分。大多数实现将其设置为 0。一些现代协议栈为 TCP 连接生成伪随机流标签,以改进 ECMP 负载均衡。路由器可以在源+目标+流标签上进行哈希,以在多个等成本路径之间分配流量。将其设置为 0 可以工作,但会阻止基于流的负载均衡。
我应该使用逐跳选项头部吗?
很少。逐跳强制每个路由器检查数据包,这会减慢处理速度。由于安全问题,许多网络限制速率或丢弃带有逐跳头部的数据包。主要的合法用途是路由器警报(用于 MLD)和超大数据包选项(用于大于 65,535 字节的数据包)。对于典型应用程序,完全避免逐跳。如果你需要它,请彻底测试,因为中间盒可能会丢弃你的流量。
为什么 IPv6 删除了头部校验和?
性能和冗余。IPv4 路由器在每一跳重新计算校验和,因为 TTL 改变。这浪费了 CPU 周期。IPv6 依赖链路层校验和(以太网 CRC)和传输层校验和(TCP/UDP)进行错误检测。现代网络具有低错误率。TCP/UDP 的端到端校验和捕获错误而不给路由器带来负担。权衡:UDP 校验和在 IPv6 中成为强制性的(在 IPv4 中是可选的),以保持完整性检查。
防火墙如何处理扩展头部?
小心。防火墙必须解析整个扩展头部链以找到传输头部(TCP/UDP)和用于过滤的端口号。复杂的链会减慢处理速度并可能隐藏恶意有效载荷。最佳实践:限制链深度,丢弃弃用的头部(类型 0 路由),在检查之前重组分片,并限制具有异常头部的数据包的速率。一些防火墙默认丢弃所有扩展头部,这会破坏分片和 IPsec——将它们配置为允许基本头部。