Pi hole local Dynamic DNS resolver
Dynamic local dns changer.
You probably know of ddns services that allow the dynamic change of a (sub) hostname. to point a webaddress to a changing web ip address. This is kinda the same but then for local system. But there is DNS/DHCP (and a lot of other local systems) i hear you say that always point to the right ip. Well your not wrong but there are two use cases that are not capable with dns/dhcp and other local systems
1st ip of a list of servers
For my home assistant setup i have local whisper setup for when the internet is down. I dont have home assistant on a fast system. My fastest system is my laptop blue-mage but that one is not up 24/7 so i need a fail over. By making a list of ip addresses in priority of system speed and then ping then untill you get a respond you have the ip for a hostname for your fastest whisper server.
vpn on/off hostname
My laptops have a vpn system to keep connected to my homelab. By selecting between the local ip or the vpn ip i have a hostname that always connects to my laptop where ever it is. (vpn needs to be enabled when outside local lan)
Code and stuff
This script uses pihole or dnsmasq as dns system with a additional host file. that is fed by scripts in a crontab.
pihole/dnsmasq config.
Pi hole is under everlasting change. the setup just changed i hope it stays this for a while
set etc_dnsmasq_d = true in misc in /etc/pihole/pihole.toml
create a file /etc/dnsmasq.d/99-dyndns.conf
with the content addn-hosts=/etc/dyn-hosts.conf
create a empty file with atleast one row end (or else dnsmasq wont start) /etc/dyn-hosts.conf
ddns script
here is the overall script to manage the /etc/dns-hosts.conf file. if you use dnsmasq you need to edit the systemctl restart
dont forget making it execuable
/usr/local/bin/dyndnsmasq.sh
#!/bin/bash
# Script to add or update a hostname's IP address in $dyn_file
# Check for required arguments
if [ $# -ne 2 ]; then
echo "Usage: $0 <ip_address> <hostname>"
exit 1
fi
ip_address="$1"
hostname="$2"
dyn_file="/etc/dyn-hosts.conf"
# Check if IP address is valid (basic check)
if [[ ! "$ip_address" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
echo "Invalid IP address: $ip_address"
exit 1
fi
# Check if hostname is valid (basic check - can be more strict)
if [[ ! "$hostname" =~ ^[a-zA-Z0-9.-]+$ ]]; then
echo "Invalid hostname: $hostname"
exit 1
fi
# Create a temporary file to store the modified $dyn_file content
temp_file=$(mktemp)
# Check if the hostname already exists in $dyn_file and update or add
if grep -q "$hostname" "$dyn_file"; then
# Hostname exists, update the IP address. Capture the changes.
if sed "s/^\([0-9.]*\)\s\+${hostname}\$/${ip_address} ${hostname}/" "$dyn_file" > "$temp_file"; then
echo "Updated IP address for $hostname to $ip_address"
else
echo "Error updating IP address for $hostname"
rm "$temp_file"
exit 1
fi
else
# Hostname does not exist, add a new entry
echo "$ip_address $hostname" >> "$temp_file"
echo "Added $hostname with IP address $ip_address"
# Copy the original content of $dyn_file to the temp file, then append the new line.
cat "$dyn_file" >> "$temp_file"
fi
# Compare the original $dyn_file with the new content in the temp file
if ! cmp -s "$dyn_file" "$temp_file"; then # -s for silent comparison
cat "$temp_file" > "$dyn_file"
# Files are different, overwrite $dyn_file and restart dnsmas
systemctl restart pihole-FTL # or dnsmasq if you use dnsmasq
else
echo "No changes needed to $dyn_file."
rm "$temp_file" # Clean up the temporary file
fi
exit 0
script for a hostname
Here is one example script edit and duplicate i keep them in /root/bin/
#!/bin/bash
# List of IP addresses to ping
IP_STRING="192.168.5.80 10.209.212.9 192.168.5.6"
hostname="whisper.hlab"
# Function to check if IP is reachable
check_ip_reachable() {
ip="$1"
ping -c 1 -W 1 "$ip" >/dev/null 2>&1
}
# Main script
for ip in $IP_STRING; do
if check_ip_reachable "$ip"; then
echo "Found reachable IP: $ip"
/usr/local/bin/dyndnsmasq.sh "$ip" "$hostname"
exit 0
fi
done
echo "No reachable IP found in the list."
Final result.
if you loaded it in a crontab or executed the script. you have whisper.hlab pointing to the 1st ip found. No online services are used so the system works when your home is offline.