IPv6 的 STUN 服务器 xoring

STUN server xoring of IPv6

我正在尝试根据 RFC 5389:

解码 STUN 成功响应

If the IP address family is IPv6, X-Address is computed by taking the mapped IP address in host byte order, XOR'ing it with the concatenation of the magic cookie and the 96-bit transaction ID, and converting the result to network byte order.

Magic cookie 是一个常量,它是 0x2112A442。

我的交易 ID 是:0x6FA22B0D9C5F5AD75B6A4E43。

我的 X-Address (IPv6) 在主机字节顺序中是:

0x034A67D82F4B3657B193039A8BA8FDA1

我是否必须将主机字节顺序 X-Address 与网络中的 Magic Cookie 和事务 ID 或主机字节顺序的串联进行异或运算?

在第一种情况下,网络字节顺序连接等于:

0x2112A442 6FA22B0D9C5F5AD75B6A4E43

第一个字节0x03与0x21异或,最后一个字节0xA1与0x43异或

但在第二种情况下,主机字节顺序连接是:

0x434E6A5BD75A5F9C0D2BA26F 42A41221

第一个字节 0x03 与 0x43 异或,最后一个字节 0xA1 与 0x21 异或。

另一种可能的行为是,如果它单独获取 Magic cookie 和事务 ID 并将其转换为主机字节顺序,但将它们连接起来并保留 header 顺序:

0x42A41221 434E6A5BD75A5F9C0D2BA26F

第一个字节 0x03 与 0x42 异或,最后一个字节 0xA1 与 0x6F 异或。

一切都按网络字节顺序完成。

但问题是,对于 IPv6 地址,"host byte order" 和 "network byte order" 之间没有区别。 IPv6 地址始终被理解为一个 16 字节的数组。并且单个字节没有 "byte order"。在 "C" 代码中,我们将 IPv6 地址表示为:

 unsigned char ipv6address[16];

或者根据 sockaddr_in6 结构;

 struct sockaddr_in6 addr;
 unsigned char* ipv6addresss = addr.sin6_addr.s6_addr; // points to a sequence of 16 bytes

将其与 IPv4 进行对比,IPv4 通常在代码中作为 32 位整数传递。在 IPv4 情况下,您通常不得不调用 htonlntohl 函数。

除非您要将 IPv6 地址维护为 8 个 16 位整数数组而不是字节数组,否则您不必过多考虑字节顺序和字节顺序。 (事实上​​,我建议您不要考虑 16 字节 IP 地址的字节顺序)。

示例:

我的 IPv6 地址是这样的:

2001:0000:9d38:6abd:347d:0d08:3f57:fefd

作为十六进制字节数组,逻辑上写为:

200100009d386abd347d0d083f57fefd

当我的 STUN 服务器收到来自这个 IPv6 地址的绑定请求时,它应用以下 XOR 操作来发回 XOR-MAPPED-ADDRESS。假设它与您的交易 ID 相同,并且包含表示支持 RFC 5389 的魔术 cookie (2112A442 6FA22B0D9C5F5AD75B6A4E43)

XOR:
     200100009D386ABD347D0D083F57FEFD
     2112A4426FA22B0D9C5F5AD75B6A4E43

结果:

     0113A442F29A41B0A82257DF643DB0BE

同理,收到STUN绑定响应的客户端对这个具有相同事务id的字节数组进行逆异或操作

XOR:
     0113A442F29A41B0A82257DF643DB0BE
     2112A4426FA22B0D9C5F5AD75B6A4E43

结果:

     200100009D386ABD347D0D083F57FEFD

您可以参考 Stuntman 的源代码,如果这有助于举例说明如何应用 xor 映射操作。异或运算为here on GitHub。此处的代码不区分带有魔术 cookie 的交易 ID 和不带有魔术 cookie 的交易 ID。它只是把交易id当作一个16字节的逻辑序列。

以上内容处理了 IPv6 地址。但是,如果 16 位端口值被视为 short 或 16 位整数,则它必须进行字节翻转。在 C 代码中,这通常通过调用 ntohs 来处理。