From patchwork Mon Feb 12 13:03:45 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: vpn-select/configurehood: Reorganize code to start and stop VPN From: Adrian Schmutzler X-Patchwork-Id: 782 Message-Id: <1518440625-2512-1-git-send-email-freifunk@adrianschmutzler.de> To: franken-dev@freifunk.net Date: Mon, 12 Feb 2018 14:03:45 +0100 This patch is meant to tidy up the code in vpn-select and to repair some inconveniences left over from the transfer to KeyXchangeV2. 1. VPN configuration and start/stop are separated now. This is resonable since the configuration is now done by the hood file, which is checked for changes elsewhere, so we call vpn-configure only if changes are found. The start/stop however is affected by more transient conditions like internet availability etc. 2. The code to set up general config and individual fastd/L2TP peers has been moved to a library. 3. This patch deactivates VPN for 5 minutes if no internet is present during the configurehood call. To disable this, just remove the topmost /usr/sbin/vpn-stop. Regarding issue #72, both should work, since we do not create a config if VPN is missing. 4. Tunneldigger is not started without peers like before Behavior changes: - This patch will destroy the previous VPN configuration if none is given in the current hood file. - Since vpn-configure includes the setup of L2TP peers, gateway L2TP files are only queried during hood file-based configuration, not every 5 minutes as before. - VPN is disabled during the phase were a changed (!) hood file is evaluated and config is reset. - With the current state (no changes as suggested in 3.), no VPN processes are running if WAN is disconnected. Config will be present if the chosen hood supports it. Signed-off-by: Adrian Schmutzler Reviewed-by: Robert Langhammer Tested-by: Adrian Schmutzler --- Dieser Patch soll nicht als Konkurrenz zu Christians Patch diskutiert werden, sondern als Vorschlag für eine langfristigere Lösung. In den Details gibt es sicher noch Optimierungspotential. --- .../fff/fff-hoods/files/usr/sbin/configurehood | 12 +-- src/packages/fff/fff-vpn-select/Makefile | 2 +- .../files/lib/functions/fff/vpn-select | 100 +++++++++++++++++++++ .../fff-vpn-select/files/usr/sbin/vpn-configure | 11 +++ .../fff/fff-vpn-select/files/usr/sbin/vpn-select | 87 ------------------ .../fff/fff-vpn-select/files/usr/sbin/vpn-start | 8 ++ .../fff/fff-vpn-select/files/usr/sbin/vpn-stop | 6 ++ 7 files changed, 133 insertions(+), 93 deletions(-) create mode 100644 src/packages/fff/fff-vpn-select/files/lib/functions/fff/vpn-select create mode 100755 src/packages/fff/fff-vpn-select/files/usr/sbin/vpn-configure delete mode 100755 src/packages/fff/fff-vpn-select/files/usr/sbin/vpn-select create mode 100755 src/packages/fff/fff-vpn-select/files/usr/sbin/vpn-start create mode 100755 src/packages/fff/fff-vpn-select/files/usr/sbin/vpn-stop diff --git a/src/packages/fff/fff-hoods/files/usr/sbin/configurehood b/src/packages/fff/fff-hoods/files/usr/sbin/configurehood index 90d81d1..c1c8eeb 100755 --- a/src/packages/fff/fff-hoods/files/usr/sbin/configurehood +++ b/src/packages/fff/fff-hoods/files/usr/sbin/configurehood @@ -85,6 +85,7 @@ else #UPLINK: No uplink download if internet present #if no Internet, we connect to the hidden AP and download the file from another Node in range else + /usr/sbin/vpn-stop # Stop VPN processes if router has no internet # connect to wireless hidden ap here and download the json File from the nearest router # Only do that, when we have no gateway in range. If the Uplinkrouter changed the hood, we lost the GW and do this automatically again, I think! Nice idea? if ! isGatewayAvailable ; then @@ -197,6 +198,8 @@ if [ -s "$hoodfile" ]; then if [ "$sumnew" != "$sumold" ] ; then echo "New file detected, we reconfigure the Node"; + /usr/sbin/vpn-stop # stop VPN during reconfiguration (so we can start again with new config) + json_select hood json_get_var hood name @@ -270,6 +273,8 @@ if [ -s "$hoodfile" ]; then newntp="${ntpip}" # requires routable address, no link-local [ "$newntp" = "$oldntp" ] || setTimeserver "${newntp}" # only rewrite if changed + /usr/sbin/vpn-configure # Configure VPN, but do not start it + # copy the file to webroot so that other mesh routers can download it; # copy only after all other steps so IF can be reentered if something goes wrong cp "$hoodfile" "$hoodfilecopy" @@ -281,12 +286,9 @@ if [ -s "$hoodfile" ]; then echo "We have no new file. We do nothing. We try it again in 5 minutes..."; fi - # and now we get to vpn-select script and load VPNs directly from /tmp/keyxchangev2data + # Start already configured VPN if router has internet + hasInternet && /usr/sbin/vpn-start - if hasInternet ; then - sh /usr/sbin/vpn-select - fi - # now we load the prefix from the hoodfile and set this to br-mesh json_select network json_get_var prefix ula_prefix diff --git a/src/packages/fff/fff-vpn-select/Makefile b/src/packages/fff/fff-vpn-select/Makefile index 4e2d89b..27cff09 100644 --- a/src/packages/fff/fff-vpn-select/Makefile +++ b/src/packages/fff/fff-vpn-select/Makefile @@ -1,7 +1,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=fff-vpn-select -PKG_VERSION:=1 +PKG_VERSION:=3 PKG_RELEASE:=1 PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) diff --git a/src/packages/fff/fff-vpn-select/files/lib/functions/fff/vpn-select b/src/packages/fff/fff-vpn-select/files/lib/functions/fff/vpn-select new file mode 100644 index 0000000..72022f4 --- /dev/null +++ b/src/packages/fff/fff-vpn-select/files/lib/functions/fff/vpn-select @@ -0,0 +1,100 @@ +#!/bin/sh +# Copyright 2018 Adrian Schmutzler +# License GPLv3 + +. /lib/functions/fff/keyxchange +. /usr/share/libubox/jshn.sh + +make_config() { + # Create VPN config + # + # Call without parameters + + index_l2tp=0 + index_json=1 + json_load "$(cat "$hoodfile")" + json_select vpn + # get VPN peers + while json_select "$index_json" > /dev/null + do + json_get_var protocol protocol + # Current design requires "fastd" for both fastd and L2TP, decision is made by gateway + if [ "$protocol" == "fastd" ]; then + json_get_var servername name + json_get_var key key + json_get_var address address + json_get_var port port + + if [ "l2tp" = "$(wget -T10 "${address}/vpn.txt" -O - 2>/dev/null)" ]; then + # Setup L2TP + make_l2tp "$address" "$port" "$index_l2tp" + index_l2tp=$((index_l2tp + 1)) + else + # Setup fastd + make_fastd "$servername" "$address" "$port" "$key" + fi + fi + json_select ".." # back to vpn + index_json=$(( index_json + 1 )) + done + json_select ".." # back to root +} + +make_fastd() { + # Create fastd config + # + # Syntax: make_fastd
+ + if [ $# -ne "4" ] + then + return 1 + fi + + local servername=$1 + local address=$2 + local port=$3 + local key=$4 + + filename="/etc/fastd/fff/peers/$servername" + echo "#name \"${servername}\";" > "$filename" + echo "key \"${key}\";" >> "$filename" + echo "remote ipv4 \"${address}\" port ${port};" >> "$filename" + echo "" >> "$filename" + echo "float yes;" >> "$filename" + + return 0 +} + +make_l2tp() { + # Create L2TP config + # + # Syntax: make_l2tp
+ + if [ $# -ne "3" ] + then + return 1 + fi + + local address=$1 + local port=$2 + local count=$3 + + # Use MAC address as hostname if not set + hostname="$(cat /proc/sys/kernel/hostname)" + [ "$hostname" = "LEDE" ] && hostname="" + [ "$hostname" = "" ] && hostname="$(awk '{ mac=toupper($1); gsub(":", "", mac); print mac }' /sys/class/net/br-mesh/address 2>/dev/null)" + + L2PORT=$((port + 10000)) + + uci -q set "tunneldigger.$count=broker" + uci -q set "tunneldigger.$count.address=${address}:$L2PORT" + uci -q set "tunneldigger.$count.uuid=$hostname" + uci -q set "tunneldigger.$count.interface=l2tp$count" + uci -q set "tunneldigger.$count.enabled=1" + uci -q set "tunneldigger.$count.hook_script=/etc/tunneldigger/tunneldigger.hook" + uci -c /tmp commit tunneldigger + + return 0 +} + +# vim: set noexpandtab:tabstop=4 diff --git a/src/packages/fff/fff-vpn-select/files/usr/sbin/vpn-configure b/src/packages/fff/fff-vpn-select/files/usr/sbin/vpn-configure new file mode 100755 index 0000000..cb488ce --- /dev/null +++ b/src/packages/fff/fff-vpn-select/files/usr/sbin/vpn-configure @@ -0,0 +1,11 @@ +#!/bin/sh + +. /lib/functions/fff/vpn-select + +# remove old config in any case +>/etc/config/tunneldigger +[ ! -d /tmp/fastd_fff_peers ] && mkdir /tmp/fastd_fff_peers +rm /tmp/fastd_fff_peers/* + +# Only write config if hood file is present and greater 0 byte +[ -s "$hoodfile" ] && make_config 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 deleted file mode 100755 index 85930a8..0000000 --- a/src/packages/fff/fff-vpn-select/files/usr/sbin/vpn-select +++ /dev/null @@ -1,87 +0,0 @@ -#!/bin/sh - -. /lib/functions/fff/keyxchange -. /usr/share/libubox/jshn.sh - -make_config() { -# remove old config ->/etc/config/tunneldigger -rm /tmp/fastd_fff_peers/* -count=0 -Index=1 -json_load "$(cat "$hoodfile")" -json_select vpn -# get fastd peers -while json_select "$Index" > /dev/null -do - json_get_var protocol protocol - if [ "$protocol" == "fastd" ]; then - 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 ipv4 \"${address}\" port ${port};" >> "$filename" - echo "" >> "$filename" - echo "float yes;" >> "$filename" - - # ask for Broker and select the tunnel - if [ "l2tp" = "$(wget -T10 "${address}/vpn.txt" -O - 2>/dev/null)" ]; then - # Gateway offers l2tp - L2PORT=$((port + 10000)) - UUID=$hostname - - uci set tunneldigger.$count=broker - uci set tunneldigger.$count.address="${address}:$L2PORT" - uci set tunneldigger.$count.uuid="$UUID" - uci set tunneldigger.$count.interface="l2tp$count" - uci set tunneldigger.$count.enabled="1" - uci set tunneldigger.$count.hook_script='/etc/tunneldigger/tunneldigger.hook' - uci -c /tmp commit tunneldigger - count=$((count + 1)) - # remove this fastd-peer - rm "$filename" - fi - fi - json_select ".." # back to vpn - Index=$(( Index + 1 )) -done -json_select ".." # back to root -} - -# main - -# Only do something when file is here and greater 0 byte -if [ -s "$hoodfile" ]; then - # set some vars - hostname=$(cat /proc/sys/kernel/hostname) - mac=$(awk '{ mac=toupper($1); gsub(":", "", mac); print mac }' /sys/class/net/br-mesh/address 2>/dev/null) - [ "$hostname" = "LEDE" ] && hostname="" - [ "$hostname" = "" ] && hostname="$mac" - - 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 left - [ "$(ls /etc/fastd/fff/peers/* 2>/dev/null)" ] && /etc/init.d/fastd start - /etc/init.d/tunneldigger start - else - # check if new tunneldigger conf is different - sumold=$(sha256sum /etc/config/tunneldigger) - make_config - sumnew=$(sha256sum /etc/config/tunneldigger) - [ "$sumnew" != "$sumold" ] && /etc/init.d/tunneldigger restart - /etc/init.d/fastd reload - - # 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 -fi diff --git a/src/packages/fff/fff-vpn-select/files/usr/sbin/vpn-start b/src/packages/fff/fff-vpn-select/files/usr/sbin/vpn-start new file mode 100755 index 0000000..592b871 --- /dev/null +++ b/src/packages/fff/fff-vpn-select/files/usr/sbin/vpn-start @@ -0,0 +1,8 @@ +#!/bin/sh + +if [ "$(ls /etc/fastd/fff/peers/* 2>/dev/null)" ] ; then + pidfile="/tmp/run/fastd.fff.pid" + ([ -s "$pidfile" ] && [ -d "/proc/$(cat "$pidfile")" ]) || /etc/init.d/fastd start +fi + +uci -q get tunneldigger.@broker[0] > /dev/null && /etc/init.d/tunneldigger start 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 100755 index 0000000..f931d7e --- /dev/null +++ b/src/packages/fff/fff-vpn-select/files/usr/sbin/vpn-stop @@ -0,0 +1,6 @@ +#!/bin/sh + +/etc/init.d/tunneldigger stop + +pidfile="/tmp/run/fastd.fff.pid" +([ -s "$pidfile" ] && [ -d "/proc/$(cat "$pidfile")" ]) && /etc/init.d/fastd stop