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!
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:
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
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:
So it would be like:
Save and exit. Now edit
/etc/openvpn/<VPN name here>.conf and look for the following line:
Change it to:
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:
And put a
# in front of it:
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
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.
#1. Setting up a static IP (optional, but recommended)
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
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 188.8.131.52 184.108.40.206
You’re free to use any DNS nameservers you like. Personally, I like the new CloudFlare
220.127.116.11s. 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:
# net.ipv4.ip_forward = 1
net.ipv4.ip_forward = 1
Just remove that
#, save and move on.
Next, enable that forwarding
sudo sysctl -p
And now the hard part.
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.
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!
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?
#5. Forward that IP (optional but recommended)
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
Now, since China is great for these TCP RST packets that drop your VPN connection sporadically (so you have to remote into your passthrough box and fix it), I wrote a Python script that helps me out with the entire process.
Any improvements in the form of pull requests would be welcome!
If you got to this part, congratulations! Enjoy that VPN gateway as much as I do using mine.