Getting Started Building Your Own Wireguard VPN Server

This tutorial was created and tested using Ubuntu 20.10 on Digital Ocean. It will likely work fine with other distributions but some modifications may be needed.

Server Side Setup

Create new droplet using Ubuntu 20.10 and choose the region you prefer.

Log into server and make sure system is up to date

apt-get update && apt-get upgrade
Reboot if there are update that require it

Optional: customize the shell settings
git clone https://github.com/flipsidecreations/dotfiles.git
cd /root/dotfiles/
Run the install.sh

Next we need to enable IP Forwarding. IP forwarding is the ability for an operating system to accept incoming network packets on one interface, recognize that it is not meant for the system itself, but that it should be passed on to another network. Edit the file /etc/sysctl.conf and change and uncomment to the line that says net.ipv4.ip_forward=1

Now reboot or run sysctl -p to activate the changes.

Install wireguard
apt-get install wireguard

Go to to the Wireguard config cd /etc/wiregaurd and then run the following command to generate the public and private keys for the server.
umask 077; wg genkey | tee privatekey | wg pubkey > publickey

The run cat privatekey and copy it so we can put it in to the server config file.

Create the /etc/wireguard/wg0.conf
vim /etc/wireguard/wg0.conf

This will get the basic server side setup and we will be coming back to this file to add the peers later.

[Interface]
PrivateKey = <Your Private Key Goes Here>
Address = 192.168.69.1/24
ListenPort = 51820
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

To test that the server works run wg-quick up wg0 to bring up the interface. Running wg-quick down will bring the interface down.

If you want the wg0 interface to be active on boot you need to run
systemctl enable wg-quick@wg0

Then you can use to systemctl start wg-quick@wg0 start the server, systemctl stop wg-quick@wg0 stop the server and systemctl status wg-quick@wg0 to check the status.

Linux Client Side Setup
Install wireguard
apt-get install wireguard

Go to to the Wireguard config cd /etc/wiregaurd and then run the following command to generate the public and private keys for the server.
umask 077; wg genkey | tee privatekey | wg pubkey > publickey

The run cat privatekey and copy it so we can put it in to the server config file.

Create the /etc/wireguard/youtube.conf
vim /etc/wireguard/youtube.conf

[Interface]
PrivateKey = <Your Private Key Goes Here>
Address=192.168.69.2/24

Run wg-quick up youtubevpn to make sure the system comes up and run wg-quick down youtubevpn to take down the interface.

Getting the Wireguard Systems Talking

On the Ubuntu Digital Ocean server edit /etc/wireguard/wg0.confand add the peer information

[Interface]
 Address = 192.168.69.1/24
 PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
 PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
 ListenPort = 51820
 PrivateKey = <This Ubuntu Servers Private Key>

[Peer]
# Test Debian Client
 PublicKey=<The Public Key of the Debian Client>
 AllowedIPs=192.168.69.2
 PersistentKeepalive=25

On the Debian linux client edit /etc/wireguard/youtube.confand add the peer information

[Interface]
PrivateKey = <This Debian Client Private Key Goes Here>
 Address=192.168.69.2/24

[Peer]
# Ubuntu Digital Ocean Server
 PublicKey=<Public Key From Ubuntu Digital Ocean Server>
 Endpoint=<Public IP of Ubuntu Digital Ocean Server>:51820
 AllowedIPs = 0.0.0.0/0 # Forward all traffic to server

Once both sides have been complete and Wireguard restarted on both side the system should be able to communicate. You can first test from the Debian Client by running ping 192.168.69.1 to make sure the tunnels are working and then try getting out the internet by running ping 1.1.1.1 on the Debian and confirm response.

Turning on the UFW firewall on the server
It is easy to enable the UFW firewall there are a few ports we need to open first, port 22 TCP for ssh management and 51820 UDP for Wireguard. To do this simply:

ufw allow 22/tcp
ufw allow 51820/udp
ufw enable

Add other or change ports if needed for your configuration.

As mentioned in the video, the clients on the same subnet can talk to each other. I was wondering if this traffic passes through the server? Or a direct connection is established between the clients? Like ZeroTier.

I am trying to see if Wireguard would be a better alternative over ZeroTier.

The inter communication of the clients is occurring in the server. For the clients to talk direct separate tunnels between them would need to be made.

1 Like

I have an issue where I can ONLY ping the Wireguard server and nothing else on the network where the server resides :frowning:

So Can only talk to the server and nothing else on the network :frowning:
Any clues?
Thanks

Figured it…

For some reason the line for forwarding in /etc/sysctl.conf did not save when I removed the #.

Fixed :slight_smile:

1 Like

Hi Lawrence,

Hope you are keeping well :+1:

I have set up the WireGuard server and all seems well apart from VoIP when using an iPhone and the WireGuard client.

Any ideas? It refuses to register with multiple VoIP providers when connected to the WireGuard VPN.

Does it work when you connect another devices that is not an iPhone?

Same fate on Windows 10 using Zoiper.

I’m going to spin up a new VM at a different host to see if it makes any difference.

Looks like its the host and the routing, tried via AWS and the VoIP connections work fine using WireGuard :slightly_smiling_face: :+1:

1 Like

Installed and configured this on my Ubuntu 18.04 server and connected my android using the WireGuard app. Worked flawlessly and connected on the first hit. Maintains connection bouncing on and off of wifi.

It just… Works.

Follow up for the windows client… it just doesn’t work. I end up with a network interface with no DNS or gateway and Windows doesn’t work well with that. I was able to add a DNS entry but the interface never gets a gateway so its just “no internet access”.
I pulled a stupid, i block all DNS traffic not going through my router.

1 Like

I thought there was a licensing dispute that prevented this from being incorporated into BSD kernel space rather than user space? Perhaps I’m wrong on this account. Would be nice if this was integrated into pfSense.

I’m having trouble when I get to the step for testing the wireguard interface with wg-quick up wg0. I get the following error.

name:/etc/wireguard# wg-quick up wg0
[#] ip link add wg0 type wireguard
RTNETLINK answers: Operation not supported
Unable to access interface: Protocol not supported
[#] ip link delete dev wg0
Cannot find device "wg0"
name:/etc/wireguard#

A quick google of this error brings up a few results, mainly that you need to have the kernel headers installed. Though, it would appear I have them already.

name:~$ uname -r
5.4.0
name:/etc/wireguard# ls /usr/src/linux-headers-5.4.0-54
Documentation  arch    drivers  ipc     net       sound   virt
Kbuild         block   fs       kernel  samples   tools
Kconfig        certs   include  lib     scripts   ubuntu
Makefile       crypto  init     mm      security  usr
name:/etc/wireguard# ls /usr/src/
linux-headers-5.4.0-54  linux-headers-5.4.0-54-generic  wireguard-1.0.20200611
name:/etc/wireguard#

Unless its the ‘wireguard-1.0.20200611’ part that is the issue? Not sure how I’d go about fixing that.

My other thought was perhaps my wireguard wg0.conf is bad. I’m running on a VPS, and here is the default network interface setup in /etc/network/interfaces.

name:/etc/wireguard# cat /etc/network/interfaces
# This configuration file is auto-generated.
# WARNING: Do not edit this file, otherwise your changes will be lost.
# Please edit template /etc/network/interfaces.template instead.
auto lo
iface lo inet loopback
# Auto generated venet0 interfaces
auto venet0
iface venet0 inet static
        address 127.0.0.1
        netmask 255.255.255.255
        broadcast 0.0.0.0
        up route add default dev venet0
iface venet0 inet6 static
        address ::2
        netmask 128
        up ip -6 r a default dev venet0
        up ip addr add [IPV6 ADDRESS] dev venet0
auto venet0:0
iface venet0:0 inet static
        address [IPV4 ADDRESS]
        netmask 255.255.255.255
name:/etc/wireguard#

I think there are some programs out there that don’t like the interface sub-designations (venet0:0), but I am assuming wireguard can handle that just fine. Here is where I plug that into wg0.conf.

name:/etc/wireguard# cat wg0.conf
[Interface]
PrivateKey = [PRIVATE KEY HERE]
Address = 192.168.69.1/24
ListenPort = 51820
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o venet0:0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o venet0:0 -j MASQUERADE
name:/etc/wireguard#

Any suggestions?

The only differnce i notice is in the PostUp and PostDown. I used the following:

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

Change the ens3 to your wg0 in both lines.

Have been using wireguard for a while now with pia and pivpn and have only ever had good experiences with it, lower cpu usage on my pi and increased battery life on my devices. The only problem i have had is with pia and it not connecting at my school even when openvpn does but that is the only problem i have ever had with it do far.

I did all my testing with newer kernel versions and It appears that you are using the older kernel 5.4.0 and wireguard was added to to 5.6.x. I think you can load wireguard-dkms and that should allow it to work in the your older version.

Would there need to an adjustment to PostUp and PostDown values if Wireguard is listening on one interface and forwarding traffic through another?

The very fact the Wireguard requires manual IP address assignments rather than a build in DHCP server is really annoying. This is 2020.

You are misunderstanding why it was written the way it was. They wrote the protocol and relied on the existing IP stack in Linux and other operating systems so the system could me implemented in more diverse ways.