From 7526802233c74651c3a42cb87b8b160352f55e00 Mon Sep 17 00:00:00 2001 From: Daniel Lenski Date: Thu, 24 Sep 2020 17:14:00 -0700 Subject: [PATCH] add working do_attempt_reconnect This initial implementation requires iproute2. It find all routes that match the VPN gateway (excluding those matching "dev $TUNDEV", since the goal is to prevent loopback), and simply tries adding them one-by-one. See https://gitlab.com/openconnect/openconnect/-/issues/17 for the original motivation for adding `reason=attempt-reconnect`. See https://github.com/dlenski/vpn-slice/pull/14#issuecomment-489293114 for a discussion of the complexities of implementing it correctly. Signed-off-by: Daniel Lenski --- vpnc-script | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/vpnc-script b/vpnc-script index 4e2d6ea..4749c8c 100755 --- a/vpnc-script +++ b/vpnc-script @@ -245,6 +245,22 @@ if [ -n "$IPROUTE" ]; then $IPROUTE route flush cache 2>/dev/null } + set_vpngateway_route_attempt_reconnect() { + # We'll attempt to add a host route to the gateway through every route that matches + # its address (excluding those through TUNDEV because the goal is to avoid loopback). + + echo "$VPNGATEWAY" | grep -q : && FAMILY=-6 ROOT=::/0 || FAMILY=-4 ROOT=0/0 + $IPROUTE $FAMILY route show to "$VPNGATEWAY" root "$ROOT" | grep -v "dev $TUNDEV" | cut -d' ' -f2- | + while read LINE ; do + # We do not want to use 'replace', since a route to the gateway that already + # exists is mostly likely the correct one (e.g. the case of a reconnect attempt + # after dead-peer detection, but no change in the underlying network devices). + # Using "add" will succeed at most once + $IPROUTE $FAMILY route add `echo "$VPNGATEWAY $LINE" | fix_ip_get_output` 2>/dev/null && break + done + $IPROUTE $FAMILY route flush cache 2>/dev/null + } + del_vpngateway_route() { $IPROUTE route $route_syntax_del "$VPNGATEWAY" $IPROUTE route flush cache 2>/dev/null @@ -369,6 +385,11 @@ else # use route command route add -host "$VPNGATEWAY" $route_syntax_gw "`get_default_gw`" } + set_vpngateway_route_attempt_reconnect() { + # FIXME: needs implementation similar to IPROUTE version + set_vpngateway_route + } + del_vpngateway_route() { route $route_syntax_del -host "$VPNGATEWAY" $route_syntax_gw "`get_default_gw`" } @@ -1047,6 +1068,10 @@ do_disconnect() { destroy_tun_device } +do_attempt_reconnect() { + set_vpngateway_route_attempt_reconnect +} + #### Main if [ -z "$reason" ]; then @@ -1075,6 +1100,8 @@ case "$reason" in # be left with a route to the VPN server through the VPN # itself, which would need to be fixed. run_hooks attempt-reconnect + do_attempt_reconnect + run_hooks post-attempt-reconnect ;; reconnect) # After successfully re-establishing the session. -- 2.50.1