Set Up Your Own WireGuard VPN Server on Ubuntu 24.04/22.04/20.04 (2024)

This tutorial is going to show you how to set up your own WireGuard VPN server on Ubuntu. WireGuard is made specifically for the Linux kernel. It runs inside the Linux kernel and allows you to create fast, modern, and secure VPN tunnel.

WireGuard VPN Features

  • Lightweight and super fast speed, blowing OpenVPN out of the water.
  • Cross-platform. WireGuard can run on Linux, BSD, macOS, Windows, Android, iOS, and OpenWRT.
  • User authentication is done by exchanging public keys, similar to SSH keys.
  • It assigns static tunnel IP addresses to VPN clients. Some folks may not like it, but it can be very useful in some cases.
  • Mobile devices can switch between Wi-Fi and mobile network seamlessly without dropping any connectivity.
  • It aims to replace OpenVPN and IPSec in most use cases.

WireGuard is my VPN protocol of choice to eliminate the need to set up TLS encryption for my private networks.

Requirements

To follow this tutorial, you will need a VPS (Virtual Private Server) that can access blocked websites freely (Outside of your country or Internet filtering system). I recommend Kamatera VPS, which features:

  • 30 days free trial.
  • Starts at $4/month (1GB RAM)
  • High-performance KVM-based VPS
  • 9 data centers around the world, including United States, Canada, UK, Germany, The Netherlands, Hong Kong, and Isreal.

Follow the tutorial linked below to create your Linux VPS server at Kamatera.

  • How to Create a Linux VPS Server on Kamatera

Once you have a VPS running Ubuntu, follow the instructions below.

This tutorial assumes that the VPN server and VPN client are both running Ubuntu operating system.

Step 1: Install WireGuard on Ubuntu Server and Desktop

Log into your Ubuntu server, then run the following commands to install WireGuard.

Ubuntu 24.04/22.04/20.04

Ubuntu 24.04/22.04/20.04 ships with a Linux kernel that has a built-in wireguard module, so simply run the following commands.

sudo apt updatesudo apt install wireguard wireguard-tools

Ubuntu 18.04

Ubuntu 18.04 ships with Linux kernel 4.15, so users need to install the hardware-enablement kernel first (HWE), which will install kernel 5.4 on your system.

sudo apt updatesudo apt install linux-generic-hwe-18.04-edge

Restart your Ubuntu 18.04 server and install WireGuard.

sudo shutdown -r nowsudo apt install wireguard wireguard-tools wireguard-dkms

Install WireGuard on the Client Side

Then use the same commands to install WireGuard on your local Ubuntu computer (the VPN client). Note that you also need to install the openresolv package on the client to configure DNS server.

sudo apt install openresolv

Step 2: Generate Public/Private Keypair

Server

Run the following command on the Ubuntu server to create a public/private key pair, which will be saved under /etc/wireguard/ directory.

wg genkey | sudo tee /etc/wireguard/server_private.key | wg pubkey | sudo tee /etc/wireguard/server_public.key

Set Up Your Own WireGuard VPN Server on Ubuntu 24.04/22.04/20.04 (1)

Client

Run the following command to create a public/private key pair on the local Ubuntu computer (the VPN client).

wg genkey | sudo tee /etc/wireguard/client_private.key | wg pubkey | sudo tee /etc/wireguard/client_public.key

Step 3: Create WireGuard Configuration File

Server

Use a command-line text editor like Nano to create a WireGuard configuration file on the Ubuntu server. wg0 will be the network interface name.

sudo nano /etc/wireguard/wg0.conf

Copy the following text and paste it to your configuration file. You need to use your own server private key and client public key.

[Interface]Address = 10.10.10.1/24ListenPort = 51820PrivateKey = cD+ZjXiVIX+0iSX1PNijl4a+88lCbDgw7kO78oXXLEc=[Peer]PublicKey = AYQJf6HbkQ0X0Xyt+cTMTuJe3RFwbuCMF46LKgTwzz4=AllowedIPs = 10.10.10.2/32

Set Up Your Own WireGuard VPN Server on Ubuntu 24.04/22.04/20.04 (2)

Where:

  • Address: Specify the private IP address of the VPN server. Here I’m using the 10.10.10.0/24 network range, so it won’t conflict with your home network range. (Most home routers use 192.168.0.0/24 or 192.168.1.0/24). 10.10.10.1 is the private IP address for the VPN server.
  • PrivateKey: The private key of VPN server, which can be found in the /etc/wireguard/server_private.key file on the server.
  • ListenPort: WireGuard VPN server will be listening on UDP port 51820, which is the default.
  • PublicKey: The public key of VPN client, which can be found in the /etc/wireguard/client_public.key file on the client computer.
  • AllowedIPs: IP addresses the VPN client is allowed to use. In this example, the client can only use the 10.10.10.2 IP address inside the VPN tunnel.

Save and close the file. (To save a file in Nano text editor, press Ctrl+O, then press Enter to confirm. Press Ctrl+X to exit.)

Change the file permission mode so that only root user can read the files.

sudo chmod 600 /etc/wireguard/ -R

Client

Use a command-line text editor like Nano to create a WireGuard configuration file on your local Ubuntu computer. wg-client0 will be the network interface name.

sudo nano /etc/wireguard/wg-client0.conf

Copy the following text and paste it to your configuration file. You need to use your own client private key and server public key.

[Interface]Address = 10.10.10.2/24DNS = 10.10.10.1PrivateKey = cOFA+x5UvHF+a3xJ6enLatG+DoE3I5PhMgKrMKkUyXI=[Peer]PublicKey = RaoAdsIEIwgV9DHNSubxWVG+nZ1GP/c3OU6A/efBJ0I=AllowedIPs = 0.0.0.0/0Endpoint = 12.34.56.78:51820PersistentKeepalive = 25

Where:

  • Address: Specify the private IP address of the VPN client.
  • DNS: specify 10.10.10.1 (VPN server) as the DNS server. It will be configured via the resolvconf command. You can also specify multiple DNS servers for redundancy like this: DNS = 10.10.10.1 8.8.8.8
  • PrivateKey: The client’s private key, which can be found in the /etc/wireguard/client_private.key file on the client computer.
  • PublicKey: The server’s public key, which can be found in the /etc/wireguard/server_public.key file on the server.
  • AllowedIPs: 0.0.0.0/0 represents the whole Internet, which means all traffic to the Internet should be routed via the VPN.
  • Endpoint: The public IP address and port number of VPN server. Replace 12.34.56.78 with your server’s real public IP address.
  • PersistentKeepalive: Send an authenticated empty packet to the peer every 25 seconds to keep the connection alive. If PersistentKeepalive isn’t enabled, the VPN server might not be able to ping the VPN client.

Save and close the file.

Change the file mode so that only root user can read the files.

sudo chmod 600 /etc/wireguard/ -R

Step 4: Enable IP Forwarding on the Server

In order for the VPN server to route packets between VPN clients and the Internet, we need to enable IP forwarding. Edit sysctl.conf file.

sudo nano /etc/sysctl.conf

Add the following line at the end of this file.

net.ipv4.ip_forward = 1

Save and close the file. Then apply the changes with the below command. The -p option will load sysctl settings from /etc/sysctl.conf file. This command will preserve our changes across system reboots.

sudo sysctl -p

Step 5: Configure IP Masquerading on the Server

We need to set up IP masquerading in the server firewall, so that the server becomes a virtual router for VPN clients. I will use UFW, which is a front end to the iptables firewall. Install UFW on Ubuntu with:

sudo apt install ufw

First, you need to allow SSH traffic.

sudo ufw allow 22/tcp

Next, find the name of your server’s main network interface.

ip -c a

As you can see, it’s named enp3s0 on my Ubuntu server.

Set Up Your Own WireGuard VPN Server on Ubuntu 24.04/22.04/20.04 (3)

To configure IP masquerading, we have to add iptables command in a UFW configuration file.

sudo nano /etc/ufw/before.rules

By default, there are some rules for the filter table. Add the following lines at the end of this file. Replace enp3s0 with your own network interface name.

# NAT table rules*nat:POSTROUTING ACCEPT [0:0]-A POSTROUTING -s 10.10.10.0/24 -o enp3s0 -j MASQUERADE# End each table with the 'COMMIT' line or these rules won't be processedCOMMIT

In Nano text editor, you can go to the end of the file by pressing Ctrl+W, then pressing Ctrl+V.

Set Up Your Own WireGuard VPN Server on Ubuntu 24.04/22.04/20.04 (4)

The above lines will append (-A) a rule to the end of POSTROUTING chain of the nat table. It will link your virtual private network with the Internet. And also hide your network from the outside world. So the Internet can only see your VPN server’s IP, but can’t see your VPN client’s IP, just like your home router hides your private home network.

Make sure there are no spaces at the beginning of each line.

By default, UFW forbids packet forwarding. We can allow forwarding for our private network. Find the ufw-before-forward chain in this file and add the following 3 lines, which will accept packet forwarding if the source IP or destination IP is in the 10.10.10.0/24 range.

# allow forwarding for trusted network-A ufw-before-forward -s 10.10.10.0/24 -j ACCEPT-A ufw-before-forward -d 10.10.10.0/24 -j ACCEPT

Set Up Your Own WireGuard VPN Server on Ubuntu 24.04/22.04/20.04 (5)

Save and close the file. Then enable UFW.

sudo ufw enable

If you have enabled UFW before, then you can use systemctl to restart UFW.

sudo systemctl restart ufw

Now if you list the rules in the POSTROUTING chain of the NAT table by using the following command:

sudo iptables -t nat -L POSTROUTING

You can see the Masquerade rule.

Set Up Your Own WireGuard VPN Server on Ubuntu 24.04/22.04/20.04 (6)

It can take some time for UFW to process the firewall rules. If the masquerade rule doesn’t show up, then restart UFW again (sudo systemctl restart ufw).

Step 6: Install a DNS Resolver on the Server

Since we specify the VPN server as the DNS server for client, we need to run a DNS resolver on the VPN server. We can install the bind9 DNS server.

sudo apt install bind9

Once it’s installed, BIND will automatically start. You can check its status with:

systemctl status bind9

Sample output:

 named.service - BIND Domain Name Server Loaded: loaded (/lib/systemd/system/named.service; enabled; vendor preset: enabled) Active: active (running) since Sun 2020-05-17 08:11:26 UTC; 37s ago Docs: man:named(8) Main PID: 13820 (named) Tasks: 5 (limit: 1074) Memory: 14.3M CGroup: /system.slice/named.service └─13820 /usr/sbin/named -f -u bind

If it’s not running, start it with:

sudo systemctl start bind9

Edit the BIND DNS server’s configuration file.

sudo nano /etc/bind/named.conf.options

Add the following line to allow VPN clients to send recursive DNS queries.

allow-recursion { 127.0.0.1; 10.10.10.0/24; };

Set Up Your Own WireGuard VPN Server on Ubuntu 24.04/22.04/20.04 (7)

Save and close the file. Then edit the /etc/default/named files.

sudo nano /etc/default/named

Add -4 to the OPTIONS to ensure BIND can query root DNS servers.

OPTIONS="-u bind -4"

Save and close the file.

By default, BIND enables DNSSEC, which ensures that DNS responses are correct and not tampered with. However, it might not work out of the box due to trust anchor rollover and other reasons. To make it work properly, we can rebuild the managed key database with the following commands.

sudo rndc managed-keys destroysudo rndc reconfig

Restart BIND9 for the changes to take effect.

sudo systemctl restart bind9

Then you need to run the following command to allow VPN clients to connect to port 53.

sudo ufw insert 1 allow in from 10.10.10.0/24

Step 7: Open WireGuard Port in Firewall

Run the following command to open UDP port 51820 on the server.

sudo ufw allow 51820/udp

Step 8: Start WireGuard

server

Run the following command on the server to start WireGuard.

sudo systemctl start [emailprotected]

Enable auto-start at system boot time.

sudo systemctl enable [emailprotected]

Check its status with the following command. Its status should be active (exited).

systemctl status [emailprotected]

Now WireGuard server is ready to accept client connections.

Client

Start WireGuard.

sudo systemctl start [emailprotected]

Enable auto-start at system boot time.

sudo systemctl enable [emailprotected]

Check its status:

systemctl status [emailprotected]

Now go to this website: https://icanhazip.com/ to check your public IP address. If everything went well, it should display your VPN server’s public IP address instead of your client computer’s public IP address.

You can also run the following command to get the current public IP address.

curl https://icanhazip.com

Troubleshooting Tips

Check if Port 51820 is open

First of all, install the nmap port scanner on the VPN client.

sudo apt install nmap

And scan the UDP port 51820 of the server. Replace 12.34.56.78 with your server’s real public IP address.

sudo nmap -sU -pU:51820 12.34.56.78

If WireGuard server is running, the port scan result should be open or open|filtered.

Set Up Your Own WireGuard VPN Server on Ubuntu 24.04/22.04/20.04 (8)

If the scan result is closed, then WireGuard server is not running, or you didn’t open UDP port 51820 in the firewall.

Set Up Your Own WireGuard VPN Server on Ubuntu 24.04/22.04/20.04 (9)

Check the log of the WireGuard server to find if there’s any wrong.

sudo journalctl -eu wg-quick@wg0

Can’t ping

You can ping from the VPN client to VPN server (ping 10.10.10.1) to see if the tunnel works. If you see the following error message in the ping,

ping: sendmsg: Required key not available

it might be that the AllowedIPs parameter is wrong, like a typo. After fixing the typo, restart both the VPN server and VPN client.

Another reason might be that you forgot to add ListenPort = 51820 in the server config file.

Public IP Doesn’t Change

If the VPN tunnel is successfully established, but the client public IP address doesn’t change, that’s because the masquerading or forwarding rule in your UFW config file is not working. I once had a typo in the /etc/ufw/before.rules file, which caused my computer not to be able to browse the Internet.

Note that I don’t recommend using SaveConfig=true in the [Interface] section of the WireGuard configuration file. SaveConfig tells WireGuard to save the runtime configuration on shutdown. So if you add additional [Peer] in the configuration file and then restart WireGuard, your newly-added configs will be overwritten.

Enable Debug logging in Linux Kernel

If you use Linux kernel 5.6+, you can enable debug logging for WireGuard with the following command.

sudo su -echo module wireguard +p > /sys/kernel/debug/dynamic_debug/control

Then you can view the debug logs with

sudo dmesg -wH | grep wireguard

or

sudo journalctl -kf | grep wireguard

If you see the following error, it means the public key is wrong.

Invalid handshake initiation

Restart

If your VPN still doesn’t work, try restarting the VPN server.

sudo systemctl restart [emailprotected]

Then stop the VPN client.

sudo systemctl stop [emailprotected]

And upgrade software packages on the VPN client.

sudo apt update; sudo apt upgrade

Next, reboot the VPN client.

sudo shutdown -r nowsudo systemctl start [emailprotected]

If your WireGuard VPN can only work after a restart, consider adding a cron job to automatically restart the service.

sudo crontab -e

Add the following line in this file.

@daily systemctl restart [emailprotected]

Speed Comparison between WireGuard & OpenConnect

On one of my VPS servers, I installed both WireGuard and OpenConnect VPN server. The speed test is as follows. It might not look fast to you, because the connection between my computer and the VPN server isn’t very good. How fast you can get depends on the latency and packet loss rate between the VPN client and VPN server.

  • WireGuard is the winner. It’s nearly 3 times faster than OpenConnect.
  • OpenConnect over TCP BBR is faster than OpenConnect over UDP. Surprise? Folks often say UDP is faster than TCP.

WireGuard is able to reach 52296 Kbps (about 51 Mbit/s) when playing YouTube videos.

Set Up Your Own WireGuard VPN Server on Ubuntu 24.04/22.04/20.04 (10)

OpenConnect (TLS with TCP BBR algorithm) is able to reach 16504 Kbps (about 16 Mbit/s) when playing YouTube videos.

Set Up Your Own WireGuard VPN Server on Ubuntu 24.04/22.04/20.04 (11)

OpenConnect (TLS on UDP) is able to reach 12997 Kbps (about 12.7 Mbit/s) when playing YouTube videos.

Set Up Your Own WireGuard VPN Server on Ubuntu 24.04/22.04/20.04 (12)

Adding Additional VPN Clients

WireGuard is designed to associate one IP address with one VPN client. To add more VPN clients (Windows, Android, iOS, etc), you need to create a unique private/public key pair for each client, then add each VPN client’s public key in the server’s config file (/etc/wireguard/wg0.conf) like this:

[Interface]Address = 10.10.10.1/24PrivateKey = UIFH+XXjJ0g0uAZJ6vPqsbb/o68SYVQdmYJpy/FlGFA=ListenPort = 51820[Peer]PublicKey = 75VNV7HqFh+3QIT5OHZkcjWfbjx8tc6Ck62gZJT/KRA=AllowedIPs = 10.10.10.2/32[Peer]PublicKey = YYh4/1Z/3rtl0i7cJorcinB7T4UOIzScifPNEIESFD8=AllowedIPs = 10.10.10.3/32[Peer]PublicKey = EVstHZc6QamzPgefDGPLFEjGyedJk6SZbCJttpzcvC8=AllowedIPs = 10.10.10.4/32

Each VPN client will have a static private IP address (10.10.10.2, 10.10.10.3, 10.10.10.4, etc). Restart the WireGuard server for the changes to take effect.

sudo systemctl restart [emailprotected]

Then add WireGuard configuration on each VPN client as usual.

Configure VPN Client on iOS/Andorid

Since I have an iPhone, I will show you how to configure WireGuard client on iOS. Install the WireGuard app from the App store. Then open this app and click the Add a tunnel button.

You have 3 methods to create a new WireGuard tunnel.

  • create from file or archive
  • create from QR code
  • Create from scratch

Choose the QR code method, since it’s easier. Run the following command on the server to generate a WireGuard public/private key for the iOS client.

wg genkey | sudo tee /etc/wireguard/ios_private.key | wg pubkey | sudo tee /etc/wireguard/ios_public.key

Next, create a WireGuard config file for the iOS client.

sudo nano /etc/wireguard/ios.conf

Add the following lines.

[Interface]Address = 10.10.10.3/24DNS = 10.10.10.1PrivateKey = mNiZvB+sASN/+ZiJkMyan1ZZOzCXkrjYPlbg7rZJ7Fc=[Peer]#VPN serverPublicKey = OMaXX7XD+wEYWfYyFcZZBN4vFSC16A1e8t80ONiJKWY=AllowedIPs = 0.0.0.0/0Endpoint = 12.34.56.78:51820PersistentKeepalive = 25

Where:

  • Address: Specify the private IP address for the iOS client.
  • DNS: specify 10.10.10.1 (the VPN server) as the DNS server. You can also specify multiple DNS servers for redundancy like this: DNS = 10.10.10.1,8.8.8.8. Note that the iOS app doesn’t support the DNS = 10.10.10.1 8.8.8.8 syntax.
  • PrivateKey: The iOS client’s private key, which can be found in the /etc/wireguard/ios_private.key file.
  • PublicKey: The server’s public key, which can be found in the /etc/wireguard/server_public.key file on the server.
  • AllowedIPs: 0.0.0.0/0 represents the whole Internet, which means all traffic to the Internet should be routed via the VPN.
  • Endpoint: The public IP address and port number of VPN server. Replace 12.34.56.78 with your server’s real public IP address.
  • PersistentKeepalive: Send an authenticated empty packet to the peer every 25 seconds to keep the connection alive. If PersistentKeepalive isn’t enabled, the VPN server might not be able to ping the VPN client.

Save and close the file. Then run the following command on the WireGuard VPN server to generate a QR code from the iOS config file.

sudo apt install qrencodesudo cat /etc/wireguard/ios.conf | qrencode -t ansiutf8

Next, scan a QR code from the iOS WireGuard app, so the content in the /etc/wireguard/ios.conf file will be imported to the WireGuard iOS client.

Once the tunnel is added on the iOS client, we also need to add a [peer] in the WireGaurd server config file.

sudo nano /etc/wireguard/wg0.conf

Like this:

[Interface]Address = 10.10.10.1/24PrivateKey = UIFH+XXjJ0g0uAZJ6vPqsbb/o68SYVQdmYJpy/FlGFA=ListenPort = 51820[Peer]PublicKey = 75VNV7HqFh+3QIT5OHZkcjWfbjx8tc6Ck62gZJT/KRA=AllowedIPs = 10.10.10.2/32[Peer]# iOS clientPublicKey = YYh4/1Z/3rtl0i7cJorcinB7T4UOIzScifPNEIESFD8=AllowedIPs = 10.10.10.3/32

Save and close the file. Then restart the WireGuard VPN server.

sudo systemctl restart [emailprotected]

Now you can establish WireGuard VPN connection from the iOS app.

Configure Windows Client

Download the WireGuard installer for Windows.

Once it’s installed, start the WireGuard program. You need to right-click on the left sidebar to create a new empty tunnel. It will automatically create a public/private key for the Windows client.

Set Up Your Own WireGuard VPN Server on Ubuntu 24.04/22.04/20.04 (13)

Now you need to add other information.

[Interface]PrivateKey = mNiZvB+sASN/+ZiJkMyan1ZZOzCXkrjYPlbg7rZJ7Fc=Address = 10.10.10.4/24 DNS = 10.10.10.1[Peer]# VPN serverPublicKey = OMaXX7XD+wEYWfYyFcZZBN4vFSC16A1e8t80ONiJKWY=AllowedIPs = 0.0.0.0/0Endpoint = 12.34.56.78:51820PersistentKeepalive = 25

Where:

  • Address: Specify the private IP address for the Windows client.
  • DNS: specify 10.10.10.1 (the VPN server) as the DNS server. You can also specify multiple DNS servers for redundancy like this: DNS = 10.10.10.1,8.8.8.8. Note that the Windows app doesn’t support the DNS = 10.10.10.1 8.8.8.8 syntax.
  • PrivateKey: The Windows client’s private key, which is automatically created.
  • PublicKey: The server’s public key, which can be found in the /etc/wireguard/server_public.key file on the server.
  • AllowedIPs: 0.0.0.0/0 represents the whole Internet, which means all traffic to the Internet should be routed via the VPN.
  • Endpoint: The public IP address and port number of VPN server. Replace 12.34.56.78 with your server’s real public IP address.
  • PersistentKeepalive: Send an authenticated empty packet to the peer every 25 seconds to keep the connection alive. If PersistentKeepalive isn’t enabled, the VPN server might not be able to ping the VPN client.

Hint: On Windows, you can use the PowerShell program to SSH into your Linux server.

Set Up Your Own WireGuard VPN Server on Ubuntu 24.04/22.04/20.04 (14)

Save the configuration.

Once the tunnel is added on the Windows client, we also need to add a [peer] in the WireGaurd server config file.

sudo nano /etc/wireguard/wg0.conf

Like this:

[Interface]Address = 10.10.10.1/24PrivateKey = UIFH+XXjJ0g0uAZJ6vPqsbb/o68SYVQdmYJpy/FlGFA=ListenPort = 51820[Peer]PublicKey = 75VNV7HqFh+3QIT5OHZkcjWfbjx8tc6Ck62gZJT/KRA=AllowedIPs = 10.10.10.2/32[Peer]# iOS clientPublicKey = YYh4/1Z/3rtl0i7cJorcinB7T4UOIzScifPNEIESFD8=AllowedIPs = 10.10.10.3/32[Peer]# Windows clientPublicKey = wJpwC/gCWXZTGa5lQReKowRvymaaEUav0N1qeK74HlQ=AllowedIPs = 10.10.10.4/32

Save and close the file. Then restart the WireGuard VPN server.

sudo systemctl restart [emailprotected]

Now you can establish WireGuard VPN connection on Windows.

Automatic-Restart When VPN Connection Drops

Sometimes the VPN connection would drop due to various reasons. You can run the following command to check if the VPN client can ping the VPN server’s private IP address (10.10.10.1). If the ping is unsuccessful, then the command on the right will be executed to restart the VPN client. || is the OR operator in Bash. It executes the command on the right only if the command on the left returned an error.

ping -c9 10.10.10.1 > /dev/null || systemctl restart [emailprotected]

The ping will be done 9 times, i.e 9 seconds. You can use a for loop in the Bash shell to make the whole command run 6 times, i.e. 54 seconds.

for ((i=1; i<=6; i++)) do (ping -c9 10.10.10.1 > /dev/null || systemctl restart [emailprotected]) done

Now we can create a Cron job to automate this task. Edit the root user’s crontab file on the VPN client.

sudo crontab -e

Bash isn’t the default shell in Cron. You can add the following line at the beginning of the Crontab file to make it the default.

SHELL=/bin/bash

Then add the following line at the end of this file.

* * * * * for ((i=1; i<=6; i++)) do (ping -c9 10.10.10.1 > /dev/null || systemctl restart [emailprotected]) done

This Cron job will run every minute, and there will be 6 checks every minute. Save and close the file.

How to Enable IPv6 in WireGuard VPN

Edit the WireGuard server config file.

sudo nano /etc/wireguard/wg0.conf

Add private IPv6 address along with the IPv4 address.

[Interface]Address = 10.10.10.1/24, fda9:4efe:7e3b:03ea::1/64ListenPort = 51820PrivateKey = cD+ZjXiVIX+0iSX1PNijl4a+88lCbDgw7kO78oXXLEc=[Peer]PublicKey = AYQJf6HbkQ0X0Xyt+cTMTuJe3RFwbuCMF46LKgTwzz4=AllowedIPs = 10.10.10.2/32, fda9:4efe:7e3b:03ea::2/64

Save and close the file. Restart WireGuard server.

sudo systemctl restart wg-quick@wg0

Then edit the WireGuard client config file.

sudo nano /etc/wireguard/wg-client0.conf

Add private IPv6 address along with the IPv4 address.

[Interface]Address = 10.10.10.2/24, fda9:4efe:7e3b:03ea::2/64DNS = 10.10.10.1PrivateKey = cOFA+x5UvHF+a3xJ6enLatG+DoE3I5PhMgKrMKkUyXI=[Peer]PublicKey = RaoAdsIEIwgV9DHNSubxWVG+nZ1GP/c3OU6A/efBJ0I=AllowedIPs = 0.0.0.0/0, ::0/0Endpoint = 12.34.56.78:51820PersistentKeepalive = 25

Save and close the file. Then restart WireGuard client.

sudo systemctl restart wg-quick@wg-client0

If you encounter the following error,

RTNETLINK answers permission denied

Then you need to enable IPv6 on the client.

sudo nano /etc/sysctl.d/60-custom.conf

Add the following lines.

net.ipv6.conf.all.disable_ipv6 = 0net.ipv6.conf.default.disable_ipv6 = 0net.ipv6.conf.lo.disable_ipv6 = 0

Save and close the file. Then apply the changes.

sudo sysctl -p /etc/sysctl.d/60-custom.conf

Enable IPv6 Forwarding on the VPN server

Then we need to enable IP forwarding for IPv6 on the VPN server. Edit sysctl.conf file.

sudo nano /etc/sysctl.d/60-custom.conf

Add the following line in this file.

net.ipv6.conf.all.forwarding=1

Save and close the file. Then apply the changes with the below command.

sudo sysctl -p /etc/sysctl.d/60-custom.conf

Configure IPv6 Masquerading on the Server

Next, we need to set up IPv6 masquerading in the server firewall, so that the server becomes a virtual router for VPN clients.

sudo nano /etc/ufw/before6.rules

By default, there are some rules for the filter table. Add the following lines at the end of this file. Replace ens3 with your own network interface name.

# NAT table rules*nat:POSTROUTING ACCEPT [0:0]-A POSTROUTING -s fda9:4efe:7e3b:03ea::/64 -o ens3 -j MASQUERADE# End each table with the 'COMMIT' line or these rules won't be processedCOMMIT

In Nano text editor, you can go to the end of the file by pressing Ctrl+W, then pressing Ctrl+V.

Set Up Your Own WireGuard VPN Server on Ubuntu 24.04/22.04/20.04 (15)

By default, UFW forbids packet forwarding. We can allow forwarding for our private IPv6 network. Find the ufw6-before-forward chain in this file and add the following 3 lines, which will accept packet forwarding if the source IP or destination IP is in the fda9:4efe:7e3b:03ea::/64 range.

# Allow IPv6 forwarding for VPN-A ufw6-before-forward -s fda9:4efe:7e3b:03ea::/64 -j ACCEPT-A ufw6-before-forward -d fda9:4efe:7e3b:03ea::/64 -j ACCEPT

Set Up Your Own WireGuard VPN Server on Ubuntu 24.04/22.04/20.04 (16)

Save and close the file. Restart UFW for the change to take effect.

sudo systemctl restart ufw

Now if you list the rules in the POSTROUTING chain of the NAT table by using the following command:

sudo ip6tables -t nat -L POSTROUTING

You can see the Masquerade rule.

Set Up Your Own WireGuard VPN Server on Ubuntu 24.04/22.04/20.04 (17)

Advanced Usage

Now I will show you how to use policy routing, split tunneling, and VPN kill switch with WireGuard VPN. Note that it’s not recommended to use them in conjunction with each other. If you use policy routing, then you should not enable split tunneling or VPN kill switch, and vice versa. This section is for advanced users. If you are a WireGuard beginner and don’t know what they are used for, then don’t apply the instructions in this section.

Policy Routing

By default, all traffic on the VPN client will be routed through the VPN server. Sometimes you may want to route only a specific type of traffic, based on the transport layer protocol and the destination port. This is known as policy routing.

Policy routing is configured on the client computer, and we need to stop the VPN connection first.

sudo systemctl stop [emailprotected]

Then edit the client configuration file.

sudo nano /etc/wireguard/wg-client0.conf

For example, if you add the following 3 lines in the [interface] section, then WireGuard will create a routing table named “1234” and add the ip rule into the routing table. In this example, traffic will be routed through VPN server only when TCP is used as the transport layer protocol and the destination port is 25, i.e, when the client computer sends emails.

Table = 1234PostUp = ip rule add ipproto tcp dport 25 table 1234PreDown = ip rule delete ipproto tcp dport 25 table 1234

Set Up Your Own WireGuard VPN Server on Ubuntu 24.04/22.04/20.04 (18)

Note: The client should be running Ubuntu 20.04 or up in order to configure policy routing. The ip utility on Ubuntu 18.04 doesn’t support the ipproto and dport argument.

Save and close the file. Then start the WireGuard client.

sudo systemctl start [emailprotected]

If you want to route traffic for TCP port 80 and 443, use the following syntax.

Table = 1234PostUp = ip rule add ipproto tcp dport 80 table 1234; ip rule add ipproto tcp dport 443 table 1234PreDown = ip rule delete ipproto tcp dport 80 table 1234; ip rule delete ipproto tcp dport 443 table 1234

Remember that you should stop the WireGuard VPN connection before changing policy routing rules.

You can also specify a port range like below (TCP port 26 to TCP port 10240).

Table = 1234PostUp = ip rule add ipproto tcp dport 26-10240 table 1234PreDown = ip rule delete ipproto tcp dport 26-10240 table 1234

If you want to specify both TCP and UDP ports, then remove ipproto tcp.

Table = 1234PostUp = ip rule add dport 26-10240 table 1234PreDown = ip rule delete dport 26-10240 table 1234

You might want to configure the VPN client to use the VPN tunnel only when the traffic is destined to certain IP addresses. You can do so with the to option.

Table = 1234PostUp = ip rule add to 10.0.0.0/24 table 1234PreDown = ip rule delete to 10.0.0.0/24 table 1234

Split Tunneling

By default, all traffic on the VPN client will be routed through the VPN server. Here’s how to enable split tunneling, so only traffic to the 10.10.10.0/24 IP range will be tunneled through WireGuard VPN. This is useful when you want to build a private network for several cloud servers, because VPN clients will run on cloud servers and if you use a full VPN tunnel, then you will probably lose connection to the cloud servers.

Edit the client configuration file.

sudo nano /etc/wireguard/wg-client0.conf

Change

AllowedIPs = 0.0.0.0/0

To

AllowedIPs = 10.10.10.0/24

So traffic will be routed through VPN only when the destination address is in the 10.10.10.0/24 IP range. Save and close the file. Then restart WireGuard client.

sudo systemctl restart [emailprotected]

You can also allow multiple IP ranges. Let’s say the VPN server also manages the 10.10.20.0/24 network, then you can configure AllowedIPs on the VPN client like this:

AllowedIPs = 10.10.10.0/24, 10.10.20.0/24

So the VPN client can reach the 10.10.20.0/24 network via the VPN server, and vice versa.

To add a single IP address, use the following syntax.

AllowedIPs = 10.10.10.0/24, 10.10.20.0/24, 8.8.8.8/32

This tells the client to use the VPN server when communicating with 8.8.8.8.

VPN Kill Switch

By default, your computer can access the Internet via the normal gateway when the VPN connection is disrupted. You may want to enable the kill switch feature, which prevents the flow of unencrypted packets through non-WireGuard interfaces.

Stop the WireGuard client process.

sudo systemctl stop [emailprotected]

Edit the client configuration file.

sudo nano /etc/wireguard/wg-client0.conf

Add the following two lines in the [interface] section.

PostUp = iptables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECTPreDown = iptables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT

Like this:

[Interface]Address = 10.10.10.2/24DNS = 10.10.10.1PrivateKey = cOFA+x5UvHF+a3xJ6enLatG+DoE3I5PhMgKrMKkUyXI=PostUp = iptables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECTPreDown = iptables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT[Peer]PublicKey = RaoAdsIEIwgV9DHNSubxWVG+nZ1GP/c3OU6A/efBJ0I=AllowedIPs = 0.0.0.0/0Endpoint = 12.34.56.78:51820PersistentKeepalive = 25

Save and close the file. Then start the WireGuard client.

sudo systemctl start [emailprotected]

Multiple Addresses in WireGuard Interface

A WireGuard interface can have multiple IP addresses. For example, you can have two IP addresses on the VPN client.

[Interface]Address = 10.10.10.2/24Address = 10.10.10.3/24....

In this case, you need to allow multiple IP addresses on the VPN server for this particular client, or the VPN client might not be able to connect to the VPN server.

[Peer]...AllowedIPs = 10.10.10.2/32, 10.10.10.3/32

You can use the following command to check the IP addresses belongs to a network interface.

ip -c a

Note

  • The ifconfig command can show only IP address for a network interface.
  • If you set up another WireGuard interface in a new .conf file, then it needs to bind to a port other than 51820, or you will see the ” Address already in use” error.

Wrapping Up

That’s it! I hope this tutorial helped you install and configure WireGuard on Ubuntu. As always, if you found this post useful, then subscribe to our free newsletter to get more tips and tricks 🙂

Rate this tutorial

[Total: 24 Average: 5]

Set Up Your Own WireGuard VPN Server on Ubuntu 24.04/22.04/20.04 (2024)

References

Top Articles
Latest Posts
Article information

Author: Sen. Ignacio Ratke

Last Updated:

Views: 6548

Rating: 4.6 / 5 (76 voted)

Reviews: 91% of readers found this page helpful

Author information

Name: Sen. Ignacio Ratke

Birthday: 1999-05-27

Address: Apt. 171 8116 Bailey Via, Roberthaven, GA 58289

Phone: +2585395768220

Job: Lead Liaison

Hobby: Lockpicking, LARPing, Lego building, Lapidary, Macrame, Book restoration, Bodybuilding

Introduction: My name is Sen. Ignacio Ratke, I am a adventurous, zealous, outstanding, agreeable, precious, excited, gifted person who loves writing and wants to share my knowledge and understanding with you.