# Run OpenVPN in a Linux network namespace 2022-02-04 Users may wish to conceal their home IP for a variety of reasons. This is often done with a proxy such as Tor. Redirecting all traffic through a proxy is slow however and may not be necessary for all applications. Making only specific applications use a proxy can be done using Linux network namespaces. This guide assumes you're using OpenVPN, though any type of VPN should work. ## Creating a new network namespace A new network namespace can be created with the `ip` utility: ```sh $ ip netns add mynetns ``` To execute a program inside this namespace, use `ip netns exec` ```sh $ ip netns exec mynetns ip l 1: lo: mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 ``` For `ip`, a shorter syntax is: ```sh $ ip -n mynetns l ``` To allow connections to the outside world a `veth` device must be added. ```sh $ ip l add mynetns_a type veth peer name mynetns_b $ ip l ... 6: mynetns_b@mynetns_a: mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000 link/ether 0a:3d:7c:b3:f9:a4 brd ff:ff:ff:ff:ff:ff 7: mynetns_a@mynetns_b: mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000 link/ether 0e:94:83:65:95:e8 brd ff:ff:ff:ff:ff:ff ``` We now need to move one of the interfaces into the proper namespace: ```sh $ ip l set mynetns_a netns mynetns $ ip -n mynetns l 1: lo: mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 7: mynetns_a@if6: mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 0e:94:83:65:95:e8 brd ff:ff:ff:ff:ff:ff link-netnsid 0 ``` Give the interfaces an IP: ```sh $ ip -n mynetns a add 192.168.0.2/24 dev mynetns_a $ ip a add 192.168.0.1/24 dev mynetns_b ``` Bring the interfaces up: ```sh $ ip -n mynetns l set up dev mynetns_a $ ip l set up dev mynetns_b ``` You should now be able to send packets through the interface: ``` $ ping 192.168.0.2 PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data. 64 bytes from 192.168.0.2: icmp_seq=1 ttl=64 time=0.040 ms ``` ## Forwarding packets We now need to forward packets to the interface. Since we're using IPv4 we'll use NAT: ```sh $ echo 1 > /proc/sys/net/ipv4/ip_foward $ iptables -t filter -A FORWARD -i mynetns_b -j ACCEPT $ iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE ``` Configure the default route: ```sh $ ip -n mynetns r add default via 192.168.0.1 ``` To test if it works, try pinging a public IP: ``` $ ip netns exec ping demindiro.com PING demindiro.com (104.244.79.104) 56(84) bytes of data. 64 bytes from mail.salt-inc.org (104.244.79.104): icmp_seq=1 ttl=62 time=0.165 ms ``` ## Running OpenVPN inside the namespace Running any service inside the namespace is trivial: ```sh $ cd /etc/openvpn $ ip netns exec openvpn myvpn.conf ``` ## Service script This `run` script can be used with `runit`: ```sh #!/bin/sh ip netns add mynetns ip l add mynetns_a type veth peer name mynetns_b ip l set mynetns_a netns mynetns ip a add 192.168.0.1/24 dev mynetns_b ip -n mynetns a add 192.168.0.2/24 dev mynetns_a ip l set up mynetns_b ip -n mynetns l set up mynetns_a ip -n mynetns r add default via 192.168.0.1 echo 1 > /proc/sys/net/ipv4/ip_forward iptables -t filter -A FORWARD -i mynetns_b -j ACCEPT iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE cd /etc/openvpn exec ip netns exec mynetns openvpn myvpn.conf ``` For cleanup, use this `finish` script: ```sh #!/bin/sh ip netns del mynetns echo 0 > /proc/sys/net/ipv4/ip_forward iptables -t filter -D FORWARD -i mynetns_b -j ACCEPT iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE ``` In any service that should use the VPN, add this: ```sh sv start myvpn || exit # ... exec ip netns exec mynetns myservice ... ```