Being the fiddler I am, I have a tendency quite often to ask the question. Is the tool I am using to do a job the right tool? Is there something better for my use case out there?

As such a few weeks ago an article on Wireguard being added to the Linux Kernel piqued my interest.

Disclaimer

Remember this is my journey, i've written this as a guide for myself and it might help others. If your setup isn't the same or you break your system because you just copied and pasted things without understanding what you are doing. Welcome to Linux.

This is just one guys journey not a personal afront against your beliefs. I'm open to opinion and grown up discussion, but cannot be bothered with trolls.

Also I know I can't spell and my grammar is terrible, you don't need to tell me.

Please NOTE

I do not work for, am affliated with, or make any money from Wireguard.

The article suggested that Wireguard offered better cryptology, easier setup, faster connection, better battery life on the Android client and specifically that the code even at this early stage as a beta was better maintained and written than OpenVPN.

I've been using OpenVPN and OpenVPN-AS for years and to be honest have never found it that hard to setup and its always seemed to do what it says on the tin. Claims like the ones above however I just had to give this a go.

Having googled around found a few simple how-to guides and tried them, i objectively failed getting Wireguard to do much more than connect. I couldn't get it to do much more than that, it didn't seem to be able to return traffic back to the device.

This however may have something to do with my home LAN setup which is has a Double NAT on it and while i'm hosting internet accessible services (like this blog) simple port forwarding from the router doesn't work. It needs a bit more than that.

While the IP's have been changed to protect the innocent, this pretty much outlines my home setup.

My FTTP internet comes into an Asus router, this then routes all incoming traffic to 10.10.10.5 which is where I have a 6 puck Google WiFi mesh spread over my whole house.

One of the Pucks has a switch connected to to, which my home lan falls off, this is currently made up of 4 Ubuntu servers and 2 Windows servers. One of the Windows Servers is acting as an AD and provides internal DNS, External DNS if forwarded to 192.168.50.1 the master Puck which hands it over to GoogleDNS.

While not overly complex the Double NAT causes fun and I have static routes to 192.168.50.0/24 on the Asus router to get round issues.

With this in mind and failing tragically, I did some research and came to the conclusion that I needed to change the iptables that most of the instructions say to use in the config file and add some form of DNS local on the server Wireguard is running on. PiHole seemed to be the choice fo the community for this.

So with that knowledge in mind the following is how I've setup Wireguard to obtain a RoadWarrior like VPN setup from my Android phone and OpenSUSE Laptop.

Its worth noting that there is much more to Wireguard than just this style of setup, it works with a peer to peer system and setting up site to site VPN's or cross domain VPN's or even being used to encypt traffic between any two servers can be done just as easily with a little modification. The VPN is so light and fast it won't have a huge effect on most peoples cross server communication.

This might help someone else as well as there are a few things the normal google of Wireguard setup doesn't note.

What am I installing on as a Server?

Wireguard is installed on Ubuntu 18.04 (4Gb RAM Gigabrix (very low spec CPU)

Note:

All commands run as root (sudo -s)

Server Setup

Installing Wireguard

The installation of Wireguard is a painless process on Ubuntu of adding a PPA repository and installing the software

add-apt-repository ppa:wireguard/wireguard apt-get update apt-get install wireguard

Key setup

The core premise of Wireguard communcation is to be cryptologically sound, and security comes first. Where on OpenVPN as an example there are user assigned account. Each client (peer) we want to connect to the central VPN server communicates using keys rather than username/password.

Before we setup the clients (peers) we need to setup the certificates for the central server our roadwarriors are going to connect back to.

cd /etc/wireguard wg genkey | tee privatekey | wg pubkey > publickey

You can simply see your keys under /etc/wireguard either by

cat privatekey cat publickey

The server side keys are setup and you will need the publickey later to setup the clients (peers)

Create /etc/wireguard/wg0.conf

The core configuration for Wireguard is done using the /etc/wireguard/wg0.conf file.

wg0 is the virtual network card that Wireguard creates for the VPN to connect to. What we are actually setting up here is a config readable by the Wireshark wgquick command. There are other ways of doing this, this however is well documented on the internet.

Edit the file

nano /etc/wireguard/wg0.conf

My example config is going to look like this

[Interface] Address = 10.10.100.1/24 SaveConfig = false ListenPort = 45678 PrivateKey = HHBGgkhhkhJ#lJJKnotMYActualKeyJKJHJK= PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o enp3s0 -j MASQUERADE PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o enp3s0 -j MASQUERADE

Lets break this down for the server [Interface] as to what we have here.

Address - This is the IP for your Wireguard server, its a virtual IP accessible on your lan and should not be the same IP range as your Lan's IP range.

SaveConfig — if set to ‘true’, the configuration is saved from the current state of the interface upon shutdown. I want to be dure i'm in control of the configuration so I set false.

ListenPort - This is the Port the service is listening on, and you'll need to set it to something no ther service is listening on. You will need this if you need to setup port forwarding on your router later.

PrivateKey - Remember those two keys you setup earlier in /etc/wireguard on your server? run cat privatekey and copy the output here. (no trailling spaces)

Postup and Postdown - I'm absolutly no iptables wizard, so this next bit is a bit wooly, however note my ethernet card is enp3s0 you might have eth0 or something else run ip a to find the ethernet card name and change the config to match yours.

PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o enp3s0 -j MASQUERADE PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o enp3s0 -j MASQUERADE

The first thin you should notice is that post up and post down the main difference is -A vs -D

-A appends the rule to the firewall when the wg0 interface comes up and -D deletes it when wg0 is taken down

-i — Sets the incoming network interface and -o sets the outgoing interface. many of the instructions online use only -i however my home setup only works if i define the outgoing interface as well

-j — Jumps to the specified target when a packet matches a particular rule

MASQUERADE is an iptables target that can be used instead of SNAT target (source NAT) when external ip of the inet interface is not known at the moment of writing the rule (when server gets external ip dynamically)

Service Test

Now we have installed the software, setup the cryptology and created a config, we should test this all and make sure it come up as expected.

wg-quick up wg0

will bring up the new Wireguard virtual interface, you can confirm this by running.

wg

If everthing has worked you should see something like this.

interface: wg0 public key: bbhhy65bnkmnkYeAHR1ghtKKJJJ= private key: (hidden) listening port: 45678

At this point we should take the interface down

wg-quick down wg0

Enable packet forward

Most linux distros don't allow packet forwarding by default, Ubuntu certainly doesn't so we need to add some config to the OS or the postup and post down commands won't work.

nano /etc/sysctl.conf

Add these two lines if you haven’t done this before

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

Save the file, reboot or enable it immediately with this

sysctl -p

Service Start

If everything is working fine, the next stage is to setup Wireguard so we can use it as a service which starts on boot.

First enable the Wireguard Service

systemctl enable wg-quick@wg0

Next start the service

systemctl start wg-quick@wg0

the output of the systemctl status command should look like this



Feb 19 20:09:09 external systemd[1]: Stopped WireGuard via wg-quick(8) for wg0.

Feb 19 20:09:09 external systemd[1]: Starting WireGuard via wg-quick(8) for wg0...

Feb 19 20:09:09 external wg-quick[23367]: [#] ip link add wg0 type wireguard

Feb 19 20:09:09 external wg-quick[23367]: [#] wg setconf wg0 /dev/fd/63

Feb 19 20:09:09 external wg-quick[23367]: [#] ip -4 address add 10.10.100.1/24 dev wg0

Feb 19 20:09:09 external wg-quick[23367]: [#] ip link set mtu 1420 up dev wg0

Feb 19 20:09:09 external wg-quick[23367]: [#] iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FO

Feb 19 20:09:09 external systemd[1]: Started WireGuard via wg-quick(8) for wg0.

Server setup complete

The Ubuntu server setup is now complete, however as the intention is to access the server on my network from the outside world there is some networking which needs to be done.

This is always the awkward part of a guide like this because i'm not going to help you setup your network. I'm hoping that some of the things i've documented here help you google search for your own setup.

Network setup

2 Routers, 2 NAT Networks

I have 2 routers running on this setup, the "edge" router (Asus) is on a 10.10.10.0/24 network and the "internal" router (Google Wifi) is on a 192.168.50.0/24 network

Note

The plan here is to have the 10.10.10.0/24 lan act as a DMZ type network and i'll eventually move the server for external services like Wireguard onto that Lan

Port Forwarding on router

You will need to setup port forwarding from the external IP address of the router to the IP the Google Wifi is connected to using port 45678 tcp/udp

This is out of scope for this guide, sorry..

Port Forwarding on Google Wifi

Google have a tendency to change wording and titles on apps, hopefully not to much, however it might happen.

1. Open the Google Wifi app on your phone.

2. Tap the 4 dots

then Network & general.

3. In the ‘Network’ section, tap Advanced networking.

4. Tap Port forwarding/management. then +

5. Choose the tab for the type of IP address that you’re forwarding, IPv4

6. Select the device (the server you installed WireGuard on) that you want from the list and tap Next.

6. For IPv4: Enter the port number you used in the /etc/wg0.conf file 45678.



7. Choose TCP and UDP.

8. Tap Done.

At this point we are able to communicate from the internet, through the router to the Wireguard server.

pi-hole install

At this point when setting up clients I was able to use IP communication internally and over the internet using the Wiregaurd VPN, however my internal DNS was eluding me.

Some Googling pointed me to Pi-Hole and Wireguard.

Pi-Hole should be installed on the same Ubuntu server WireGuard is installed on.

Note down your wireguard’s server IP address

Before moving forward we need to know some information about this network. the Pi-Hole setup will ask several questions

Type the following command:

ip a show dev wg0

If you following the wireguard installation here , ip should be 10.10.100.1/24

You also need to provide wg0 as an interface name including your default gateway IP address such as 192.168.2.1 (this is different for every server , save your own by below command):

ip r | grep default` default via 192.168.50.1 dev br0 online

So we have

Wiregaurd Interface: wg0 Wiregaurd IP: 10.10.100.1 Wiregaurd Subnet: 255.255.255.0 Default Gateway: 192.168.50.1 Upstream DNS Server: 192.168.50.11

Install PI-HOLE

The installation of Pi-Hole comes down from the internet, on the same box Wireguard is installed on run the install command as follows:

wget -O basic-install.sh https://install.pi-hole.net

Setup Pi-Hole

bash basic-install.sh

The installer is going to ask a bunch of questions referencing your setup. Important information you will need to know.

Questions during setup

CHOOSE AN INTERFACE FOR PI-HOLE: wg0 (select and press ‘space’ then enter)

SELECT PROTOCOLS FOR DNS SERVER

SETUP A STATIC IP ADDRESS (SELECT NO)

Next enter Wireguard’s server IP address as follows:

Finally enter your default router/gateway IP address:

Confirm the settings:

SETUP UPSTREAM DNS IP ADDRESS

In case if you have an apache2 or any other server install then dont install the lighttpd server comes with pihole

And you are done:

Test it

Type the following command on Pi-hole to see if DNS is working or not:

host cyberciti.biz 10.10.100.1



Sample outputs:

Using domain server:

Name: 10.10.100.1

Address: 10.10.100.1#53

Aliases: cyberciti.biz has address 75.126.153.202

cyberciti.biz mail is handled by 1 aspmx.l.google.com.

cyberciti.biz mail is handled by 10 aspmx2.googlemail.com.

cyberciti.biz mail is handled by 10 aspmx3.googlemail.com.

cyberciti.biz mail is handled by 5 alt1.aspmx.l.google.com.

cyberciti.biz mail is handled by 5 alt2.aspmx.l.google.com.

Restart

Restart wireguard on server so this installation is picked up.

systemctl restart wg-quick@wg0

Configuring Pihole with Wireguard

This will be pertinent in the next session I've added it here for information purposes

On your chosen Client (Android, IOS, Linux)

Open the tunnel you created.

Edit the tunnel

Put pihole ip (10.10.100.1) in the DNS instead whatever was there previously and save.

Setting up a client

Having setup the server I am now going to look at setting up the clients, I've got two systems I want to connect to the VPN, my mobile phone (Android) and my laptop (OpenSuse Tumbleweed)

Both these clients are called Peers in the Wireguard world.

Android Setup

The Wireguard App for Android is available at the Google Play store: https://play.google.com/store/apps/details?id=com.wireguard.android&hl=en_US

or f-droid - https://f-droid.org/en/packages/com.wireguard.android/

Install and open it.

Generate Keys

Once the app is open click on the + symbol

Choose "Create from Scratch"

Give the Config a Name

Press the Generate Button, this will generate a public and private key

Enter the IP address of the phone when it connects to the Server, make sure you use /32 as the subnet mask

Add the DNS server which whould be the IP of your Wireguard Server's wg0 interface.

Add the Server (peer)

Press the Add Peer button

This allows us to setup the peer connection back to the Ubuntu Wireguard server

You will need the public key you generated on the server here

cat /etc/wireguard/publickey

Set Allowed IPs to 0.0.0.0/0

Enter the ip and port (sorry my screengrab forgot to add the port) as

my.vpn.url:45678 87.43.123.234:45678

Click on the save icon

Add Peer information to wgo.conf on server

Back on the Wireguard server open the wg0.conf file

nano /etc/wireguard/wg0.conf

and add the peer section

[Peer] PublicKey = <public key from your android device> AllowedIPs = 10.10.100.50/32

The PublicKey will be the same one generated on your phone when you pressed the generate button

In our example we used.

Save and exit the file

Restart the Wireguard service on the server

systemctl restart wg-quick@wg0

Go back and try the Android connection on your 3/4G connection

Linux Client using Network-Manager

From command line?

As we have seen from setting up the server, and understanding that Wireguard is a peer to peer VPN, you could just setup the Client the same way as the server is, by installing Wireguard, adding an [Interface] and [Peer] section to wg0.conf and add new public and private keys.

However if you are using Gnome or KDE chances are you are using Network Manager in the Gui, it supports the Wireshark VPN and is a prettier method of getting the Client to talk.

Install Wireguard

I'm using OpenSUSE Tumbleweed

zypper install wireguard-kmp-default wireguard-tools

We need to generate public and private keys

cd /etc/wireguard wg genkey | tee privatekey | wg pubkey > publickey

Add a New connection

I'm using KDE on OpenSUSE so the manu might look a bit different for you

Open the Networks Drop down in the panel and click on the settings cog in the top right.

In the Connections window at the bottom right click the + button to add a new VPN

Choose a connection type and under VPN Connections select WireGuard

On the New Connection (Wireguard) screen complete the following

Connection name: The name must have NO spaces or special characters Private Key: This is the private key you just created on this client. Listen Port: Leave blank Autorotate peers: Untick

Click on Peers

This is where we setup the connection information for the server (peer)

The fields you need to fill in are:

Public Key: Enter the public key from your Wireguard server Allowed IPs: 0.0.0.0/0 Endpoint address: The URL or IP externally of your Wireguard server Endpoint port: In our example 45678

Click on OK

This will take you to the New Connection page again, click on the IPv4 tab

Under the IPv4 page

Method: Manual DNS Servers: the 10.10.100.1 IP of our Wireguard/Pihole server in our example Search domain: If you are using an internel DNS server, and have an internal domain, add this here.

Click on Add to add an IP Address

Add the next IP Address for this client (example 10.10.100.51) set the netmask to 255.255.255.255 as we use /32 addresses on the clients. and leave the gateway blank

Click on Save and Save again.

Note:

I found this Network manager interface to be really finicky if you format things like names wrong and it throws up errors or just doesn't save.

Head back to your Wireguard server

Edit the wg0 config file

nano /etc/wireguard/wg0.conf

Add a/another [Peer] Section (in this example i will expand on the previous addition of the Android peer

[Peer] PublicKey = PublicKeyFromAndroidPhone AllowedIPs = 10.10.100.50/32 [Peer] PublicKey = PublicKeyFromLinuxSetup= AllowedIPs = 10.10.100.51/32

Save and Exit the file

Restart the Wireguard server

systemctl restart wg-quick@wg0

And test

Troubleshooting

There is a lot to unpack here, if you've not done anything with public or private keys getting these mixed up can be a problem.

Effectivly the private key stays on the server or client and only in the local config to that device.

The public keys go in the peer sections, so the clients need the servers public key and the server needs the clients publick key in the [peer] section in the wg0.conf

The Port Forwarding needs to be done right, and might need checking on your setup, its really difficult to cover this as all routers do this different.

use the systemctl status command to check that the wg0.conf file has loaded it needs to be formatted well.

Things im looking to do

Having got myself working, this seems very automatable, i've had a play with a few of the web front ends for managing this, i think however if i get my wg0.conf under git control i can do some automation on adding peers as needed from a script.

Observations

I have shut down all my OpenVPN connections and been using wifeguard soley for a week.

It uses less battery on my Samsung Note 9 than the OpenVPN client, and i run it all day while on the office Wifi

The Linux connectivity is quciker to connect than OpenVPN and much smaller in footprint.

Pi-hole is pretty cool at ad blocking but can be annoying on some sites.

URLs