From db97382758c0f5f366b57757b4dc3ee793ba66a4 Mon Sep 17 00:00:00 2001 From: "D. Berge" Date: Sat, 9 Aug 2025 18:30:26 +0200 Subject: [PATCH] Add scripts to automatically update the LAN DNS records. ./sbin/update-dns.sh may be called at regular intervals (one hour or so) via crontab. It will automatically detect: - its local host name (*.lan.dougal.aaltronav.eu); and - which IP has internet access, if any. Armed with that information and with the dynamic DNS API password stored in DYNDNS_PASSWD in ~/.dougalrc, it will update the relevant DNS record. For this to work, the first `lan.dougal` hostname in the Nginx configuration must be the one that is set up for dynamic update. Other `lan.dougal` hostnames should be CNAME records pointing to the first one. --- sbin/get-ip.sh | 19 +++++++++++++++++++ sbin/update-dns.sh | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100755 sbin/get-ip.sh create mode 100755 sbin/update-dns.sh diff --git a/sbin/get-ip.sh b/sbin/get-ip.sh new file mode 100755 index 0000000..77c4510 --- /dev/null +++ b/sbin/get-ip.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +# Find the interface used for the default route (e.g., to reach 8.8.8.8) +INTERFACE=$(ip route get 8.8.8.8 | awk '{for(i=1;i<=NF;i++) if ($i=="dev") {print $(i+1); exit}}') + +if [ -z "$INTERFACE" ] || [ "$INTERFACE" = "lo" ]; then + echo "No valid default route found." >/dev/stderr + exit 1 +fi + +# Extract the primary IPv4 address from the interface (excluding loopback) +IP=$(ip -4 addr show dev "$INTERFACE" scope global | grep -oP '(?<=inet\s)\d{1,3}(\.\d{1,3}){3}(?=/)' | head -n1) + +if [ -z "$IP" ]; then + echo "No global IPv4 address found on $INTERFACE." >/dev/stderr + exit 1 +fi + +echo "$IP" diff --git a/sbin/update-dns.sh b/sbin/update-dns.sh new file mode 100755 index 0000000..088bddf --- /dev/null +++ b/sbin/update-dns.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +# Path to Nginx configuration file +NGINX_CONFIG="/etc/nginx/vhosts.d/dougal.conf" + +# Extract the first hostname matching 'lan.dougal' from the config +# Assumes server_name lines like: server_name hostname1 hostname2; +HOSTNAME=$(grep -oE '[a-zA-Z0-9.-]*lan\.dougal[a-zA-Z0-9.-]*' "$NGINX_CONFIG" | head -n 1) + +if [ -z "$HOSTNAME" ]; then + echo "Error: No matching hostname found in $NGINX_CONFIG" + exit 1 +fi + +# Path to IP retrieval script +IP_SCRIPT="$HOME/software/sbin/get-ip.sh" + +# Get the current IPv4 address +IP_ADDRESS=$("$IP_SCRIPT") + +if [ -z "$IP_ADDRESS" ]; then + echo "Error: Failed to retrieve IP address from $IP_SCRIPT" + exit 1 +fi + +# Check for DYNDNS_PASSWD environment variable +if [ -z "$DYNDNS_PASSWD" ]; then + echo "Error: DYNDNS_PASSWD environment variable is not set" + exit 1 +fi + +# Hurricane Electric DynDNS update URL +UPDATE_URL="https://dyn.dns.he.net/nic/update?hostname=$HOSTNAME&password=$DYNDNS_PASSWD&myip=$IP_ADDRESS" + +# Send the update request and capture the response +RESPONSE=$(curl -s "$UPDATE_URL") + +# Output the response for logging/debugging +echo "Update response for $HOSTNAME ($IP_ADDRESS): $RESPONSE" +