Files
bpfire/src/scripts/ipsec-interfaces
Peter Müller 66c3619872 Early spring clean: Remove trailing whitespaces, and correct licence headers
Bumping across one of our scripts with very long trailing whitespaces, I
thought it might be a good idea to clean these up. Doing so, some
missing or inconsistent licence headers were fixed.

There is no need in shipping all these files en bloc, as their
functionality won't change.

Signed-off-by: Peter Müller <peter.mueller@ipfire.org>
2022-02-18 23:54:57 +00:00

278 lines
7.0 KiB
Bash

#!/bin/bash
###############################################################################
# #
# IPFire.org - A linux based firewall #
# 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 #
# 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 <http://www.gnu.org/licenses/>. #
# #
###############################################################################
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 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[@]}"
local action
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
# Check if this a net-to-net connection
[ "${type}" = "net" ] || continue
# Determine the interface name
case "${interface_mode}" in
gre|vti)
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
# 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" "${local}"
"remote" "${remote}"
)
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
ip link change dev "${intf}" \
type "${interface_mode}" "${args[@]}" &>/dev/null
# Create a new interface and bring it up
else
log "Creating interface ${intf}"
if ! ip link add name "${intf}" type "${interface_mode}" "${args[@]}"; then
log "Could not create interface ${intf}"
continue
fi
fi
# Add an IP address
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}"
# Bring up the interface
ip link set dev "${intf}" up
done < "${VPN_CONFIG}"
fi
# Delete all other interfaces
local intf
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
case "${intf}" in
gre0|gretap0)
continue
;;
esac
# Check if interface is on the list
local i found="false"
for i in ${interfaces[@]}; do
if [ "${intf}" = "${i}" ]; then
found="true"
break
fi
done
# Nothing to do if interface was found
${found} && continue
# Delete the interface
log "Deleting interface ${intf}"
ip link del "${intf}" &>/dev/null
done
# (Re-)Apply all static routes
/etc/init.d/static-routes start
}
main || exit $?