#!/bin/bash ############################################################################### # # # IPFire.org - A linux based firewall # # Copyright (C) 2024 Michael Tremer # # # # This program is free software: you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation, either version 3 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program. If not, see . # # # ############################################################################### # # # This script tries to keep WireGuard connections with dynamic peers alive # # # # It resolves the endpoint if it is an FQDN, and if so, will check if the # # currently connected endpoint matches any of the resolved IP addresses. If # # not it will reload the WireGuard configuration in the hope that wg will # # update the kernel with the new IP address and the connection comes back up # # again. # # # ############################################################################### . /etc/sysconfig/rc . ${rc_functions} # Fetches the first endpoint that is currently active on the given interface current_endpoint() { local intf="${1}" local pubkey local endpoint # List the first endpoint (are there even more than one?) wg show "${intf}" endpoints | while read -r pubkey endpoint; do echo "${endpoint%:*}" break done return 0 } # Resolves a hostname resolve() { local endpoint="${1}" dig +short "A" "${endpoint}" 2>/dev/null } main() { local -A settings=() # Read WireGuard settings readhash settings /var/ipfire/wireguard/settings # Do nothing if WireGuard is not enabled if [ "${settings[ENABLED]}" != "on" ]; then return 0 fi local line while IFS=',' read -r -a line; do local id="${line[0]}" local enabled="${line[1]}" local type="${line[2]}" local name="${line[3]}" local endpoint="${line[7]}" # Only process enabled net-to-net connections case "${enabled},${type}" in on,net) ;; *) continue ;; esac # The endpoint must be an FQDN case "${endpoint}" in # Ignore IP addresses [0-9]*.[0-9]*.[0-9]*.[0-9]*) continue ;; # Ignore if we don't know the endpoint "") continue ;; esac local address local match=0 # Fetch the current endpoint address local current_address="$(current_endpoint "wg${id}")" # Walk through all IP addresses the FQDN resolves to for address in $(resolve "${endpoint}"); do if [ "${current_address}" = "${address}" ]; then match=1 break fi done # If there has been no match, we have to reload everything if [ "${match}" -eq 0 ]; then exec /etc/init.d/wireguard reload fi done < /var/ipfire/wireguard/peers return 0 } main "$@" || exit $?