11. DHCP 唯一标识符 (DUID)
每个 DHCP 客户端和服务器都有一个 DUID. DHCP 服务器使用 DUID 来识别客户端, 以选择配置参数并把 IA 与客户端关联. DHCP 客户端在需要标识服务器的消息中使用 DUID 来识别服务器. 关于 DHCP 消息中 DUID 表示方式的详细信息, 见第 21.2 节和第 21.3 节.
客户端和服务器必须把 DUID 视为不透明值, 并且只能比较 DUID 是否相等. 客户端和服务器不应该以任何其他方式解释 DUID. 客户端和服务器不得把 DUID 限制为本文档定义的类型, 因为未来可能定义额外的 DUID 类型. 需要注意, 试图解析 DUID 以获得客户端链路层地址是不可靠的, 因为不能保证客户端仍在使用生成该 DUID 时所使用的同一个链路层地址. 此外, 随着更多客户端采用 [RFC7844] 中定义的隐私措施, 这种尝试会越来越不可靠. 如果需要这种能力, 建议改为依赖 Client Link-Layer Address 选项 [RFC6939].
DUID 被承载在选项中, 因为它的长度可能可变, 并且并非所有 DHCP 消息都需要它. DUID 设计为在所有 DHCP 客户端和服务器之间唯一, 并且对任何特定客户端或服务器保持稳定. 也就是说, 客户端或服务器使用的 DUID 如果可能就不应该随时间变化. 例如, 设备的 DUID 不应因设备网络硬件变化或虚拟接口变化而改变, 例如客户驻地设备路由器中可能出现或消失的逻辑 PPP (over Ethernet) 接口. 客户端可以按 [RFC7844] 的规定更改其 DUID.
存在多种 DUID 类型的动机是, DUID 必须全局唯一, 同时还必须易于生成. 对于任意给定设备而言, 易于生成的全局唯一标识符类型可能差异很大. 此外, 某些设备可能不包含任何持久存储. 这类设备无法保留生成的 DUID, 因此 DUID 方案必须能够适应这些设备.
11.1. DUID 内容
DUID 由以网络字节序表示的 2-octet 类型代码组成, 后跟数量可变的 octet, 这些 octet 构成实际标识符. DUID 的长度不包括类型代码, 至少为 1 octet, 最多为 128 octets. 当前定义了以下类型:
| 类型 | 描述 |
|---|---|
| 1 | 链路层地址加时间 |
| 2 | 基于 Enterprise Number 的供应商分配唯一 ID |
| 3 | 链路层地址 |
| 4 | Universally Unique Identifier (UUID) [RFC6355] |
表 2: DUID 类型
上述前 3 种类型的 DUID 可变字段格式如下所示. 第 4 种类型 DUID-UUID [RFC6355] 可用于设备固件设置中存有 UUID 的场景.
11.2. 基于链路层地址加时间的 DUID (DUID-LLT)
这种 DUID 包含一个值为 1 的 2-octet type 字段, 一个 2-octet hardware type 代码, 以及一个包含时间值的 4 octets 字段, 后跟生成 DUID 时连接到 DHCP 设备的任意一个网络接口的链路层地址. 时间值是生成 DUID 的时间, 表示为自 2000 年 1 月 1 日午夜 (UTC) 起的秒数, 对 2^32 取模. hardware type 必须是 IANA 分配的有效硬件类型, 见 [IANA-HARDWARE-TYPES]. 时间和 hardware type 都以网络字节序存储. 对于 Ethernet 硬件类型, 链路层地址按 [RFC2464] 描述的规范形式存储.
下图展示 DUID-LLT 的格式:
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| DUID-Type (1) | hardware type (16 bits) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| time (32 bits) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
. .
. link-layer address (variable length) .
. .
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
图 4: DUID-LLT 格式
只要接口能够为该链路类型提供全局唯一的链路层地址, 网络接口的选择就可以完全任意. 同一个 DUID-LLT 应该用于配置连接到该设备的所有网络接口, 无论生成 DUID-LLT 时使用的是哪个接口的链路层地址.
使用这种 DUID 的客户端和服务器必须把 DUID-LLT 存储在稳定存储中, 并且即使生成 DUID-LLT 所用的网络接口被移除, 也必须继续使用该 DUID-LLT. 没有任何稳定存储的客户端和服务器不得使用这种 DUID.
使用这种 DUID 的客户端和服务器如果可能, 应在生成 DUID 前尝试配置时间, 并且在生成 DUID 时必须使用某种时间源, 例如实时时钟, 即使该时间源在生成 DUID 前无法配置. 使用时间源可以降低两个相同 DUID-LLT 被生成的可能性, 例如当网络接口从某个客户端移除后又被另一个客户端用来生成 DUID-LLT 时. 即使时钟在生成 DUID 前未配置, 两个 DUID-LLT 发生冲突的可能性也非常低.
这种 DUID 生成方法建议用于所有通用计算设备, 例如台式计算机和笔记本电脑, 也建议用于包含某种可写非易失性存储的设备, 例如打印机, 路由器等.
这种生成 DUID 的算法可能导致客户端标识符冲突. 使用该机制生成 DUID-LLT 的 DHCP 客户端必须提供一个管理接口, 用新生成的 DUID-LLT 替换现有 DUID.
11.3. 供应商基于 Enterprise Number 分配的 DUID (DUID-EN)
供应商向设备分配这种形式的 DUID. 该 DUID 由供应商在 IANA 维护的已注册 Private Enterprise Number [IANA-PEN] 中的 4-octet 编号组成, 后跟供应商分配的唯一标识符. 下图总结了 DUID-EN 的结构:
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| DUID-Type (2) | enterprise-number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| enterprise-number (contd) | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
. identifier .
. (variable length) .
. .
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
图 5: DUID-EN 格式
标识符来源由定义它的供应商决定, 但每个 DUID-EN 的每个标识符部分都必须对使用它的设备唯一, 并且必须不晚于首次使用时分配给设备并存储在某种非易失性存储中. 对于物理设备, 这通常表示在制造过程中分配. 对于虚拟机, 这通常表示在镜像创建时或首次启动时分配. 生成的 DUID 应记录在不可擦除存储中. enterprise-number 是供应商在 IANA 维护的已注册 Private Enterprise Number [IANA-PEN]. enterprise-number 以无符号 32-bit 数字存储.
这种类型的 DUID 示例可能如下:
+---+---+---+---+---+---+---+---+
| 0 | 2 | 0 | 0 |126|217| 12|192|
+---+---+---+---+---+---+---+---+
|132|211| 3 | 0 | 9 | 18|
+---+---+---+---+---+---+
图 6: DUID-EN 示例
此示例包括值为 2 的 2-octet type 和 Enterprise Number (32473) (来自 [RFC5612]), 后跟 8 octets 标识符数据 (0x0CC084D303000912).
11.4. 基于链路层地址的 DUID (DUID-LL)
这种 DUID 由 2 octets 的 DUID type 3 和一个 2-octet 网络 hardware type 代码组成, 后跟永久连接到客户端或服务器设备的任意一个网络接口的链路层地址. 例如, 某个节点的网络接口实现在不太可能被移除并在别处使用的芯片中, 则可以使用 DUID-LL. hardware type 必须是 IANA 分配的有效硬件类型, 见 [IANA-HARDWARE-TYPES]. hardware type 以网络字节序存储. 链路层地址按 [RFC2464] 描述的规范形式存储. 下图展示 DUID-LL 的格式:
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| DUID-Type (3) | hardware type (16 bits) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
. .
. link-layer address (variable length) .
. .
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
图 7: DUID-LL 格式
只要接口能够提供唯一的链路层地址, 且永久连接到正在生成 DUID-LL 的设备, 网络接口的选择就可以完全任意. 同一个 DUID-LL 应该用于配置连接到该设备的所有网络接口, 无论生成 DUID 时使用的是哪个接口的链路层地址.
DUID-LL 建议用于具有永久连接的网络接口及链路层地址, 且没有非易失性可写稳定存储的设备. 如果 DHCP 客户端或服务器无法判断某个网络接口是否永久连接到运行 DHCP 客户端的设备, 则不应该使用 DUID-LL.
11.5. 基于 Universally Unique Identifier 的 DUID (DUID-UUID)
这种 DUID 由包含 128-bit UUID 的 16 octets 组成. [RFC6355] 详细说明何时使用这种类型, 以及如何选择适当的 UUID 来源.
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| DUID-Type (4) | UUID (128 bits) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| |
| |
| -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
图 8: DUID-UUID 格式