Set up a self-hosted VPN using Wireguard
VPN (Virtual Private Network) allows users to connect to a private network remotely as if the user’s computer is connected directly to a private network. This technology was originally developed to allow remote access to the company’s internal private network, because employees are not actually present at the internal network location.
VPN servers are deployed on internal network locations. This server is on a public network and can be accessed using VPN clients by employees. Authentication is required to connect to VPN Server. Communication between VPN Server and VPN Client is secured using the tunneling protocol. Note that this communication may be encrypted or not, but usually in most VPN protocols it is encrypted.
Other uses of VPN are to obtain anonymity when accessing the Internet or to avoid geographical restrictions that are imposed when accessing multiple websites. In such a case, the network the user wants to connect to is not a private network, but an Internet network.
Many VPN protocols have been developed over the years. These protocols use different tunneling protocols and encryption algorithms for communication between server and client.
One such protocol, which came into widespread use recently, is Wireguard. Wireguard is lighter, simpler and more performance than traditional VPN protocols used such as OpenVPN, IPSec. This has been implemented for Windows, Mac OS and a large number of Linux distributions. On Linux, this is implemented as a kernel module. It is available at the official Ubuntu 20.04 repository.
In this article, we will look at how to set up VPN Server and Wireguard Clients in Ubuntu 20.04.
For this article, I set up a Wireguard Server on Ubuntu 20.04 Linode and a Wireguard Client on my local machine with Ubuntu 20.04.
Wireguard package installs Server and Wireguard Client. Run the following commands on the Server machine and the Client machine.
sudo apt install wireguard
We need to generate a set of public / private key pairs to authenticate and secure Wireguard connections. This can be done using the following command:
sudo su cd /etc/wireguard umask 077 wg genkey | tee private_key | wg pubkey > public_key
Note that we are doing all configuration tasks as superuser. The reason is that access to the / etc / wireguard directory is prevented for normal users, and directory access cannot be obtained only with sudo rights only for normal users.
Next, we set the file creation mask to 077. This means that every time a new file is created in this folder with any process, the permission will automatically close with 077. Eg. if a file is created in this folder with 777 permission, it is automatically closed and the permission becomes 700. This is done so that only the file owner has all the permissions on the file, and everyone does not have permission.
In the next line, we create a public / private key pair for the server. They are stored in private_key and public_key files. To see the key, run:
cat private_key cat public_key
Copy the private key, we need it in the next step.
Never share your private key publicly!
Let’s create a configuration file for the Wireguard Server. You can choose any name for the file. We will create the wg0.conf file in this example.
[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 that we previously copied to line 5 in the code above.
We must configure Wireguards on a (virtual) subnet that is different from the server’s IP Address. 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 server’s IP address and interface, run:
The highlighted part is the IP Address
Note the server’s IP address. This is required during client configuration.
The interface used by the server, as seen in the picture above, is eth0. The interface name can differ based on the user’s network, it can be wlan0 or wlp2s0 if the user is connected to a WiFi network using a wireless card.
Replace <INTERFACE_NAME> in PostUp and PostDown with your interface; in this example it is eth0. PostUp and Post Down directives are used to determine which commands should be run when the server starts and stops respectively. In our example, we use the iptables command to set IP rules so that the server’s IP Address is shared by clients. Rules will drop after 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 use a UFW firewall on the server, we must allow UDP connection to the port for the VPN server, 51190.
ufw allow 51190/udp
Now that the configuration is complete, we can start the VPN Wireguard 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 for Wireguard is more or less the same as server configuration. We create a key for the client, and then make a configuration file.
To generate public / private key pairs for clients, run:
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
Check that they have been created, using
Copy the displayed private key as we need to add it to the configuration file for client.
Create the configuration file with any name you wish. We will be creating it with the name
wg0-client for this example.
Add the following configuration.
# IP Address and Private Key of the Client
Address = 10.20.43.2/24
PrivateKey = <Private Key of the Client>
# 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 Peers to the Server
Now we have a VPN server and an active and running client. However, a secure tunnel between the two is not created unless we establish a peer to peer connection between the server and the 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).
Append the following lines to the file.
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.
Test 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:
Next, open a web browser and open any website to check whether you can connect to the Internet from the client machine. You can also check your internet connectivity from the command line using wget.
Now, we have examined tunnel connectivity and Internet connectivity. If both of them are functioning, we now need to ensure that all internet traffic that comes to the client passes through the server.
For this, we only need to check the client’s IP Address as seen by the Internet. One way to do this is to visit whatsmyip.org. Or else from the command line, we can request another similar service called IP info, using Curl.
Run the following on the client machine
Yes This is the Linode public IP address where the VPN server is hosted. This is how anonymity is achieved by using VPN, because across the Internet now VPN server IPs are seen and not your computer.
Ease of management is one of the most important advantages of Wireguard compared to traditional VPN software such as OpenVPN, which requires higher network management and routing knowledge. However, there is a lack of detailed official documentation for Wireguards that can cause problems if your Wireguard settings make a mistake or do not function as expected.
However, 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 protocol and technology it uses, you can visit the official website.