A VPN (Virtual Private Network) allows the user to connect to a private network remotely as if the user’s computer was directly connected to the private network. The technology was initially developed in order to allow remote access to a company’s internal private network, for employees not actually present in the location of the internal network.

A VPN Server is deployed at the location of the internal network. This server is on the public network and can be accessed using a VPN client by the employee. Authentication is needed to connect to the VPN Server. The communication between the VPN Server and VPN Client is secured using a tunnelling protocol. Note that this communication may or may not be encrypted, but usually in most VPN protocols it is encrypted.

Another use of VPN is to gain anonymity when accessing the Internet or to circumvent geographical restrictions imposed while accessing some websites. In such cases, the network the user wants to connect to is not a private network, but instead, it is the Internet.

Many VPN protocols have been developed over the years. These protocols make use of different tunnelling protocols and encryption algorithms for communication between the server and the client.

One such protocol, which is gaining wide use recently, is Wireguard. Wireguard is lighter, simpler and more performant than well known traditionally used VPN protocols such as OpenVPN, IPSec. It is already implemented for Windows, Mac OS and a large of number of Linux distributions. In Linux, it is implemented as a kernel module. It is available in official repositories of Ubuntu 20.04.

In this article, we will see how to set up a Wireguard VPN Server and Client in Ubuntu 20.04.

Installation

For this article, I am setting up a Wireguard Server on a Ubuntu 20.04 Linode and Wireguard Client on my local machine with Ubuntu 20.04.

The package wireguard installs both Wireguard Server and Client. Run the following command on both the Server machine and Client machine.

sudo apt install wireguard

Server Configuration

Security Keys

We need to generate a set of public/private key pairs in order to authenticate and secure the Wireguard connection. This can be done using the following commands:

sudo su
cd /etc/wireguard
umask 077
wg genkey | tee private_key | wg pubkey > public_key

Note that we are doing all the configuration tasks as a superuser. The reason is that access to the directory /etc/wireguard is prevented for normal users, and directory access cannot be gained with just sudo privileges for a normal user.

Next, we set the file creation mask to 077. This means that whenever a new file is created in this folder by any process, its permissions will be automatically masked with 077. Eg. if a file is created in this folder with permissions 777, it is automatically masked and permissions effectively become 700. This is done so that only the owner of the file has all permissions on the file, and everyone else has no permissions.

On the next line, we generate the public/private key pair for the server. They are saved in files private_key and public_key. To view the keys, run:

cat private_key
cat public_key

Copy the private key, we need it in the next step.

Note: Never share your private key publicly!

Configuration File

Let’s create a configuration file for the Wireguard Server. You can choose any name for the file. We will create a file wg0.conf in this example.

vim wg0.conf

Add the following to the file.

[Interface]
Address = 10.20.43.1/24
SaveConfig = true
ListenPort = 51190
PrivateKey = <Server Private Key previously generated>

PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o <INTERFACE_NAME> -j MASQUERADE; 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; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -o <INTERFACE_NAME> -j MASQUERADE

Paste the Private Key which we previously copied into line 5 in the code above.

We have to configure Wireguard on a different (virtual) subnet than the IP Address of the server. Here, I have used 10.20.43.1 for the server and will use 10.20.43.2 for the client. Any subnet can be used here. To get the IP Address of the server and the interface, run:

ifconfig
The highlighted part is the IP Address

Note the IP Address of the server. This is required during client configuration.

The interface used by the server, as seen in the image above, is eth0. The interface name can differ based on user’s network, it can be wlan0 or wlp2s0 in case the user is connected to a WiFi network using a wireless card.

Replace the <INTERFACE_NAME> in PostUp and PostDown with your interface; in this example it is eth0. PostUp and PostDown directives are used to specify which commands should be run when the server starts and stops respectively. In our example, we use the iptables command to set IP rules such that the server’s IP Address is shared by the clients. The rules will drop once the server stops.

Save and exit the file. When using vim, press Esc, then type :wq and press Enter to save and exit.

If you are using a ufw firewall on the server, we need to allow UDP connections to the port for VPN server, 51190.

ufw allow 51190/udp

Starting the Service

Now as the configuration is done, we can start the Wireguard VPN service.

To enable the service to start at boot time, run:

systemctl enable wg-quick@wg0

Note that here wg0 is the name of the configuration file.

To start the service, run:

service wg-quick@wg0 start

Verify that the service has started successfully:

service wg-quick@wg0 status

Verify that the interface we created in the configuration file has started, using the IP command.

ip a show wg0

The Wireguard VPN Server is now set up and running. Let’s configure the client now.

Client Configuration

Client Configuration for Wireguard is more or less the same as a server configuration. We generate the keys for the client, and then create a configuration file.

Security Keys

To generate the public/private key pair for the client, run:

sudo su
cd /etc/wireguard
umask 077
wg genkey | tee client_private_key | wg pubkey > client_public_key

The public and private keys for the client are now generated respectively in files client_private_key and client_public_key.

Check that they have been created, using cat command.

cat client_private_key
cat client_public_key

Copy the displayed private key as we need to add it to the configuration file for client.

Configuration File

Create the configuration file with any name you wish. We will be creating it with the name wg0-client for this example.

vim wg0-client.conf

Add the following configuration.

[Interface]
# IP Address and Private Key of the Client
Address = 10.20.43.2/24
PrivateKey = <Private Key of the Client>

[Peer]
# Public key, IP Address and Port of the Server
PublicKey = <Public Key of the Server, generated in previous steps>
Endpoint = <IP Address of the Server>:51190
AllowedIPs = 0.0.0.0/0, ::/0

Enter the subnet address for the client. As described previously, we use 10.20.43.2 for the client in this example.

Add the client private key generated in previous step into line 4 in the configuration code above.

Under ‘Peer’, we add information about the Wireguard VPN server we want to connect to.

Enter the public key of the server. Enter the server’s IP Address, which we previously noted, and port in the given format against Endpoint. This is the port that we specified in the server configuration file and on which VPN service on the server started.

Allowed IPs should be entered as given (0.0.0.0/0) so that any request on a dynamic public IP used by the client will always forward to VPN server.

Save and exit the file. When using vim, press Esc, then type :wq and press Enter to save and exit.

Enable the client service to run with every boot, and start it.

systemctl enable wg-quick@wg-client
service wg-quick@wg-client start

Verify if the service has started.

service wg-quick@wg-client status

Adding Peer to the Server

Now we have the VPN server and client up and running. However, a secure tunnel between the two is not established unless we establish a peer to peer connection between the server and client.

Go back to the server. First, stop the VPN service.

service wg-quick@wg0 stop

Next, open the configuration file to add configuration for the peer (client).

vim /etc/wireguard/wg0.conf

Append the following lines to the file.

[Peer]
PublicKey = <Public Key of Client>
AllowedIPs = 10.20.43.2/32

Now, start the VPN service again.

service wg-quick@wg0 start

That’s it! This is all the configuration needed for Wireguard VPN client and server setup. Let’s now test our VPN.

Testing the VPN

First, let’s do a simple ping from the client to the server, to make sure the VPN tunnel communication works. Run the following on the client:

ping 10.20.43.1

Next, open a web browser and open any website to check if you are able to connect to the Internet from the client machine. You can also check your internet connectivity from the command line using wget.

wget <some_sample_website>

Now, we have checked the tunnel connectivity and the Internet connectivity. If both are working, we now need to make sure that all internet traffic coming to client is passing through the server.

For this, we simply need to check the IP Address of the client as seen by the Internet. One way to do it is to go to whatsmyip.org. Or else from the command line, we can query another similar service called IP info, using Curl.

Run the following on the client machine

curl https://ipinfo.io/ip

Yes. It is the public IP Address of the Linode where the VPN server is hosted. This is how anonymity is achieved using VPN, since all over the Internet now the IP of the VPN server is seen and not of your computer.

Conclusion

The ease of setup is one of the most important advantages of Wireguard over traditional VPN software like OpenVPN, which needs a higher level of networking and routing knowledge to set up. However, there is a lack of detailed official documentation for Wireguard which might cause problems if your Wireguard setup is throwing errors or not working as expected.

Nevertheless, Wireguard is an excellent choice if you want a self hosted VPN for secure communication over the Internet. To learn more about Wireguard and the protocols and technologies it uses, you can check out the official site.