How to check if lan dns server is down, change dns option 6 and force all clients to renew lease or reconnect?

I have an internal dns server for my lan (eg. pihole, adguard, technitium, nextdns, etc) and sometimes the server is down (it's too noisy, down for maintenaince, turning it off to save power, etc).
Since the server is down, none of the other clients can resolve dns.
The dns setting is set using dhcp option 6

#/etc/config/dhcp

config dhcp 'lan'
	option interface 'lan'
	option start '100'
	option limit '150'
	option leasetime '12h'
	option dhcpv4 'server'
	option dhcpv6 'hybrid'
	option ra 'hybrid'
	list ra_flags 'managed-config'
	list ra_flags 'other-config'
	option dhcp_option '6,192.168.100.10'

I was thinking to check if host is down (eg. 192.168.100.10 with ping), using uci to change dhcp.lan.dhcp_option (change value or delete), restart dnsmasq and network services and force clients to renew dhcp leases (hoping the clients pick up the new config)

I would like to use a script and a cronjob for this

#!/bin/sh

# Host to check
HOST="192.168.100.10"
CONFIG_OPTION="dhcp.lan.dhcp_option"
CONFIG_VAL="6,192.168.100.10"

# Ping the host and check the exit status

CURRENT_DHCP_OPTION=$(uci get $CONFIG_OPTION)

if ping -c 1 $HOST > /dev/null 2>&1; then
	echo "Host $HOST is up"
	if [ "$CURRENT_DHCP_OPTION" != "$CONFIG_VAL" ]; then
	echo "Change DHCP servers to good DHCP servers"
		uci set $CONFIG_OPTION="$CONFIG_VAL"
		uci commit dhcp
		/etc/init.d/dnsmasq restart
		echo "Restart network (1)"
		/etc/init.d/network stop
		sleet 3
		/etc/init.d/network start
		sleep 2
		PID=$(pidof udhcpc) && kill -SIGUSR1 "$PID"
	else
		echo "won't change dhcp option value (1)"
	fi
else
	echo "Host $HOST is down"
	if [ "$CURRENT_DHCP_OPTION" = "$CONFIG_VAL" ]; then
		echo "Delete dhcp option"
		uci delete dhcp.lan.dhcp_option
		uci commit dhcp
		/etc/init.d/dnsmasq restart
		echo "Restart network (2)"
		# /etc/init.d/network restart
		/etc/init.d/network stop
		sleet 3
		/etc/init.d/network start
		sleep 2
		PID=$(pidof udhcpc) && kill -SIGUSR1 "$PID"
	else
		echo "won't change dhcp option value (2)"
	fi
fi

I've verified the script does its job but clients won't pickup the change. The client (eg. windows) has to manually disconnect and reconnect for dns settings to take effect.

Is there anything that can be done (from openwrt side) to force clients to renew dhcp settings or reconnect?

Are there better ways to archieve the same task?

TL;DR,
Give your clients 2 DNS servers at the DHCP lease time, first is your faulty one that goes down every time because "reasons", and second a NextDNS that has 99.99% uptime and probably with proper configs. When you upstream NextDNS with your rules, and downstream dnsmasq to clients, unless you configured it wrong, it won't ever go down.

1 Like

but assuming I can not have a second dns server, just delete the dns option 6 and tell clients to ignore my dns server, just use a public one

As far as I know, no. Closest you can get is probably to use a much shorter lease time.

Configure the OpenWrt device as the DNS, then change its upstream server.

1 Like

Not until they renew their DHCP lease, though. So, I see you have a 12h lease time set. So lets assume that a device gets a lease and 1 minute later your local DNS server goes down. The client won't check in for a new DHCP lease for another 5 hours and 59 minutes (unless the client is forced to renew its lease by an action on the client side such as a physical disconnection/reconnection cycle of the ethernet/wifi link, rebooting of the client device, or a local OS force renew (usually a user operation).

Therefore, whatever your internal DNS is... double your hardware (you can even use an old Pi or similar SBC) so you have redundancy and send both via dhcp option 6. Or send your local DNS + public DNS at the same time via DHCP option 6.

1 Like