VPNs are extremely useful. They allow you to create a secure tunnel between two systems on the Internet. A properly configured Debian Wireguard configuration routes data to networks which would otherwise be inaccessible.
In this tutorial, we’re going to set up one such technology. Wireguard is a relatively new entry to this field. Its first stable release was in March of 2020. Compared to other solutions, this isn’t very long. With that said, it has numerous features which make it a very attractive alternative to its competition.
Wireguard is a simpler alternative to other VPNs. Its modern architecture makes it small, lightweight and fast.
Wireguard vs OpenVPN
Battle tested for over 20 years, OpenVPN is an industry standard. Comparatively, Wireguard is a newcomer in this field. However, despite its relative infancy, it is very popular for several reasons.
The first is its much smaller attack surface. Wireguard’s entire implementation is ~5000 lines of code. Additionally, it trades support for the numerous different encryption algorithms offered in other solutions for only ChaCha20. While a much smaller codebase and lock-in for one specific encryption algorithm may sound like a bad thing, the reality is much different.
The result of these opinionated changes is a client/server which both only contain ~5,000 lines of code. This simplifies outside auditing. It also prevents the use of insecure encryption which would compromise the security of the overall system. Wireguard eliminates the complex public key infrastructure of OpenVPN in favor of a much simpler and easy to deploy shared key setup. Finally, the small code base coupled with Wireguard’s kernel module results in an extremely fast VPN. Often, it is several oders of magnitude speedier than other solutions. Its extreme speed means that it is possible to completely saturate much larger links than would be possible in traditional solutions.
However, Wireguard does come with a few sharp edges. As a much newer solution, it lacks the extensive testing which OpenVPN has received throughout its history. Though it has a much smaller codebase, its lack of widespread adoption thus far means that it is possible for critical security bugs to work their way into the code. An additional area severely lacking in Wireguard is its debugging capabilities. The kernel loads both client and sever as modules. Other than very limited output in /var/log/messages, it does not provide an easy method to determine if an error occurred during handshaking.
Due to the lack of sophisticated logging in Wireguard, we’re going to rely heavily on tcpdump to fix any problems with our tunnel. Using tcpdump, we can trace the path of data flow and narrow down any areas where breaks occur.
If you want to go a more traditional route, I’ve also written about configuring OpenVPN on Linux.
Debian Wireguard Configuration
Key Generation
We’ll be using Debian Linux 11 on both systems. First, let’s go ahead and install Wireguard on the server itself.
sudo apt install wireguard
The next step in configuring Wireguard is to generate the cryptographic keys used by both the client and server. For the sake of simplicity, we will generate both keypairs on the server. Run the following commands:
sudo su
cd /etc/wireguard
mkdir -p keys/{server,client}
# Server Keys
cd keys/server
wg genkey | tee privatekey | wg pubkey > publickey
# Client Keys
cd ../client
wg genkey | tee privatekey | wg pubkey > publickey
cd ../..
Code language: PHP (php)
In a production environment, it’s preferable to generate the key pairs separately. The server does not need the private keys of its clients. Preventing it from coming into contact with them helps keep the tunnel secure.
After this is done, we have all the key pairs we need. The client is unable to connect until it has its cryptographic keys. The details of how to get them there are left up to you. An easy solution is to use the scp command to send them over the network. In a worst case scenario, manually type the keys into the client’s configuration file. However, extra care must be taken to prevent typos. As stated earlier, Wireguard does not provide detailed debugging information. It will claim it is connected, even if the handshake fails due to mistyped keys. This is very frustrating to debug.
Wireguard Server Configuration
Now that the keys are in place, we need to cinfifure the server to use them. On the Wireguard server, open /etc/wireguard/wg0.conf and type the following:
[Interface]
Address = 10.1.0.1/24
PrivateKey = xxxxxxxxxxxxxxxxxxxxxxxx=
[Peer]
PublicKey = xxxxxxxxxxxxxxxxxxxxxxxx=
AllowedIPs = 10.1.0.2/24
Code language: PHP (php)
Replace both the PrivateKey and PublicKey sections with the keys generated in keys/server. Once this is done, we’re ready to start the server. The Wireguard package automatically creates a SystemD compatible service ready to be deployed:
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0
Code language: CSS (css)
Our server is now running. Run the following command to check its state:
sudo systemctl status wg-quick@wg0
Code language: CSS (css)
Note that everything after the ‘@’ sign references the configuration file. So, rather than name the configuration file wg0.conf, you could name it my-laptop.conf and replace wg0 in the aforementioned commands.
Wireguard Client Configuration
Now that the server is fully configured, it’s time to do the same for the client. There’s very few differences between the server and client, but they are crucial to making sure the tunnel functions correctly. On the client, we once again need to install Wireguard:
sudo apt install wireguard
Now, open /etc/wireguard/client1.conf and enter the following:
[Interface]
Address = 10.1.0.2/24
PrivateKey = xxxxxxxxxxxxxxxxxxxxxxxx=
[Peer]
PublicKey = xxxxxxxxxxxxxxxxxxxxxxxx=
AllowedIPs = 10.1.0.1/24
Endpoint = <Your Server's IP>
Code language: HTML, XML (xml)
Save the file. Then, start the service by running the following commands:
sudo systemctl enable wg-quick@client1
sudo systemctl start wg-quick@client1
Code language: CSS (css)
Your tunnel should be working at this point. Run the following command on the client to ping the server:
ping 10.0.1.1
Code language: CSS (css)
If you got a response, you’re good to go! If not, follow the checklist below.
Verifying Wireguard Functionality
So, your VPN tunnel isn’t working. The first step in debugging this process is to ensure that all routers and firewalls between your client and server are configured correctly. Run the following command on the server:
tcpdump udp port 51195
Now run this command on the client:
systemctl restart wg-quick@wg0
Code language: CSS (css)
Check the server again. If packets came through, the issue is most likely related to either your VPN tunnel’s IP network or a typo in your keys. First make sure that the IP range used internally in the tunnel does not conflict with a network connected to either of the two devices. Also, make sure that you entered your keys correctly on both the client and server.
Be First to Comment