Wireguard Basic Setup

Wireguard is a very lightweight and relatively new secure network tunnel, operating at Layer3 and is actually implemented as a kernel virtual network interface for Linux. One of the strong points of Wireguard besides being very lightweight is that it is also very straightforward and easy to setup. Being lightweight is not necessarily good because of resource consumption but because it is most probably more secure than alternatives such as OpenVPN. Less code, less attack surface but, as far as I know it didn't go through complex security audits and it didn't have yet enough time to proove how reliable it is if we compare it to OpenVPN. I personally recommend Wireguard over OpenVPN if you don't want to consume too much of your time to setup a VPN but at the same time want a secure and reliable one.

I will setup Wireguard for one of the most common scenarios, one where client is behind a NAT and server is listening on public IP address

In my case server is a Debian VPS and client is my own machine - Artix Linux

Generate key pairs

Before we create configurations we need some keys to start with, and you can generate private key and a public one using the private with one line:

wg genkey | tee privatekey | wg pubkey > publickey

Just in case you wonder exactly how this works I'll break it down:

Good OPSEC implies to generate these keys as root, put them in a folder where owners are root:root and folder permissions must be 700. Permissions of both keys must be 400

Create Wireguard Configurations

We can now create server configuration, so open a shell on server machine and switch to root user. Now create a file called for example wg0.conf in /etc/wireguard containing the following:

[Interface] Address = 10.1.10.1/24 PrivateKey = YOUR_SERVER_PRIVATE_KEY ListenPort = 51820 PreUp = iptables --table nat --append POSTROUTING --jump MASQUERADE --out-interface eth0 PreDown = iptables --table nat --delete POSTROUTING --jump MASQUERADE --out-interface eth0 [Peer] PublicKey = YOUR_CLIENT_PUBLIC_KEY AllowedIPs = 10.1.10.2/32

Be careful to correctly copy the keys which you have previously generated, I copied the wrong keys twice so if it doesn't work please double check this first

Do the same now but on the client machine and add the following content in the wg0.conf file:

[Interface] Address = 10.1.10.2/24 PrivateKey = YOUR_CLIENT_PRIVATE_KEY [Peer] PublicKey = YOUR_SERVER_PUBLIC_KEY AllowedIPs = 0.0.0.0/0, ::/0 Endpoint = PUBLIC_IP_OF_SERVER:51820 PersistentKeepalive = 25 # Ensure connections remain active, especially useful over NAT

You can change the IPs and subnets and also the listening ports and use whatever values you want, just make sure it's not the same as some other existing interface on one of the machines

Before starting the interfaces using these configurations you need to make sure that the client can connect to the server on the port which you have specified, in this case port 51820. In my case the server is Debian and there is a built-in firewall for all Debian based Linux Distros and it's called ufw. If this is your case please use following command to display existing firewall rules:

└─[$] ufw status numbered Status: active To Action From -- ------ ---- [ 1] 80/tcp ALLOW IN Anywhere [ 2] 443/tcp ALLOW IN Anywhere [ 6] 51820/udp ALLOW IN {Your_Public_IP} [ 7] 80/tcp (v6) ALLOW IN Anywhere (v6) [ 8] 443/tcp (v6) ALLOW IN Anywhere (v6)

As you can see I allow traffic IN from anywhere on ports 80 and 443 as I run nginx webserver and I need to allow http and https traffic for all IPs. And I also already have a rule to allow on 51820 (default port for wireguard) UDP from my public IP. To add such a rule run the following:

─[$] sudo ufw allow 51820/udp from {Your_Public_IP}

Please note that if your public IP changes you will not be able to access 51820 because UFW will deny you. It's safer to allow your public IP than to allow all IPs, even though if a malicious entity finds out your public IP which is not a difficult task it can spoof your IP in a request to access 51820, but to actually connect to server it will need your wireguards keys also.

Now you can go ahead and just issue the following to start the interface:

┌─[aisfrog@Pineapple] - [~] - [3167] └─[$] sudo wg-quick up wg0 [#] ip link add wg0 type wireguard [#] wg setconf wg0 /dev/fd/63 [#] ip -4 address add 10.1.10.2/32 dev wg0 [#] ip link set mtu 1420 up dev wg0 [#] wg set wg0 fwmark 51820 [#] ip -6 route add ::/0 dev wg0 table 51820 [#] ip -6 rule add not fwmark 51820 table 51820 [#] ip -6 rule add table main suppress_prefixlength 0 [#] nft -f /dev/fd/63 [#] ip -4 route add 0.0.0.0/0 dev wg0 table 51820 [#] ip -4 rule add not fwmark 51820 table 51820 [#] ip -4 rule add table main suppress_prefixlength 0 [#] sysctl -q net.ipv4.conf.all.src_valid_mark=1 [#] nft -f /dev/fd/63 ┌─[aisfrog@Pineapple] - [~] - [3168] └─[$] ifconfig wg0 wg0: flags=209 UP,POINTOPOINT,RUNNING,NOARP mtu 1420 inet 10.1.10.2 netmask 255.255.255.255 destination 10.1.10.2 unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 1000 (UNSPEC) RX packets 1 bytes 92 (92.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 10 bytes 1224 (1.1 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 ┌─[aisfrog@Pineapple] - [~] - [3169] └─[$] ping -c 1 10.1.10.1 PING 10.1.10.1 (10.1.10.1) 56(84) bytes of data. 64 bytes from 10.1.10.1: icmp_seq=1 ttl=64 time=53.7 ms --- 10.1.10.1 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 53.676/53.676/53.676/0.000 ms

It works! I've pinged 10.1.10.1 which is the IP of the server and my wg0 interface IP is 10.1.10.2 just as configured

This can be useful when you want to have a secure and encrypted connection between two machines and is especially useful because once the tunnel is created, you have a "direct" connection with the peer and your ISP cannot know any of the data you actually exchange and it bypasses firewalls because it's like you're on the same LAN

NOTE: If you encounter any issues with wireguard at some point it might be that you've updated your kernel and you need to restart your system to be able to use Wireguard