Virtual Private Network (VPN) software technology was adopted years ago by enterprises for securely establishing office-to-office connections and for allowing traveling employees to access in-house applications. Since then, VPN has proved to be a useful technology for individuals who want to protect their privacy or access geographically-restricted services from other regions. Setting up a self-hosted VPN service has been discouragingly difficult so far, but now, Wireguard VPN is here.
Wireguard has been in development for a few years. The important milestone, version 1.0, was achieved in March 2020. At the same time, it was included in Linux kernel version 5.6. Since not many (server) computers in production use run the latest kernel, Wireguard must be installed and configured on those machines for secure networking. In this step-by-step guide, we install Wireguard on Debian Linux computers that take the roles of a VPN server and a client.
Installing Wireguard on Debian
Note: Before installing Wireguard from the apt package management system, save your iptables settings (for instance, you can enter command: iptables-save > firewall.rules). The early version of the installation package wiped out existing iptables settings, and replaced them with its own firewall rules.
To start installation, open your Terminal and type this into the command line:
apt-get install wireguard-tools
apt-get install wireguard-dkms
apt-get install wireguard
You may also have to install:
apt-get install dkms
After running these commands, test that everything required for Wireguard was installed:
If the command doesn’t output anything, all the needed modules should be there.
Configuring Wireguard server
Exactly the same Wireguard software is installed on Linux servers and clients, because each computer’s VPN configuration specifies its role. Wireguard apps are available for Windows, Android, Apple MacOS and for iOS as well.
Let’s start the configuration work by creating a directory for the Wireguard settings:
chmod 700 /etc/wireguard
Create private and public keys that are needed to establish secure tunnels between the server and its clients:
cd /etc/wireguard wg genkey | tee privatekey | wg pubkey > publickey
In an editor app, create file wg0.conf into the /etc/wireguard directory, and insert the following lines in there:
The interface address can be any IP from the private IP address space, as long as you use the same subnet for the clients as well.
Copy and paste the value to the Privatekey field from /etc/wireguard/privatekey file.
Listenport can be any free port, 51820 is the Wireguard default.
Configuring Wireguard VPN client
If you are going to configure one or more VPN clients, now is the perfect time to ensure that you can easily copy keys from one device to another. I used Nextcloud as a temporary storage for transferring the keys from one device to another, but Evernote, Dropbox, email, or whatever service you trust and feel comfortable to use is fine.
Install the same software packages on the Linux client as you did on the server. Test with modprobe command that all required modules are installed.
Generate the private and public keys into the /etc/wireguard directory, just like you did on the server.
Create the following wg0.conf file into the client’s /etc/wireguard directory in an editor program.
[Peer] PublicKey= Endpoint= . . . :51820 AllowedIPs=0.0.0.0/0 #if this computer is behind a NAT, add line: PersistentKeepAlive = 25
Publickey is the server‘s public key (/etc/wireguard/publickey) that you have to copy from the server and paste here.
Endpoint is the server’s public IP address, followed by the server’s Wireguard port.
If AllowedIPs is all zeros, all this computer’s network traffic is routed via the VPN when the tunnel is switched on. It is possible to select which traffic is routed via the VPN by modifying the value of this field.
To complete the client configuration, you also have to edit wg0.conf file on the server. Insert the following lines into the end of the file:
[Peer] #home laptop PublicKey= AllowedIPs=192.168.2.2/32
Publickey: You have to paste the public key of the client computer here.
AllowedIPs specifies the IP address of the client inside the VPN tunnel.
Now, you can test the shiny new VPN if it securely connects your computers. Enter the following command both on the server and on the client:
wg-quick up wg0
On the client, test if it can talk to the server:
(or ping 192.168.2.2, if you are tapping the server keyboard)
If you get a response, congratulations, you have a secure tunnel between those two computers.
This is, however, not the end of the story. You probably want to get out to the public internet through the VPN. It requires a little bit of more work: routing traffic in to the tunnel from the internet and out from the tunnel.
Routing Wireguard VPN network traffic to the internet
Since this step involves the default Linux firewall iptables, there are many ways to do it, and the correct settings also depend on the rules already saved in server’s iptables. Here are the settings that have worked for all my Debian servers.
Enter the following commands:
iptables -A INPUT -p udp -m udp --dport 51820 -j ACCEPT
iptables -A FORWARD -i wg0 -j ACCEPT
iptables -A FORWARD -o wg0 -j ACCEPT
Try pinging, for instance, bbc.com or cnn.com. If you don’t get a response, the first place to troubleshoot is operating system’s forwarding settings.
Enter the following command to view the current network settings
The command displays a long list of items, but look for the value of net.ipv4.ip_forward
If it is 0, forwarding to external addresses is disabled. Allow forwarding with the command:
sysctl -w net.ipv4.ip_forward=1
Ping to an external address to verify. If it works, you can make the setting permanent by creating file /etc/sysctl.d/local.conf and inserting this line into the file:
net.ipv4.ip_forward = 1
(the advice where to save conf changes is from the Debian readme file located in sysctl.d directory).
When you are trying to start Wireguard using the wg-quick command, but it throws error messages, here are solutions to a couple of common problems.
/usr/bin/wg-quick: line 32: resolvconf: command not found
The solution is to link to a file in another location:
ln -s /usr/bin/resolvectl /usr/local/bin/resolvconf
Another problem when starting wg-quick may be:
Failed to set DNS configuration: Unit dbus-org.freedesktop.resolve1.service not found
The easiest way to solve this is to start systemd-resolved service, but there are other solutions if you want to use another service. For systemd- resolved, the command is:
systemctl start systemd-resolved