Access your local network from anywhere with WireGuard VPN

For a very long time, I have been using SSH tunneling to access my selfhosted services. This works great, but exposes your server to a multitude of threats. I had to implement additional defenses, such as the Fail2Ban daemon to automatically ban IPs after multiple failed login attempts.

I decided that a better option would be to simply implement a VPN. I ended up choosing WireGuard as it’s built into the kernel, and offers great throughput if I needed to transfer files over the VPN.

Here is how I set up a VPN using WireGuard:

Network topology

Wireguard example topology

Peer1 connects to SERVER over the internet. SERVER has a route to the LAN (192.168.1.0/24) network, allowing Peer1 to access resources on the LAN.

Installing WireGuard

The first step to setting up a WireGuard is ensuring you have WireGuard installed and available to use. On Ubuntu, this can be done by running the following command:

sudo apt install wireguard

Now that WireGuard is installed, we will need to create a key for both peers: the client and server.

Creating keys

The following commands will generate a public and private key for each peer.

wg genkey | (umask 0077 && tee server.key) | wg pubkey > server.pub
wg genkey | (umask 0077 && tee peer1.key) | wg pubkey > peer1.pub

You should now see a .key and .pub for both server and peer1. The .key will be the private key, and .pub the public key.

Enabling IPv4 forwarding

By default, IPv4 forwarding is disabled on most Linux distributions. You will need to enable this feature, so iptables can forward packets on to the LAN interface.

To do this, run these commands:

sysctl net.ipv4.ip_forward=1

IPv4 forwarding is now enabled, but this is not a persistent configuration change. To make this change persistent, you will need to edit the sysctl configuration files. This is located at /etc/sysctl.d/99-sysctl.conf.

Open this file, and uncomment the line that contains this text: net.ipv4.ip_forward=1. Save the file.

The configuration change will now apply on each boot.

Creating the server configuration file

Create the configuration folder and file:

mkdir /etc/wireguard
vim /etc/wireguard/wg0.conf

Inside of wg0.conf, add the following lines:

[Interface]
Address = 192.168.99.1/24
ListenPort = 51820
PrivateKey = SERVER Private Key
PostUp = iptables -A FORWARD -i br0 -o %i -j ACCEPT; iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o br0 -j MASQUERADE
PostDown = iptables -D FORWARD -i br0 -o %i -j ACCEPT; iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o br0 -j MASQUERADE
 
[Peer]
PublicKey = Peer1 public key
AllowedIPs = 192.168.99.2/32

Replace br0 with the network interface that connects to your LAN. In most cases, this will be eth0 or something along the lines of enp1s0. Use the ip a command to determine this.

Next, add in the SERVER private key, and the public key for peer1 into this file.

Creating a configuration file for the client

This file will work as a configuration for the client:

[Interface]
PrivateKey = Peer1 private key
Address = 192.168.99.2/32 
 
[Peer]
PublicKey = SERVER public key
AllowedIPs = 192.168.99.0/24, 192.168.1.0/24
Endpoint = SERVER:51820

Add in the private key for the client (Peer1) under Interface, and the public key of the server under Peer.

Next, you’ll need to add in the public IP address, or if the IP address is dynamic, a hostname that utilises dynamic DNS. This will go under the endpoint. Leave 51820 as-is unless you have changed it, as this is the port WireGuard will use.

The AllowedIPs configuration option will allow Peer1 to access both the LAN and VPN (192.168.99.0/24) networks.

The WireGuard interface will listen on UDP port 51820. Remember to port forward this in your router settings if your server is behind NAT, and allow the port through your firewall if you are running one.

Starting WireGuard

Now that you have both the client and server configurations set up, you can now start WireGuard on each peer.

On the server, I’ll use wg-quick to quickly bring up the interface, and then run the wg command to verify it is running:

wg-quick up /etc/wireguard/wg0.conf
wg

To make the WireGuard interface start upon boot, you can enable the systemd service for it:

systemctl enable wg-quick@wg0

For my client, I am using the WireGuard Windows application. To configure it, you will need to the generated configuration into it, and add in the keys where required. Once it’s configured, you can then connect to the VPN.

Other clients, such as the iOS and Android clients, will be configured in a similar fashion.

That’s it! You should now be able to access your local network resources over a VPN. You can test connectivity by pinging the server peer address (192.168.99.1), and a LAN address such as 192.168.1.1. If you get a reply from both addresses, everything is working as it should.