IPv6-only flag set on v6 sockets prevents the use of v4-mapped addresses

Daniel Gröber dxld at darkboxed.org
Sat Aug 19 19:16:32 UTC 2023


Hi Nathaniel,

On Sat, Aug 19, 2023 at 05:34:00PM +0100, Nathaniel Filardo wrote:
> DNS absolutely can and does

I mean I can (and used to) enter fe80::/64 link local addressess into DNS
but it turns out this is actually forbidden by the RFCs but nothing will
stop you. I'm not convinced putting ::ffff: into DNS is a legitimate
use-case given that it it entirely up to an application whether it uses the
IPV6_V6ONLY socket option or dual-stack sockets instead as you've
noticed. This is supported by my reading of RFC4038.

I checked RFC4291/5156 for mentions of how IPv4-mapped v6 addresses are to
be treated but they don't mention any restrictions. So I guess it's up to
us to decide whether it's a legitimate use-case or not. Unless anyone else
has a reference to the contrary?

> In my use case they arise because I have scripts that take wireguard peer
> addresses and register them with my DNS service provider, and it's
> simpler to update a single AAAA record per peer regardless of address
> family than it is to switch between having an AAAA and A record for the
> name.
> 
> At the very least, the radio silence after the kernel accepts a
> v4-mapped v6 address is unexpected behavior.

Not really, in networking traffic black holes are pretty common. I'd expect
the ::ffff:0.0.0.0/96 traffic to get sent via the default route and being
filtered somewhere. Expected behaviour, some people might want to use
::ffff:0.0.0.0/96 as their NAT64 prefix for example. Though that might be
ill advised when a standardized local prefix exists ;)

> More generally, I don't see what good setting the v6only flag here is
> doing (in fact, that's true in general; there are very few
> circumstances, and most of those are for *listening* sockets, where
> v6only seems remotely sensible; the v4 to v6 migration is such a
> mess), so "the established wg behavior" makes no sense to me.

What you're probably not seeing is that there's a technical reason wg
doesn't use a single socket: The code currently supports CONFIG_IPV6 not
being set, so then it can't rely on being able to create a v6 socket! The
way it's written it's just easier to have two sockets and not switch
between v4-only and v6-mapped sockets.

I'm a IPv6-only-or-bust kind of guy so IMO we should just mandate
CONFIG_IPV6 and get rid of a whole bunch of legacy IPv4 code (yey), but
eh. someones probably going to complain about code-size for their v4-only
legacy use-case then :]

> (It's also plausibly true that I'm the first to *notice* this aspect
> of the established behavior!)

You're not, I noticed too when I was working-around the lack of the
AddressFamily= option with a PostUp= script using `getent ahostsv6` and
while the additional `| sed -n '/^::ffff:/d;s/\s*DGRAM.*$//p'` pushed the
PostUp= line over 80 characters I don't consider it an overly onerous
requirement :)

> In any case, in decreasing order of preference, I'd suggest:
> 1. Drop the v6only flag on peer sockets and allow the kernel speak to
> v4-mapped v6 addresses.
> 2. I missed something and v6only does serve a purpose; add special
> handling for v4-mapped v6 addresses to the wg kernel interface,
> bending them into v4 sockaddrs internally.
> 3. For some reason 2 isn't acceptable either, so add special handling
> to the wg userspace tools and do the transmogrification there.
> 4. For some reason none of that is tolerable, so have the kernel
> reject v4-mapped v6 addresses rather than silently accept them and
> fail to speak.

I don't like any of those. The way I see it your DynDNS approach is broken
please use the appropriate rrtype for each address-family. Note my opinion
is not authoritive here, Jason likely has the final say or, recently, more
likely lack of say ;)

In userspace we ask getaddrinfo() not to return v4-mapped addressess by
having AI_V4MAPPED unset, unfortunately this doesn't work when you enter
those addresses into DNS (a libc bug perhaps? *hint* *hint*). I would
suggest filtering them on our side if they get returned anyway and emitting
a warning so this is less of a stumbling block for the next poor soul.

I do wonder what the behavoir of the other wg implementations is on this
point, if it's inconsistent with the kernel impl. that's even more reason
to warn about it.

--Daniel


More information about the WireGuard mailing list