From a5bf74a6df654c5b9a0d419278c0c4a57f460c92 Mon Sep 17 00:00:00 2001 From: Laurent Ghigonis Date: Sun, 16 Jun 2013 17:07:00 +0200 Subject: add covpn - Wrapper to run OpenVPN with server push filtering, tcp/udp/defgw modes --- covpn/README.txt | 25 ++++++++++++++ covpn/conf/covpn.conf | 21 ++++++++++++ covpn/conf/openvpn-up.sh | 47 ++++++++++++++++++++++++++ covpn/conf/openvpn.conf | 30 +++++++++++++++++ covpn/covpn.sh | 85 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 208 insertions(+) create mode 100644 covpn/README.txt create mode 100644 covpn/conf/covpn.conf create mode 100755 covpn/conf/openvpn-up.sh create mode 100644 covpn/conf/openvpn.conf create mode 100755 covpn/covpn.sh diff --git a/covpn/README.txt b/covpn/README.txt new file mode 100644 index 0000000..c6893bb --- /dev/null +++ b/covpn/README.txt @@ -0,0 +1,25 @@ +covpn - Wrapper to run OpenVPN with server push filtering, tcp/udp/defgw modes +2013, Laurent Ghigonis + + +sudo covpn.sh [-g] [-t] + +Examples +======== + +# Run in UDP mode and not modifying default gateway (default) +./covpn.sh conf/ + +# Run in UDP mode, overriding the default gateway +# (restores it on exit) +./covpn.sh -g conf/ + +# Run in TCP mode +./covpn.sh -t conf/ + + +Configuration +============= + +Configuration is in conf/ by default +You should edit covpn.conf and openvpn.conf, and add your OpenVPN keys there diff --git a/covpn/conf/covpn.conf b/covpn/conf/covpn.conf new file mode 100644 index 0000000..06e1f6c --- /dev/null +++ b/covpn/conf/covpn.conf @@ -0,0 +1,21 @@ +# Configuration file for copvn + +# OpenVPN configuration options, for covpn.sh + +CONF_UDP_REMOTE="X.X.X.X 1194" # IP of the VPN concentrator + UDP port +CONF_TCP_REMOTE="X.X.X.X 443" # IP of the VPN concentrator + TCP port + +# Filtering pushed options from server, for openvpn-up.sh + +# Your DNS IP (regex), via dhcp-option DNS +# Set to "disable" to forbid any DNS changes +EXPECTED_DNS="192.168.99.254" +# Attributed IP range (regex) +EXPECTED_IP_RANGE="192.168.99.[0-9]+" +# VPN subnet IP range (regex) +EXPECTED_ROUTE_RANGE="192.168.99.[0-9]+" +# VPN subnet netmask (regex) +EXPECTED_ROUTE_MASK="255.255.255.0" +# VPN default gateway (regex) +EXPECTED_GATEWAY="192.168.99.254" + diff --git a/covpn/conf/openvpn-up.sh b/covpn/conf/openvpn-up.sh new file mode 100755 index 0000000..0f017a1 --- /dev/null +++ b/covpn/conf/openvpn-up.sh @@ -0,0 +1,47 @@ +#!/bin/sh + +# OpenVPN up.sh script, part of covpn +# Filters input from OpenVPN, usefull for checking IPs/ranges/DNS pushed by an +# OpenVPN server +# 2013 Laurent Ghigonis + +# Reads its configuration (EXPECTED_* vars) from $covpn_conf + +# Some env vars also available: +# script_context=init +# script_type=up + +if [ ! -f $covpn_conf ]; then + echo "covpn openvpn-up.sh: ERROR: $covpn_conf not found !" + exit 99 +fi +. $covpn_conf + +dns=`echo $foreign_option_1 |cut -d' ' -f3` +if [ X"$dns" != X"" -a X"$EXPECTED_DNS" != X"disable" ]; then + echo $dns |egrep -q "^$EXPECTED_DNS$" ||exit 10 +else + dns="none" +fi +echo $dev |egrep -q "^tun[0-9]$" ||exit 11 +test $tun_mtu -gt 200 -a $tun_mtu -lt 2000 ||exit 12 +echo $ifconfig_local |egrep -q "^$EXPECTED_IP_RANGE$" ||exit 13 +echo $ifconfig_remote |egrep -q "^$EXPECTED_IP_RANGE$" ||exit 14 +echo $route_network_1 |egrep -q "^$EXPECTED_ROUTE_RANGE$" ||exit 15 +echo $route_netmask_1 |egrep -q "^$EXPECTED_ROUTE_MASK$" ||exit 16 +echo $route_network_2 |egrep -q "^$EXPECTED_GATEWAY$" ||exit 17 + +/usr/sbin/ip addr add $ifconfig_local peer $ifconfig_remote dev $dev ||exit 20 +/usr/sbin/ip link set $dev mtu $tun_mtu ||exit 21 +/usr/sbin/ip link set $dev up ||exit 22 +/usr/sbin/ip route add ${route_network_1}/${route_netmask_1} dev $dev ||exit 23 +if [ X"$openvpn_gateway" = X"1" ]; then + /usr/sbin/ip route add $remote_1 via $route_net_gateway + /usr/sbin/ip route delete default + /usr/sbin/ip route add 0/1 via $route_network_2 + /usr/sbin/ip route add 128/1 via $route_network_2 +fi +if [ $dns != "none" ]; then + cp /etc/resolv.conf /etc/resolv.conf.bak-covpn + echo "nameserver $dns" > /etc/resolv.conf ||exit 24 +fi diff --git a/covpn/conf/openvpn.conf b/covpn/conf/openvpn.conf new file mode 100644 index 0000000..494f812 --- /dev/null +++ b/covpn/conf/openvpn.conf @@ -0,0 +1,30 @@ +# OpenVPN client configuration file +# Part of covpn + +client +dev tun +# proto: given by covpn command line, see covpn.conf +# remote: given by covpn command line, see covpn.conf + +resolv-retry infinite +nobind + +persist-key +persist-tun + +ca ca.crt +cert client.crt +key client.key + +ns-cert-type server +tls-auth ta.key 1 + +comp-lzo + +ifconfig-noexec +route-noexec +script-security 2 +up openvpn-up.sh +user openvpn +group openvpn + diff --git a/covpn/covpn.sh b/covpn/covpn.sh new file mode 100755 index 0000000..6139909 --- /dev/null +++ b/covpn/covpn.sh @@ -0,0 +1,85 @@ +#!/bin/sh + +# covpn - Wrapper to run OpenVPN with server push filtering, tcp/udp/defgw modes +# 2013 Laurent Ghigonis + +# Works together with correct openvpn-up.sh +# Uses same config file for UDP and TCP, passing --proto and --remote in command line +# Change of default gateway and DNS is done in openvpn-up.sh +# Passes env var 'openvpn_gateway' to openvpn-up.sh in case default gw is set to VPN +# Passes env var 'covpn_conf' to openvpn-up.sh to load it's configuration + +usage_exit() { + echo "`basename $0` [-g] [-t] " + exit 1 +} + +restore() { + restore_gateway + restore_dns +} + +restore_gateway() { + echo "INFO: check_gateway" + gw_cur=`ip route show 0/0 |cut -d' ' -f3` + echo "INFO: gw_cur=$gw_cur" + if [ "$gw_before" != "$gw_cur" ]; then + echo "INFO: Gateway changed (before=$gw_before, cur=$gw_cur)" + echo "INFO: Restoring previous default gw" + /usr/sbin/ip route delete default + /usr/sbin/ip route add default via $gw_before + fi +} + +restore_dns() { + echo "INFO: check_dns" + if [ -f /etc/resolv.conf.bak-covpn ]; then + echo "INFO: restoring previous DNS" + mv /etc/resolv.conf.bak-covpn /etc/resolv.conf + fi +} + +if [ `id -u` -ne 0 ]; then + echo "must be root" + exit 1 +fi + +gw_before=`ip route show 0/0 |cut -d' ' -f3` + +opts="$(getopt -o gth -l gateway,tcp,help -n "$program" -- "$@")" +openvpn_proto="udp" +gateway=0 +err=$? +echo "INFO: gw_before=$gw_before" +eval set -- "$opts" +while true; do case $1 in + -g|--gateway) gateway=1; shift;; + -t|--tcp) openvpn_proto="tcp"; shift ;; + -h|--help) usage_exit ;; + --) shift; break ;; +esac done +test $err -ne 0 && usage_exit +test $# -lt 1 && usage_exit +conf_path=`readlink -f $1` +shift + +covpn_conf="$conf_path/covpn.conf" +if [ ! -f $covpn_conf ]; then + echo "ERROR: missing covpn.conf in $conf_path !" + exit 1 +fi +. $covpn_conf + +if [ $openvpn_proto = "udp" ]; then + openvpn_remote="$CONF_UDP_REMOTE" +else + openvpn_remote="$CONF_TCP_REMOTE" +fi + +trap restore INT TERM EXIT + +/usr/sbin/openvpn --setenv openvpn_gateway $gateway \ + --setenv covpn_conf $covpn_conf \ + --cd $conf_path --config openvpn.conf --chroot $conf_path \ + --proto $openvpn_proto --remote $openvpn_remote $@ + -- cgit v1.2.3-59-g8ed1b