NetworkConfiguration / dhcpcd

DHCP / IPv4LL / IPv6RA / DHCPv6 client.
https://roy.marples.name/projects/dhcpcd
BSD 2-Clause "Simplified" License
337 stars 109 forks source link

please add hook to restart dnsmasq when IPv6 prefix has changed #107

Closed perkelix closed 2 years ago

perkelix commented 2 years ago

version: 9.4.1

It would be desirable for dhcpcd to ship a hook to reload dnsmasq whenever the IPV6 prefix has changed.

rsmarples commented 2 years ago

You have such a hook already. ROUTERADVERT, BOUND6, RENEW6, REBIND6, REBOOT6, DELEGATED6, EXPIRE6 can all do this. These hooks will tell you that an event which may contain a prefix has happened. It even tells you what the prefixes are for that event - just not if they have changed or not.

perkelix commented 2 years ago

Let me rephrase that. We need a script to do this for us.

I'm working on one. Patch upcoming. What I currently have:

# 70-dnsmasq: Reload dnsmasq to propagate IPv6 prefix changes.
case "$reason" in
        EXPIRE6|DELEGATED6)
        invoke-rc.d dnsmasq restart || invoke-rc.d dnsmasq start || :
        if command -v logger >/dev/null 2>&1; then
                logger -i -p daemon.info -t "dhcpcd-pd" "Info: Restarted dnsmasq via dhcpcd. Reason: $reason $new_delegated_dhcp6_prefix"
        fi
esac

One thing I need to avoid unnecessary reloads is to compare $new_delegated_dhcp6_prefix with something like $old_delegated_dhcp6_prefix (which we don't seem to have) i.e. if the prefix remains the same, don't reload.

rsmarples commented 2 years ago

You're not doing anything with dnsmasq config though, so why are you reloading it?

perkelix commented 2 years ago

As far as I know, dnsmasq isn't able to adapt on the fly to changing IPv6 addresses on its interface. Please correct me if I'm wrong.

rsmarples commented 2 years ago

You're wrong

https://github.com/imp/dnsmasq/blob/770bce967cfc9967273d0acfb3ea018fb7b17522/src/netlink.c#L219

perkelix commented 2 years ago

Noted.

Sure enough, without this script, dnsmasq simply advertises the old prefix as deprecated.

I guess this also means that Debian needs to update its IPv6 Prefix Delegation wiki page. :)

perkelix commented 2 years ago

However, there's no indication of whether dnsmasq is able to deal with changes in /etc/resolv.conf at all. As far as I can tell, this is the main reason why e.g. OpenWRT reloads dnsmasq upon WAN changes.

rsmarples commented 2 years ago

dnsmasq re-reads /etc/resolv.conf when that changes - see https://thekelleys.org.uk/dnsmasq/docs/setup.html "Automatic nameserver configuration."

dhcpcd also supports resolvconf(8) - as part of this project we have https://github.com/NetworkConfiguration/openresolv which can configure dnsmasq better for upstream resolvers.

johnnylambada commented 1 year ago

I'm hijacking this thread a bit because the solution to my problem was a slightly modified version of @perkelix 's script.

I'm building a headless IPv4 router out of my raspberry pi and was finding that dnsmasq would not work on the first boot. I'd have to reboot the rpi after the first boot and it would work.

A bit of background for rpi:

  1. image the SD card on another computer
  2. apply power to rpi
  3. it does its first time config (ssh keys, etc) and reboots itself silently
  4. we now have what I'm calling first boot

Every time I would get to step 4, dnsmasq would not work. In the logs it would say something like:

...
Nov 16 22:32:21 box dnsmasq[526]: no servers found in /etc/resolv.conf, will retry
Nov 16 22:32:21 box dnsmasq[526]: read /etc/hosts - 5 addresses
Nov 16 22:32:21 box systemd[1]: Started dnsmasq - A lightweight DHCP and caching DNS server.
Nov 16 22:32:30 box dnsmasq[526]: reading /etc/resolv.conf
Nov 16 22:32:30 box dnsmasq[526]: using nameserver 192.168.86.1#53

Which looks correct, but did not, in fact, work. A lease would never be given. Once I physically rebooted the machine again, dnsmasq would work properly. I tried adding a stub /etc/resolv.conf file and that didn't help. What did help was adding this script to the /usr/lib/dhcpcd/dhcpcd-hooks/ directory:

# 70-dnsmasq: Reload dnsmasq when interface is up
if $if_configured && $if_up; then
        invoke-rc.d dnsmasq restart || invoke-rc.d dnsmasq start || :
        if command -v logger >/dev/null 2>&1; then
                logger -i -p daemon.info -t "dhcpcd-crom" "Info: Restarted dnsmasq via dhcpcd. Reason: $reason"
        fi
fi

The script basically restarts dnsmasq from scratch whenever the interface restarts. Thank you to @perkelix for pointing me in the right direction!