Created
July 12, 2020 16:16
-
-
Save nehaljwani/0f63165bf842e22d8d9e80e05f1a53f1 to your computer and use it in GitHub Desktop.
OpenFortiVPN Inside Linux Network Namespace
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# start openconnect tunnel and shell inside Linux network namespace | |
# | |
# this is a fork of schnouki's script, see original blog post | |
# https://schnouki.net/posts/2014/12/12/openvpn-for-a-single-application-on-linux/ | |
# | |
# original script can be found here | |
# https://gist.github.com/Schnouki/fd171bcb2d8c556e8fdf | |
# ------------ adjust values below ------------ | |
NS_NAME="mycompanyvpn" | |
NS_EXEC="sudo ip netns exec $NS_NAME" | |
VPN_ENDPOINT="vpn.mycompany.com" | |
VPN_USER="<username>" | |
WIRED_INTERFACE="enp1s0" | |
WIRELESS_INTERFACE="wlp2s0" | |
OUT_IF="${NS_NAME}0" | |
IN_IF="${NS_NAME}1" | |
OUT_IP="10.202.200.1" | |
IN_IP="10.202.200.2" | |
#set -uxeo pipefail | |
start_vpn() { | |
echo -n "VPN Password: " | |
read -s VPN_PASS | |
echo "Add network interface" | |
# create the network namespace | |
sudo ip netns add "$NS_NAME" | |
# start the loopback interface in the namespace | |
eval $NS_EXEC ip addr add 127.0.0.1/8 dev lo | |
eval $NS_EXEC ip link set lo up | |
# create virtual network interfaces that will let OpenVPN (in the | |
# namespace) access the real network, and configure the interface in the | |
# namespace (${IN_IF}) to use the interface out of the namespace (${OUT_IF}) | |
# as its default gateway | |
sudo ip link add "${OUT_IF}" type veth peer name "${IN_IF}" | |
sudo ip link set "${OUT_IF}" up | |
sudo ip link set "${IN_IF}" netns "${NS_NAME}" up | |
sudo ip addr add "${OUT_IP}"/24 dev "${OUT_IF}" | |
eval $NS_EXEC ip addr add "${IN_IP}"/24 dev "${IN_IF}" | |
eval $NS_EXEC ip link set dev "${IN_IF}" mtu 1492 | |
eval $NS_EXEC ip route add default via "${OUT_IP}" dev "${IN_IF}" | |
# make sure ipv4 forwarding is enabled | |
sudo sysctl -w net.ipv4.ip_forward=1 | |
# configure the nameserver to use inside the namespace | |
# TODO use VPN-provided DNS servers in order to prevent leaks | |
sudo mkdir -p "/etc/netns/${NS_NAME}" | |
cat <<EOF | sudo tee "/etc/netns/${NS_NAME}/resolv.conf" || exit 1 | |
nameserver 8.8.8.8 | |
nameserver 8.8.4.4 | |
EOF | |
# IPv4 NAT, you may need to adjust the interface name prefixes | |
sudo iptables -t nat -A POSTROUTING -o "${WIRED_INTERFACE}" -m mark --mark 0x29a -j MASQUERADE | |
sudo iptables -t nat -A POSTROUTING -o "${WIRELESS_INTERFACE}" -m mark --mark 0x29a -j MASQUERADE | |
sudo iptables -t mangle -A PREROUTING -i "${OUT_IF}" -j MARK --set-xmark 0x29a/0xffffffff | |
# start openconnect in the namespace | |
echo "Starting VPN" | |
set +x | |
# Works well with v1.10.0 | |
# Works well with v1.11.0 (auto adds search domain too, nice!) | |
# Doesn't work well with v1.12.0 (tries to use resolvconf, which doesn't work) | |
# eval $NS_EXEC /home/wani/repos/openfortivpn/openfortivpn -vvv $VPN_ENDPOINT:443 --username=$VPN_USER --otp=1 -p$VPN_PASS & | |
# Works well with v1.13.3 (requires the use of --use-resolveconf=0) | |
# Works will with v1.14.1 | |
eval $NS_EXEC /home/wani/repos/openfortivpn/openfortivpn --use-resolvconf=0 -vvv $VPN_ENDPOINT:443 --username=$VPN_USER --otp=1 -p$VPN_PASS & | |
# wait for the tunnel interface to come up | |
while ! eval $NS_EXEC ip link show dev vpn0 >/dev/null 2>&1 ; do sleep .5 ; done | |
} | |
stop_vpn() { | |
echo "Stopping VPN" | |
sudo ip netns pids $NS_NAME | sudo xargs -rd'\n' kill -SIGINT | |
# TODO wait for terminate | |
sleep 2 | |
# clear NAT | |
sudo iptables -t nat -D POSTROUTING -o "${WIRED_INTERFACE}" -m mark --mark 0x29a -j MASQUERADE | |
sudo iptables -t nat -D POSTROUTING -o "${WIRELESS_INTERFACE}" -m mark --mark 0x29a -j MASQUERADE | |
sudo iptables -t mangle -D PREROUTING -i "${OUT_IF}" -j MARK --set-xmark 0x29a/0xffffffff | |
echo "Delete network interface" | |
sudo rm -rf "/etc/netns/${NS_NAME}" | |
sudo ip netns delete "${NS_NAME}" | |
sudo ip link delete "${OUT_IF}" | |
} | |
#start_vpn | |
# start app inside network namespace | |
#eval $NS_EXEC su ${USER} | |
#trap stop_vpn EXIT |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I typically use this like this (in a tmux session):
source openfortivpn_inside_netns.sh start_vpn
When I want to close it, I do (in the same tmux session):
To use this tunnel to SSH to my office computer, I have this in ~/.bashrc:
And then I use it like this:
And I have a password less sudo rule in
/etc/sudoers