Is this a support request?
Is there an existing issue for this?
Current Behavior
This looks a lot like an issue with the Tailscale client and not headscale, per se, but I wanted to document it just in case someone else runs into it.
On a headscale node with a variety of clients (iOS, linux, MacOS), nodes with only IPv6 fail to register with consistency. No testing was done with Windows.
Example:
Headscale node is dual-stacked with A and AAAA records, client is dual stacked: no issues
Headscale is dual-stacked with A and AAAA records, client is IPv4-only: no issues
Headscale is dual-stacked with A and AAAA records, client is IPv6-only with a NAT64: Failure in ability to register
Headscale is dual-stacked with only AAAA record, client is IPv6-only with a NAT64: Successful in ability to register
If the A record is re-added, the client will degrade over time as noted in the client alerts.
From doing packet captures it appears that if there is an A record the Tailscale client will continually try to make that work, trending toward preferring IPv4, which is counter to the default selection algorithm defined in RFC6724. Strangely, when the exact same host connects to tailscale with IPv6-only there are no issues even over months and months of time.
This could be a happy eyeballs problem, regardless the clients should use the available protocols.
I have also not tried to connect without a NAT64 in the path yet.
On static, non-portable linux hosts adding the IPv6 name and address to /etc/hosts resolves the issue. On MacOS this did not seem to work. Will try adding the AAAA to the local caching resolver.
Expected Behavior
Client and server both prefer IPv6 as defined in RFC6724
Steps To Reproduce
Set up headscale in a dual-stacked deployment with both A and AAAA records.
Connect from an IPv6-only client with a NAT64.
Environment
- OS:
MacOS 26.5.2
Debian Linux 13
Ubuntu Linux 24.04.2
Ubuntu Linux 22.04.5
- Headscale version:
headscale version v0.29.2
commit: 8eea89488c642f3d5f617fab5493d5f51f6f4ad0
build time: 2026-07-01T14:47:39Z
built with: go1.26.4 linux/amd64
- Tailscale version:
Linux 1.98.4
tailscale commit: 9e69045b291a7cb1edc714442d68e83b95d05e6b
long version: 1.98.4-t9e69045b2-ged3a62f14
other commit: ed3a62f143dd73c8aae368d9c639ea49de878f9b
go version: go1.26.3 (tailscale/go e877d97384)
MacOS 1.98.5
tailscale commit: 8f8fe6a2e167459ed0f62616287b61b0b0a54eb5
long version: 1.98.5-t8f8fe6a2e-gc1619fb10
other commit: c1619fb10d5db0f7cb1d109d5b67d053f7751508
go version: go1.26.3 (tailscale/go e877d97384)
Runtime environment
Debug information
These can be provided privately.
Is this a support request?
Is there an existing issue for this?
Current Behavior
This looks a lot like an issue with the Tailscale client and not headscale, per se, but I wanted to document it just in case someone else runs into it.
On a headscale node with a variety of clients (iOS, linux, MacOS), nodes with only IPv6 fail to register with consistency. No testing was done with Windows.
Example:
Headscale node is dual-stacked with A and AAAA records, client is dual stacked: no issues
Headscale is dual-stacked with A and AAAA records, client is IPv4-only: no issues
Headscale is dual-stacked with A and AAAA records, client is IPv6-only with a NAT64: Failure in ability to register
Headscale is dual-stacked with only AAAA record, client is IPv6-only with a NAT64: Successful in ability to register
If the A record is re-added, the client will degrade over time as noted in the client alerts.
From doing packet captures it appears that if there is an A record the Tailscale client will continually try to make that work, trending toward preferring IPv4, which is counter to the default selection algorithm defined in RFC6724. Strangely, when the exact same host connects to tailscale with IPv6-only there are no issues even over months and months of time.
This could be a happy eyeballs problem, regardless the clients should use the available protocols.
I have also not tried to connect without a NAT64 in the path yet.
On static, non-portable linux hosts adding the IPv6 name and address to /etc/hosts resolves the issue. On MacOS this did not seem to work. Will try adding the AAAA to the local caching resolver.
Expected Behavior
Client and server both prefer IPv6 as defined in RFC6724
Steps To Reproduce
Set up headscale in a dual-stacked deployment with both A and AAAA records.
Connect from an IPv6-only client with a NAT64.
Environment
Runtime environment
Debug information
These can be provided privately.