]> git.ipfire.org Git - ipfire-2.x.git/blobdiff - src/scripts/ipsec-interfaces
suricata: Change midstream policy to "pass-flow"
[ipfire-2.x.git] / src / scripts / ipsec-interfaces
index 4ba2980e57e416e0b4f46d8da964fcf8689512bf..23512b9bd93b005e98892f46fa60cd0107875981 100644 (file)
@@ -2,7 +2,7 @@
 ###############################################################################
 #                                                                             #
 # IPFire.org - A linux based firewall                                         #
-# Copyright (C) 2015 IPFire Team                                              #
+# Copyright (C) 2007-2022  IPFire Team  <info@ipfire.org>                     #
 #                                                                             #
 # 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        #
@@ -23,19 +23,82 @@ shopt -s nullglob
 
 VPN_CONFIG="/var/ipfire/vpn/config"
 
+ROUTE_TABLE="220"
+ROUTE_TABLE_PRIO="128"
+
+eval $(/usr/local/bin/readhash /var/ipfire/ethernet/settings)
 eval $(/usr/local/bin/readhash /var/ipfire/vpn/settings)
 
+# Get RED interface name
+if [ -r "/var/ipfire/red/iface" ]; then
+       RED_INTF="$(</var/ipfire/red/iface)"
+else
+       RED_INTF="red0"
+fi
+
 VARS=(
-       id status name lefthost type ctype x1 x2 x3 leftsubnets
-       remote righthost rightsubnets x5 x6 x7 x8 x9 x10 x11 x12
-       x13 x14 x15 x16 x17 x18 x19 x20 x21 proto x22 x23 x24
-       route x26 mode interface_mode interface_address interface_mtu rest
+       id status name lefthost type ctype psk local local_id leftsubnets
+       remote_id remote rightsubnets x3 x4 x5 x6 x7 x8 x9 x10 x11 x12
+       x13 x14 x15 x16 x17 x18 x19 proto x20 x21 x22
+       route x23 mode interface_mode interface_address interface_mtu rest
 )
 
 log() {
        logger -t ipsec "$@"
 }
 
+resolve_hostname() {
+       local hostname="${1}"
+
+       dig +short A "${hostname}" | tail -n1
+}
+
+ip_encode() {
+       local address="${1}"
+
+       local int=0
+       for field in ${address//./ }; do
+               int=$(( $(( ${int} << 8 )) | ${field} ))
+       done
+
+       echo ${int}
+}
+
+function ip_in_subnet() {
+       local address="${1}"
+       local subnet="${2}"
+
+       local netmask="${subnet#*/}"
+
+       # Convert netmask to prefix if necessary
+       case "${netmask}" in
+               [0-9]+)
+                       ;;
+               *)
+                       netmask="$(netmask2prefix "${netmask}")"
+                       ;;
+       esac
+
+       local vlsm=$(( -1 << $(( 32 - ${netmask} )) ))
+
+       [ "$(( $(ip_encode "${address}") & ${vlsm} ))" -eq "$(( $(ip_encode "${subnet%/*}") & ${vlsm} ))" ]
+}
+
+netmask2prefix() {
+       local netmask="${1}"
+       local mask="$(ip_encode "${netmask}")"
+
+       local cidr=0
+       local x="$(( 128 << 24 ))" # 0x80000000
+
+       while [ $(( ${x} & ${mask} )) -ne 0 ]; do
+               [ ${mask} -eq ${x} ] && mask=0 || mask=$(( ${mask} << 1 ))
+               cidr=$(( ${cidr} + 1 ))
+       done
+
+       echo "${cidr}"
+}
+
 main() {
        # Register local variables
        local "${VARS[@]}"
@@ -43,8 +106,17 @@ main() {
 
        local interfaces=()
 
+       # Flush IPsec routes
+       ip route flush table "${ROUTE_TABLE}"
+
+       # Remove lookups
+       ip rule del lookup "${ROUTE_TABLE}"
+
        # We are done when IPsec is not enabled
        if [ "${ENABLED}" = "on" ]; then
+               # Enable route table lookup
+               ip rule add lookup "${ROUTE_TABLE}" prio "${ROUTE_TABLE_PRIO}"
+
                while IFS="," read -r "${VARS[@]}"; do
                        # Check if the connection is enabled
                        [ "${status}" = "on" ] || continue
@@ -58,6 +130,38 @@ main() {
                                        local intf="${interface_mode}${id}"
                                        ;;
                                *)
+                                       # Install routes
+                                       local address
+
+                                       local _address
+                                       for _address in ${GREEN_ADDRESS} ${BLUE_ADDRESS} ${ORANGE_ADDRESS}; do
+                                               local leftsubnet
+                                               for leftsubnet in ${leftsubnets//\|/ }; do
+                                                       if ip_in_subnet "${_address}" "${leftsubnet}"; then
+                                                               address="${_address}"
+                                                               break
+                                                       fi
+                                               done
+
+                                               # End loop when address is set
+                                               [ -n "${address}" ] && break
+                                       done
+
+                                       local rightsubnet
+                                       for rightsubnet in ${rightsubnets//\|/ }; do
+                                               # Ignore default
+                                               case "${rightsubnet}" in
+                                                       0.0.0.0/*)
+                                                               continue
+                                                               ;;
+                                               esac
+
+                                               log "Creating route to ${rightsubnet} (via ${address} and ${RED_INTF})"
+                                               ip route add table "${ROUTE_TABLE}" "${rightsubnet}" proto static \
+                                                       dev "${RED_INTF}" src "${address}"
+                                       done
+
+                                       # No interface processing required
                                        continue
                                        ;;
                        esac
@@ -65,16 +169,46 @@ main() {
                        # Add the interface to the list of all interfaces
                        interfaces+=( "${intf}" )
 
+                       # Compat for older connections
+                       if [ "${local}" = "off" ]; then
+                               if [ "${VPN_IP}" = "%defaultroute" ]; then
+                                       local=""
+                               else
+                                       local="${VPN_IP}"
+                               fi
+                       fi
+
+                       # Handle %defaultroute
+                       if [ -z "${local}" ]; then
+                               if [ -r "/var/ipfire/red/local-ipaddress" ]; then
+                                       local="$(</var/ipfire/red/local-ipaddress)"
+
+                               elif [ "${RED_TYPE}" = "STATIC" -a -n "${RED_ADDRESS}" ]; then
+                                       local="${RED_ADDRESS}"
+                               fi
+                       fi
+
+                       # Resolve any hostnames
+                       if [[ ! ${remote} =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
+                               remote="$(resolve_hostname "${remote}")"
+                       fi
+
                        local args=(
-                               "local" "${VPN_IP}"
-                               "remote" "${righthost}"
-                               "ttl" "255"
+                               "local" "${local}"
+                               "remote" "${remote}"
                        )
 
-                       # Add key for VTI
-                       if [ "${interface_mode}" = "vti" ]; then
-                               args+=( key "${id}" )
-                       fi
+                       case "${interface_mode}" in
+                               gre)
+                                       # Add TTL
+                                       args+=( "ttl" "255" )
+                                       ;;
+
+                               vti)
+                                       # Add key for VTI
+                                       args+=( "key" "${id}" )
+                                       ;;
+                       esac
 
                        # Update the settings when the interface already exists
                        if [ -d "/sys/class/net/${intf}" ]; then
@@ -94,6 +228,11 @@ main() {
                        ip addr flush dev "${intf}"
                        ip addr add "${interface_address}" dev "${intf}"
 
+                       # Disable IPsec policy lookup for VTI
+                       if [ "${interface_mode}" = "vti" ]; then
+                               sysctl -qw "net.ipv4.conf.${intf}.disable_policy=1"
+                       fi
+
                        # Set MTU
                        ip link set dev "${intf}" mtu "${interface_mtu}"
 
@@ -104,7 +243,7 @@ main() {
 
        # Delete all other interfaces
        local intf
-       for intf in /sys/class/net/gre* /sys/class/net/vti*; do
+       for intf in /sys/class/net/gre[0-9]* /sys/class/net/vti[0-9]*; do
                intf="$(basename "${intf}")"
 
                # Ignore a couple of interfaces that cannot be deleted
@@ -130,6 +269,9 @@ main() {
                log "Deleting interface ${intf}"
                ip link del "${intf}" &>/dev/null
        done
+
+       # (Re-)Apply all static routes
+       /etc/init.d/static-routes start
 }
 
 main || exit $?