]> git.ipfire.org Git - people/ms/ipfire-2.x.git/commitdiff
wireguard: Select the correct source IP address for N2N peers
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 27 Sep 2024 15:39:22 +0000 (17:39 +0200)
committerMichael Tremer <michael.tremer@ipfire.org>
Tue, 22 Apr 2025 14:48:53 +0000 (16:48 +0200)
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 <michael.tremer@ipfire.org>
src/initscripts/networking/functions.network
src/initscripts/system/wireguard

index eb83b183daa0df72340474176ce5e79713304eb5..3c0f2e3ad6811ef6597a9c6d69b1b5c815ec70d3 100644 (file)
@@ -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.
index 0de356613b01c0f704a4c80e81a8602c01ef29c8..cb78d80abf3f9fbc3989f641c70a9d45d1811567 100644 (file)
@@ -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