If you’re tired of dnsmasq wiping the cachefile every time it has to restart (usually because your cable provider has set DHCP lease time to a very short 1 or 2 hours, and you get a new IP address each time), so you can never really build up a good-sized cachefile, this will set it up to repopulate the dnsmasq cachefile on each restart of dnsmasq.
You’re going to need an external USB drive to save dnsmasq logfiles to. Mine is /dev/sda2, and the logfile sits at /mnt/sda2/dns/dnsmasq.log.
In a terminal window connected to the router, issue:
mkdir /mnt/sda2/dns touch /mnt/sda2/dns/dnsmasq.log chown -R dnsmasq:dnsmasq /mnt/sda2/dns chmod 755 /mnt/sda2/dns
In the LuCI interface, under Networking >> DNS >> Log tab, check the Log queries checkbox, and under Log Facility, enter the path to your logfile: /mnt/sda2/dns/dnsmasq.log
Click Save & Apply. You’ll see the /mnt/sda2/dns/dnsmasq.log file size growing.
Of course, we don’t want it to grow forever, so we have to trim it.
Under System >> Scheduled Tasks, enter:
# Trim DNS Pre-Warming Log 0 4 * * * tail -n 100000 /mnt/sda2/dns/dnsmasq.log > /mnt/sda2/dns/dnsmasq.log.tmp && mv /mnt/sda2/dns/dnsmasq.log.tmp /mnt/sda2/dns/dnsmasq.log
You can set that 100000 to whatever number you want. I recommend 10000 (the maximum default dnsmasq cachefile size)… I’ve increased my dnsmasq cachefile size to 100000.
Now, we’ve got the logfile growing, we’ve got the logfile trimmer set up. Now we have to set up the code to repopulate the cachefile, and a way to trigger it.
Create a file and set permissions:
touch /etc/dns_cache_prewarm.sh chmod +x /etc/dns_cache_prewarm.sh
Populate that file with this code:
#!/bin/sh LOGFILE="/mnt/sda2/dns/dnsmasq.log" [ -f "$LOGFILE" ] || exit 0 logger -t dns_cache_prewarm "DNS cachefile repopulate started." # Find the word "forwarded" anywhere on the line and validate the next field as an FQDN awk '{ for(i=1; i<NF; i++) { if($i == "forwarded" && $(i+1) ~ /^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/) { print $(i+1) } } }' "$LOGFILE" \ | grep -vE '\.arpa$' \ | sort -u \ | while read -r domain; do nslookup "$domain" 127.0.0.1 >/dev/null 2>&1 & sleep 0.2 logger -t dns_cache_prewarm "DNS cachefile: ${domain} repopulated" done logger -t dns_cache_prewarm "DNS cachefile repopulate complete."
If your OpenWRT throws an error, it’s going to most likely be that sleep 0.2… BusyBox’s sleep command only takes integer values. Either change it to sleep 1 or install the coreutils-sleep package.
Ok, now we have to trigger that code. In /etc/init.d/dnsmasq, you’ll see the code:
reload_service() { rc_procd start_service "$@" procd_send_signal dnsmasq "$@" }
Change that to:
reload_service() { rc_procd start_service "$@" procd_send_signal dnsmasq "$@" (sleep 3 && /etc/dns_cache_prewarm.sh) & }
Now, when dnsmasq restart, in your logs, you’ll see entries like:
user.notice: dns_cache_prewarm: DNS cachefile repopulate started. user.notice: dns_cache_prewarm: DNS cachefile: url8947.nightly.pray.com repopulated user.notice: dns_cache_prewarm: DNS cachefile: use1-nf.naver.com.akadns.net repopulated user.notice: dns_cache_prewarm: DNS cachefile: v10.events.data.microsoft.com repopulated user.notice: dns_cache_prewarm: DNS cachefile: v20.events.data.microsoft.com repopulated user.notice: dns_cache_prewarm: DNS cachefile: valid.apple.com repopulated user.notice: dns_cache_prewarm: DNS cachefile: variations.brave.com repopulated user.notice: dns_cache_prewarm: DNS cachefile: video-fa.scdn.co repopulated user.notice: dns_cache_prewarm: DNS cachefile: www.bing.com repopulated user.notice: dns_cache_prewarm: DNS cachefile: www.collegeboard.org repopulated user.notice: dns_cache_prewarm: DNS cachefile: www.facebook.com repopulated user.notice: dns_cache_prewarm: DNS cachefile: www.google.com repopulated user.notice: dns_cache_prewarm: DNS cachefile: www.googleapis.com repopulated user.notice: dns_cache_prewarm: DNS cachefile: www.gstatic.com repopulated user.notice: dns_cache_prewarm: DNS cachefile: www.msftncsi.com repopulated user.notice: dns_cache_prewarm: DNS cachefile: www.spotify.com repopulated user.notice: dns_cache_prewarm: DNS cachefile: www.youtube.com repopulated user.notice: dns_cache_prewarm: DNS cachefile repopulate complete.
TO-DO: Change the /etc/dns_cache_prewarm.sh code to allow turning off logging by degrees. I started this code late at night, and I’ve got to sleep. Tomorrow.