Create your own VPN with Wireguard

In this post I’m going to describe succinctly how to configure your own VPN on a remote VPS with Wireguard. Of course you can host your own VPN server from home, if you’re not behind a NAT and have a public IP address, and you’ve enabled port forwarding on your router, but in this case you also have to have a DDNS service to reach your network from outside. But in this example I’m going to setup Wireguard on a remote VPS with a fix dedicated IP address.

Why would you even need your own VPN?

When you enable your VPN interface you create a secure tunnel from your device to your VPN server, and the traffic going through are going to be encrypted. This can be useful if you have to connect to a public unprotected Wi-Fi access point, or a network you don’t necessarily trust. According the articles I’ve read online Wireguard uses a lightweight, but strong encryption which is usually faster compared to OpenVPN.
For me the most useful use case is that I can access my home network securely from outside: I can check the status of my torrents, read data from my sensors, turn on/off my smart devices or just watch some TV shows on my home plex server.
With using a VPN service you can also access country-restricted contents (e.g. restricted TV shows on Netflix or HBO which are not available in your country), or you can just access contents which are blocked by your ISP.
It’s a good idea to have your own VPN if are really concerned about privacy and you don’t trust other VPN providers.

1) Install Wireguard

I’ve installed Wireguard on the latest Debian distro, with the following command:

sudo apt install wireguard

2) Generate private and public key pairs

Generate private and public key pairs for the server: First we create a private and a corresponding public key with the appropriate permissions with the following commands and place them in the /etc/wireguard folder:

wg genkey | sudo tee /etc/wireguard/private.key
sudo chmod go= /etc/wireguard/private.key
sudo cat /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key

Later we’ll need to do same process for the clients as well.

3) Enable traffic forwarding

To enable IP forwarding we’ll need to open and edit the following file with sudo privileges:

sudo nano /etc/sysctl.conf

Uncomment the following lines (if you’re not intent to use IPv6 just leave it as it is):

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

To load and verify the new settings from the configuration file run the following command, you should see in the output the lines you’ve changed:

sudo sysctl -p

4) Create wg0.conf

To configure Wireguard we need to create wg0.conf file, with the following content:

sudo nano /etc/wireguard/wg0.conf
[Interface]
Address = 10.1.0.1/24
Address = fd64:7e8a:af9f::1/64
SaveConfig = true
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostUp = ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -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
PostDown = ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
ListenPort = 51820
PrivateKey = <place your sever’s private key here>

When we turn on the wg0 interface the PostUp firewall rules are going to be applied: with the first rule we accept packages of the wg0 interface on the FORWARD chain, with the second rule we can accomplish the NAT, basically we switch our private IP address to the address of the eth0 interface. I’ve written a short post about NAT, you can check it here. When we turn off the interface we delete these rules. Again if you don’t want to use IPv6 just delete the rules starting with ‘ip6tables’. Before writing these rules make sure your interface is called ‘eth0’ by typing

ip route

The first line of the routing table should look something like this:

 default via <public IP address> dev <interface name> ...

If the name of the interface is different simply change eth0 in wg0.conf.
To the PrivateKey line copy the private key you’ve generated before, you can display the key with

sudo cat /etc/wireguard/private.key

With the ‘Address’ lines we assign a private IPv4 and – if you need – an IPv6 address to the interface, feel free to choose whatever you want.
There is a great article on DigitalOcean how you should generate IPv6 address from the fd00::/8 block for Wireguard.

5) Open port for Wireguard

By default Wireguard uses UDP port 51820, it can be changed of course in the configuration file created above. We’re going to need to enable this port with ufw:

   sudo ufw allow 51820/udp
   sudo ufw reload

6) Client configuration

The configuration of the clients is very similar to the servers configuration. We need to create a private and public key pair the same way as described above, then create wg0.conf which will be a bit different this time:

[Interface]
Privatekey = <the client’s private key>
Address = 10.1.0.2/24, fd64:7e8a:af9f::2/64

[Peer]
Publickey = <the server’s public key>
Endpoint = <server’s public IP address>:51820
AllowedIPs = 10.1.0.0/24, fd64:7e8a:af9f::/64

The AllowedIPs line can be a bit confusing, it means that my client will only send packets through the VPN tunnel if the destination address is in the 10.1.0.0/24 subnet (similarly with IPv6): it is useful if you only want to access your home network via VPN. If you want to send every data through the VPN tunnel (basically you want to pretend to be somewhere else), then simply replace this line: AllowedIPs = 0.0.0.0/0, ::/0

7) Server side client configuration

We are not done with the client configuration yet. Open the wg0.conf on the server and paste the following after the [Interface] section:

[Peer]
PublicKey = <your client’s public key>
AllowedIPs = 10.1.0.2/32, fd64:7e8a:af9f::2/128

I recommend using the /32 mask here, since I don’t use to change my IP addresses on the client side.

8) Turn on wg0 and test the connection

When we are finished with the configuration on both the client and the server side, we can turn on the wg0 interface with the following command:

    sudo wg-quick up wg0

Run the same command on the client side as well. If we’re sending every data through our VPN tunnel (with the AllowedIPs = 0.0.0.0/0, ::/0 section), we can verify that our public IP address has been changed, for example on whoer.com. The IP displayed here should be the same as your server’s public IP address. From now on you should be able to ping your server’s wg0 interface (10.1.0.1 in this case), and if you have multiple clients (you can add as many as you want), you can access them as well.
Remember if you want to change wg0.conf, first you have to turn down the interface with the following command:

sudo wg-qucik down wg0

9) Configure an Android phone with QR code

You probably want to access your VPN with your smartphone as well. In this section I’m going to describe how to do that simply by scanning a QR code, instead of typing your configuration manually which can be pretty arduous and time consuming.
I’m going to create the configuration file of the Wireguard interface in a separate folder (with the private and public key generation as well) with the following commands:

sudo mkdir /etc/wireguard/android_client
wg genkey | sudo tee /etc/wireguard/android_client/android_private.key | wg pubkey | sudo tee /etc/wireguard/android_client/android_public.key
sudo nano /etc/wireguard/android_client/android.conf

Simply edit the andoid.conf according to the example I’ve discribed above:

[Interface]
PrivateKey = <your android client’s private key>
Address = 10.1.0.4/24

[Peer]
Publickey = <your server’s public key>
Endpoint = <your servers public IP address>:51820
AllowedIPs = 0.0.0.0/0

Edit wg0.conf as the following, insert a new peer to the end of the file:

[Peer]
PublicKey = <your android client’s public key>
AllowedIPs = 10.1.0.4/32

We are going to need qrencode (sudo apt install qrencode) to genere a .png file from the android.conf file:

sudo cat /etc/wireguard/android_client/android.conf | qrencode -o wg_android_conf.png

The wg_android_conf.png file is placed wherever you’ve issued the command, you can copy it to your local machine with scp or by using ftp for example. Open the image and scan it with your android device.