How to Set Up WireGuard VPN on Ubuntu 22.04

ComputingPost
11 min readDec 10, 2022

--

Wireguard is an open-source cross-platform Virtual Private Network (VPN) implementation that uses state-of-the-art cryptography. It supports IPv4 and IPv6 connections. It is faster, simpler, and more functional than IPSec and OpenVPN protocols. It is designed as a general-purpose VPN to run on embedded interfaces and super computers and runs on Linux, Windows, macOS, iOS, Android, and various other platforms.

Wireguard’s encryption works using private and public keys for peers to establish an encrypted tunnel between themselves.

This tutorial will cover how to install Wireguard VPN on a Ubuntu 22.04 server and connect to it using a Ubuntu client.

Prerequisites

  • A server running Ubuntu 22.04 supports both IPv4 and IPv6 connections.
  • A client running Ubuntu 22.04 to connect to the Wireguard server. For our tutorial, we will be using our local machine as our client but you can use a remote server for it.
  • A non-root user with sudo privileges.
  • The uncomplicated Firewall(UFW) is enabled and running.
  • Everything is updated.
  • $ sudo apt update && sudo apt upgrade

Step 1 — Install Wireguard and Generating a Key Pair

Ubuntu 22.04 ships with the latest version of Wireguard. Install Wireguard.

$ sudo apt install wireguard

The next step is to generate a private and public keypair for the server. Create a private key for the server using the wg genkey command.

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

Change the permissions to protect the private key. The chmod go= command blocks other users and groups from accessing the file. You will receive the encoded key on your terminal. Note the key because it will be required later.

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

Next, generate the corresponding public key derived from the private key. Use the wg pubkey to generate the public key. The following command has three parts, where the first part outputs the private key which is used by the wg pubkey command to generate the public key which is then stored in the respective file.

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

You will again receive the public key on the terminal. Make a note of it.

Step 2 — Choosing IPv4 and IPv6 Addresses

We need to define private IPv4 and IPv6 addresses to use with your Wireguard server and peers.

Choosing an IPv4 Range

To use Wireguard with IPv4 peers, the server needs a range of private IPv4 addresses for its tunnel interface. You can choose any range of IP addresses 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 our tutorial, we will use 10.8.0.0/24 as a block of IP addresses from the first range of reserved IPs. This range allows up to 255 peer connections. You can also use the private IP range provided by your hosting company.

Choosing an IPv6 Range

According to the RFC algorithm, the recommended way to obtain a unique IPv6 prefix is to combine the time of day with a unique value like machine ID. Those values are then hashed and truncated to use as a unique address within the reserved private fd00::/8 block of IPs.

The first step is to collect a 64-bit timestamp using the date utility.

$ date +%s%N

It will generate an output similar to the following which is the number of seconds elapsed since the Unix Epoch time (00:00 UTC 1 January 1970).

1659342559092041940

Note the value for later use. Next, copy the machine-id value of your server. This value is unique to every system.

$ cat /var/lib/dbus/machine-id

You will get a similar output.

d97e195db6584d63aeedfdc35dc83c7f

Next, combine the timestamp with the machine-id and hash the string using the SHA-1 algorithm.

printf  | sha1sum

Replace the and the values in the above command from before. You will receive another hash value.

$ printf 1659342559092041940d97e195db6584d63aeedfdc35dc83c7f | sha1sum

d789c02d9d8faef806d40ec15b307d4d9c8ec4bc -

Run the following command to trim the printf output in accordance with the RFC algorithm.

$ printf d789c02d9d8faef806d40ec15b307d4d9c8ec4bc | cut -c 31-

You should get the following output.Advertisement

4d9c8ec4bc

In the above output, the set of bytes is 4d 9c 8e c4 bc. Generate the IPv6 address by appending the 5 bytes above with the fd prefix in the following way.

Using the bytes previously generated with the /64 subnet size the resulting prefix will be the following.

Unique Local IPv6 Address Prefix

fd4d:9c8e:c4bc::/64

To allocate an IP for the server, add 1 after the final :: characters. The resulting address will be fd4d:9c8e:c4bc::1/64. Peers use the IP address by adding another increment such as fd4d:9c8e:c4bc::2/64.

Step 3 — Configure Wireguard

Generate a configuration file and open for it editing.

$ sudo nano /etc/wireguard/wg0.conf

Paste the following code in it. Replace the server_private_key with the private key generated in step 1. You can change the listening port to anything you like.

[Interface]

PrivateKey = server_private_key

Address = 10.8.0.1/24, fd4d:9c8e:c4bc::/64

ListenPort = 51820

SaveConfig = true

Save the file by pressing Ctrl + X and entering Y when prompted.

Step 4 — Configure Wireguard Network

To route the peer’s traffic through the Wireguard server, you need to configure IP forwarding. Open the file /etc/sysctl.conf for editing.

$ sudo nano /etc/sysctl.conf

Uncomment the following lines by removing the hash sign in front of it.

# Uncomment the next line to enable packet forwarding for IPv4

net.ipv4.ip_forward=1



# 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

Save the file by pressing Ctrl + X and entering Y when prompted. Verify the new values using the following command.

$ sudo sysctl -p

net.ipv4.ip_forward = 1

net.ipv6.conf.all.forwarding = 1

vm.swappiness = 0

Now your Wireguard server will forward all incoming traffic from the VPN ethernet device to others on the server, and from there to the public internet. This allows the server to route all web traffic from the peer via the server’s IP address and will hide the client’s IP address.

The next step is to configure firewall rules for the forwarding to work properly.

Step 5 — Configure Wireguard Server’s Firewall

To allow the VPN traffic through the server’s firewall, you need to enable masquerading that provides on-the-fly dynamic network address translation (NAT) to route client connections.

Find the public network interface of your Wireguard server.

$ ip route list default

default via 209.23.8.1 dev eth0 proto static

According to the above command, eth0 is the public interface.

Open the Wireguard configuration file to add the firewall rules to your Wireguard server.

$ sudo nano /etc/wireguard/wg0.conf

Paste the following lines at the bottom of the file after the SaveConfig = true line.

. . .

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

Save the file by pressing Ctrl + X and entering Y when prompted.

The PostUp lines run when the Wireguard server starts the VPN tunnel. The first rule allows forwarding IPv4 and IPv6 traffic. The second and third rule configures masquerading for IPv4 and IPv6 traffic. The PreDown lines run when the Wireguard server stops the VPN tunnel.

The last step in configuring the firewall is to allow traffic to and from the Wireguard UDP port. Use the Uncomplicated Firewall (UFW) to open the Wireguard port.

Check the status of the firewall.

$ sudo ufw status

You should see something like the following.

Status: active



To Action From

-- ------ ----

OpenSSH ALLOW Anywhere

OpenSSH (v6) ALLOW Anywhere (v6)

Open the 51820 port configured in step 1. If you are using a different port for Wireguard, open that port.

$ sudo ufw allow 51820/udp

Disable and re-enable the UFW firewall to load the changes from all the files modified in this step.

$ sudo ufw disable

$ sudo ufw enable

Check the status again to confirm.

Status: active



To Action From

-- ------ ----

OpenSSH ALLOW Anywhere

51820/udp ALLOW Anywhere

OpenSSH (v6) ALLOW Anywhere (v6)

51820/udp (v6) ALLOW Anywhere (v6)

Your Wireguard server is configured to handle the VPN traffic, including forwarding and masquerading for peers.

Step 6 — Start the WireGuard Server

Wireguard can be configured to run as a service using the wg-quick script. Enable the Wireguard service.

$ sudo systemctl enable wg-quick@wg0.service

The wg0 part of the service name corresponds to the /etc/wireguard/wg0.conf file. This means you can create as many VPN tunnels as you want by using a different configuration file and service.

Start the Wireguard service.

$ sudo systemctl start wg-quick@wg0.service

Check the status of the service.

$ sudo systemctl status wg-quick@wg0.service

You will get a similar output.

? wg-quick@wg0.service - WireGuard via wg-quick(8) for wg0

Loaded: loaded (/lib/systemd/system/wg-quick@.service; enabled; vendor preset: enabled)

Active: active (exited) since Mon 2022-08-01 11:35:59 UTC; 6s 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: 3935 ExecStart=/usr/bin/wg-quick up wg0 (code=exited, status=0/SUCCESS)

Main PID: 3935 (code=exited, status=0/SUCCESS)

CPU: 216ms



Aug 01 11:35:58 wireguard wg-quick[3935]: [#] wg setconf wg0 /dev/fd/63

Aug 01 11:35:58 wireguard wg-quick[3935]: [#] ip -4 address add 10.8.0.1/24 dev wg0

Aug 01 11:35:58 wireguard wg-quick[3935]: [#] ip -6 address add fd4d:9c8e:c4bc::/64 dev wg0

Aug 01 11:35:59 wireguard wg-quick[3935]: [#] ip link set mtu 1420 up dev wg0

Aug 01 11:35:59 wireguard wg-quick[3935]: [#] ufw route allow in on wg0 out on eth0

Aug 01 11:35:59 wireguard wg-quick[3978]: Rule added

Aug 01 11:35:59 wireguard wg-quick[3978]: Rule added (v6)

Aug 01 11:35:59 wireguard wg-quick[3935]: [#] iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE

Aug 01 11:35:59 wireguard wg-quick[3935]: [#] ip6tables -t nat -I POSTROUTING -o eth0 -j MASQUERADE

Aug 01 11:35:59 wireguard systemd[1]: Finished WireGuard via wg-quick(8) for wg0.

Step 7 — Installing and Configuring a Wireguard Peer

Install the Wireguard client on the Ubuntu 22.04 based peer.

$ sudo apt update

$ sudo apt install wireguard

If you are installing on a local Ubuntu desktop, then Wireguard is probably pre-installed.

Create the Wireguard Peer’s Key Pair

Generate a key pair on the peer in the same way as you did in step 1. Also, give permissions to the private key.

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

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

Create the public key.

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

Create the Peer Configuration file

To create the peer configuration file you need the following things:

  • The base64 encoded private key generated on the peer.
  • The IPv4 and IPv6 address ranges defined on the Wireguard server.
  • The base64 encoded public key from the Wireguard server.
  • The public IP address and port number of the Wireguard server. If your server and the client have an IPv6 connection, you need to use the IPv6 address.

Create and open the Peer configuration file for editing.

$ sudo nano /etc/wireguard/wg0.conf

Paste the following code in it.

[Interface]

PrivateKey = peer_private_key

Address = 10.8.0.2/24

Address = fd4d:9c8e:c4bc::2/64



[Peer]

PublicKey = JySX9hMJFyAqZA+mNvJsArKW7yY8I7ROsQKTZZR/RH8=

AllowedIPs = 10.8.0.0/24, fd4d:9c8e:c4bc::/64

Endpoint = 209.23.10.202:51820

PersistentKeepalive = 15

Save the file by pressing Ctrl + X and entering Y when prompted.

The first key is the private key generated on the peer. The first address line uses an IPv4 address from the subnet chosen earlier. The second address line uses an IPv6 address from the subnet chosen earlier.

The second key is the public key generated on the server. The AllowedIPs uses the IPv4 and IPv6 ranges chosen before that instruct the peer to only send traffic over the VPN if the destination system has an IP address in either range. You can omit the IPv6 addresses if you are only using the IPv4 connection.

Configure Peer to route all traffic over the Tunnel

Find the IP address that the system uses as its default gateway. Run the following ip route command.

$ ip route list table main default

You will get a similar output.

default via 69.28.84.1 dev eth0 proto static

Note the gateway’s IP address and device name. Find the public IP of the peer.

$ ip -brief address show eth0

You will receive a similar output.

eth0             UP             69.28.84.160/23 2607:f170:14:13::910/64 fe80::200:45ff:fe1c:54a0/64

Open the peer configuration file for editing.

$ sudo nano /etc/wireguard/wg0.conf

Paste the following lines before the [Peer] section.

PostUp = ip rule add table 200 from 69.28.84.160

PostUp = ip route add table 200 default via 69.28.84.1

PreDown = ip rule delete table 200 from 69.28.84.160

PreDown = ip route delete table 200 default via 69.28.84.1



[Peer]

. . .

Save the file by pressing Ctrl + X and entering Y when prompted.

The PostUp command creates a rule to check for any routing entries in table 200 when the IP matches the system's public IP. The PreDown command ensures traffic processed by table 200 uses the 203.0.113.1 gateway for routing instead of the Wireguard interface.

Configure Peer’s DNS Resolvers

Run the following command on the server by replacing eth0 with your ethernet's device name if it is different.

$ resolvectl dns eth0

You will receive a similar output.

Link 2 (eth0): 209.208.127.65 209.208.25.18 2001:4860:4860::8888 2001:4860:4860::8844

Open the peer’s configuration file.

$ sudo nano /etc/wireguard/wg0.conf

Add the following code before the [Peer] line.

DNS = 209.208.127.65 2001:4860:4860::8888



[Peer]

. . .

Save the file by pressing Ctrl + X and entering Y when prompted.

Step 8 — Adding the Peer’s Public Key to the Wireguard Server

Check the public key on the Wireguard peer.

$ sudo cat /etc/wireguard/public.key

PeURxj4Q75RaVhBKkRTpNsBPiPSGb5oQijgJsTa29hg=

Run the following command on your Wireguard server.

$ sudo wg set wg0 peer PeURxj4Q75RaVhBKkRTpNsBPiPSGb5oQijgJsTa29hg= allowed-ips 10.8.0.2,fd24:609a:6c18::2

To update the allowed-ips for an existing peer, run the above command again by changing the IP address.

Check the status of the tunnel on the server.

$ sudo wg

interface: wg0

public key: U9uE2kb/nrrzsEU58GD3pKFU3TLYDMCbetIsnV8eeFE=

private key: (hidden)

listening port: 51820



peer: PeURxj4Q75RaVhBKkRTpNsBPiPSGb5oQijgJsTa29hg=

allowed ips: 10.8.0.2/32, fd24:609a:6c18::2/128

Step 9 — Connecting the Peer to the Tunnel

Install resolvconf package in case you are routing all traffic through the VPN.

$ sudo apt install resolvconf

Start the tunnel on the peer.

$ sudo wg-quick up wg0

You will receive a similar output.

[#] ip link add wg0 type wireguard

[#] wg setconf wg0 /dev/fd/63

[#] ip -4 address add 10.8.0.2/24 dev wg0

[#] ip -6 address add fd4d:9c8e:c4bc::2/64 dev wg0

[#] ip link set mtu 1420 up dev wg0

[#] resolvconf -a tun.wg0 -m 0 -x

[#] ip rule add table 200 from 69.28.84.160

[#] ip route add table 200 default via 69.28.84.1

Check the status of the tunnel on the peer.

$ sudo wg

interface: wg0

public key: nbkscqPcItMsFtv3R/ylrcC9knA+3F0Z/UVCkGx/DFw=

private key: (hidden)

listening port: 45392



peer: JySX9hMJFyAqZA+mNvJsArKW7yY8I7ROsQKTZZR/RH8=

endpoint: 209.23.10.202:51820

allowed ips: 10.8.0.0/24, fd24:609a:6c18::/64

latest handshake: 23 seconds ago

transfer: 92 B received, 212 B sent

persistent keepalive: every 15 seconds

This confirms the connection between the peer and the VPN.

Verify that the peer is using the VPN.

$ ip route get 10.0.8.1

10.0.8.1 dev wg0 table 51820 src 10.8.0.2 uid 1000

cache

If you are using IPv6, use the following command instead.

$ ip -6 route get fd24:609a:6c18::1

fd24:609a:6c18::1 from :: dev wg0 proto kernel src fd24:609a:6c18::2 metric 256 pref medium

Use the following command to disconnect the peer.

$ sudo wg-quick down wg0

[#] ip link delete dev wg0

[#] resolvconf -d tun.wg0 -f

Use the following command to remove the peer configuration on the server.

$ sudo wg set wg0 peer nbkscqPcItMsFtv3R/ylrcC9knA+3F0Z/UVCkGx/DFw= remove

Conclusion

This completes the tutorial on setting and configuring a Wireguard VPN on a Ubuntu 22.04 server and connecting it with a client. If you have any questions, post them in the comments below.

https://www.computingpost.com/how-to-set-up-wireguard-vpn-on-ubuntu-22-04/?feed_id=21450&_unique_id=6394d499f3908

--

--

ComputingPost

ComputingPost — Linux Howtos, Tutorials, Guides, News, Tips and Tricks.