How to Set Up Wireguard VPN Server on Ubuntu 22.04

How to Set Up Wireguard VPN Server on Ubuntu 22.04

WireGuard is an open-source general-purpose VPN (Virtual Private Network) designed for fast, secure, and easy-to-use connections between devices. It uses state-of-the-art cryptography and is designed to be simple, lightweight, and efficient.

It is currently available on multiple platforms, including Linux, Windows, and macOS. It supports both IPv4 and IPv6 connections.

WireGuard uses public and private keys to establish encrypted tunnels between peers to ensure security. It is much faster compared to other VPN protocols such as OpenVPN and IPSec.

In this tutorial, we are going to learn how to set up WireGuard on an Ubuntu 22.04 server.

First, let’s take a look at the prerequisites needed for this tutorial and make sure you have everything ready before proceeding further.

Pre-Requisites

For this tutorial, we need:

  • An Ubuntu 22.04 server that supports both IPv4 and IPv6 connections.
  • An Ubuntu 22.04 peer machine with which WireGuard Server will connect. We are using our local machine as our peer for this tutorial but a remote server can also be used.
  • A non-root user with sudo privileges.

Execute the below commands in their respective order to make sure everything is up to date.

sudo apt update
sudo apt upgrade

Now that we have fulfilled all the prerequisites, we can begin the tutorial. Follow this step-by-step guide to set up WireGuard on Ubuntu 22.04 server.

Install WireGuard

The first step is to install WireGuard VPN on our server. WireGuard will be installed when the below command is executed.

sudo apt install wireguard

You might be prompted to enter the sudo password when executing the above command. And then, the system will ask you whether you want to proceed with the installation. Enter Y to continue.

After the WireGuard installation is complete, it is time to generate the public and private keys needed for encrypted communication between peers.

Generate Keypair

First, we are going to generate a private key using the below command. The wg genkey command is used to generate private keys while the wg pubkey command is used to generate public keys.

wg genkey | sudo tee /etc/wireguard/private.key

The output of the above command is the private key, as shown in the picture below.

Output
cFqdP6KW7gaOdeIlVIoXqHbMHhNmeZ2LaVj5vPBETmc=

The private key will be printed on the terminal. Make a note of it. A copy of this private key is also stored at /etc/wireguard/private.key file.

Now we have to change access to this key file so that only root users can access the private key file. The below command will achieve this.

sudo chmod go= /etc/wireguard/private.key

Now the last step is to generate a corresponding public key to our private key. This is done by using the wg pubkey command in the following way. First, take a look at the following command, and then we’ll dissect the command to understand it better.

sudo cat /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key

The above command will also return a single line output which is the public key associated with the private key we generated first. Make a note of this key, as any peer wishing to connect to the server will need this public key to get access.

Now let’s dissect the above command. The above command is made up of three different commands chained together using the | (pipe) operator:

  • sudo cat /etc/wireguard/private.key: this command fetches the private key.
  • wg pubkey: this command takes the output of the first command as input and uses it to generate a respective public key.
  • sudo tee /etc/wireguard/public.key: this command takes the output public key and places it into the /etc/wireguard/public.key file.

Select IPv4 and IPv6 Address

Now that we have installed WireGuard and generate key pairs that will be used to encrypt traffic from and to the server. We can proceed to the next step which is configuring the IPv4 and IPv6 addresses that will be used for communication between the Server and peers wanting to connect to it.

For IPv4

For IPv4 peers, the server needs a range of IPv4 addresses for clients and its tunnel interface. Any range of IP addresses can be selected from the following reserved blocks of addresses:

10.0.0.0 to 10.255.255.255 (10/8 prefix)
172.16.0.0 to 172.31.255.255 (172.16/12 prefix)
192.168.0.0 to 192.168.255.255 (192.168/16 prefix)

For this tutorial we are selecting the 10.8.0.0/24 block of IP addresses as this range will allow up to 255 peer connections. The WireGuard server is going to use the above-selected range to assign IPs to peers.

For IPv6

If you want to use WireGuard with IPv6, you will have to generate a unique IPv6 prefix based on the RFC algorithm.

According to RFC the best way to get a unique IPv6 prefix is to combine the time of the day with a unique value from the system such as a serial number or device ID. The resulting set of bits can be used as a unique address within the reserved private “fd00::/8” block of IPs once those values have been hashed.

To get started, collect a 64-bit timestamp for your system by executing the below command.

date +%s%N

The above command will generate an output similar to the one written below which is the time elapsed in seconds since the Unix Epoch (00:00 UTC 1 January 1970).

Output
1662132483303862200

Make sure to note down this value too, along with the private and public keys, as all this information will be used in server configuration.

Next, copy the machine id for your server as this value is unique for every server. Execute the below command to get the machine id.

cat /var/lib/dbus/machine-id
Output
8d87100241cbed3b363218d362a9f92f

Now the last step is to combine the timestamp and the machine id using the SHA-1 algorithm. It will also hash the result value. The general format of the command is written below.

printf <timestamp><machine-id> | sha1sum

Substitute your timestamp and machine id in the above command and run it. By inserting the above value, the command will look as follows (you should insert your own machine id and timestamp to generate a unique IPv6 prefix).

printf 16621324833038622008d87100241cbed3b363218d362a9f92f | sha1sum

The output will be a hash value similar to the one shown below.

Output
a311a36a27ac476015998855190908d5a3acc4fd -

Now run the above command again combined with the cut command to trim the above output in accordance with the RFC algorithm, which is to get the last 5 hexadecimal encoded bytes from the above hash.

printf a311a36a27ac476015998855190908d5a3acc4fd | cut -c 31-
Output
d5a3acc4fd

In the above example output, the set of bytes is d5 a3 ac c4 fd.

The IPv6 prefix is generated by appending the above 5 bytes with the fd prefix while separating every 2 bytes with a ":" for readability. And for simplicity, we are restricting the subnet size to /64.

So the above output will become:

fdd5:a3ac:a4fd::/64

This fdd5:a3ac:a4fd::/64 will be used to assign IP addresses to your WireGuard tunnel interface. For example, to allocate an IP to the server, add 1 after the :: character.

Configure WireGuard

Before beginning the configuration, make sure that you have executed the above steps and have the necessary data i.e private key, IPv4, or IPv6 address range.

Create a new configuration file using the nano text editor. You can use any other editor if you prefer.

sudo nano /etc/wireguard/wg0.conf

Now paste the following lines in the file while putting in your respective private key and IP address values.

[Interface]
PrivateKey = cFqdP6KW7gaOdeIlVIoXqHbMHhNmeZ2LaVj5vPBETmc=
Address = 10.8.0.1/24, fdd5:a3ac:a4fd::1/64
ListenPort = 51820
SaveConfig = true

Save the file by pressing Ctrl+X and then enter Y to exit.

Configure WireGuard Network

You do not need to complete this step if you are merely connecting a peer to the WireGuard Server to access server-side services.

To configure forwarding, open the /etc/sysctl.conf file using nano editor by executing the below line.

sudo nano /etc/sysctl.conf

The file looks like below:

word image 15098 2

Uncomment the following lines by removing the # sign.

For IPv4:

Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1

For IPv6:

# Uncomment the next line to enable packet forwarding for IPv6
#  Enabling this option disables Stateless Address Autoconfiguration
#  based on Router Advertisements for this host
net.ipv6.conf.all.forwarding=1

If you plan to use both IPv4 and IPv6 you have to uncomment both lines.

Press Ctrl+X to save changes and then enter Y to exit.

Now to confirm that the changes have been made you can execute the below command which will read the file and load new values for the current terminal session.

sudo sysctl -p
Output
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1

Now our WireGuard Server can forward traffic coming from the virtual VPN ethernet device to peers on the server and to the public internet. This configuration will allow you to route web traffic from your WireGuard peer via your server IP while hiding your client’s IP address.

However, we will first need to configure some firewall rules for the proper flow of traffic.

Configure WireGuard Server Firewall

Now we are going to configure the WireGuard server Firewall so that the traffic from and to the server is routed correctly.

First, we are going to find the public network interface of our WireGuard server by executing the below-mentioned command.

ip route list default
Output
default via 172.22.32.1 dev eth0

The above output shows that eth0 is the public interface.

Now we add the Firewall rules to the server by editing the WireGuard configuration file. Execute the below command to edit the file using nano.

sudo nano /etc/wireguard/wg0.conf

Paste the following lines at the bottom of this file.

PostUp = ufw route allow in on wg0 out on eth0
PostUp = iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
PostUp = ip6tables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
PreDown = ufw route delete allow in on wg0 out on eth0
PreDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
PreDown = ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

Then press Ctrl+X to save and then enter Y to exit the file.

If you are using just IPv4 exclude the ip6tables lines. In the same manner, if you are only using IPv6 then remove the iptables lines. Otherwise past the above lines as it is.

The last thing left is to allow traffic on the WireGuard UDP port. The default port is 51820 but if you configured another port in the configuration file, edit the below command to mention that port before execution.

To open the 51820 port execute the below command.

sudo ufw allow 51820/udp
Output
Rules updated
Rules updated (v6)

To open the SSH port if you have not enabled it, execute the below command.

sudo ufw allow OpenSSH
Output
Rules updated
Rules updated (v6)

Now shut down and restart the Firewall to confirm that all changes have taken effect. Execute the below commands in their respective order to disable and enable Firewall.

sudo ufw disable
sudo ufw enable

Then execute the below command to check the status.

sudo ufw status
Output
Status: active

To                         Action      From
--                         ------      ----
Apache                     ALLOW       Anywhere
51820/udp                  ALLOW       Anywhere
OpenSSH                    ALLOW       Anywhere
Apache (v6)                ALLOW       Anywhere (v6)
51820/udp (v6)             ALLOW       Anywhere (v6)
OpenSSH (v6)               ALLOW       Anywhere (v6)

Start the Server

Now we are going to configure the WireGuard server to run as a service using the built-in wg-quick script. By making it a service, we can configure WireGuard to start at boot. Run the below command to do this.

sudo systemctl enable [email protected]
Output
Created symlink /etc/systemd/system/multi-user.target.wants/[email protected] → /lib/systemd/system/[email protected].

Now start the service:

sudo systemctl start [email protected]
Output
[email protected] - WireGuard via wg-quick(8) for wg0
     Loaded: loaded (/lib/systemd/system/[email protected]; enabled; vendor preset: enabled)
     Active: active (exited) since Mon 2022-04-18 17:22:13 UTC; 2s ago
       Docs: man:wg-quick(8)
             man:wg(8)
             https://www.wireguard.com/
             https://www.wireguard.com/quickstart/
             https://git.zx2c4.com/wireguard-tools/about/src/man/wg-quick.8
             https://git.zx2c4.com/wireguard-tools/about/src/man/wg.8
    Process: 98834 ExecStart=/usr/bin/wg-quick up wg0 (code=exited, status=0/SUCCESS)
   Main PID: 98834 (code=exited, status=0/SUCCESS)
        CPU: 193ms

Apr 18 17:22:13 thats-my-jam wg-quick[98834]: [#] wg setconf wg0 /dev/fd/63
Apr 18 17:22:13 thats-my-jam wg-quick[98834]: [#] ip -4 address add 10.8.0.1/24 dev wg0
Apr 18 17:22:13 thats-my-jam wg-quick[98834]: [#] ip -6 address add fdd5:a3ac:a4fd::1/64 dev wg0
Apr 18 17:22:13 thats-my-jam wg-quick[98834]: [#] ip link set mtu 1420 up dev wg0
Apr 18 17:22:13 thats-my-jam wg-quick[98834]: [#] ufw route allow in on wg0 out on ens3
Apr 18 17:22:13 thats-my-jam wg-quick[98890]: Rule added
Apr 18 17:22:13 thats-my-jam wg-quick[98890]: Rule added (v6)
Apr 18 17:22:13 thats-my-jam wg-quick[98834]: [#] iptables -t nat -I POSTROUTING -o ens3 -j MASQUERADE
Apr 18 17:22:13 thats-my-jam wg-quick[98834]: [#] ip6tables -t nat -I POSTROUTING -o ens3 -j MASQUERADE
Apr 18 17:22:13 thats-my-jam systemd[1]: Finished WireGuard via wg-quick(8) for wg0.

The output shows that the server is up and running without defined IPv4 and IPv6 addresses.

Set Up WireGuard on the Client Side

Now we are going to take a look at how to configure a WireGurad peer so that clients can connect to your server.

Install WireGuard

First, we need to install WireGuard on the client machine by executing the below lines.

sudo apt update
sudo apt install wireguard

Generate Peer Keypair

Now we need to generate a key pair for the clients the same way we did for the server in Generate Keypair section.

Execute the below command to generate the private key.

wg genkey | sudo tee /etc/wireguard/private.key

The above command will return a single-line output. Please note it down.

This command will edit the access of the file so that only root users can view it.

sudo chmod go= /etc/wireguard/private.key

Now execute the below command to generate a public key.

sudo cat /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key

Make sure to note down this public key too.

Create WireGuard Peer Configuration File

To do this, make sure you have the necessary information, which includes the private key for the peer, the IPv4 and IPv6 ranges defined on the Server, the public key from the Server, the Public Address and IP port of the WireGuard Server.

After making sure that you have the above information execute the below line to create a configuration file using the nano editor.

sudo nano /etc/wireguard/wg0.conf

Then paste the following lines in it.

[Interface]
PrivateKey = private_key of peer
Address = 10.8.0.3/24
Address = fdd5:a3ac:a4fd::3/64

[Peer]
PublicKey = JySX9hMJFyAqZA+mNvJsArKW7yY8I7ROsQKTZZR/RH8=
AllowedIPs = 10.8.0.0/24, fdd5:a3ac:a4fd::/64
Endpoint = 209.23.10.202:51820

Now press Ctrl+X to save and then enter Y to exit the file. The first address is the IPv4 address from the 10.8.0.0/24 subnet we configured, and the second address is the IPv6 address from the subnet. Just keep in mind to make these addresses different from the IP configured for the Server.

Add Public Key of Peer to the Server

Run the below command to check the public key of the WireGuard peer.

sudo cat /etc/wireguard/public.key
Output
5EyjWrD3EuPputqrX0+B5Kepeow9XBuJ1RGEI1w2+VM=

Now login to the server and execute the below command.

sudo wg set wg0 peer PeURxj4Q75RaVhBKkRTpNsBPiPSGb5oQijgJsTa29hg= allowed-ips 10.8.0.2,fdd5:a3ac:a4fd::2

Anytime in the future, if you wish to update allowed IPs for a peer, execute the above command by replacing the IP addresses mentioned with the updated ones.

Now run the below command to check the status of the tunnel.

sudo wg

Connect Peer to the Tunnel

Run the below command to start the tunnel on the peer.

sudo wg-quick up wg0

You will get the following output.

[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.8.0.3/24 dev wg0
[#] ip -6 address addfdd5:a3ac:a4fd::3/64 dev wg0
[#] ip link set mtu 1420 up dev wg0
[#] resolvconf -a tun.wg0 -m 0 -x

You can run the below command to confirm the status of the tunnel on the peer.

sudo wg

Conclusion

In this tutorial, we learned about everything there is to know about setting up the WireGuard VPN on the Ubuntu 22.04 server.

We learned how to install WireGuard on the server and how to select the range of IPv4 and IPv6 addresses for the server. This same process has to be done for the peer who is going to connect to the server.

Then we configured WireGuard for the peer and added the public key of the peer to the server so that the peer can connect to the server.

0 Shares:
Subscribe
Notify of
guest
Receive notifications when your comment receives a reply. (Optional)
Your username will link to your website. (Optional)

0 Comments
Inline Feedbacks
View all comments
You May Also Like