From 44d83181295f2ca527da9376ead2f19e69845cbc Mon Sep 17 00:00:00 2001 From: Guilherme Rugai Freire Date: Thu, 8 Feb 2024 02:19:18 -0300 Subject: [PATCH] initial commit --- .gitignore | 2 + LICENSE | 22 ++++++ README.md | 31 ++++++++ split-vpn-manager.sh | 178 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 233 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100755 split-vpn-manager.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..929f908 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.ovpn +auth-user-pass diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..4d43b57 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2024 Guilherme Rugai Freire + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/README.md b/README.md new file mode 100644 index 0000000..bfaf532 --- /dev/null +++ b/README.md @@ -0,0 +1,31 @@ +# Split VPN Manager + +Simple script to manage vpn inside net namespaces and run programs inside of them. + +> Currently only supports openvpn, but wireguard and openconnect are in my plans. + +## Usage + +``` +Usage: + ./split-vpn-manager.sh launch_openvpn --name NETNS_NAME --config CONFIG_FILE --auth AUTH_FILE + starts a vpn connection and create the net namespace + + ./split-vpn-manager.sh run NETNS_NAME CMD + runs a command in the specified net namespace + +NOTE: Always run this script with privileged permissions (currently not) +``` + +## Exit codes + +``` +EXIT_SUCCESS=0 +EXIT_INVALID_COMMAND=1 +EXIT_INVALID_ARGS=2 +EXIT_MISSING_VALID_ARG=3 +EXIT_NOT_ROOT=4 +EXIT_FILE_DOESNOT_EXISTS=5 +EXIT_NOT_ENOUGH_ARGS=6 +``` + diff --git a/split-vpn-manager.sh b/split-vpn-manager.sh new file mode 100755 index 0000000..6e5f608 --- /dev/null +++ b/split-vpn-manager.sh @@ -0,0 +1,178 @@ +#!/bin/sh + +EXIT_SUCCESS=0 +EXIT_INVALID_COMMAND=1 +EXIT_INVALID_ARGS=2 +EXIT_MISSING_VALID_ARG=3 +EXIT_NOT_ROOT=4 +EXIT_FILE_DOESNOT_EXISTS=5 +EXIT_NOT_ENOUGH_ARGS=6 + +split_vpn_manager=$0 +command=$1 +shift + +root_or_exit() { + root_or_exit_message=$1 + + user_id="$(id -u)" + if [ "$user_id" -ne 0 ]; then + echo "$root_or_exit_message" + exit $EXIT_NOT_ROOT + fi +} + +assert_args() { + arg_name=$1 + min_args=$2 + args_count=$3 + + if [ "$min_args" -gt "$args_count" ]; then + echo "Not enough args for $arg_name in command $command" + exit $EXIT_NOT_ENOUGH_ARGS + fi +} + +assert_file() { + file_desc=$1 + file=$2 + if [ -z "$file" ]; then + echo "Missing $file_desc file" + exit $EXIT_MISSING_VALID_ARG + else + if [ ! -f "$file" ]; then + echo "File does not exist: $file" + exit $EXIT_FILE_DOESNOT_EXISTS + fi + fi +} + +launch_openvpn() { + root_or_exit "Need to be root in order to run $command" + + while [ $# -gt 0 ]; do + arg_name=$1 + shift + + case $arg_name in + --config) + assert_args --config 1 $# + openvpn_config=$1 + ;; + --auth) + assert_args --auth 1 $# + openvpn_auth=$1 + ;; + --name) + assert_args --auth 1 $# + openvpn_name=$1 + ;; + *) + echo "Invalid args for command $command: $arg_name" + exit $EXIT_INVALID_ARGS + ;; + esac + + shift + done + + assert_file "openvpn config" "$openvpn_config" + assert_file "openvpn auth" "$openvpn_auth" + if [ -z "$openvpn_name" ]; then echo "Missing vpn name in $command" && exit $EXIT_MISSING_VALID_ARG; fi + + openvpn \ + --auth-nocache --script-security 2 --route-nopull --redirect-gateway \ + --ifconfig-noexec --route-noexec \ + --up "$split_vpn_manager up-netns $openvpn_name" --down "$split_vpn_manager down-netns $openvpn_name" \ + --config "$openvpn_config" \ + --mute-replay-warnings \ + --auth-user-pass "$openvpn_auth" + + exit $EXIT_SUCCESS +} + +up_netns() { + netns_name=$1 + shift + + ip netns add "$netns_name" + + ip netns exec "$netns_name" ip link set dev lo up + + ip link set dev "$1" up netns "$netns_name" mtu "$2" + + ip netns exec "$netns_name" ip addr add dev "$1" \ + "$4/${ifconfig_netmask:-30}" \ + ${ifconfig_broadcast:+broadcast "${ifconfig_broadcast}"} + + if [ -n "$ifconfig_ipv6_local" ]; then + ip netns exec "$netns_name" ip addr add dev "$1" \ + "$ifconfig_ipv6_local/112" + fi + + ip netns exec "$netns_name" ip route add default via "$route_vpn_gateway" + + echo "nameserver 8.8.8.8" | resolvconf -x -a "$1.inet" + + exit $EXIT_SUCCESS +} + +down_netns() { + netns_name=$1 + shift + + ip netns delete "$netns_name" + + exit $EXIT_SUCCESS +} + +run() { + root_or_exit "Need to be too in order to run inside a namespace" + + assert_args "vpn name" 1 $# + netns_name=$1 + shift + + assert_args "running" 1 $# + + ip netns exec "$netns_name" sudo -u "$SUDO_USER" "$@" + + exit $EXIT_SUCCESS +} + +help() { + echo "Usage:" + echo " $0 launch_openvpn --name NETNS_NAME --config CONFIG_FILE --auth AUTH_FILE" + echo " starts a vpn connection and create the net namespace" + echo "" + echo " $0 run NETNS_NAME CMD" + echo " runs a command in the specified net namespace" + echo "" + + user_id="$(id -u)" + if [ "$user_id" -ne 0 ]; then + echo "NOTE: Always run this script with privileged permissions (currently not)" + else + echo "NOTE: Always run this script with privileged permissions" + fi + + +} + +case "$command" in + launch_openvpn) + launch_openvpn "$@";; + up-netns) + up_netns "$@";; + down-netns) + down_netns "$@";; + run) + run "$@";; + help|--help) + help;; + *) + echo "Invalid command: $command" + exit $EXIT_INVALID_COMMAND + ;; +esac +