|
Message-ID: <CAPDSy+4m+m5xjc63t-3Jnt-bdA8BQKHt60fTMnx1LgCyXnO2yA@mail.gmail.com>
Date: Thu, 7 Mar 2024 14:50:53 -0800
From: David Schinazi <dschinazi.ietf@...il.com>
To: Rich Felker <dalias@...c.org>
Cc: musl@...ts.openwall.com
Subject: Re: mDNS in musl
On Wed, Mar 6, 2024 at 6:42 PM Rich Felker <dalias@...c.org> wrote:
> On Wed, Mar 06, 2024 at 04:17:44PM -0800, David Schinazi wrote:
> > As Jeffrey points out, when the IETF decided to standardize mDNS, they
> > published it (RFC 6762) at the same time as the Special-Use Domain
> Registry
> > (RFC 6761) which created a process for reserving domain names for custom
> > purposes, and ".local" was one of the initial entries into that registry.
> > The UTF-8 vs punycode issue when it comes to mDNS and DNS is somewhat of
> a
> > mess. It was discussed in Section 16 of RFC 6762 but at the end of the
> day
> > punycode won. Even Apple's implementation of getaddrinfo will perform
> > punycode conversion for .local instead of sending the UTF-8. So in
> practice
> > you wouldn't need to special-case anything here.
>
> OK, these are both really good news!
>
> > There's also very much a policy matter of what "locally over
> > > multicast" means (what the user wants it to mean). Which interfaces
> > > should be queried? Wired and wireless ethernet? VPN links or other
> > > sorts of tunnels? Just one local interface (which one to prioritize)
> > > or all of them? Only if the network is "trusted"? Etc.
> > >
> >
> > You're absolutely right. Most mDNS systems try all non-loopback non-p2p
> > multicast-supporting interfaces, but sending to the default route
> interface
> > would be a good start, more on that below.
>
> This is really one thing that suggests a need for configurability
> outside of what libc might be able to offer. With normal DNS lookups,
> they're something you can block off and prevent from going to the
> network at all by policy (and in fact they don't go past the loopback
> by default, in the absence of a resolv.conf file). Adding mDNS that's
> on-by-default and not configurable would make a vector for network
> traffic being generated that's probably not expected and that could be
> a privacy leak.
>
Totally agree. I was thinking through this both in terms of RFCs and in
terms of minimal code changes, and had a potential idea. Conceptually,
sending DNS to localhost is musl's IPC mechanism to a more feature-rich
resolver running in user-space. So when that's happening, we don't want to
mess with it because that could cause a privacy leak. Conversely, when
there's a non-loopback IP configured in resolv.conf, then musl acts as a
DNS stub resolver and the server in resolv.conf acts as a DNS recursive
resolver. In that scenario, sending the .local query over DNS to that other
host violates the RFCs. This allows us to treat the configured resolver
address as an implicit configuration mechanism that allows us to
selectively enable this without impacting anyone doing their own DNS
locally.
> > When you do that, how do you control which interface(s) it goes over?
> > > I think that's an important missing ingredient.
> >
> > You're absolutely right. In IPv4, sending to a link-local multicast
> address
> > like this will send it over the IPv4 default route interface. In IPv6,
> the
> > interface needs to be specified in the scope_id. So we'd need to pull
> that
> > out of the kernel with rtnetlink.
>
> There's already code to enumerate interfaces, but it's a decent bit of
> additional machinery to pull in as a dep for the stub resolver,
Yeah we'd need lookup_name.c to include netlink.h - it's not huge though,
netlink.c is 50 lines long and statically linked anyway right?
> and
> it's not clear how to do it properly for IPv4 (do scope ids work with
> v4-mapped addresses by any chance?)
>
Scope IDs unfortunately don't work for IPv4. There's the SO_BINDTODEVICE
socket option, but that requires elevated privileges. For IPv4 I'd just use
the default route interface.
Another issue you haven't mentioned: how does TCP fallback work with
> mDNS? Or are answers too large for standard UDP replies just illegal?
>
Good point, I hadn't thought of that. That handling for mDNS is defined in
[1]. In the ephemeral query mode that we'd use here, it works the same as
for regular DNS: when you receive a response with the TC bit, retry the
query with TCP. The slight difference is that you send the TCP to the
address you got the response from (not to the multicast address that you
sent the original query to). From looking at the musl code, we'd need a
small tweak to __res_msend_rc() to use that address. Luckily that code
already looks at the sender address so we don't need any additional calls
to get it.
[1] https://www.rfc-editor.org/rfc/rfc6762#section-18.5
> > Unlike general unioning
> > > of sources, which is really problematic, the mDNS stuff seems to be
> > > putting the decision which source to use *before* making any queries,
> > > which is a lot less problematic.
> >
> > I'm not familiar with what you mean by unioning here, are you referring
> to
> > interface selection, DNS name server selection, or something else?
>
> By unioning I just mean providing a view of the hostname space that's
> the union of two or more sources of information (nameservers that
> aren't just redundant sources for the same DNS root).
>
Ah right. Yeah for mDNS the split is clean, that's part of why they
reserved .local for this.
> > So is there something wrong with the solution presented in the wiki
> > > page? Because that is generally the answer we recommend: If you want
> any
> > > name resolution other than DNS, write a proxy that does what you want
> > > and point resolv.conf to it. Similarly, if you want any user database
> > > lookup other than local files, write an nscd proxy that does what you
> > > want.
> >
> > That's certainly an option. Ideally I'd rather avoid adding additional
> > processes that can be failure points, when the stub can send these itself
> > with a very small modification.
>
> FWIW this is generally the approach musl takes. But if mDNS is
> sufficiently standardized, intended to be supported in stub resolvers
> by the standards, and doesn't have strong reasons not to do it, it
> might be acceptable.
>
Great!
> > Reason for that is that that is the most generic way to support any
> > > other name service besides DNS. It avoids the dependency on dynamic
> > > loading that something like glibc's nsswitch would create, and would
> > > avoid having multiple backends in libc. I really don't think anyone
> > > wants to open that particular door. Once mDNS is in there, someone will
> > > add NetBIOS, just you wait.
> >
> >
> > I'm definitely supportive of the slippery slope argument, but I think
> > there's still a real line between mDNS and NetBIOS. mDNS uses a different
> > transport but lives inside the DNS namespace, whereas NetBIOS is really
> its
> > own thing - NetBIOS names aren't valid DNS hostnames.
> >
> > Let me know what you think of the above. If you think of mDNS as its own
> > beast then I can see how including it wouldn't really make sense. But if
> > you see it as an actual part of the DNS, then it might be worth a small
> > code change :-)
>
> I'm not worried about slippery slopes to NetBIOS. :-P I am concerned
> about unwanted network traffic that can't be suppressed, privacy
> leaks, inventing new configuration knobs, potentially pulling in more
> code & more fragility, getting stuck supporting something that turns
> out to have hidden problems we haven't thought about, etc.
>
Those are great reasons, and I totally agree with those goals. If we scope
the problem down with the details higher up in this email, we have a way to
turn this off (set the resolver to localhost), we avoid privacy leaks in
cases where the traffic wasn't going out in the first place, we don't have
to add more configuration knobs because we're reusing an existing one, and
the amount of added code would be quite small. Limiting things to the
default interface isn't a full multi-network solution, but for those I
think it makes more sense to recommend running your own resolver on
loopback (you'd need elevated privileges to make this work fully anyway).
Coding wise, I think this would be pretty robust. The only breakage I
foresee is cases where someone built a custom resolver that runs on a
different machine and somehow handles .local differently than what the RFCs
say. That config sounds like a bad idea, and a violation of the RFCs, but
that doesn't mean there isn't someone somewhere who's doing it. So there's
a non-zero risk there. But to me that's manageable risk.
What do you think?
Thanks,
David
Content of type "text/html" skipped
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.