Wherein I set up OpenVPN on my VPS so that I can access my home network (which is behind forced NAT and can't accept inbound connections of any kind) while I'm away from home.
I live in student accommodation where I receive 'free Internet' (indirectly paid for through exorbitant rent fees) provided by KeySurf/KeyCom. This is accessible in two different ways:
Connecting to either of these gets you a captive portal where you must log in with your KeySurf account. You can also use the web interface to add specific devices by MAC address, which is necessary for stuff like the Nintendo 3DS.
I'm 99% sure that everybody in the building shares the same external IP address, though I haven't confirmed this for sure -- I know that my devices definitely do. Regardless, there is no way to set up port forwarding of any kind... so good luck getting remote access!
A friend gave me a TP-Link TL-WR710N router running OpenWRT (which I've since upgraded to LEDE 17.01.4). This has allowed me to set up a miniature home network, which is quite useful as it means that my laptop and desktop (plus VMs running on the latter) can communicate with each other reliably.
Of course, this only works when I'm actually physically there. Can I remotely access the network so that I can work on my desktop and access files when I'm not at home? The answer is yes -- but it took me the better part of a day to figure out the correct series of magical incantations (and a couple of experiments with magical "it just works" software packages that didn't end up actually working, like ZeroTier One and SoftEther VPN).
I'll spare you the details of how I actually got there and just describe the setup I ended up with, and how it works...
The router is running LEDE 17.01.4 and is accessing the Internet through the WAN interface. I've configured IP addressing as follows:
10.99.4.1
10.99.4.100
10.99.4.101
255.255.254.0
I assigned static leases to my machines to make working with them easier, but this isn't strictly necessary for the OpenVPN setup to function.
Note: I've got the subnet mask set to 255.255.254.0
rather than the somewhat
more obvious 255.255.255.0
as a leftover from one of my failed experiments
(following somebody else's guide to set up ZeroTier One). The latter would
probably work as well, but I'm hesitant to change now that I have things
working.
My VPS is currently running OpenVPN 2.4 on Arch Linux.
I used easy-rsa to create a certificate infrastructure with keys for the server, router and laptop. This is a fairly standard setup; there are plenty of guides for this.
The following files from the process are in /etc/openvpn/server
: ca.crt
,
server.crt
, server.key
, ta.key
, dh.pem
, as well as the following
configuration in server.conf
:
port 1194
proto udp
dev tun
ca ca.crt
cert server.crt
key server.key
dh dh.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
client-config-dir ccd
client-to-client
keepalive 10 120
tls-crypt ta.key
cipher AES-256-CBC
compress lz4-v2
push "compress lz4-v2"
persist-key
persist-tun
status openvpn-status.log
verb 3
Note about the setup -- the OpenVPN network is on 10.8.0.0
with subnet mask
255.255.255.0
. The OpenVPN server automatically assigns itself IP 10.8.0.1
.
Additionally, you need to create a client configuration directory at
/etc/openvpn/server/ccd
, containing the following files.
Note that the name of the file needs to match the 'common name' specified when
you created the certificate for that device. No extension!
ifconfig-push 10.8.0.200 10.8.0.1
iroute 10.99.4.0 255.255.254.0
push "route 10.8.0.0 255.255.255.0 10.8.0.1"
The ifconfig-push
command assigns the router to 10.8.0.200
on the OpenVPN
network.
The iroute
command tells the OpenVPN server to route all packets on the
10.99.4.0
subnet (my home network) towards this device.
The push route
command tells the router to route all OpenVPN network packets
towards the OpenVPN server.
ifconfig-push 10.8.0.100 10.8.0.1
push "route 10.99.4.0 255.255.254.0 10.8.0.1"
The ifconfig-push
command assigns the laptop to 10.8.0.100
on the OpenVPN
network.
The push route
command tells the laptop to route all home network packets
through the OpenVPN server.
No iroute
is needed because the only packets going to the laptop are
destined for the laptop itself -- this is in contrast to the router, where
packets going to the home network need to be explicitly directed towards it.
This is a modified and pruned version of the template client configuration. I'm using it with Tunnelblick on macOS, but I see no reason it wouldn't work on other platforms as well.
The following files are included alongside the configuration: ca.crt
,
laptop.crt
, laptop.key
, ta.key
client
dev tun
proto udp
remote tres.wuffs.org 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert laptop.crt
key laptop.key
tls-crypt ta.key
verb 3
Getting OpenVPN to work on the router is pretty straightforward, thankfully.
Install openvpn-openssl
using opkg
.
The following files should be in /etc/openvpn
: ca.crt
, router.crt
,
router.key
, ta.key
, along with the following configuration in vpn.conf
:
client
dev tun
proto udp
remote tres.wuffs.org 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert router.crt
key router.key
tls-crypt ta.key
verb 3
Run /etc/init.d/openvpn start
and with any luck, OpenVPN will start.
You may find it helpful when debugging to simply run OpenVPN in the foreground
using openvpn /etc/openvpn/vpn.conf
and view the log messages - this goes
for the setup on the other devices too, not just the router.
Once all of this has been set up, you should have both devices connected to
the VPN and you should be able to ping across the OpenVPN network: the router
should be able to ping the laptop at 10.8.0.100
, and the laptop should be
able to ping the router at 10.8.0.100
.
However, to make the home network accessible, you'll need to set up forwarding on the firewall. Thankfully this is pretty straightforward via the firewall settings in LEDE's LuCI.
From Network > Interfaces, select Add new interface, and enter the following:
tun0
tun0
Now go to Network > Firewall. Create a new Zone, with the following settings:
tun
tun0
lan
onlylan
onlySave and apply everything.
If all has gone well you should now be able to access devices on the home
network (the 10.99.4.x
subnet) while connected to the VPN, no matter where
you are.
There are a couple of issues I didn't bother trying to troubleshoot and fix because I was already tired of OpenVPN/firewall configuration and I'm not particularly bothered by them.
SMB (Windows file sharing) appears to work fine over the network, but names
are not resolved automatically so you must for example access \\10.99.4.100
rather than \\TRASH
.
OpenVPN client 1 (the laptop) can access the 10.99.4.x
subnet, but the
server itself can't. This is probably pretty straightforward to fix by adding
extra routing rules but I didn't want the hassle.
Let me know on Twitter (@_Ninji) or through some other means if you found this useful!
Previous Post: An Unholy Combination: Closure Compiler, Preact and JSX
Next Post: Mouse Adventures #1: Introduction