Securing external traffic on a budget with Wireguard

Jul 9, 2025 by José Carrasquel Vera | 192 views

Linux Sysadmin

https://cylab.be/blog/427/securing-external-traffic-on-a-budget-with-wireguard

In this post I will explain how I configured my home network so that external traffic is tunneled through a Wireguard VPN server.

HomeNetwork.png

⚠ It might be that your router already has this functionality out of the box, so read its manual before continuing.

This post is based on the Wireguard Quick Start and a wonderful pi-hole guide that explains how to access your pi-hole and use its capabilities from outside your home network.

The hardware

  • Router: Any modern router should work. In my case, I’m using a Tplink Archer C6. As a nice-to-have, its dhcp server should be configurable.
  • Server: Any “server” running Linux should work. In particular, any Linux single board computer. In my case, I already have a LePotato at home running Pi-Hole and Immich. If your router allows console access, it could be possible follow this post using the router as the server.

⚠ If you’re planning on tunneling lots of traffic then perhaps the LePotato is not your best option as its ethernet port is only 100Mbps.

Preparation

Your server should already have a running operating system. In my case, I installed Armbian following the documentation. This step is beyond the scope of this post as it was pretty straightforward.

Make sure your server has a fixed ip within the network. This can be done by configuring the network manually in your server, or by configuring your router’s dhcp server to always lease the same ip to your server.

You would also need remote VPN server with Wireguard capabilities. For this post, I’ve created a free account on ProtonVPN.

Warning: Make sure you trust the VPN server. It effectively is a man in the middle.

Wireguard tunnel setup

First let’s install Wireguard in the server

server$ sudo apt install wireguard wireguard-tools

Most VPN providers would generate a Wireguard configuration for you. ProtonVPN’s should be similar to this:

[Interface]
PrivateKey = redacted
Address = 10.2.0.2/32
DNS = 10.2.0.1

[Peer]
# NL-FREE#49
PublicKey = /nzl9zyzlLm97wJsBv7BpFS5gWxzYCYpcm9WWm1ohUw=
AllowedIPs = 0.0.0.0/0
Endpoint = 169.150.196.96:51820

With this configuration, Wireguard would create a new network interface with IP 10.2.0.2/32, use DNS server 10.2.0.1 and add a route.

The option AllowedIPs tells Wireguard the ranges of source ips to a accept from the peer. Moreover, as we will see later on, it will add a route of these ranges through the Wireguard interface.

💡 If your VPN provider supports IPv6, you can configure Wireguard to also tunnel IPv6 traffic. You do this by adding an additional IPv6 ip and ranges to the Address and AllowedIPs fields, respectively. For example, Address = 10.100.0.1/24, fd08:4711::1/64 and AllowedIPs = 10.100.0.2/32, fd08:4711::2/128.

I have commented out the DNS line as I have my own dns server (pi-hole) and saved the file to /etc/wireguard/wg1.conf.

Now lets activate the Wireguard tunnel

server$ sudo systemctl start wg-quick@wg1
server$ sudo systemctl enable wg-quick@wg1
server$ sudo wg
interface: wg1
  public key: ZDtvbn8qosVefaTYadgMaEe33wQwGDkx3TVDLYi2O1A=
  private key: (hidden)
  listening port: 46228
  fwmark: 0xca6c

peer: /nzl9zyzlLm97wJsBv7BpFS5gWxzYCYpcm9WWm1ohUw=
  endpoint: 169.150.196.96:51820
  allowed ips: 0.0.0.0/0
  latest handshake: 2 seconds ago
  transfer: 2.39 KiB received, 16.93 KiB sent

This shows that the tunnel has been established. More precisely, a systemctl status wg-quick@wg1 will show exactly what was run:

 ip -4 address add 10.2.0.2/32 dev wg1
 ip link set mtu 1420 up dev wg1
 wg set wg1 fwmark 51820
 ip -4 route add 0.0.0.0/0 dev wg1 table 51820
 ip -4 rule add not fwmark 51820 table 51820
 ip -4 rule add table main suppress_prefixlength 0
 sysctl -q net.ipv4.conf.all.src_valid_mark=1
 iptables-restore -n

We can see that the routing has changed:

server$ sudo traceroute -m 1 dns0.eu
traceroute to dns0.eu (188.172.219.65), 1 hops max, 60 byte packets
 1  10.2.0.1 (10.2.0.1)  8.672 ms  8.467 ms  8.314 ms

Server as gateway

We have successfully set up a Wireguard tunnel between our server and our remote VPN provider. Now we need to configure it as a gateway for our network. For this we need to follow three steps: enable packet forwarding on our server, enable NAT on wg1 and reconfigure other devices on our network to use our server as gateway.

Packet forwarding

In the file /etc/sysctl.d/99-sysctl.conf, uncomment the lines

net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1

and apply the changes

server$ sudo sysctl -p
...
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
...

This configuration gives your server router-like capabilities.

NAT

As our regular router, our server needs to NAT traffic to allow returning packets to reach other devices in our home network. The interface doing the NAT should be the “external” one, in our case wg1.

This can be done with iptables -w -t nat -A POSTROUTING -o wg1 -j MASQUERADE.

We want to run this command every time the interface is up. Luckily Wireguard can be configured to run commands after the interface is up and after the interface goes down. In our case, we add the following lines to the interface section of /etc/wireguard/wg1.conf

PostUp = iptables -w -t nat -A POSTROUTING -o wg1 -j MASQUERADE; ip6tables -w -t nat -A POSTROUTING -o wg1 -j MASQUERADE
PostDown = iptables -w -t nat -D POSTROUTING -o wg1 -j MASQUERADE; ip6tables -w -t nat -D POSTROUTING -o wg1 -j MASQUERADE

Now we restart the service wg-quick@wg1 to activate the nat:

server$ systemclt restart wg-quick@wg1
server$ sudo iptables -S -t nat | grep wg1
-A POSTROUTING -o wg1 -j MASQUERADE

Configure devices in your network

This step depends on your setup and your personal choices. The idea is simple, route the traffic you want to tunnel through your server instead of your router. You can route all external traffic by selecting your server as the gateway. More advanced users can select which traffic to tunnel by modifying the routing tables. For devices that don’t allow advanced configuration, you can try to pass routing options or gateway through DCHP.

I have configured my laptop to use my lepotato server (192.168.0.164) as gateway:

laptop$ traceroute dns0.eu -m 2
traceroute to dns0.eu (192.71.249.67), 2 hops max
  1   192.168.0.164  3,276ms  1,775ms  2,059ms 
  2   *  10.2.0.1  11,155ms  10,947ms 

This blog post is licensed under CC BY-SA 4.0

This website uses cookies. More information about the use of cookies is available in the cookies policy.
Accept