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 #!/bin/sh
# Usage: vpn-select <path-to-hood-file> # 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 . /usr/share/libubox/jshn.sh
hoodfile="$1" hoodfile="$1"
make_config() { # load protocol_order
# remove old config protocol_order="$(uci get fff.vpnselect.protocol_order)"
rm /tmp/fastd_fff_peers/*
# prepare # source functions
Index=1 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")" 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 json_select vpn
json_get_keys vpn_keys
# get fastd peers for k in $vpn_keys; do
while json_select "$Index" > /dev/null json_select $k
do
json_get_var protocol protocol json_get_var protocol protocol
if [ "$protocol" = "fastd" ]; then offered_protocols="$offered_protocols $protocol"
# 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
json_select ".." # back to vpn json_select ".." # back to vpn
Index=$(( Index + 1 ))
done done
json_select ".." # back to root
}
# Only do something if file is there and not empty; otherwise exit 1 # select most preferred protocol for this hood
if [ -s "$hoodfile" ]; then selected_protocol=$(for proto in $protocol_order; do echo $offered_protocols | grep -o $proto && break; done)
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
# fastd start/stop for various situations # configure selected vpns
pidfile="/tmp/run/fastd.fff.pid" for key in $vpn_keys; do
if [ "$(ls /etc/fastd/fff/peers/* 2>/dev/null)" ]; then json_select $key
([ -s "$pidfile" ] && [ -d "/proc/$(cat "$pidfile")" ]) || /etc/init.d/fastd start json_get_var protocol protocol
else [ "$protocol" = "$selected_protocol" ] && "${protocol}_addpeer"
([ -s "$pidfile" ] && [ -d "/proc/$(cat "$pidfile")" ]) && /etc/init.d/fastd stop json_select ".." # back to vpn
fi done
fi
exit 0
else
echo "vpn-select: Hood file not found or empty!"
exit 1
fi 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