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 情况下,您通常不得不调用 htonl
和 ntohl
函数。
除非您要将 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
来处理。
我正在尝试根据 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 情况下,您通常不得不调用 htonl
和 ntohl
函数。
除非您要将 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
来处理。