From: Michael Tremer Date: Fri, 27 Sep 2024 15:39:22 +0000 (+0200) Subject: wireguard: Select the correct source IP address for N2N peers X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=76ea485d9edb781328e307c68b1f878d933408e5;p=people%2Fstevee%2Fipfire-2.x.git wireguard: Select the correct source IP address for N2N peers This is so that the firewall chooses the correct IP address when trying to establish connections to the remote networks. Signed-off-by: Michael Tremer --- diff --git a/src/initscripts/networking/functions.network b/src/initscripts/networking/functions.network index eb83b183d..3c0f2e3ad 100644 --- a/src/initscripts/networking/functions.network +++ b/src/initscripts/networking/functions.network @@ -246,6 +246,46 @@ network_address_in_network() { [ "${address}" -ge "${netaddr}" -a "${address}" -le "${broadcast}" ] } +# Takes a network and list of IP addresses and will return the first IP address +# that is in the given network. +first_address_in_network() { + local network="${1}" + shift + + local addr + for addr in $@; do + if network_address_in_network "${addr}" "${network}"; then + echo "${addr}" + return 0 + fi + done + + return 1 +} + +# Returns the first of IPFire's own IP addresses that is in any of the given networks +ipfire_address_in_networks() { + local addresses=() + + local var + for var in GREEN_ADDRESS BLUE_ADDRESS ORANGE_ADDRESS; do + if [ -n "${!var}" ]; then + addresses+=( "${!var}" ) + fi + done + + local network + for network in $@; do + # Find and end after the first match + if first_address_in_network "${network}" "${addresses[@]}"; then + return 0 + fi + done + + # Nothing found + return 1 +} + dhcpcd_get_pid() { # This function returns the pid of a dhcpcd by a given # network device, if a pidfile exists. diff --git a/src/initscripts/system/wireguard b/src/initscripts/system/wireguard index 0de356613..cb78d80ab 100644 --- a/src/initscripts/system/wireguard +++ b/src/initscripts/system/wireguard @@ -21,6 +21,7 @@ . /etc/sysconfig/rc . ${rc_functions} +. /etc/rc.d/init.d/networking/functions.network INTF="wg0" @@ -65,6 +66,9 @@ generate_config() { ip route add "${CLIENT_POOL}" dev "${INTF}" fi + local args + local src + while read -r id enabled type name pubkey endpoint port remote_subnets \ remarks local_subnets psk keepalive _rest; do # Skip peers that are not enabled @@ -89,8 +93,22 @@ generate_config() { # Apply the routes if [ "${type}" = "net" ]; then + local_subnets=( "${local_subnets//|/,}" ) + + # Find an IP address of the firewall that is inside the routed subnet + src="$(ipfire_address_in_networks "${local_subnets[@]}")" + for remote_subnet in ${remote_subnets//|/,}; do - ip route add "${remote_subnet}" dev "${INTF}" + args=( + "${remote_subnet}" "dev" "${INTF}" + ) + + # Add the preferred source if we found one + if [ -n "${src}" ]; then + args+=( "src" "${src}" ) + fi + + ip route add "${args[@]}" done fi fi