ping6.net
基础知识

IPv6 头部格式:结构、字段和扩展头部

理解 IPv6 数据包头部结构、其 8 个字段以及扩展头部的工作原理。与 IPv4 进行比较,并了解简化设计如何改进路由。

ping6.net2024年12月14日10 min read
IPv6头部数据包结构扩展头部网络

为什么 IPv6 改变了头部#

IPv4 的头部是几十年来有机增长的。添加了选项,字段被重新利用,最后你得到了一个可变长度的头部,有 14 个不同的字段(有些是可选的)和一个复杂的结构,路由器必须在每一跳仔细解析。

TL;DR - 快速摘要

要点:

  • 固定 40 字节头部,8 个字段(vs IPv4 的可变 20-60 字节,14+ 字段)
  • 从基本头部中移除头部校验和和分片以实现更快的路由
  • 扩展头部(逐跳、路由、分片等)提供可选功能
  • 流量类(QoS)、流标签(每流路由)和简化的下一个头部链接

跳转至: 八个字段 | 扩展头部 | 为什么没有校验和

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正常流量
46EF(加速转发)101110VoIP、实时
34AF41100010高优先级数据
26AF31011010中等优先级数据
10AF11001010低优先级数据

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 头部之后的头部类型。这就是指定扩展头部和上层协议的方式。

常见值

协议/扩展描述
6TCP传输控制协议
17UDP用户数据报协议
58ICMPv6IPv6 的互联网控制消息协议
0逐跳选项扩展头部,必须是第一个
43路由路由扩展头部
44分片分片扩展头部
60目标选项目标选项扩展头部
51AH认证头部(IPsec)
50ESP封装安全有效载荷(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(生存时间)字段,但名称更准确——它计算跳数,而不是时间。

常见初始值

操作系统/协议栈默认跳数限制原因
Linux64RFC 4861 建议
Windows128历史默认值
Cisco IOS64标准合规性
BSD64KAME 协议栈默认值

为什么不同的值对于指纹识别很重要

你可以通过查看接收数据包中的跳数限制来猜测源操作系统:

接收到的跳数限制: 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 类型 3

7. 源地址(128 位)#

数据包发送者的 IPv6 地址。始终 128 位,没有例外。

格式:标准 IPv6 地址表示法

2001:db8:1234:5678:9abc:def0:1234:5678

特殊考虑

**未指定地址(::)**仅在特定情况下有效:

  • 重复地址检测(DAD)
  • 地址分配前的 DHCP 请求
  • 某些 ICMPv6 消息

**链路本地地址(fe80::/10)**是有效的源地址,但仅在本地链路上。路由器不转发具有链路本地源的数据包。

多播地址永远不是有效的源地址。具有多播源的数据包应立即丢弃。

实际问题:源地址选择

当主机具有多个 IPv6 地址(使用 SLAAC、DHCPv6 和隐私扩展很常见)时,它必须选择用作源的地址。RFC 6724 定义了选择算法,优先选择:

  1. 与目标地址范围相同的地址
  2. 具有更长匹配前缀的地址
  3. 非弃用地址
  4. 具有更高偏好的地址

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 头部比较#

理解什么改变了有助于欣赏设计决策。

功能IPv4IPv6为什么改变
头部大小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 定义了存在多个扩展头部时的推荐顺序:

  1. 逐跳选项(0)
  2. 目标选项(当存在路由头部时用于中间目标)
  3. 路由(43)
  4. 分片(44)
  5. 认证头部(51)
  6. 封装安全有效载荷(50)
  7. 目标选项(60)(用于最终目标)
  8. 上层(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(一个数据包的所有分片相同)

分片如何工作

  1. 源尝试发送大数据包
  2. 接收 ICMPv6 数据包太大消息
  3. 将数据包分片成较小的片段
  4. 为每个片段添加分片头部
  5. 目标根据标识字段重组

示例

原始 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                               .
.                                                               .
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

用例

  • 对齐填充
  • 应用程序特定选项
  • 未来扩展而不更改基本头部

可以在头部链中出现两次:

  1. 在路由头部之前(由中间目标处理)
  2. 在 ESP/AH 头部之后(由最终目标处理)

认证头部(类型 51)和 ESP(类型 50)#

提供认证和加密的 IPsec 头部。

AH(51):提供认证和完整性,但不提供机密性。很少使用,因为 ESP 可以做同样的事情加上加密。

ESP(50):提供机密性、认证和完整性。VPN 和加密通信的标准。

IPsec 是超出头部结构的大主题。关键点:这些头部从一开始就是 IPv6 设计的一部分,不像 IPv4 中 IPsec 是后来添加的。

处理扩展头部#

主机必须

  • 按顺序处理所有扩展头部
  • 支持所有标准扩展头部
  • 根据下一个头部值处理未知头部

路由器通常

  • 仅检查逐跳选项
  • 转发其他扩展头部而不处理
  • 出于安全考虑,可能会限制速率或丢弃带有某些头部的数据包

防火墙考虑

扩展头部使防火墙复杂化,因为:

  • 传输头部(TCP/UDP)可能在数据包深处
  • 必须解析整个链以找到用于过滤的端口
  • 攻击者可以使用复杂的头部链混淆有效载荷

最佳实践:

  • 限制扩展头部链长度
  • 丢弃带有弃用头部的数据包(类型 0 路由)
  • 在检查之前重组分片
  • 限制带有逐跳选项的数据包的速率

为什么没有校验和?#

IPv4 包含一个头部校验和,路由器必须在每一跳重新计算(因为 TTL 改变)。IPv6 故意省略了这个。

原因

  1. 链路层已经有校验和:以太网有 CRC32。Wi-Fi 有校验和。现代链路层是可靠的。

  2. 传输层校验和:TCP 和 UDP 包括覆盖数据和头部的校验和。端到端验证无论如何都会发生。

  3. 路由器性能:在每一跳重新计算校验和浪费 CPU 周期。高速路由器每秒转发数十亿个数据包——消除校验和计算有帮助。

  4. 错误很少见:现代网络具有低比特错误率。校验和捕获的错误比 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 SYN

Wireshark#

Wireshark 提供详细的头部分析:

过滤器

# 所有 IPv6 流量
ipv6
 
# 带有特定扩展头部的数据包
ipv6.nxt == 0    # 逐跳
ipv6.nxt == 43   # 路由
ipv6.nxt == 44   # 分片
ipv6.nxt == 60   # 目标选项
 
# 分片数据包
ipv6.fragment
 
# 特定流量类别
ipv6.tclass == 46  # 加速转发

头部检查

  1. 在数据包详细信息中展开「Internet Protocol Version 6」
  2. 查看所有 8 个字段清楚标记
  3. 扩展头部显示为单独的层
  4. 右键单击字段进行过滤

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-QOS

MTU 不匹配#

问题: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 地址

使用我们的 IPv6 验证器检查地址格式,使用我们的 Ping 工具测试连接并检查响应中的头部字段。

常见问题#

为什么 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——将它们配置为允许基本头部。