mirror of
https://github.com/vincentmli/bpfire.git
synced 2026-04-09 18:45:54 +02:00
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>
278 lines
7.0 KiB
Bash
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 $?
|