Having got to grip with the tools and the command line last month this month I've been getting my daily drivers and applications working which means getting the Applications I need to use and connectivity back home working.
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.
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.
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)
All commands run as root (sudo -s)
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
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)
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
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)
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.
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.
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
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: Stopped WireGuard via wg-quick(8) for wg0.
Feb 19 20:09:09 external systemd: Starting WireGuard via wg-quick(8) for wg0...
Feb 19 20:09:09 external wg-quick: [#] ip link add wg0 type wireguard
Feb 19 20:09:09 external wg-quick: [#] wg setconf wg0 /dev/fd/63
Feb 19 20:09:09 external wg-quick: [#] ip -4 address add 10.10.100.1/24 dev wg0
Feb 19 20:09:09 external wg-quick: [#] ip link set mtu 1420 up dev wg0
Feb 19 20:09:09 external wg-quick: [#] iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FO
Feb 19 20:09:09 external systemd: 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.
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
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.
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
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
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
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:
Type the following command on Pi-hole to see if DNS is working or not:
host cyberciti.biz 10.10.100.1
Using domain server:
Aliases: cyberciti.biz has address 188.8.131.52
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 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.
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
Install and open it.
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
Set Allowed IPs to 0.0.0.0/0
Enter the ip and port (sorry my screengrab forgot to add the port) as
Click on the save icon
Add Peer information to wgo.conf on server
Back on the Wireguard server open the wg0.conf file
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.
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.
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.
Update Server Peer
Head back to your Wireguard server
Edit the wg0 config file
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
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.
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.