Created
February 26, 2026 19:59
-
-
Save fuomag9/e226fa1178957d5303ff97bee292ce2e to your computer and use it in GitHub Desktop.
wg-reresolve-dns.sh
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # wg-reresolve-dns.sh — Re-resolve DNS for WireGuard peers managed by systemd-networkd | |
| # Reads .netdev files, resolves endpoint hostnames, and updates via `wg set`. | |
| set -euo pipefail | |
| export LC_ALL=C | |
| NETDEV_DIR="/etc/systemd/network" | |
| update_peer() { | |
| local iface="$1" pubkey="$2" endpoint="$3" | |
| local host port current_endpoint resolved_ip current_ip | |
| # Split endpoint into host:port | |
| if [[ "$endpoint" =~ ^\[(.+)\]:([0-9]+)$ ]]; then | |
| host="${BASH_REMATCH[1]}" | |
| port="${BASH_REMATCH[2]}" | |
| elif [[ "$endpoint" =~ ^(.+):([0-9]+)$ ]]; then | |
| host="${BASH_REMATCH[1]}" | |
| port="${BASH_REMATCH[2]}" | |
| else | |
| echo "WARNING: Cannot parse endpoint: $endpoint" >&2 | |
| return 0 | |
| fi | |
| # Skip if endpoint is already a bare IP address | |
| if [[ "$host" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]] || [[ "$host" =~ : ]]; then | |
| return 0 | |
| fi | |
| # Resolve hostname | |
| resolved_ip=$(getent ahosts "$host" 2>/dev/null | awk 'NR==1{ print $1 }') || true | |
| if [ -z "$resolved_ip" ]; then | |
| echo "WARNING: Cannot resolve $host for $iface" >&2 | |
| return 0 | |
| fi | |
| # Get current endpoint from wg show (use awk fixed-string match to avoid regex issues with +/= in keys) | |
| current_endpoint=$(wg show "$iface" endpoints 2>/dev/null \ | |
| | awk -v key="$pubkey" '$1 == key { print $2 }') || true | |
| if [ -z "$current_endpoint" ]; then | |
| echo "WARNING: Peer $pubkey not found on $iface" >&2 | |
| return 0 | |
| fi | |
| # Extract current IP (strip port) | |
| if [[ "$current_endpoint" =~ ^\[(.+)\]:[0-9]+$ ]]; then | |
| current_ip="${BASH_REMATCH[1]}" | |
| elif [[ "$current_endpoint" =~ ^(.+):[0-9]+$ ]]; then | |
| current_ip="${BASH_REMATCH[1]}" | |
| else | |
| current_ip="" | |
| fi | |
| if [[ "$resolved_ip" != "$current_ip" ]]; then | |
| echo "Updating $iface peer ${pubkey:0:8}...: $current_ip -> $resolved_ip ($host:$port)" | |
| wg set "$iface" peer "$pubkey" endpoint "$resolved_ip:$port" | |
| fi | |
| } | |
| # --- Main loop over .netdev files --- | |
| for netdev_file in "$NETDEV_DIR"/*.netdev; do | |
| [ -f "$netdev_file" ] || continue | |
| iface="" | |
| is_wireguard=0 | |
| in_peer=0 | |
| pubkey="" | |
| endpoint="" | |
| while IFS= read -r raw_line || [[ -n "$raw_line" ]]; do | |
| # Strip inline comments and leading/trailing whitespace | |
| line="${raw_line%%#*}" | |
| line="${line#"${line%%[![:space:]]*}"}" | |
| line="${line%"${line##*[![:space:]]}"}" | |
| [ -z "$line" ] && continue | |
| # Detect section headers | |
| if [[ "$line" == "["* ]]; then | |
| # Flush previous peer | |
| if [[ $in_peer -eq 1 && -n "$pubkey" && -n "$endpoint" && -n "$iface" ]]; then | |
| update_peer "$iface" "$pubkey" "$endpoint" | |
| fi | |
| pubkey="" | |
| endpoint="" | |
| in_peer=0 | |
| [[ "$line" == "[WireGuardPeer]" ]] && in_peer=1 | |
| continue | |
| fi | |
| key="${line%%=*}" | |
| value="${line#*=}" | |
| key="${key#"${key%%[![:space:]]*}"}"; key="${key%"${key##*[![:space:]]}"}" | |
| value="${value#"${value%%[![:space:]]*}"}"; value="${value%"${value##*[![:space:]]}"}" | |
| if [[ $in_peer -eq 0 ]]; then | |
| case "$key" in | |
| Name) iface="$value" ;; | |
| Kind) [[ "$value" == "wireguard" ]] && is_wireguard=1 ;; | |
| esac | |
| else | |
| case "$key" in | |
| PublicKey) pubkey="$value" ;; | |
| Endpoint) endpoint="$value" ;; | |
| esac | |
| fi | |
| done < "$netdev_file" | |
| # Flush last peer in file | |
| if [[ $in_peer -eq 1 && -n "$pubkey" && -n "$endpoint" && -n "$iface" && $is_wireguard -eq 1 ]]; then | |
| update_peer "$iface" "$pubkey" "$endpoint" | |
| fi | |
| done |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Use like this
/etc/systemd/system/wg-reresolve-dns.service
/etc/systemd/system/wg-reresolve-dns.timer