[GH-ISSUE #250] Use nsswitch.conf on Linux or document that it isn't used #118

Open
opened 2026-03-07 22:21:04 +03:00 by kerem · 11 comments
Owner

Originally created by @briansmith on GitHub (Oct 24, 2017).
Original GitHub issue: https://github.com/hickory-dns/hickory-dns/issues/250

One advantage of nsswitch.conf, IIUC, is that it can control whether /etc/hosts is read and/or whether DNS servers are used at all. I don't know if it is worthwhile to support it. If it isn't deemed worthwhile then it should be documented as part of #249 as a different from glibc.

Originally created by @briansmith on GitHub (Oct 24, 2017). Original GitHub issue: https://github.com/hickory-dns/hickory-dns/issues/250 One advantage of nsswitch.conf, IIUC, is that it can control whether /etc/hosts is read and/or whether DNS servers are used at all. I don't know if it is worthwhile to support it. If it isn't deemed worthwhile then it should be documented as part of #249 as a different from glibc.
Author
Owner

@briansmith commented on GitHub (Oct 24, 2017):

FWIW, I don't have an immediate need for this, AFAICT. I just filed it for completeness sake as I was auditing the code.

<!-- gh-comment-id:338872397 --> @briansmith commented on GitHub (Oct 24, 2017): FWIW, I don't have an immediate need for this, AFAICT. I just filed it for completeness sake as I was auditing the code.
Author
Owner

@bluejekyll commented on GitHub (Oct 26, 2017):

I think it's just hosts where this is relevant, right?

<!-- gh-comment-id:339823824 --> @bluejekyll commented on GitHub (Oct 26, 2017): I think it's just `hosts` where this is relevant, right?
Author
Owner

@rumpelsepp commented on GitHub (May 31, 2018):

nsswitch.conf is also relevant for mdns.

<!-- gh-comment-id:393611241 --> @rumpelsepp commented on GitHub (May 31, 2018): nsswitch.conf is also relevant for mdns.
Author
Owner

@bluejekyll commented on GitHub (May 31, 2018):

I think the big issue here is that we've incorporated /etc/hosts file lookup as part of the project, and that's just one part of the picture as it relates to nsswitch.conf. nsswitch.conf has a number of rules, and while some are applicable to DNS, others are not. I don't know what it would look like to support this, and I wonder if what we really need to do is move things to a higher level (i.e. something else that manages nsswitch and calls out to the resolver and others as necessary).

nsswitch.conf is also relevant for mdns.

mdns still has some known issues in trust-dns, beyond configuration as well.

<!-- gh-comment-id:393616204 --> @bluejekyll commented on GitHub (May 31, 2018): I think the big issue here is that we've incorporated `/etc/hosts` file lookup as part of the project, and that's just one part of the picture as it relates to `nsswitch.conf`. `nsswitch.conf` has a number of rules, and while some are applicable to DNS, others are not. I don't know what it would look like to support this, and I wonder if what we really need to do is move things to a higher level (i.e. something else that manages `nsswitch` and calls out to the resolver and others as necessary). > nsswitch.conf is also relevant for mdns. mdns still has some known issues in trust-dns, beyond configuration as well.
Author
Owner

@rumpelsepp commented on GitHub (May 31, 2018):

mdns still has some known issues in trust-dns, beyond configuration as well.

yep. Sry for digging out this issue, I was just reading through the issue tracker and dumped a thought.

nsswitch.conf is a complex beast, since it is extendable I fear there is no generic way to support this properly and completely in pure TRust-DNS.

if what we really need to do is move things to a higher level (i.e. something else that manages nsswitch and calls out to the resolver and others as necessary).

IMO this would be pretty much the same as duplicating std::net::ToSocketAddrs on a TRust-DNS level. The problem is, that the intention of nsswitch.conf is the other way round: TRust-DNS can be part of the call chain in nsswitch.confinstead of being a reimplementation of that "higher level":

hosts:          files mdns4_minimal [NOTFOUND=return] dns myhostname

So, the only way to get it right would be creating nss-plugins using TRust-DNS and let glibc do the nsswitch.conf magic. That's how systemd does it with its magic systemd-resolved crap. If everything is configured properly, then TRust-DNS would be called automatically when some program calls std::net::ToSocketAddrs. The /etc/hosts lookup can then be omitted in TRust-DNS.

I think about something like this:

hosts:          files mdns_trustdns [NOTFOUND=return] trustdns myhostname
<!-- gh-comment-id:393622379 --> @rumpelsepp commented on GitHub (May 31, 2018): > mdns still has some known issues in trust-dns, beyond configuration as well. yep. Sry for digging out this issue, I was just reading through the issue tracker and dumped a thought. nsswitch.conf is a complex beast, since it is extendable I fear there is no generic way to support this properly and completely in pure TRust-DNS. > if what we really need to do is move things to a higher level (i.e. something else that manages nsswitch and calls out to the resolver and others as necessary). IMO this would be pretty much the same as duplicating `std::net::ToSocketAddrs` on a TRust-DNS level. The problem is, that the intention of `nsswitch.conf` is the other way round: TRust-DNS can be part of the call chain in `nsswitch.conf`instead of being a reimplementation of that "higher level": ``` hosts: files mdns4_minimal [NOTFOUND=return] dns myhostname ``` So, the only way to get it right would be creating nss-plugins using TRust-DNS and let `glibc` do the `nsswitch.conf` magic. That's how systemd does it with its magic systemd-resolved crap. If everything is configured properly, then TRust-DNS would be called automatically when some program calls `std::net::ToSocketAddrs`. The `/etc/hosts` lookup can then be omitted in TRust-DNS. I think about something like this: ``` hosts: files mdns_trustdns [NOTFOUND=return] trustdns myhostname ```
Author
Owner

@bluejekyll commented on GitHub (May 31, 2018):

the only way to get it right would be creating nss-plugins using TRust-DNS and let glibc do the nsswitch.conf magic.

Thanks for that! I'm always thinking in the context of usage internally in Rust projects, not as system config option. This is a great idea. We should do that. It's somewhat related to #483, as we'd need that first.

<!-- gh-comment-id:393687248 --> @bluejekyll commented on GitHub (May 31, 2018): > the only way to get it right would be creating nss-plugins using TRust-DNS and let glibc do the nsswitch.conf magic. Thanks for that! I'm always thinking in the context of usage internally in Rust projects, not as system config option. This is a great idea. We should do that. It's somewhat related to #483, as we'd need that first.
Author
Owner

@briansmith commented on GitHub (May 31, 2018):

nsswitch.conf is a complex beast, since it is extendable I fear there is no generic way to support this properly and completely in pure TRust-DNS.

Also, I think some projects probably are using Trust-DNS at least in part specifically to avoid that stuff.

IMO, nsswitch.conf processing should be done in some higher-layer crate that uses Trust-DNS as a dependency.

Perhaps that should have been done for /etc/hosts and the Windows equivalent too, though I think that extant functionality isn't as problematic as nsswitch.conf so IMO it shouldn't be a priority to take it out.

<!-- gh-comment-id:393692104 --> @briansmith commented on GitHub (May 31, 2018): > nsswitch.conf is a complex beast, since it is extendable I fear there is no generic way to support this properly and completely in pure TRust-DNS. Also, I think some projects probably are using Trust-DNS at least in part specifically to avoid that stuff. IMO, nsswitch.conf processing should be done in some higher-layer crate that uses Trust-DNS as a dependency. Perhaps that should have been done for `/etc/hosts` and the Windows equivalent too, though I think that extant functionality isn't as problematic as nsswitch.conf so IMO it shouldn't be a priority to take it out.
Author
Owner

@msehnout commented on GitHub (Jun 1, 2018):

I think about something like this:
hosts: files mdns_trustdns [NOTFOUND=return] trustdns myhostname

What would be the advantage here? Would you like to implement Trust-DNS support directly into glibc?

I'm using Unbound as a local resolver and I simply lock my /etc/resolv.conf to prevent NetworkManager from writing to it. This way I can keep nsswitch untouched.

nameserver 127.0.0.1

glibc contacts Unbound whenever it wants to resolve some name.

<!-- gh-comment-id:393807681 --> @msehnout commented on GitHub (Jun 1, 2018): > I think about something like this: > hosts: files mdns_trustdns [NOTFOUND=return] trustdns myhostname What would be the advantage here? Would you like to implement Trust-DNS support directly into glibc? I'm using Unbound as a local resolver and I simply lock my `/etc/resolv.conf` to prevent NetworkManager from writing to it. This way I can keep nsswitch untouched. ``` nameserver 127.0.0.1 ``` glibc contacts Unbound whenever it wants to resolve some name.
Author
Owner

@rumpelsepp commented on GitHub (Jun 1, 2018):

What would be the advantage here?

The advantage is you don't violate layers. Your example with /etc/resolv.conf is only valid for the dns entity in nsswitch.conf.

Would you like to implement Trust-DNS support directly into glibc?

No. You only need an nss plugin, that can be written in rust with some linker flags.

I'm using Unbound as a local resolver and I simply lock my /etc/resolv.conf to prevent NetworkManager from writing to it.

You can just enable unbound in the NetworkManager config, this way NetworkManager can notify unbound when you enable VPN etc. Locking /etc/resolv.conf via chattr is not a good idea (I assume you mean chattr +i by "locking"). See NetworkManager.conf(5), search for unbound.


The main problem here in this issue is, that resolving via /etc/hosts normally is triggered via the files backend in nsswitch.conf(5)(see FILES section). TRust-DNS reads /etc/hosts as well.

Let's assume you use some TRust-DNS resolver binary from #483, listening on 127.0.0.1. When you put nameserver 127.0.0.1 into /etc/resolv.conf, the following happens when a program calls getaddrinfo(3); this hosts line is in nsswitch.conf:

hosts:          files mdns_trustdns [NOTFOUND=return] trustdns myhostname
  • files: Read /etc/hosts, this fails, the chain continues.
  • mdns_trustdns: Call into some *.so that implements mDNS lookup for *.local. If it is not a *.local lookup, the chain continues.
  • trustdns: Call trust-dns plugin, read /etc/hosts again. Make DNS requests, ...
  • myhostname: Not reached when DNS succeeds. (No idea why this is the last entry...).

The admin is free to disable lookups via /etc/hosts system widely by removing the files entry. But TRust-DNS would happily continue reading /etc/hosts. So the right place to configure the host lookup backends for the whole system is nsswitch.conf.

To integrate into this mechanism nss-plugins with limited scope can be provided and will be picked up by glibc. Since glibc provides a well defined interface this plugins can be written in any language which is C ABI compatible (rust can).


To sum up, @msehnout your example with /etc/resolv.conf makes complete sense, when your resolver only does DNS. When you start mixing things up (/etc/hosts, mDNS, ...), it will cause problems for admins who alter nsswitch.conf for whatever reasons (one could e.g. store hostnames in some database instead).


Here is a nss plugin in rust, which can be used to steal some ideas: https://github.com/outlook/libnss-aad

<!-- gh-comment-id:393822010 --> @rumpelsepp commented on GitHub (Jun 1, 2018): > What would be the advantage here? The advantage is you don't violate layers. Your example with `/etc/resolv.conf` is only valid for the `dns` entity in `nsswitch.conf`. > Would you like to implement Trust-DNS support directly into glibc? No. You only need an [nss plugin](http://www.gnu.org/software/libc/manual/html_mono/libc.html#Extending-NSS), that can be written in rust with some linker flags. > I'm using Unbound as a local resolver and I simply lock my /etc/resolv.conf to prevent NetworkManager from writing to it. You can just enable unbound in the NetworkManager config, this way NetworkManager can notify unbound when you enable VPN etc. Locking `/etc/resolv.conf` via `chattr` is not a good idea (I assume you mean `chattr +i` by "locking"). See [`NetworkManager.conf(5)`](https://manpages.debian.org/stretch/network-manager/NetworkManager.conf.5.en.html), search for `unbound`. ------- The main problem here in this issue is, that resolving via `/etc/hosts` normally is triggered via the `files` backend in [`nsswitch.conf(5)`](https://manpages.debian.org/stretch/manpages/nsswitch.conf.5.en.html)(see FILES section). TRust-DNS reads `/etc/hosts` as well. Let's assume you use some TRust-DNS resolver binary from #483, listening on `127.0.0.1`. When you put `nameserver 127.0.0.1` into `/etc/resolv.conf`, the following happens when a program calls `getaddrinfo(3)`; this hosts line is in `nsswitch.conf`: ``` hosts: files mdns_trustdns [NOTFOUND=return] trustdns myhostname ``` * files: Read `/etc/hosts`, this fails, the chain continues. * mdns_trustdns: Call into some *.so that implements mDNS lookup for `*.local`. If it is not a `*.local` lookup, the chain continues. * trustdns: Call trust-dns plugin, read `/etc/hosts` *again*. Make DNS requests, ... * myhostname: Not reached when DNS succeeds. (No idea why this is the last entry...). The admin is free to disable lookups via `/etc/hosts` system widely by removing the files entry. But TRust-DNS would happily continue reading `/etc/hosts`. So the right place to configure the host lookup backends for the whole system is `nsswitch.conf`. To integrate into this mechanism nss-plugins with limited scope can be provided and will be picked up by glibc. Since glibc provides a well defined interface this plugins can be written in any language which is C ABI compatible (rust can). ---------------------- To sum up, @msehnout your example with `/etc/resolv.conf` makes complete sense, when your resolver **only** does DNS. When you start mixing things up (`/etc/hosts`, mDNS, ...), it will cause problems for admins who alter `nsswitch.conf` for whatever reasons (one could e.g. store hostnames in some database instead). ---- Here is a nss plugin in rust, which can be used to steal some ideas: https://github.com/outlook/libnss-aad
Author
Owner

@msehnout commented on GitHub (Jun 1, 2018):

To sum up, @msehnout your example with /etc/resolv.conf makes complete sense, when your resolver only does DNS.

That was my point actually. I think we should do only DNS. Let the standard mechanism for hosts lookup handle the files.

Regarding the unbound section in NetworkManager.conf(5), that is exactly what I am using, but the whole architecture of NetworkManager -> dnssec-trigger -> Unbound is a mess. I'd like to use trust-dns as a replacement and connect it directly to NetworkManager via D-Bus, but first I need the standalone resolver.

<!-- gh-comment-id:393853671 --> @msehnout commented on GitHub (Jun 1, 2018): > To sum up, @msehnout your example with /etc/resolv.conf makes complete sense, when your resolver only does DNS. That was my point actually. I think we should do only DNS. Let the standard mechanism for **hosts** lookup handle the files. Regarding the unbound section in NetworkManager.conf(5), that is exactly what I am using, but the whole architecture of NetworkManager -> dnssec-trigger -> Unbound is a mess. I'd like to use trust-dns as a replacement and connect it directly to NetworkManager via D-Bus, but first I need the standalone resolver.
Author
Owner

@rumpelsepp commented on GitHub (Jun 1, 2018):

Regarding the unbound section in NetworkManager.conf(5), that is exactly what I am using, but the whole architecture of NetworkManager -> dnssec-trigger -> Unbound is a mess.

Ok, sry for assuming you do some chattr mess. I have seen this in the wild a few times...

<!-- gh-comment-id:393854996 --> @rumpelsepp commented on GitHub (Jun 1, 2018): > Regarding the unbound section in NetworkManager.conf(5), that is exactly what I am using, but the whole architecture of NetworkManager -> dnssec-trigger -> Unbound is a mess. Ok, sry for assuming you do some `chattr` mess. I have seen this in the wild a few times...
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/hickory-dns#118
No description provided.