Package to quickly switch DNS servers for network clients

Hi All -- seeking help/pointers for if a package already exists to help me out, or how I might think about starting to code one up. (I'm by no means an expert developer, but am happy to tinker around.)

Here's the situation: I have a pi-hole running unbound that serves as the DNS for all clients on my network. I force this to be the case by using the "6" option under Interfaces > Edit > DHCP Server > Advanced Settings > DHCP-Options. (I.e., that is set to 6,192.168.1.5 which is the IP of my pi-hole.) I also then have port forwards set up so that all attempted outgoing traffic on ports 64, 853, or 5353 is forced to the pi-hole (for each of 3 different firewall zones).

Normally this all works great. Every once in a while I'm doing something with the pi-hole that brings it down (updating, tinkering, etc). So that others on my network don't loose DNS, I then go into LUCI and manually change the DHCP-Options to something else (e.g., 6,9.9.9.9) and then have to go to the port forwards and un-enable all those rules.

So, the question is: Is there some script/package that could automate this for me? I'm imagining some sort of screen where I can easily toggle between DNS servers and then it goes in the background and changes all the DHCP-Options and port forward rules with one click.

As I said above: exists already? broad interest? pointers for where I should look to start figuring out how to code this up myself?

Thanks!

Not an expert on this topic, but some thoughts which I hope will be helpful...

  • I'm not aware of a package that would do what you're asking.
  • Consider that your DHCP configuration will not be easy/possible to change mid-lease
  • you may find that you need to action on the router itself, not the clients.

Regarding the DHCP option 6 update: let' say that you have a host that just got a DHCP lease/renewal a few minutes before your PiHole goes down, and your DHCP lease time is 12 hours. The host in question will not be due to renew the lease until 6 hours (50% lease time) has passed. In general, there is no way for the DHCP server to force renew or send 'corrections' until the DHCP client renews. Therefore, you'll basically have 6 hours before that specific host would be able to 'catch up' to the new change.

You could make your lease time really short such that you'd only be talking about minutes or so, but that's rather inefficient.

You could also consider bouncing the entire network. When hosts reconnect, they'll request a new lease. If it's just one router with no other switches or APs, this is trivially simple. But if there are other APs and swiches, it's hard or impossible to do. It's also pretty disruptive.

However, I'd advise the following options:
A) Get a backup PiHole on your network. Work on one, bring it back up, then work on the other. You can use an old Pi or other small SBCs for this purpose (an original BeagleBone would do the trick). Then, option 6 would send 2 addresses and your client devices should always have a backup available.

B) Use the router as the DNS server. In this situation, you don't even need to advertise option 6 -- the router's address will be sent as the DNS address by default unless you add option 6. Use the same firewall rules to prevent the use of external DNS servers. And finally, set the router's system DNS to the PiHole. Now, your main router will be the DNS server for the hosts on the network and it's DNS server will be the Pi. If the Pi goes down, you can use either a backup pihole (idea #1 above) and/or change the system DNS to an alternate like 9.9.9.9 or whatever you want. To achieve this final bit, you could use a script that would test for PiHole DNS periodically (maybe a combination of pings and a dns lookup)... if the test fails, you could use UCI commands to change the system DNS server (in dnsmasq) to the alternate. Then, when the test succeeds again, switch it back.

Thanks! Helpful. Two follow-up questions:

  1. When you say "set the router's system DNS to the PiHole". I have always had a bit of confusion in the right way to do that. Is it by setting the "Custom DNS Server" in the WAN interface? Or is it by setting "DNS forwardings" in the DHCP and DNS "General Settings"?

  2. With the firewall rules -- do I now force all port 53 traffic to go to my router? Or do I still force it to the pi-hole?

Thanks!

^^ this. Use a public DNS on your WAN (or the DHCP supplied DNS from your ISP).

Force it to your router. Sorry, I should have been more clear about that.
This way, all requests always go to your router, and your router forwards those requests to the pihole. If the Pihole is down, you can detect it on the router and then change that DNS server (from the earlier question) to a desired alternate.

Ah, thanks! That actually helps explain a lot about the different DNS settings in LUCI.

Your method works, but the problem it now causes is with the pi-hole. Since all DNS queries now "come from" the router, the pi-hole doesn't know which client is making the request! These wreaks havoc on the legibility of the query log and also disables any sort of client-specific blocking.

I guess there's not really a way around that?

ah... good point. I'm not sure about how to work around the client specific issue. But it is possible someone else will have an idea.

Otherwise, maybe a second (backup) Pihole is the way to go if that's a critical feature for you.

I figured out an intermediate solution. I set the router's DNS server to the Pi like you suggested. Then I had the port forward/firewall forward port 53 to the pi instead of to the router. So the clients on my network don't know that they're using the pi, since they still see the router as their DNS server. But the pi knows which client is contacting it.

This makes things slightly easier as I don't have to set the Option 6 in the DNS settings, so when I switch away from the Pi for DNS I can just uncheck the port forwarding rules in the firewall which is quite easy to do.

Oh... great idea! Glad you thought of that.

So yes, make sure your OpenWrt system DNS is something public that won't go down when you're working on your PiHole.

You may even be able to create a script to detect the PiHole down condition and turn off (and on) the forwarding rule automatically.