在我的双栈 LAN 中,绑定服务器解析本地域(*.something.internal
)的 A 和 AAAA 记录:
# bind zone file db.internal
webserver1.something IN AAAA 2001:908:532:bca0:211:32ff:fee5:8627
webserver1.something IN A 192.168.78.93
所有 LAN 网络服务器都监听 IPv4 和 IPv6。访问服务器时,IPv6 优先(如预期),但Firefox 和 Safari 中的本地客户端(也充当网络服务器)除外。Chrome 对所有服务器都使用 IPv6 地址。我使用了这三种浏览器中开发人员工具的“网络”选项卡来比较和验证行为。
我也在about:networking#dnslookuptool
Firefox 中使用了该功能,Firefox 仅为我的客户端持续反转 IPv4 / IPv6 IP 的顺序。
下一步,我使用 curl 进行了检查,看到了(几乎)相同的事情。curl 首先解析 IPv6,然后继续使用本地机器的 IPv4 地址:
# This is my local client and webserver
curl -Iv https://static.something.internal/
* Host static.something.internal:443 was resolved.
* IPv6: 2001:908:532:bca0:10e0:6db1:72f1:9c2f
* IPv4: 192.168.78.55
* Trying 192.168.78.55:443...
* Connected to static.something.internal (192.168.78.55) port 443
# This is another webserver on the LAN
curl -Iv https://nuc.something.internal/
* Host nuc.something.internal:443 was resolved.
* IPv6: 2001:908:532:bca0:1e69:7aff:feaf:7455
* IPv4: 192.168.78.42
* Trying [2001:908:532:bca0:1e69:7aff:feaf:7455]:443...
* Connected to nuc.something.internal (2001:908:532:bca0:1e69:7aff:feaf:7455) port 443
为什么 Firefox、Safari 和 curl 会优先为本地计算机使用 IPv4(与 Chrome 不同)? 这可能与请求是从域解析到的同一个 IPv6 地址发送的这一事实有关(即使 curl 在强制使用时毫无问题地使用此地址curl -Iv -6 https://static.something.internal
)?
/etc/hosts
注意:如果我在本地机器上填充(使用127.0.0.1
和::1
作为其域)而不是使用我的 DNS 服务器,则所有应用程序都会优先考虑 IPv6(使用 Firefox 和 Safari 重复了以下 curl 测试):
curl -Iv https://static.something.internal/
* Host static.something.internal:443 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
* Trying [::1]:443...
* Connected to static.something.internal (::1) port 443
正如我已经评论的那样:curl 团队已确认该行为源于返回的有序列表
getaddrinfo()
(并且已实施更改)。我向 Mozilla 提交了一份有关 Firefox 的报告,该报告仍悬而未决。这可能需要考虑到在操作系统级别可以选择首选项。Windows 和 Linux 都具有优先使用 IPv6 而不是 IPv4 的机制,反之亦然。然后使用 getaddrinfo() 将该信息呈现给应用程序。
应用程序可以覆盖吗?我怀疑是的,但这似乎不是新领域。
看:
https://weblog.lkiesow.de/20220311-make-linux-prefer-ipv4.html
https://learn.microsoft.com/en-us/troubleshoot/windows-server/networking/configure-ipv6-in-windows
https://www.ietf.org/rfc/rfc3484.txt
“我们的地址选择背景源自最常见的实现架构,该架构将目标地址的选择与源地址的选择分开。因此,我们针对这些任务有两种不同的算法。这些算法旨在很好地协同工作,并且它们共享一种管理策略覆盖机制。
“在此实现架构中,应用程序使用 getaddrinfo() 之类的 API [10],这些 API 将地址列表返回给应用程序。此列表可能包含 IPv6 和 IPv4 地址(有时表示为 IPv4 映射地址)。然后,应用程序使用 connect() 或 sendto() 将目标地址传递给网络堆栈。然后,应用程序通常会尝试列表中的第一个地址,循环遍历地址列表,直到找到一个有效的地址。无论如何,网络层永远不会处于需要从多个备选方案中选择一个目标地址的情况。”