There are multiple options when trying to access services in the home network. The most obvious option is usually to open a port on your router and allow access from the internet to the services in the home network. This requires either a static IP, use of a dynamic DNS service, or to constantly query the IP of the router whenever needing to access the service. These issues aside, there are big risks to allowing port forwarding on the home router. Assuming that there isn’t a need to make services accessible to the entire internet, then it is much easier to just run a VPN tunnel which would allow access to services on devices within the VPN. Here we will be using Wireguard as our VPN and setup a tunnel between the VPS and a service within the local network.

Setup Link to heading

  • VPS with static IP
  • Server in the local network

VPS Setup Link to heading

Initial Setup Link to heading

Create a VPS in your chosen cloud provider. Debian will be used here. Update and upgrade the system and install unattended-upgrades for security updates.

$ cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"

Create a sudoer user to run commands instead of running as root.

adduser <username>

usermod -aG sudo <username>

Update SSH configs to prevent root login by editing /etc/ssh/sshd_config and setting PermitRootLogin no and PasswordAuthentication no. The ssh port can also be updated if desired. Add your own pub ssh key to the /home/<username>/.ssh/authorized_keys and then reload the sshd daemon.

systemctl reload sshd

Exit the root ssh session and open another ssh session using the new user.

Wireguard Installation Link to heading

Install wireguard packages.

sudo apt install -y wireguard wireguard-tools

Add Wireguard User Link to heading

sudo useradd wireguard -d /etc/wireguard
sudo chown wireguard:wireguard /etc/wireguard
sudo chmod 760 /etc/wireguard

Create Server Key Link to heading

Create a Wireguard key for the server. This can be run directly as the wireguard user.

sudo su wireguard
cd /etc/wireguard
wg genkey | tee server.key | wg pubkey > server.pub

Create the Wireguard Config File Link to heading

Wireguard config files are usually named wg0.conf.

Create the file /etc/wireguard/wg0.conf with the following content.

# Server
# This defines this instance at the wireguard server with a static IP and port.
# Other wireguard instances will connect to this one.
[Interface]
# Paste the contents of the private key file here.
PrivateKey = *****
# Address of this wireguard server within the network.
# Change the size of the subnet as required.
# Ensure that this subnet does not overlap with the subnet being used
# in the home network.
Address = 192.168.100.1/24
# Port to listen on for incoming Wireguard connections.
ListenPort = 51820

# Gateway host in home network
[Peer]
# Paste the contents of the public key of the gateway host
# running in the home network.
PublicKey = *****
# This routes connections to the listed IP addresses to/through this gateway.
# The IP 192.168.100.2 will be the wireguard IP of the gateway host
# and 192.168.50.0/24 is the subnet of the home network.
AllowedIPs = 192.168.100.2/32,192.168.50.0/24
PersistentKeepalive = 25

# Clients
[Peer]
PublicKey = *****
AllowedIPs = 192.168.100.3/32
PersistentKeepalive = 25

# Repeat this config for all other relevant clients.
# Keep incrementing the IP address for each client in the AllowedIPs configuration.

Start the Wireguard Server Link to heading

sudo systemctl start [email protected]

Enable the Wireguard Service Link to heading

sudo systemctl enable wg-quick@wg0

Check the IP Address and Network Interfaces Link to heading

Run ip a to see the network interfaces and check that there is a wg0 interface with the correct IP address configured.

Gateway Setup Link to heading

The machine used in this instance is a Raspberry Pi 4B 4GB set-up with a static local IP address and updated with security updates, etc.

The packages to install and other setup are the same as in the server setup. The main difference in this case are the public and private keys and the contents of /etc/wireguard/wg0.conf.

Generate Keys Link to heading

In the /etc/wireguard directory create the keys.

wg genkey | tee gateway.key | wg pubkey > gateway.pub

Wireguard Config Link to heading

# Gateway
# This is the gateway through which the tunnel will go to allow access to local services.
[Interface]
# This is the IP address of the gateway in the wireguard mesh network
Address = 192.168.100.2/32
# The contents of gateway.key
PrivateKey = *****

[Peer]
Endpoint = [Public Static Server IP Address]:51820
# The contents of server.pub in the wireguard server.
PublicKey = *****
AllowedIPs = 192.168.100.0/24
PersistentKeepalive = 25

Start the Wireguard Gateway Link to heading

sudo systemctl start [email protected]

Enable the Wireguard Service Link to heading

sudo systemctl enable wg-quick@wg0

Configuring the Server to Forward IPv4 Packets Link to heading

Edit /etc/sysctl.conf and set net.ipv4.ip_forward=1 then run sudo sysctl -w net.ipv4.ip_forward=1 to set the setting on the current running system without rebooting.

Add an iptables rule to forward traffic to the gateway.

sudo iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -o eth0 -j MASQUERADE

Check if the main interface is eth0, if it is not, change the command accordingly.

Configuring the Gateway Link to heading

Same as before, update /etc/sysctl.conf with net.ipv4.ip_forward=1 then run sudo sysctl -w net.ipv4.ip_forward=1.

Set-up the iptables rules.

sudo iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -j MASQUERADE

Enable Wireguard Access Through the DigitalOceam Firewall Link to heading

Add an inbound rule to the Digitalocean firewall attached to the droplet allowing UDP traffic over 51820 or whichever port was used to configure wireguard. image

Test Link to heading

Ping the server from the gateway and vice versa.

# On the gateway
ping -c 5 192.168.100.1

# On the server
ping -c 5 192.168.100.2

Add a device Link to heading

Install qrencode Link to heading

On a mobile phone, installing the tunnel via a generated QR code is the simplest way.

# Install qrencode
sudo apt install -y qrencode

Setup Client Config File Link to heading

Similar to the gateway file, set-up the configs for the next device.

Generate the public and private keys.

wg genkey | tee device.key | wg pubkey > device.pub

Create a new config file device.conf

# Device
[Interface]
# This is the IP address of the device in the wireguard mesh network
Address = 192.168.100.3/32
# The contents of device.key
PrivateKey = *****

[Peer]
Endpoint = [Public Static Server IP Address]:51820
# The contents of server.pub in the wireguard server.
PublicKey = *****
AllowedIPs = 192.168.100.0/24
PersistentKeepalive = 25

Add the device as a peer in the server wireguard config.

# Device
[Peer]
PublicKey = *****
# This IP needs to match the IP address assigned to the device.
AllowedIPs = 192.168.100.3/32
PersistentKeepalive = 25

Reload the wg-quick service on the server. This must be done whenever there is a change to wg0.conf that needs to be propagated to the running service.

sudo systemctl restart wg-quick@wg0

Generate the QR Code conf of the device config and use it to setup the Wireguard tunnel on your device.

sudo qrencode -t ansiutf8 < /etc/wireguard/device.conf 

Once setup, test with your device connected on a different network, e.g. cellular, that services on the home network can be accessed.

Repeat these steps for every new device to be added.

Troubleshooting Link to heading

Unable to ping hosts in home network from wireguard network Link to heading

Error:

ping -c 5 192.168.50.4
PING 192.168.50.4 (192.168.50.4) 56(84) bytes of data.
From 192.168.100.1 icmp_seq=1 Destination Host Unreachable
ping: sendmsg: Destination address required

Resolution:

Ensure that the POSTROUTING is set on the Wireguard Gateway.

sudo iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -j MASQUERADE