Isn’t it fun living in China? The answer is - it depends. And if you’re a foreigner craving for your Netflix binge and YouTube addiction, this just might be the solution to your problems.

Enter the network-wide VPN - your own gateway that you will set up to tunnel your entire home’s network!

Prerequisites

You will need:

  • A VPN provider that gives out OpenVPN configurations. Other protocols will work, but I will not cover them in this tutorial.
  • A server or a VM, running Ubuntu Server. Version doesn’t matter. I used the latest iso saved on my server, which I belive is 16.04 LTS. (I really need to update to 18.04 LTS, sidenote)
  • Some Linux knowledge
  • Some network knowledge
  • (optional, but important) A router that supports default gateway push through DHCP!

The last two points are important. Without proper Linux and network knowledge, you will have a broken LAN someday with no way to troubleshoot or debug! And don’t ever come complaining to me that you’ve broken your “Internet”!

A router that supports DHCP default gateway push is important. Without it, you will have to manually go around each device and set up the proper configuration so it’ll route the traffic through your new Linux router! At that point, you might as well set up the VPN on each device, but the benefit of setting this up at all without a supported router is still great that you should consider setting it up anyway. Some devices that don’t support native-VPN (such as the Chromecast, Roku Fire sticks, your smart robot cleaner) will now connect through the VPN through a simple configuration change.

So whether you’re serious about this, or it’s just a fun experiment, it’s definitely worth it to set it up. Just understand the risks before you move on. If any problems arise, you should be able to debug them.

#0. VPN setup

This tutorial will only cover OpenVPN, because that’s the widely known and used VPN protocol to this date. PPTP is a security joke (fuck people that say otherwise) and L2TP and IPSec each have their quirks when they are set up.

Grab the OpenVPN file from your VPN provider. The page should also list your unique username and password for OpenVPN. Grab that too.

(NOTE: If it does not show your unique username and password, then it might be your account username and password. Experiment and see if it works.)

Now, depending on your VPN provider, they will give you one, in-line OpenVPN file, or separated files consisting of the client keys and server certificates. As you might already know, the former is the better of the two, since you won’t have to monkey around with key configurations.

Jumping onto your VM, execute these commands:

ifconfig

This will show a slew of your current network configuration. Note down the interface name on the left side. For example, my network was:

enp2s0    Link encap:Ethernet  HWaddr <obfuscated>  
          inet addr:192.168.0.100  Bcast:192.168.0.255  Mask:255.255.255.0
          <truncated>
          
lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          <truncated>

Some things to note here. First, your Ethernet interface is enp2s0, and your IP address is 192.168.0.100. These will be important later on.

Now, install OpenVPN.

sudo apt install openvpn

Once it’s installed, load the configuration files.

First, let’s copy the .ovpn configuration.

sudo cp <VPN name here>.ovpn /etc/openvpn/<VPN name here>.conf

At this point, if you have keys included with the .ovpn file, look at the keys. They will be named like ca.rsa.2048.crt or similar, depending on what key size your VPN provider uses. Simply find the key files and copy them with this command:

sudo cp ca.rsa.2048.crt crl.rsa.2048.pem /etc/openvpn

If your provider is smart enough not to provide keys like this, you can skip the above command. Continue down below.

Now you might be wondering why we renamed that .ovpn file to .conf. Good question! It’s because for providers that make you authenticate yourself before letting you connect to the VPN server.

Next, note your username and password down in this file, /etc/openvpn/login. In the file, paste your credentials like this:

username
password

So it would be like:

cons293JEI2jd
SEIfo29*##IsF29djNF

Save and exit. Now edit /etc/openvpn/<VPN name here>.conf and look for the following line:

auth-user-pass

Change it to:

auth-user-pass /etc/openvpn/login

Now, if you have separate key files copied from above, you will need to do one more step. Find these lines:

ca ca.rsa.2048.crt
crl-verif crl.rsa.2048.pem

And change them into:

ca /etc/openvpn/ca.rsa.2048.crt
crl-verif crl.rsa.2048.pem

And you’re done!

Before you save, there’s some additional options you might want to configure. For example, you might want to disable persist-tun if you live in an environment where Internet connection is rocky. The VPN will destroy the tunnel interface when it restarts, forcing it to use the local network for the VPN server lookup. This is handy because you don’t want the VPN server lookup to happen over a dead tunnel interface where nothing is happening.

Find this line:

persist-tun

And put a # in front of it:

# persist-tun

If you want the server to keep the connection alive, find or add these following two lines:

keepalive 10 30
resolv-retry infinite

The last line isn’t strictly needed, because the default is infinite. The first line tells the OpenVPN client to ping the server (--ping) every 10 seconds, and restart (--ping-restart) if there is no response for 30 seconds. This has been handy because the Great Firewall of China likes to drop these lovely TCP RST packets at our faces. Experiment with those values if you need a more reliable connection, but I’ve found 30 seconds is pretty adequate for a smooth network drop fix without accidentally DDoSing the VPN server.

Save and now, we’ll have to test the VPN server. Since I’m in China, that’s super easy! Just ping Google. If you’re in a different country where that test is inconclusive, you could check ifconfig again.

Start the client:

sudo openvpn --config /etc/openvpn/<VPN name here>.conf

If you see Initialization Sequence Completed anywhere in the logs, congratulations! Your VPN is set up correctly! Press Ctrl-C to destroy the VPN tunnel and follow along with next steps.

At this point, you might want to set up a static IP for your VM. This is because you don’t want IPs shifting if you decide to add the IP to your default gateway settings in your router.

Log into your router administration page. The details should be underneath the router, printed out on a sticker. If you can’t find it, then just Google your router’s manufacturer and look for the IP. If that doesn’t work, check your computer’s default gateway, because usually routers push their IP through there. If all else fails then just type in addresses like 192.168.0.1 or 192.168.1.1.

If you find the IP, remember to write it down because it’ll be important later, and click on DHCP address reservations, or something named similar. Remember your MAC address from step 0? No? Then just do ifconfig again and jot down the MAC address for your Ethernet interface.

Assign it an address, then press OK. Remember that address, Now some more configurations on your VM! Edit this file, /etc/network/interfaces and find the lines:

auto enp2s0
iface enp2s0 inet dhcp

The interface name might be different. Just change it so that it looks like this (remember to keep the interface name that was in your file, NOT the ones shown here!):

auto enp2s0
iface enp2s0 inet static
   address 192.168.0.100
   netmask 255.255.255.0
   gateway 192.168.0.1
   dns-nameservers 1.1.1.1 1.0.0.1

You’re free to use any DNS nameservers you like. Personally, I like the new CloudFlare 1.1.1.1s. Remember to input the correct IP address and netmask! The IP address is the one you manually assigned on the router administration page, the netmask can be found by checking your network settings, and the gateway should be whatever it was before (check network settings on your computer) or your router’s administration IP, which is usually the default gateway on most routers.

The default gateway bit is important, because if you decide to forward the VM’s IP as the default gateway later in the DHCP push settings, your VM box might get the same IP as itself. We don’t want it talking to itself, do we? No! So make sure the default gateway is the current default gateway shown in your network settings.

Cool! Reboot the VM and the router and make sure both are accessible, and your Internet is working. Next step.

#2. Setting up the tunnel

First, let’s enable the OpenVPN service so it starts at boot.

sudo systemctl enable [email protected]<VPN name here>

Don’t write the .conf extension when you’re running this command! Then, let’s enable IPv4 forwarding. Edit this file: /etc/sysctl.conf from

# net.ipv4.ip_forward = 1

to:

net.ipv4.ip_forward = 1

Just remove that #, save and move on.

Next, enable that forwarding sysctl service!

sudo sysctl -p

And now the hard part. iptables.

#3. iptables

This part is extremely hard, probably the hardest in this tutorial. I don’t even understand most of it, but will try to explain it as best as I could.

First off, we want to allow the loopback traffic through the loopback device. Execute these two commands:

sudo iptables -A INPUT -i lo -m comment --comment "loopback-input" -j ACCEPT
sudo iptables -A OUTPUT -o lo -m comment --comment "loopback-output" -j ACCEPT

Then, we want to allow traffic coming in from the network, and traffic going out to the tunnel network. (If you don’t know these or forgot from earlier, run the VPN using the command way above, and run ifconfig to figure out the interfaces.) Execute these commands, making sure to substitute the interface names from earlier:

sudo iptables -I INPUT -i enp2s0 -m comment --comment "Local network" -j ACCEPT
sudo iptables -I OUTPUT -o tun0 -m comment --comment "VPN network" -j ACCEPT

Then we need to allow the OpenVPN traffic to pass through the box. Find the port number by looking at the .conf file we talked about earlier. It should be on the line that starts with remote. Then execute this command, making sure to replace that port number and interface name:

sudo iptables -A OUTPUT -o enp2s0 -p udp --dport 1194 -m comment --comment "OpenVPN traffic" -j ACCEPT

Next up, we need to allow certain services to operate. Execute these commands:

sudo iptables -A OUTPUT -o eth0 -p udp --dport 123 -m comment --comment "NTP service" -j ACCEPT
sudo iptables -A OUTPUT -p UDP --dport 67:68 -m comment --comment "DHCP service" -j ACCEPT
sudo iptables -A OUTPUT -o eth0 -p udp --dport 53 -m comment --comment "DNS service" -j ACCEPT

Almost there! You need to forward the traffic from the tunnel to the Ethernet interface. This bit is super important! Run these commands (and make sure to substitute relevant information):

sudo iptables -A FORWARD -i tun0 -o enp2s0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i enp2s0 -o tun0 -m comment --comment "Local network to VPN" -j ACCEPT

Cool, one last thing. You need to set POSTROUTING on your NAT, so that the Network Address Translation works across the VPN. Execute the final command (switch these interface names, remember):

sudo iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE

If you managed to follow this far without fainting, congratulations! But before you go and celebrate, you want to save these configurations so these don’t get lost over a reboot. You don’t want to painstakingly input these commands again, do you? I didn’t think so.

Install this:

sudo apt install iptables-persistent

And the installation will begin. If it asks you if it should save the current configuration, choose yes, and carry on. Let’s enable the service to run at boot:

sudo systemctl enable netfilter-persistent

If, in the far future, you add any more iptable rules, you can save them by running:

sudo netfilter-persistent save

And they will be saved.

One last, really important thing. If you want to back up these configurations, you can type

sudo iptables-save > backup.txt

To save the rules inside a text file. This is also a handy way to edit these configurations should you decide to change them. (But seriously, learn to use iptables properly and change stuff using commands instead of using the text file backup method.) Once you want to restore, use this command:

sudo iptables-restore < backup.txt

Nice! Your configuration is nearly finished!

#4. Test

Reboot the box. On the client device you want to test, change the default gateway’s IP address to the VM’s IP. It should start forwarding traffic through the VPN! Congratulations!

But this is tedious. I’m lazy. What the fuck should I do?

If your router supports default gateway switching, you can do this. (Most routers support this)

Go to the router administration page (remember it?) and click on DHCP settings. Under the Default Gateway IP address, input the VM’s IP.

Now reboot the router. If it works, great!

In odd cases, the default gateway change might actually just change the administration page’s IP address. If that happens, there’ll be an address collision, and your VM box will either lose the IP address or lose access to the local network. In severe cases your router administration page might not come up. In that case, just disconnect the VM box, reboot the router and connect to the administration page to change the default gateway back. If this is the case, then your router does not support default gateway switching. Sorry ;(

#6. Some useful scripts

If you frequently need to access that VM to restart the VPN or look at the logs, try this script:

# (new and improved) VPN script
vpn() {
   case "$1" in
   "-l" | "--logs" | "--log")
      journalctl -u [email protected]<VPN name here>
      ;;
   "-r" | "--restart")
      sudo systemctl restart [email protected]<VPN name here>
      ;;
   "-q" | "--quit")
      sudo systemctl stop [email protected]<VPN name here>
      ;; 
   "-s" | "--start")
      sudo systemctl start [email protected]<VPN name here>
      ;;
   "-?" | "-h" | "--help")
      echo -e "A script to help facilitate the VPN connection.\n\n
   -l or --logs or --log to display the log\n
   -s or --start to start the VPN\n
   -q or --quit to stop the VPN\n
   -r or --restart to restart the VPN\n"
      ;;
   *)
      echo -e "Warning, $1 is not a valid operand."
   esac
}

Just add it to your .bashrc, and source it by running . .bashrc. Then try vpn -? to see all options.

You’re ducking welcome. If you have a better script or program to share with me, please send me an email at [email protected] along with the source code so I can tinker with it.

#7. Conclusion

If you got to this part, congratulations! Enjoy that VPN gateway as much as I do using mine.

Like always, subscribe for more content, and send me an email if you need anything at [email protected] Bye!