Package: dhcpcd-base
Version: 1:10.1.0-9
Description:
When using dhcpcd-base together with systemd-resolved, the name server settings for an interface are initially configured correctly from DHCP but may then subsequently disappear, leaving no DNS server configured.
This is because the dhcpcd hook scripts contain support for resolvconf, but the implementation of resolvconf provided by systemd-resolved is very limited and does not support the full semantics required (see below).
Steps to Reproduce:
1. Install systemd-resolved (257.5-2) along with dhcpcd-base (1:10.1.0-9) and ifupdown (0.8.44)
2. Configure an interface for DHCP in /etc/network/interfaces.
As an example I am using a usermode (slirp) interface in QEMU:
allow-hotplug enp1s0
iface enp1s0 inet dhcp
3. Reboot, or restart the interface with ifdown/ifup.
4. Observe the DNS server configuration with resolvectl, repeating a few minutes later.
Expected Behaviour:
resolvectl should show the DNS server address configured by DHCP. Name resolution should work.
Observed Behaviour:
Shortly after the interface is brought up, resolvectl does indeed show that a DNS server has been configured, e.g.:
Global
Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub
Link 2 (enp1s0)
Current Scopes: DNS
Protocols: +DefaultRoute -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 172.17.2.3
DNS Servers: 172.17.2.3
Default Route: yes
But a few minutes later, the server seems to have disappeared again and DNS is no longer working:
Global
Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub
Link 2 (enp1s0)
Current Scopes: none
Protocols: -DefaultRoute -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Default Route: no
Investigation:results in a series of invocations such as the following:
Turning on the debug option for dhcpcd shows a number of hook script calls after the interface has been configured, e.g:
Apr 20 21:07:36 redacted ifup[1015]: enp1s0: executing: /usr/lib/dhcpcd/dhcpcd-run-hooks PREINIT
Apr 20 21:07:36 redacted dhcpcd[1015]: enp1s0: executing: /usr/lib/dhcpcd/dhcpcd-run-hooks PREINIT
Apr 20 21:07:36 redacted ifup[1015]: enp1s0: executing: /usr/lib/dhcpcd/dhcpcd-run-hooks NOCARRIER
Apr 20 21:07:36 redacted dhcpcd[1015]: enp1s0: executing: /usr/lib/dhcpcd/dhcpcd-run-hooks NOCARRIER
Apr 20 21:07:36 redacted ifup[1015]: enp1s0: executing: /usr/lib/dhcpcd/dhcpcd-run-hooks CARRIER
Apr 20 21:07:36 redacted dhcpcd[1015]: enp1s0: executing: /usr/lib/dhcpcd/dhcpcd-run-hooks CARRIER
Apr 20 21:07:39 redacted ifup[1015]: enp1s0: executing: /usr/lib/dhcpcd/dhcpcd-run-hooks ROUTERADVERT
Apr 20 21:07:39 redacted dhcpcd[1015]: enp1s0: executing: /usr/lib/dhcpcd/dhcpcd-run-hooks ROUTERADVERT
Apr 20 21:07:41 redacted ifup[1015]: enp1s0: executing: /usr/lib/dhcpcd/dhcpcd-run-hooks BOUND
Apr 20 21:07:41 redacted dhcpcd[1015]: enp1s0: executing: /usr/lib/dhcpcd/dhcpcd-run-hooks BOUND
Apr 20 21:12:20 redacted dhcpcd[1015]: enp1s0: executing: /usr/lib/dhcpcd/dhcpcd-run-hooks ROUTERADVERT
Apr 20 21:21:56 redacted dhcpcd[1015]: enp1s0: executing: /usr/lib/dhcpcd/dhcpcd-run-hooks ROUTERADVERT
Apr 20 21:28:29 redacted dhcpcd[1015]: enp1s0: executing: /usr/lib/dhcpcd/dhcpcd-run-hooks ROUTERADVERT
Examining the hook script /usr/lib/dhcpcd/dhcpcd-hooks/20-resolv.conf, shows that when a resolvconf binary is present, each hook call will ultimately invoke resolvconf to add or delete the DNS settings for a particular protocol on the interface. This
resolvconf -d enp1s0.dhcp -fstate for all protocols. The last information supplied for any protocol typically wins out.
resolvconf -d enp1s0.link -f
resolvconf -d enp1s0.link -f
resolvconf -d enp1s0.ra -f
resolvconf -a enp1s0.dhcp (with a resolv.conf-formatted file piped to stdin)
resolvconf -d enp1s0.ra -f
This is where the difference in semantics becomes apparent between the versions of Debian resolvconf/openresolv and the resolvconf provided by systemd-resolved:
The "traditional" resolvconf maintains a separate state for each protocol on the interface, and generates a superposition of the information from all protocols. By contrast, the systemd version ignores the protocol suffix completely and stores a single
In the particular example above, it appears that an IPv6 router advertisement for "enp1s0.ra" has deleted the DNS configuration previously set for "enp1s0.ra". I expect that various other sequences of events may lead to a similar result.
Possible Solutions:given interface (retrieved from state stored under /run/dhcpcd).
I attach a patch which modifies the dhcpcd hook scripts to work around the problem: We detect when the systemd version of resolvconf is being used and provide it with a resolv.conf fragment that contains the superposition of all the protocols on a
I have not tested the patch extensively, although it has worked well enough in my test cases.by both packages so they are to some extent integrated together. Since dhcpcd has now replaced isc-dhcp-client as the default DHCP client for trixie, this integration now seems to be rather pointless. See as follows:
Note that the ifupdown and isc-dhcp-client packages already have a their own hook scripts (borrowed from Ubuntu) for dealing with systemctl-resolved. These scripts call resolvectl to set the DNS servers, and there is a shared state that is maintained
https://sources.debian.org/src/ifupdown/0.8.44/debian/if-up.d/resolved/ https://sources.debian.org/src/isc-dhcp/4.4.3-P1-7/debian/resolved/
Remarks:propagating these bespoke workarounds into different packages, it may be better if they could all continue to use the "traditional" resolvconf/openresolv system to configure resolved.
It seems to me that the need for all these hacky hook scripts has come about because systemd's implementation of resolvconf is too limited to be of use as a drop-in replacement for resolvconf with the various "legacy" networking packages. Rather than
I think this could be accomplished fairly cleanly and easily if the systemd-resolved package were to simply omit installing the "resolvconf" symbolic link, and drop the "Provides: resolvconf" and "Conflicts: resolvconf" dependences, allowing it to beinstalled alongside the "traditional" resolvconf. At the same time, resolvconf/openresolv could be equipped with a unified hook script to detect systemd-resolved and call resolvectl. Then all the hacks elsewhere could go away!
If anyone can suggest a better forum to raise that wider issue then please let me know and I will do so.
With trixie release coming up, I would not expect to see any enthusiasm
for making these sorts of changes across multiple packages.
The issue I raised upstream has now been closed [1], after Roy produced a new release of openresolv [2] with support for systemd-resolved.
Unfortunately, IMHO the direction taken in openresolv doesn't help us much with the present bug, for the following reasons:
- It violates the principle of least surprise (from the POV of network interface configuration), by placing all name servers into the global pool, rather than assigning servers and their routing domains to specific network interfaces.
I am sure there are valid arguments for doing it that way. But it is completely at odds with how resolved is "normally" configured by all the other networking tools such as systemd-networkd, NetworkManager and dhclient.
By contrast, almost anyone installing systemd-resolved on Debian is going to expect per-interface configuration.
- In any case, an openresolv-based solution still wouldn't circumvent the package management issues we currently have in Debian, namely that the systemd-resolved package conflicts with anything providing resolvconf.
there's also the problem that we would have to duplicate any new openresolv behaviour into the resolvconf package to keep the two in step.
For the above reasons I've given up on the resolvconf approach, decided to eat my earlier words and reconsider the "hacky script" technique once more:
I have ported the resolved configuration script (originally borrowed from Ubuntu) from dhclient [3] to work with dhcpcd.
This turned out to be completely trivial, since the hook script environments provided by dhclient and dhcpcd are so similar.
Basically, it should just work.
See the attached patch.
Functionally speaking, this bespoke script solution has a lot to commend it:
- It configures resolved in the "expected" way, i.e. per interface, the same way as NetworkManager and the rest do.
- It integrates with ifupdown settings configured in /etc/network/interfaces:
Specifically, dns-nameservers, dns-search and dns-default-route can optionally be set to manually override what comes from DHCP.
- It is low-impact and follows the solution already in use, so we would hope for little or nothing in the way of unexpected breakage.
So what's not to like? Well I have never been too keen on the implementation details:
- There is code duplication and shared state between the ifupdown, dhclient and (now) dhcpcd packages.
The script needs to be maintained in step between all of these packages, which implies fragility.
Strictly speaking, we could avoid this interdependency, but at the cost of removing the useful ability to override things in /etc/network/interfaces.
I think it would be preferable if the same common script could be used by all of the above packages:
Probably the central place to put it would be inside the ifupdown package. This would not necessarily require a package dependency, if things were handled correctly.
- The script modifies some internal resolved state files under /run/systemd/resolve/netif/.
I think the only reason for doing this is in case DNS gets configured before resolved has started up: I would have thought that might be better handled with systemd service dependencies or suchlike?
- There are some other minor things, such as the use of mktemp, which I would have preferred to avoid.
Notwithstanding the above wrinkles, I do think it would be worthwhile getting something along these lines into trixie:
It will allow someone who has installed a base system with ifupdown to simply "apt install systemd-resolved" and still have things work as expected.
If there is any enthusiasm for pursuing this further then I would be prepared to do some work on tweaking the solution to order.
Suggestions welcome...
[1] https://github.com/NetworkConfiguration/dhcpcd/issues/500#issuecomment-2831237831
[2] https://github.com/NetworkConfiguration/openresolv/releases/tag/v3.15.0 [3] https://salsa.debian.org/debian/isc-dhcp/-/commit/ab10fa481ee012c52de95adfc92691c882bf78ac
Thanks for responding Roy.
On 28/04/2025 11:52, Roy Marples wrote:
By contrast, almost anyone installing systemd-resolved on Debian is going to expect per-interface configuration.
Why are people going to expect that?
Because all of the other major networking solutions in Debian do it that way.
Try configuring an interface in NetworkManager, networkd or (lately) ifupdown with dhclient and you will see what I mean.
I'm certainly not trying to make a point about whether this is right or wrong, but it is undeniably the "usual" way that systemd-resolved gets configured by everyone else.
I have a counter argument - people installing stuff expect it to just work.
See above. resolved is completely optional in Debian, as are openresolv/resolvconf.
I expect they each have their own users with possibly different expectations.
There is a PR to resolve this via the concept of DNS Delegates from poettering - https://github.com/systemd/systemd/pull/34368
Once/if that get's merged then resolved is on feature parity with other resolvers.
Presumably this isn't getting into trixie though, and I assume NetworkManager et al will still continue to configure it the "old" way unless and until they are explicitly given support for delegates?
Then let's talk about state. If resolved is restarted, it's state learned via resolvectl is lost. How do we get that back?
If it's baked in a config file like other DNS servers it's still there.
The "hacky patch" handles this by persisting the state under /run/network. As I've been at pains to point out, I'm not much of a fan of the implementation, but it is already in use by ifupdown and dhclient.
Better the devil you know I suppose.
Because of the interop with ifupdown, it does have the advantage that you can override things manually from /etc/network/interfaces.
I found that particularly useful for controlling the "default route" settings in resolved, which can force it to be more pedantic about prefix matching.
Lastly, let's talk about features.
openresolv offers the admin the ability to massage the resolv.conf data before it's applied to the DNS server.
You can append, prefix, remove and change pretty much anything as it comes in.
And like Debian's resolvconf you can also use it to just discard all inputs and keep /etc/resolv.conf alone.
Yes, but I assume there would be considerable pushback against making either package mandatory in Debian.
At the moment, the systemd-resolved package has a hard conflict with both openresolv and resolvconf so they can never be installed together.
I have raised a feature request to get this changed, but...
If that restriction were relaxed then there are various subtleties that would need to be taken care of to avoid breaking more things:
Mostly regarding the ownership and function of /usr/sbin/resolvconf and /etc/resolv.conf with various different combinations of packages installed.
And since we have *two* different resolvconf packages, any behaviour would have to be replicated in *both* of them.
Functionally speaking, this bespoke script solution has a lot to commend it:
- It configures resolved in the "expected" way, i.e. per interface, the same way as NetworkManager and the rest do.
I find it interesting that NetworkManager does this per interface for resolved and yet just treats resolvconf as a global.
Yes I noticed that too! It's a case of "when in Rome" I guess.
It is not uncommon in Debian desktop installs to use both ifupdown and NetworkManager at the same time, on different interfaces:
The former is most often used for wired interfaces and the latter for wireless networks.
This was another reason why I thought it was better to go per-interface with resolved, because it keeps things consistent in this sort of mixed setup.
If you really want to have things pushed via resolvectl then I'm happy to revisit the resolvectl helper for openresolv as I committed here:
https://github.com/NetworkConfiguration/openresolv/commit/a21cc3bd201217e2d4e271c87e1990e03622ba99
And we could work this together to satisfy your needs.
At the moment, I think the biggest hurdle we face is those package conflicts: dhcpcd can coexist with resolved, but openresolv cannot.
As I've pointed out above, removing that restriction would create other problems for us to solve.
For now, doing anything that calls resolvconf in the presence of systemd-resolved is likely to remain broken. That's why I raised this bug! :-)
The issue I raised upstream has now been closed [1], after Roy produced a new release of openresolv [2] with support for systemd-resolved.
Unfortunately, IMHO the direction taken in openresolv doesn't help us much with the present bug, for the following reasons:
- It violates the principle of least surprise (from the POV of network interface configuration), by placing all name servers into the global pool, rather than assigning servers and their routing domains to specific network interfaces.
I am sure there are valid arguments for doing it that way. But it is completely at odds with how resolved is "normally" configured by all the other networking tools such as systemd-networkd, NetworkManager and dhclient.
By contrast, almost anyone installing systemd-resolved on Debian is going to expect per-interface configuration.
For the above reasons I've given up on the resolvconf approach, decided to eat my earlier words and reconsider the "hacky script" technique once more:
I have ported the resolved configuration script (originally borrowed from Ubuntu) from dhclient [3] to work with dhcpcd.
This turned out to be completely trivial, since the hook script environments provided by dhclient and dhcpcd are so similar.
Basically, it should just work.
See the attached patch.
[3] https://salsa.debian.org/debian/isc-dhcp/-/commit/ab10fa481ee012c52de95adfc92691c882bf78ac
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 482 |
Nodes: | 16 (0 / 16) |
Uptime: | 75:09:48 |
Calls: | 9,572 |
Calls today: | 3 |
Files: | 13,666 |
Messages: | 6,142,512 |