From 2eccadc3ce575d4474df9991f64f4d738e5c1727 Mon Sep 17 00:00:00 2001 From: Robert Langhammer Date: Mon, 19 Oct 2020 23:29:05 +0200 Subject: [PATCH] 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 --- .../files/usr/lib/vpn-select.d/fastd | 34 ++++++ .../files/etc/uci-defaults/58_vpn-select | 5 + .../fff-vpn-select/files/usr/sbin/vpn-select | 104 ++++++++++-------- .../fff-vpn-select/files/usr/sbin/vpn-stop | 6 +- 4 files changed, 96 insertions(+), 53 deletions(-) create mode 100644 src/packages/fff/fff-fastd/files/usr/lib/vpn-select.d/fastd create mode 100644 src/packages/fff/fff-vpn-select/files/etc/uci-defaults/58_vpn-select mode change 100755 => 120000 src/packages/fff/fff-vpn-select/files/usr/sbin/vpn-stop diff --git a/src/packages/fff/fff-fastd/files/usr/lib/vpn-select.d/fastd b/src/packages/fff/fff-fastd/files/usr/lib/vpn-select.d/fastd new file mode 100644 index 00000000..0fde6809 --- /dev/null +++ b/src/packages/fff/fff-fastd/files/usr/lib/vpn-select.d/fastd @@ -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 +} diff --git a/src/packages/fff/fff-vpn-select/files/etc/uci-defaults/58_vpn-select b/src/packages/fff/fff-vpn-select/files/etc/uci-defaults/58_vpn-select new file mode 100644 index 00000000..71015d70 --- /dev/null +++ b/src/packages/fff/fff-vpn-select/files/etc/uci-defaults/58_vpn-select @@ -0,0 +1,5 @@ +uci set fff.vpnselect=fff +uci set fff.vpnselect.protocol_order="fastd" +uci commit fff + +exit 0 diff --git a/src/packages/fff/fff-vpn-select/files/usr/sbin/vpn-select b/src/packages/fff/fff-vpn-select/files/usr/sbin/vpn-select index 30883f50..6c6bd123 100755 --- a/src/packages/fff/fff-vpn-select/files/usr/sbin/vpn-select +++ b/src/packages/fff/fff-vpn-select/files/usr/sbin/vpn-select @@ -1,65 +1,73 @@ #!/bin/sh # Usage: vpn-select +# 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 diff --git a/src/packages/fff/fff-vpn-select/files/usr/sbin/vpn-stop b/src/packages/fff/fff-vpn-select/files/usr/sbin/vpn-stop deleted file mode 100755 index 03a160b6..00000000 --- a/src/packages/fff/fff-vpn-select/files/usr/sbin/vpn-stop +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -rm /tmp/fastd_fff_peers/* -/etc/init.d/fastd stop - diff --git a/src/packages/fff/fff-vpn-select/files/usr/sbin/vpn-stop b/src/packages/fff/fff-vpn-select/files/usr/sbin/vpn-stop new file mode 120000 index 00000000..fd632e6c --- /dev/null +++ b/src/packages/fff/fff-vpn-select/files/usr/sbin/vpn-stop @@ -0,0 +1 @@ +vpn-select \ No newline at end of file