In my dual-stack LAN, a bind server resolves local domains (*.something.internal
) for both A and AAAA records:
# 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
and all LAN webservers listen on IPv4 and IPv6. When accessing the servers, IPv6 gets prioritized (as expected) except for my local client (which also acts as a webserver) in Firefox and Safari. Chrome uses IPv6 addresses for all servers. I used the Network tab of the developer tools in all three browsers to compare and verify the behavior.
I also used the about:networking#dnslookuptool
feature in Firefox, and Firefox consistently reverses the order of IPv4 / IPv6 IPs for my client only.
As a next step, I checked with curl, and saw (almost) the same thing. curl resolves IPv6 first, but then proceeds to use the IPv4 address for the local machine:
# 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
Why do Firefox, Safari and curl prioritize IPv4 for the local machine (unlike Chrome)? Could it have something to do with the fact that the request is sent from the very same IPv6 address the domain resolves to (even though curl uses this address without a problem when forced to with curl -Iv -6 https://static.something.internal
)?
Note: If I populate /etc/hosts
on the local machine (using 127.0.0.1
and ::1
for its domains) instead of using my DNS server, all applications prioritize IPv6 (the following curl test was repeated with Firefox and Safari):
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
As I commented already: The curl team has confirmed that the behavior stems from the ordered list returned by
getaddrinfo()
(and has implemented a change already). I filed a report with Mozilla regarding Firefox, which is still pending.This may need to take into consideration that preference is selectable at the operating system level. Both Windows and Linux have a mechanism to prefer IPv6 over IPv4 and vice-versa. That information is then presented to the application using getaddrinfo().
Can application override? I suspect so, but this doesn't seem to be new territory.
See:
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
"Our context for address selection derives from the most common implementation architecture, which separates the choice of destination address from the choice of source address. Consequently, we have two separate algorithms for these tasks. The algorithms are designed to work well together and they share a mechanism for administrative policy override.
"In this implementation architecture, applications use APIs [10] like getaddrinfo() that return a list of addresses to the application. This list might contain both IPv6 and IPv4 addresses (sometimes represented as IPv4-mapped addresses). The application then passes a destination address to the network stack with connect() or sendto(). The application would then typically try the first address in the list, looping over the list of addresses until it finds a working address. In any case, the network layer is never in a situation where it needs to choose a destination address from several alternatives."