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 sushould 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:
# 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.
- Find the
- (Optional) Sometimes you'll have a firewall that drops connections after a while. To get around that, find
wireguard_PersistentKeepAliveand set it to
25(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
# Install algo
./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 using
wget -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
exitto drop back into your user shell, then
sudo cp -r /root/algo/configs .and
sudo chown $(whoami):$(whoami) -R configs. This moves the configs to your home directory and makes them accessible to you without special privileges.
cdinto the configs directory. You should see your public IP address as a folder (or the dyndns hostname if you went that route).
cdinto that, and then into the
wireguarddirectory. There will be a
.pngfile for each user you specified in
config.cfgway back in the beginning.
- Edit each of the conf files. In the
[Interface]section, remove the
DNS=line if there is one. In the
AllowedIPsto the IPv4 and IPv6 subnet of the
- If that isn't clear, you're taking the first value in the
Address=line (the default is
xis unique to each client). Change the
0, and put that in the
AllowedIPs=line, erasing whatever value is currently in there. So if you have
Address=10.19.49.2/24, you copy
10.19.49.2/24and replace the values in
10.19.49.0/24, so the entire line is
- Do the same for the IPv6 subnet, replacing the number after the
- 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 interface that 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:
1 2 3
>>> 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.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.
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.
That's all it takes to get a secure connection to your local devices from outside of your home. If you have any questions or see mistakes, please email me at email@example.com or open an issue on the GitHub repo.