How to Set Up WireGuard VPN on Ubuntu 22.04
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
to10.255.255.255
(10/8 prefix)172.16.0.0
to172.31.255.255
(172.16/12 prefix)192.168.0.0
to192.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