[PATCH v3 1/3] Support split-exclude rules from Pulse gateway

Gernot Hillier gernot.hillier at siemens.com
Wed Feb 21 08:46:42 PST 2018


The vpnc-script used by OpenConnect only supports "split include" rules (default
route unchanged, specific VPN routes added). We add support for Pulse's "split
exclude" rules (default route to VPN, exclude rules for targets to be connected
via normal uplink).

For targets specified as split-exclude by the gateway, we add additional routes
which keep traffic as-is (i.e. separate from tunnel). On platforms only
providing /sbin/route, we guess that those are reached via default gateway.
Please note that IPv6 variant is completely untested as I have no
access to according testbeds.

Tested on Linux (using ip and route command) in a IPv4 environment, "ip"
case also tested in a IPv6 dialup config (gateway is IPv4 only).

Signed-off-by: Gernot Hillier <gernot.hillier at siemens.com>
---
 vpnc-script | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 117 insertions(+)

diff --git a/vpnc-script b/vpnc-script
index ae13947..a5f6c9c 100755
--- a/vpnc-script
+++ b/vpnc-script
@@ -252,6 +252,26 @@ if [ -n "$IPROUTE" ]; then
 		$IPROUTE route flush cache
 	}
 
+	set_exclude_route() {
+		# add explicit route to keep current routing for this target
+		# (keep traffic separate from VPN tunnel)
+		NETWORK="$1"
+		NETMASK="$2"
+		NETMASKLEN="$3"
+		$IPROUTE route add `$IPROUTE route get "$NETWORK/$NETMASKLEN" | fix_ip_get_output`
+		$IPROUTE route flush cache
+	}
+
+	del_exclude_route() {
+		# FIXME: In theory, this could delete existing routes which are
+		# identical to split-exclude routes specificed by VPNGATEWAY
+		NETWORK="$1"
+		NETMASK="$2"
+		NETMASKLEN="$3"
+		$IPROUTE route $route_syntax_del "$NETWORK/$NETMASKLEN"
+		$IPROUTE route flush cache
+	}
+
 	reset_default_route() {
 		if [ -s "$DEFAULT_ROUTE_FILE" ]; then
 			$IPROUTE route replace `cat "$DEFAULT_ROUTE_FILE"`
@@ -281,6 +301,15 @@ if [ -n "$IPROUTE" ]; then
 		$IPROUTE route flush cache
 	}
 
+	set_ipv6_exclude_route() {
+		# add explicit route to keep current routing for this target
+		# (keep traffic separate from VPN tunnel)
+		NETWORK="$1"
+		NETMASKLEN="$2"
+		$IPROUTE -6 route add `$IPROUTE route get "$NETWORK/$NETMASKLEN" | fix_ip_get_output`
+		$IPROUTE route flush cache
+	}
+
 	reset_ipv6_default_route() {
 		$IPROUTE -6 route del default dev "$TUNDEV"
 		$IPROUTE route flush cache
@@ -292,6 +321,15 @@ if [ -n "$IPROUTE" ]; then
 		$IPROUTE -6 route del "$NETWORK/$NETMASKLEN" dev "$TUNDEV"
 		$IPROUTE -6 route flush cache
 	}
+
+	del_ipv6_exclude_route() {
+		# FIXME: In theory, this could delete existing routes which are
+		# identical to split-exclude routes specificed by VPNGATEWAY
+		NETWORK="$1"
+		NETMASKLEN="$2"
+		$IPROUTE -6 route del "$NETWORK/$NETMASKLEN"
+		$IPROUTE -6 route flush cache
+	}
 else # use route command
 	get_default_gw() {
 		# isn't -n supposed to give --numeric output?
@@ -323,6 +361,28 @@ else # use route command
 		route add -net "$NETWORK" $route_syntax_netmask "$NETMASK" $route_syntax_gw "$INTERNAL_IP4_ADDRESS" $route_syntax_interface
 	}
 
+	set_exclude_route() {
+		NETWORK="$1"
+		NETMASK="$2"
+		NETMASKLEN="$3"
+		if [ -z "$DEFAULTGW" ]; then
+			DEFAULTGW="`get_default_gw`"
+		fi
+		# Add explicit route to keep traffic for this target separate
+		# from tunnel. FIXME: We use default gateway - this is our best
+		# guess in absence of "ip" command to query effective route.
+		route add -net "$NETWORK" $route_syntax_netmask "$NETMASK" $route_syntax_gw "$DEFAULTGW" $route_syntax_interface
+	}
+
+	del_exclude_route() {
+		# FIXME: This can delete existing routes in case they're
+		# identical to split-exclude routes specified by VPNGATEWAY
+		NETWORK="$1"
+		NETMASK="$2"
+		NETMASKLEN="$3"
+		route $route_syntax_del -net "$NETWORK" $route_syntax_netmask "$NETMASK"
+	}
+
 	reset_default_route() {
 		if [ -s "$DEFAULT_ROUTE_FILE" ]; then
 			route $route_syntax_del default $route_syntax_gw "`get_default_gw`" $route_syntax_interface
@@ -355,6 +415,16 @@ else # use route command
 		:
 	}
 
+	set_ipv6_exclude_route() {
+		NETWORK="$1"
+		NETMASK="$2"
+		# Add explicit route to keep traffic for this target separate
+		# from tunnel. FIXME: We use default gateway - this is our best
+		# guess in absence of "ip" command to query effective route.
+		route add -inet6 -net "$NETWORK/$NETMASK" "`get_default_gw`" $route_syntax_interface
+		:
+	}
+
 	reset_ipv6_default_route() {
 		route $route_syntax_del -inet6 default "$INTERNAL_IP6_ADDRESS"
 		:
@@ -367,6 +437,13 @@ else # use route command
 		:
 	}
 
+	del_ipv6_exclude_route() {
+		NETWORK="$1"
+		NETMASK="$2"
+		route $route_syntax_del -inet6 "$NETWORK/$NETMASK"
+		:
+	}
+
 fi
 
 # =========== resolv.conf handling ====================================
@@ -731,6 +808,26 @@ do_connect() {
 
 	set_vpngateway_route
 	do_ifconfig
+	if [ -n "$CISCO_SPLIT_EXC" ]; then
+		i=0
+		while [ $i -lt $CISCO_SPLIT_EXC ] ; do
+			eval NETWORK="\${CISCO_SPLIT_EXC_${i}_ADDR}"
+			eval NETMASK="\${CISCO_SPLIT_EXC_${i}_MASK}"
+			eval NETMASKLEN="\${CISCO_SPLIT_EXC_${i}_MASKLEN}"
+			set_exclude_route "$NETWORK" "$NETMASK" "$NETMASKLEN"
+			i=`expr $i + 1`
+		done
+	fi
+	if [ -n "$CISCO_IPV6_SPLIT_EXC" ]; then
+		# untested
+		i=0
+		while [ $i -lt $CISCO_IPV6_SPLIT_EXC ] ; do
+			eval NETWORK="\${CISCO_IPV6_SPLIT_EXC_${i}_ADDR}"
+			eval NETMASKLEN="\${CISCO_IPV6_SPLIT_EXC_${i}_MASKLEN}"
+			set_ipv6_exclude_route "$NETWORK" "$NETMASKLEN"
+			i=`expr $i + 1`
+		done
+	fi
 	if [ -n "$CISCO_SPLIT_INC" ]; then
 		i=0
 		while [ $i -lt $CISCO_SPLIT_INC ] ; do
@@ -799,6 +896,26 @@ do_disconnect() {
 	else
 		reset_default_route
 	fi
+	if [ -n "$CISCO_SPLIT_EXC" ]; then
+		i=0
+		while [ $i -lt $CISCO_SPLIT_EXC ] ; do
+			eval NETWORK="\${CISCO_SPLIT_EXC_${i}_ADDR}"
+			eval NETMASK="\${CISCO_SPLIT_EXC_${i}_MASK}"
+			eval NETMASKLEN="\${CISCO_SPLIT_EXC_${i}_MASKLEN}"
+			del_exclude_route "$NETWORK" "$NETMASK" "$NETMASKLEN"
+			i=`expr $i + 1`
+		done
+	fi
+	if [ -n "$CISCO_IPV6_SPLIT_EXC" ]; then
+		# untested
+		i=0
+		while [ $i -lt $CISCO_IPV6_SPLIT_EXC ] ; do
+			eval NETWORK="\${CISCO_IPV6_SPLIT_EXC_${i}_ADDR}"
+			eval NETMASKLEN="\${CISCO_IPV6_SPLIT_EXC_${i}_MASKLEN}"
+			del_ipv6_exclude_route "$NETWORK" "$NETMASKLEN"
+			i=`expr $i + 1`
+		done
+	fi
 	if [ -n "$CISCO_IPV6_SPLIT_INC" ]; then
 		i=0
 		while [ $i -lt $CISCO_IPV6_SPLIT_INC ] ; do
-- 
2.13.6




More information about the openconnect-devel mailing list