While looking at ~/.ssh/known_hosts
I was confused to see a recent entry for an IPv6 address that didn't look like any of the hosts I might recently have connected to:
64:ff9b::8c52:7904 ssh-rsa AAAAB3NzaC1yc2EAAA...
(ssh will usually be configured with HashKnownHosts yes
these days, but it's swiched off on macOS.)
Neither RDAP or whois will show any registration information for that IP address, but it's from 64:ff9b::/96
which is the "Well-Known Prefix" for NAT64 (RFC 6052 and RFC 8215) which is a range for allowing IPv6-only services to contact IPv4-only addresses.
I was vaguely aware of IPv6 translation, but have not actually had exposure to it as I'd only (knowingly) used "dual-stack" IPv4/IPv6 systems.
You can use the ipc6calc command-line tool to get the normal IPv4 address out of a NAT64 address, and vice-versa.
% ipv6calc --action convnat64 -O ipv4addr -I ipv6addr 64:ff9b::8c52:7903
140.82.121.3
% ipv6calc --action convnat64 -I ipv4addr -O ipv6addr 140.82.121.3
64:ff9b::8c52:7903
% ipv6calc --action convnat64 -O ipv4addr -I ipv6addr 64:ff9b::8c52:7903 | xargs -I {} host {}
3.121.82.140.in-addr.arpa domain name pointer lb-140-82-121-3-fra.github.com.
So it looks like the address is one of those serving ssh for github.com
.
I connected to the EE network, found the network-supplied nameserver (which will be in /etc/resolv.conf
unless you override it in your network profile), which in this case is the private, temporary, internal IP address 172.20.10.1
of the wifi access point itself.
You can then compare queries for GitHub via the local nameserver, and Google's 8.8.8.8
(via both IPv4 and IPv6).
% dig +short github.com a @8.8.8.8
140.82.121.3
% dig +short github.com a @2001:4860:4860::8844
140.82.121.3
% dig +short github.com a @172.20.10.1
140.82.121.4
% dig +short github.com aaaa @8.8.8.8
% dig +short github.com aaaa @2001:4860:4860::8844
% dig +short github.com aaaa @172.20.10.1
64:ff9b::8c52:7904
The first thing to note GitHub is still IPv4-only in 2021! The IP address 140.82.121.3
is inside one of the ranges (140.82.112.0/20
) listed in the API meta data listing GitHub's public IP addresses. Although there are a few IPv6 ranges also listed, so perhaps IPv6 support will be forthcoming? (They recently turned on IPv6 support for Pages.)
So it looks like EE (and I'm assuming this is happening at the upstream network rather than via the access point), is using synthetic AAAA records derived from A records (DNS64 per RFC 6147) to direct IPv4 traffic via an IPv6 translation-layer (NAT64).
The way you can detect the presence of a DNS64 server is to query the record ipv4only.arpa
, a zone that doesn't have any IPv6 records, for IPv6 records (per RFC 7050). The server seems to support the AAAA synthesis, but doesn't seem to support the PTR records needed for validation (via DNSSEC).
% dig +short ipv4only.arpa a +dnssec @8.8.8.8
192.0.0.170
192.0.0.171
% dig +short ipv4only.arpa aaaa @8.8.8.8
% dig +short ipv4only.arpa aaaa @172.20.10.1
64:ff9b::c000:aa
64:ff9b::c000:ab
% dig +short ipv4only.arpa aaaa | ipv6calc --action convnat64 -O ipv4addr -I ipv6addr
192.0.0.170
192.0.0.171
% dig +short -x 64:ff9b::c000:aa +dnssec @172.20.10.1
170.0.0.192.in-addr.arpa.
% dig +short -x 64:ff9b::c000:aa +dnssec | xargs -I {} dig {} PTR +short +dnssec
% dig +short 170.0.0.192.in-addr.arpa. PTR
If I log into a remote server twice using the NAT64 address and its IPv4 address, then I'm connecting from two different addresses (in the same /24).
So it looks like IPv4 is being passed through a NAT64 gateway where NAT64 discovery is availble on the device, and probably 464XLAT (RFC 6877) for direct IPv4 requests.
Indeed, searching for "EE 464XLAT" shows a couple of documents (464xlat for mobile operators and BT & EE update) suggesting that EE moved to IPv6+NAT64 in 2018. One of the slides suggests that moving from NAT to IPv6+NAT64 would "Save on 65% of NAT load", which suggests this might become more common. It's a hack, but possibly slightly more efficient hack.
("Cost avoidance for national regulatory obligations" is also mentioned in a slide, which I read as a reference to the “Internet Connection Record” requirements imposed on network providers in the UK to record logs of subscriber activity, something which other networks have found too difficult to bolt on to their existing CGNAT architectures.)
My main takeaway from skimming this stuff is: Firstly, ISPs - and probably not just mobile ISPs - really don't want to support dual-stack and will be pushing for IPv6-only networks as soon as they can, probably using 5G as the excuse. Secondly, while IPv4 NAT is terrible, NAT64 is terrible also. Operators of network services need to ensure they're offering via IPv6 to avoid a lot of hard-to-diagnose/hard-to-reproduce access issues over the next few years.
One other thing to consider is that this is a genuine situation in which the use of third-party DNS (especially DoH/DoT) can degrade a user experience. If NAT64 performs better than 464XLAT, and a network-specific DNS64 server is needed to translate, users with third-party DNS resolvers would always receive a worse connection (for IPv4 services).