fff-vpn-select: Make vpn-select modular

vpn-select is an old relic and did not reflect the opportunities of our hoodfile.
This rewrite makes vpn-select modular to easely add new vpn-protocols.

The stuff dependent on the vpn-protocol is outsourced to files in /usr/lib/vpn-select.d/ and comes in with the respective vpn package.

vpn-stop is removed to use the protocol independent start/stop mechanism of vpn-select. Instead, a symlink is used.

We should avoid paralell vpns to the same gateway and not mix the protocol per hood. It is therefore necessary that all gateways offer the same protocols in one hood.
The most prefered protocol supported and available in the hood is selected. The order for this is defined in "uci fff.vpnselect.protocol_order" eg. "vxlan l2tp fastd"

Signed-off-by: Robert Langhammer <rlanghammer@web.de>
This commit is contained in:
Robert Langhammer 2020-10-19 23:29:05 +02:00
parent 8fe7512ae5
commit 2eccadc3ce
4 changed files with 96 additions and 53 deletions

View File

@ -0,0 +1,34 @@
protocol=fastd
fastd_clear() {
rm /tmp/fastd_fff_peers/*
}
fastd_addpeer() {
[ -d /tmp/fastd_fff_peers ] || mkdir /tmp/fastd_fff_peers
# write fastd-config
json_get_var servername name
filename="/etc/fastd/fff/peers/$servername"
echo "#name \"${servername}\";" > "$filename"
json_get_var key key
echo "key \"${key}\";" >> "$filename"
json_get_var address address
json_get_var port port
echo "remote \"${address}\" port ${port};" >> "$filename"
echo "" >> "$filename"
echo "float yes;" >> "$filename"
}
fastd_start_stop() {
/etc/init.d/fastd reload # does nothing if fastd was not running
# fastd start/stop for various situations
# this is needed for first start and if fastd comes up or disappears in hoodfile
pidfile="/tmp/run/fastd.fff.pid"
if [ "$(ls /etc/fastd/fff/peers/* 2>/dev/null)" ]; then
([ -s "$pidfile" ] && [ -d "/proc/$(cat "$pidfile")" ]) || /etc/init.d/fastd start
else
([ -s "$pidfile" ] && [ -d "/proc/$(cat "$pidfile")" ]) && /etc/init.d/fastd stop
fi
}

View File

@ -0,0 +1,5 @@
uci set fff.vpnselect=fff
uci set fff.vpnselect.protocol_order="fastd"
uci commit fff
exit 0

View File

@ -1,65 +1,73 @@
#!/bin/sh
# Usage: vpn-select <path-to-hood-file>
# To add a new protocol, put a file with three functions to /usr/lib/vpn-select.d/ .
# The file must start with protocol=name. It is most important to use the same name here and in hoodfile.
# Some parameters of the hood are available via $hood_id, $hood_name and $hood_protocol.
# The old config can be cleared in function ${protocol}_clear(). It is called first once per installed protocol.
# The function ${protocol}_addpeer() is called for every selected peer in hoodfile.
# The function ${protocol}_start_stop() is called at the end once per installed protocol.
#
# The variable $protocol_order defines the order of preference. The most preffered protocol of the available and offered protocols is selected.
# The $protocol_order is configurable via "uci fff.vpnselect.protocol_order"
# An empty protocol_order deactivates VPN.
. /usr/share/libubox/jshn.sh
hoodfile="$1"
make_config() {
# remove old config
rm /tmp/fastd_fff_peers/*
# load protocol_order
protocol_order="$(uci get fff.vpnselect.protocol_order)"
# prepare
Index=1
# source functions
for file in /usr/lib/vpn-select.d/*; do
[ -f $file ] && . "$file"
supported_protocols="$supported_protocols $protocol"
done
# compare $protocol_order with $supported_protocols
for proto in $protocol_order; do
echo "$supported_protocols" | grep -w $proto >&/dev/null || protocol_order=${protocol_order/$proto/}
done
# clear old config
for protocol in $supported_protocols; do
"${protocol}_clear"
done
# configure vpn
if [ -n "$hoodfile" ] && [ -s "$hoodfile" ] ; then
json_load "$(cat "$hoodfile")"
# load hoodparameter
json_select hood
json_get_var hood_id id
json_get_var hood_name name
json_get_var hood_protocol protocol
json_select ".."
json_select vpn
# get fastd peers
while json_select "$Index" > /dev/null
do
json_get_keys vpn_keys
for k in $vpn_keys; do
json_select $k
json_get_var protocol protocol
if [ "$protocol" = "fastd" ]; then
# set up fastd
json_get_var servername name
filename="/etc/fastd/fff/peers/$servername"
echo "#name \"${servername}\";" > "$filename"
json_get_var key key
echo "key \"${key}\";" >> "$filename"
json_get_var address address
json_get_var port port
echo "remote \"${address}\" port ${port};" >> "$filename"
echo "" >> "$filename"
echo "float yes;" >> "$filename"
fi
offered_protocols="$offered_protocols $protocol"
json_select ".." # back to vpn
Index=$(( Index + 1 ))
done
json_select ".." # back to root
}
# Only do something if file is there and not empty; otherwise exit 1
if [ -s "$hoodfile" ]; then
if [ ! -d /tmp/fastd_fff_peers ]; then
# first run after reboot
mkdir /tmp/fastd_fff_peers
make_config
# start fastd only if there are some peers
[ "$(ls /etc/fastd/fff/peers/* 2>/dev/null)" ] && /etc/init.d/fastd start
else
make_config
/etc/init.d/fastd reload
# select most preferred protocol for this hood
selected_protocol=$(for proto in $protocol_order; do echo $offered_protocols | grep -o $proto && break; done)
# fastd start/stop for various situations
pidfile="/tmp/run/fastd.fff.pid"
if [ "$(ls /etc/fastd/fff/peers/* 2>/dev/null)" ]; then
([ -s "$pidfile" ] && [ -d "/proc/$(cat "$pidfile")" ]) || /etc/init.d/fastd start
else
([ -s "$pidfile" ] && [ -d "/proc/$(cat "$pidfile")" ]) && /etc/init.d/fastd stop
fi
fi
exit 0
else
echo "vpn-select: Hood file not found or empty!"
exit 1
# configure selected vpns
for key in $vpn_keys; do
json_select $key
json_get_var protocol protocol
[ "$protocol" = "$selected_protocol" ] && "${protocol}_addpeer"
json_select ".." # back to vpn
done
fi
# start/restart/stop vpnservices
for protocol in $supported_protocols; do
"${protocol}_start_stop"
done

View File

@ -1,5 +0,0 @@
#!/bin/sh
rm /tmp/fastd_fff_peers/*
/etc/init.d/fastd stop

View File

@ -0,0 +1 @@
vpn-select