Disabling CLAT46 on macOS Ventura

posted
2023-08-12

Long story short: I run an IPv6-only network at home. Explaining why is out of scope here.

Like Ondřej Caletka and Jason Healy have already discussed in their respective posts, the past couple of macOS releases have been shipping with IPv4-to-IPv6 client-side translation (CLAT46).

Essentially this means you can transparently interact with IPv4 addresses without an IPv4 connection, provided that your IPv6 connection supports NAT64:

$ sudo networksetup -setv4off Wi-Fi
$ ping -c1 1.1.1.1
PING 1.1.1.1 (1.1.1.1): 56 data bytes
64 bytes from 1.1.1.1: icmp_seq=0 ttl=59 time=6.691 ms

--- 1.1.1.1 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 6.691/6.691/6.691/0.000 ms

See the previous links for how CLAT works in detail.

Auto-configuration on macOS

This is what little I’ve found out about the implementation.

During network setup, the com.apple.IPConfiguration subsystem decides whether CLAT should be enabled, and logs this in Console:

default 08:46:40.447314+0300    configd RTADV en0: CLAT46 enabled using address 192.0.0.2
default 08:46:42.059657+0300    configd RTADV en0: removed CLAT46 address 192.0.0.2

The IPConfiguration agent can be tinkered with using ipconfig, which returns the CLAT status through ipconfig getsummary <interface> when active:

$ ipconfig getsummary en0
<dictionary> {
  IPv6 : <array> {
    0 : <dictionary> {
      RTADV : <dictionary> {
        CLAT46Active : TRUE
        ...
      }
      ...
    }
  }
  ...
}

There’s also a sysctl flag called net.inet6.ip6.clat_debug that I assume outputs additional details in the logs. This might require running sudo ipconfig setverbose 1.

Problems in macOS Ventura

More recently, macOS Ventura seems to have relaxed the requirements to automatically enable CLAT.

My home network uses OpenWrt, and it’s configured IPv6-only with SLAAC (without DHCPv6) and has both NAT66 and NAT64 (using Jool). I haven’t set the RFC 7050 Pref64 RA flag, nor does the network have a DHCPv4 server that might advertise the RFC 8925 IPv6-Only Preferred option.

After upgrading to macOS Ventura, I was very confused to see IPv4 traffic supposedly working, until I learned about the CLAT. I think auto-configuring CLAT is great for IPv6 adoption, but it seems there are still some bugs:

  1. Firefox and other software now stubbornly prefer IPv4, although explicit IPv6 connections are handled correctly. Even attempting to force curl’s happy eyeballs implementation to give IPv6 a generous head start doesn’t work, and an IPv4 connection is made immediately:

    $ curl -vvv --happy-eyeballs-timeout-ms=1000 https://icanhazip.com
    *   Trying 104.18.114.97:443...
    * Connected to icanhazip.com (104.18.114.97) port 443 (#0)
    
  2. A more annoying bug is one that Jason Healy wrote about, where CLAT routes are sometimes misconfigured after switching networks. This has also happened to me, often after waking my laptop from sleep in the morning.

    Disconnecting and reconnecting fixes this right away, but the issue is usually back the next morning. Restarting macOS gets rid of this issue for a while, but it’ll eventually return.

Workaround

I wanted to validate that CLAT was really the source of these issues. The first thing I tried was disabling IPv4 altogether in System Settings, which can also be done using networksetup:

$ sudo networksetup -setv4off Wi-Fi

Unfortunately CLAT doesn’t care about whether IPv4 is enabled, and it’s auto-configured nevertheless. Next, I simply deleted the configured IPv4 address using ifconfig:

$ sudo ifconfig en0 delete 192.0.0.2

This did the trick, and the issues I’d seen went away immediately.

Unfortunately just removing the address doesn’t persist anywhere, and after reconnecting to the network, CLAT was auto-configured again with the same settings.

After perusing manpages and the morsels of macOS IPv6 documentation I could find, I was unable to find a nice CLAT-specific flag that could disable it.

Eventually I was able to figure out a workaround: configuring IPv4 with a link-local address from 169.254.0.0/16. Here’s an example, you might want to pick a random address from that block instead of this one:

$ sudo networksetup -setmanual Wi-Fi 169.254.1.1 255.255.255.0

ipconfig getsummary en0 now reports ConfigMethod : LinkLocal for IPv4, and more crucially, CLAT46Active is nowhere to be seen.