背景(可跳过阅读)
我有一台运行 Wireguard 的服务器,多个 Android 设备使用Wireguard 应用程序。此服务器有 2 个 WAN 连接 - 一条较快的线路,具有公共 IPv6 地址和 CG-NAT 后面的 IPv4 地址,另一条较慢的线路具有公共 IPv4 地址但没有 IPv6 连接。我使用 DDNS 服务来跟踪这两个公共 IP 地址。
Wireguard 应用程序存在一个问题:当域端点具有 IPv4 和 IPv6 地址时,它优先使用 IPv4 地址进行连接。(此问题已在多种的 地点而且看起来这个问题不会很快得到解决。)结果,所有客户端最终都使用较慢的线路进行连接,导致隧道几乎无法使用。
我的解决方法和问题
为了解决上述问题,我决定使用仅具有 AAAA 记录(没有 A 记录)的域,其中将添加以下记录:
2401:xxxx:xxxx:xxxx::1234:1
- 公共 IPv6 地址::ffff:xxx.xxx.xxx.xxx
- 公共 IPv4 地址映射形式(当然,最后两段使用正确的十六进制表示法)
我的假设是,当客户端可以使用 IPv6 连接时,将尝试第一个地址,而当客户端处于仅 IPv4 网络中(没有 IPv6 默认路由)时,将尝试第二个地址,这将完美地运行。
然而,当我尝试使用仅具有第二种类型记录(IPv4 映射地址)的域进行测试时,结果发现它根本不起作用,无论是在 Wireguard 应用程序中还是在其他任何地方。
我的观察如下:
假设:假设 IPv4 地址为 192.168.1.1,它在端口 80 上托管一个 Web 服务器,并且域中some-domain.com
有一个指向的 AAAA 记录::ffff:c0a8:101
:
http://192.168.1.1/
我可以通过浏览器访问网页http://[::ffff:192.168.1.1]/
我可以通过访问或http://[::ffff:c0a8:101]/
在我的浏览器中访问网页使用正确输出响应中的
nslookup some-domain.com
地址::ffff:192.168.1.1
http://some-domain.com
在浏览器中使用或ping6 some-domain.com
在名称未解析或者未知主机错误。
我的问题是什么导致了这种现象:是什么原因导致最终应用程序丢弃 DNS 服务器返回的 IPv4 映射 AAAA 记录,尽管当直接给出映射地址而没有域时它们可以正常工作?
答案1
应用程序不会丢弃映射的 AAAA 记录 - 它们甚至不会查询当它们处于仅 IPv4 网络中且没有配置本地 IPv6 地址时,根本不存在 AAAA 记录。
这是大多数操作系统上的系统 DNS 解析器的“标准”行为(它们期望 IPv4 地址仅在 A 记录中找到,我认为这是完全合理的假设)。例如,Linux getaddrinfo() 函数通常会传递 AI_ADDRCONFIG 标志以抑制未配置的地址系列,并会相应地跳过 A 或 AAAA 查询。
(nslookup 不使用系统解析器;此工具的全部目的是进行直接 DNS 查询,因此其行为总是不同的。)