MassiveGoldenSwan 2 Posted ... This is meant for the How-To forum, but I'm posting it as a draft here first to get feedback on it. In my case, all I need is to run certain programs within the VPN, and stop those programs from communicating if the VPN goes down. My networking knowledge is limited, but with help from my good friend fr0zen, I've got this setup going. Network namespaces are a pretty old feature of the Linux kernel at this point (2008), introduced as part of cgroups. The bulk of the logic behind setting them up for VPN usage comes from this blog post. The final scripts are posted at the end of this post, but I will explain how they do their magic to the best of my abilities. start-vpn.shThis is the primary script, the one you call directly. The other two are helper scripts. First, the variables: REMOTE=america.vpn.airdns.org BRIDGE=192.168.1.6 INTERNAL=192.168.1.8 GATEWAY=192.168.1.1 IFACE=eth0 USER=jaquer COMMAND="screen -dmS vpn -c /home/jaquer/.screenrc-vpn" CONFIG=AirVPN_America_UDP-443.ovpn REMOTE is the hostname that you will be connecting to. It comes from the .ovpn file you download from AirVPN. I suppose if you wanted to be really clever you could grep it out of the file, but I like to keep my scripts lean and mean. BRIDGE is the IP address that we will bridge with out VPN. This is the local address for your computer. Again, I'm sure you could script it if you wanted, but I assign my computers static IPs when they run important services. INTERNAL will be the IP we assign to the VPN on our local network. Again, I pick an IP I know will not be assigned to another device. GATEWAY is... your regular gateway. Usually your routed. You can determine it via ip route show. It's the IP number listed as default via. IFACE is the interface you will use to bridge the two connections. Keep in mind, this interface is brought down while the script runs. You will lose connectivity at this point, so make sure you test the script over the terminal as opposed to SSH'ing into the computer. If you happen to have two NICs, I highly recommend you run the script on the second one (eth1). USER and COMMAND are where things start to get interesting. Using namespaces, you need to prepend every command with ip netns exec vpn. The beauty of creating a screen session under the namespace means you can just switch to it, and now every program you run in it will inherit the VPN network settings. CONFIG is the path to your .ovpn file. Keep it in the same directory as the scripts. Now, we're ready to get the connectivity going. REMOTE=$(resolveip -s ${REMOTE}) We need to get the IP of the remote server now, because we won't be able to resolve it once we remove the default gateway a bit into the script. ip netns add vpn || exit 1 ip link add veth0 type veth peer name veth1 || exit 1 ifconfig veth0 0.0.0.0 up || exit 1 ip link set veth1 netns vpn || exit 1These setup the basic virtual interface for the bridge. ifdown ${IFACE} || exit 1 ifconfig ${IFACE} 0.0.0.0 up || exit 1 brctl addbr br0 || exit 1 brctl addif br0 eth1 veth0 || exit 1 ifconfig br0 ${BRIDGE} netmask 255.255.255.0 up || exit 1 Here we bring down out physical interface, and bring it back up as part of the bridge. You will lose connectivity at this point, so make sure you test the script over the terminal as opposed to SSH'ing into the computer. route add default gw ${GATEWAY} ip netns exec vpn ifconfig veth1 ${INTERNAL} netmask 255.255.255.0 up || exit 1 We re-add the gateway to the interface's route, and bring the virtual interface up. ip netns exec vpn route add ${REMOTE} gw ${GATEWAY} || exit 1 This is a clever bit of the script. We want the gateway to route packets to the remote server's IP only. Since we're calling it inside the namespace, nothing else running in the namespace will resolve. We can only connect to the remote server at this point. ip netns exec vpn su --login --command "${COMMAND}" ${USER} || exit 1 ip netns exec vpn openvpn --config ${CONFIG} --script-security 2 --up vpn-up.sh & We run the screen session inside the namespace, and run OpenVPN inside it too, with a custom script to be called when the connection is completed. PID=${!} trap "kill ${PID}; wait ${PID}" INT wait ./vpn-down.shWe capture the PID of the OpenVPN process, and wait for it to exit. The trap command will catch Ctrl+C and kill said process if we need to exit manually. Finally, we revert all the changes we made when we exit the VPN. vpn-up.sh ip route add default via ${route_vpn_gateway} echo ${ifconfig_local} > /tmp/vpn-ip.txt This script seems simple, but it's actually the one that insures we have connectivity. It adds the VPN gateway as the default, which insures that all traffic going out (except to the VPN server itself), is routed through the VPN. We also save the internal IP to a text file, because we can then use it to bind services to it for double protection. vpn-down.shThis is just the cleanup script. It will prompt you to exit the screen session and all the programs withing it first. In order to be able to delete the bridge, we have to bring our main interface down again. You will lose connectivity at this point, so make sure you test the script over the terminal as opposed to SSH'ing into the computer. To recap: As root, run start-vpn.sh. When the connection is made, switch user accounts to the USER account, and re-attach the screen session ( screen -dr vpn). Now any program you run from within the session will only use the VPN connection. Test it by running wget -qO- http://ipecho.net/plain. That's the gist of it. I hope somebody finds it helpful. Here are the full scripts: start-vpn.sh #!/bin/sh REMOTE=america.vpn.airdns.org BRIDGE=192.168.1.6 INTERNAL=192.168.1.8 GATEWAY=192.168.1.1 IFACE=eth0 USER=jaquer COMMAND="screen -dmS vpn -c /home/jaquer/.screenrc-vpn" CONFIG=AirVPN_America_UDP-443.ovpn REMOTE=$(resolveip -s ${REMOTE}) cd $(dirname ${0}) ip netns add vpn || exit 1 ip link add veth0 type veth peer name veth1 || exit 1 ifconfig veth0 0.0.0.0 up || exit 1 ip link set veth1 netns vpn || exit 1 ifdown ${IFACE} || exit 1 ifconfig ${IFACE} 0.0.0.0 up || exit 1 brctl addbr br0 || exit 1 brctl addif br0 eth1 veth0 || exit 1 ifconfig br0 ${BRIDGE} netmask 255.255.255.0 up || exit 1 route add default gw ${GATEWAY} ip netns exec vpn ifconfig veth1 ${INTERNAL} netmask 255.255.255.0 up || exit 1 ip netns exec vpn route add ${REMOTE} gw ${GATEWAY} || exit 1 ip netns exec vpn su --login --command "${COMMAND}" ${USER} || exit 1 ip netns exec vpn openvpn --config ${CONFIG} --script-security 2 --up vpn-up.sh & PID=${!} trap "kill ${PID}; wait ${PID}" INT wait ./vpn-down.shvpn-up.sh #!/bin/sh ip route add default via ${route_vpn_gateway} echo ${ifconfig_local} > /tmp/vpn-ip.txt[/code] vpn-down.sh #!/bin/sh IFACE=eth0 echo "" echo "OpenVPN exited. Exit all commands running inside VPN before continuing." echo -n "Press ENTER to continue..." read INPUT ifconfig veth0 down ifconfig br0 down ifconfig ${IFACE} down brctl delbr br0 ip netns del vpn ifconfig ${IFACE} up rm -f /tmp/vpn-ip.txt 2 lsat and rickjames reacted to this Quote Hide MassiveGoldenSwan's signature Hide all signatures It's pronounced hacker. Share this post Link to post