If you need to access your home network from somewhere other than your home, the traditional way to do that is using a VPN. However, most VPN tutorials send all of your traffic through your home network. I only wanted to reach the devices in my home network, and not send all my traffic through the VPN. So if that's what you're looking for, this is the tutorial for you.
We'll be using algo for this. Algo is a install script that sets up a WireGuard VPN server. WireGuard is a new-ish VPN program that is meant to be easier to use and faster than traditional VPN servers. It also makes it easy to only send certain IP addresses through the VPN instead of all internet traffic.
You'll need these things:
- A dedicated home internet connection, where you are the only one using your IP address. This is still common, but if your provider uses DS-Lite or CGNAT or some other form of shared IP address, this won't work, you'll need to get a server and use that. I'm not sure of a generic way to find this out, sorry.
- A computer running an up-to-date version of Ubuntu. At the time of writing, that's 18.04 and 19.10. Check the algo docs if you're reading this far into the future to see supported versions. Note: if you're using a Raspberry Pi or similar ARM computer, you'll need to use Ubuntu 19.10.
- A way to get a root shell on the aforementioned computer. This can be either via SSH from a different computer or through the terminal on the computer you're using.
- A list of devices that will be connecting to the VPN from outside your network.
- A way to forward ports from your router to the computer.
- A few hours on a cloudy weekend afternoon with good focus music and a cup of tea (other types of beverages are allowed).
Since we're all using a local computer with Ubuntu, we can shorten the algo install docs somewhat.
Get system and Python requirements
- Get a root shell.
sudo su
should work if you freshly installed Ubuntu and you're the only user. You might have to enter your password. - Make sure your system has some required things installed:
apt install git qrencode wget openssh-server python3-virtualenv
. - Clone the repo and change into the repo directory:
git clone https://github.com/trailofbits/algo && cd algo
. - Install a python virtual environment to isolate the install:
python3 -m virtualenv --python="$(command -v python3)" .env && source .env/bin/activate
. - Install the algo dependencies:
python3 -m pip install -U pip virtualenv && python3 -m pip install -r requirements.txt
. - Open config.cfg in your favorite editor. If you don't have a favorite editor, I suggest nano:
nano config.cfg
.
Edit algo config
- Edit the list of
users:
and add the list of devices you gathered when I told you to above. BE SURE TO KEEP THE INDENTATION THE SAME: 2 spaces, NOT a tab. - Change
ipsec_enabled
tofalse
. - Find the
BetweenClients_DROP
and changefalse
totrue
. - (Optional) Sometimes you'll have a firewall that drops connections after a while. To get around that, find
wireguard_PersistentKeepAlive
and set it to25
(Not a magic number, it's actually WireGuard's recommended setting). - Save and close the file. If you're using nano, that's Ctrl+X, then Y, then hit Enter. If you're using vim, it's
:x
.
Install algo
- Run
./algo
. There's several options to choose from, make sure you choose the "Install to existing Ubuntu server" on the "What provider would you like to use?" prompt. - We're going to remove the DNS settings for Wireguard later on, so don't bother setting them up here.
- The IP address options are a little confusing. The first one is the local IP address, you leave that as
localhost
. For the "Enter the public IP address of your server", you can find your public IP address usingwget -qO - https://canihazip.com/s
. You can also use a dyndns provider if you want. - The rest of the prompts can be left as their default value.
- The install should complete successfully. If it doesn't, research the error you got and try again until it does.
- Take a break, you're almost there. Do some pushups, get some water, take a short jog, and then come back.
Set up devices
- Run
exit
to drop back into your user shell, thensudo cp -r /root/algo/configs .
andsudo chown $(whoami):$(whoami) -R configs
. This moves the configs to your home directory and makes them accessible to you without special privileges. cd
into the configs directory. You should see your public IP address as a folder (or the dyndns hostname if you went that route).cd
into that, and then into thewireguard
directory. There will be a.conf
and.png
file for each user you specified inconfig.cfg
way back in the beginning.- Edit each of the conf files. In the
[Interface]
section, remove theDNS=
line if there is one. In the[Peer]
section, changeAllowedIPs
to the IPv4 and IPv6 subnet of theAddress
of the[Interface]
section. - If that isn't clear, you're taking the first value in the
Address=
line (the default is10.19.49.x/24
, wherex
is unique to each client). Change thex
to a0
, and put that in theAllowedIPs=
line, erasing whatever value is currently in there. So if you haveAddress=10.19.49.2/24
, you copy10.19.49.2/24
and replace the values inAllowedIPs
with10.19.49.0/24
, so the entire line isAllowedIPs=10.19.49.0/24
. - Do the same for the IPv6 subnet, replacing the number after the
::
with a0
. - See pictures below if you're having trouble.
Configure WireGuard for local network
Sorry this section can't be bullet points, the pictures and code get all wonky.
If you want to access computers connected to your local network but not connected to the VPN, find your local subnet. The easiest way is to run ip a
. If you're connecting wirelessly, there should be a interfacethat starts with a w
and an IP address associated with that. If you're connected via ethernet, it will be the interface beginning with e
. Here's mine as an example (it's using a wireless connection):
Copy the IP address that's in the place of the one circled (squared?) in that picture, open up a terminal and run python3
and then enter the lines prefixed with >>>, substituting your IP address for my example:
>>> import ipaddress>>> ipaddress.ip_network("192.168.1.29/24", False) IPv4Network('192.168.1.0/24')
The string in the IPv4Network
that is returned is the subnet you need to use.
If you like pictures, you started with something similar to this:
and you end with something like this:
Port forward the WireGuard port
You need to port forward UDP port 51820 to the computer running algo. Unfortunately, there's not a generic way to do this, so you'll need to research how to forward ports on your specific router.
Distribute the configuration files
For desktops and laptops, you can ssh into the computer and copy+paste the configuration. For phones and tablets, the WireGuard app can read a QR code. Algo created one for us, but it isn't valid anymore since we changed the configs. To get the configuration on your phone or tablet, run qrencode -t ansiutf8 -r x.conf
, replacing x.conf
with the name of the configuration file. The QR code will display in your terminal and you can scan it. If your terminal doesn't support UTF8, run qrencode -t png -r x.conf -o x.png
and download x.png
to your local computer to display.
IP address conflicts
If you have a common local subnet (192.168.1.0/24
or 192.168.0.0/24
are the most common), it's likely you'll eventually end up on another network that shares the same local subnet, which might prevent you from accessing the local subnet over WireGuard. If you don't need to access any of the local IPs on that network (make sure your DNS isn't using it), there's a few ways to fix it. First, if your ISP and router support IPv6, you can find the IPv6 subnet range just like you found the IPv4 subnet range a few sections up, and add that to your AllowedIPs=
line. Then you can connect to your home devices via IPv6. Second, you can connect all the devices to WireGuard so they're all accessible via the WireGuard IP address range. If neither of those are a possibility, the last option is making the IP address rules more specific. I'm not going to show you here, but read up on CIDR ranges (the /24
is the CIDR range I have in my example) and how UNIX/Linux systems route packets, and you may be able to make a more specific route.
Firewall
Algo sets up the iptables firewall to block all ports except the necessary ones for Wireguard. So if you're running some other program that listens on a port, you'll need to go in and add a firewall rule to allow that port.
Thanks for reading this! If you liked it, please share it with places that will also like it. If you are so inclined, you can buy me a Ko-Fi (other ways to donate are available as well). If you have any questions or comments, you can contact me in various ways, and I'll do my best to help you out. Follow me at @emerson@emerson.chat or subscribe to my RSS feed to be notified of future posts and hear my thoughts.