Ubuntu 22.04 WireGuard Configuration Guide
Introduction
WireGuard is a lightweight Virtual Private Network (VPN) solution supporting both IPv4 and IPv6 connections. A VPN lets you navigate untrusted networks as if you were on a secure, private network. This setup enables safe internet access from your smartphone or laptop, especially on public networks like hotel or coffee shop WiFi.
WireGuard relies on public and private keys for encrypted communication between peers. Unlike VPNs like OpenVPN and IPSec, which use Transport Layer Security (TLS) and certificates, WireGuard's single cryptographic suite keeps configuration simple and efficient.
In this guide, you’ll set up WireGuard on an Ubuntu 22.04 server and configure another machine as a peer, using both IPv4 and IPv6 for a dual-stack connection. You’ll also learn how to route peer internet traffic through the WireGuard server for gateway functionality and encrypted peer-to-peer communication.
For this tutorial, another Ubuntu 22.04 system will act as the peer, or client, to the WireGuard server. Later guides will detail setup for Windows, macOS, Android, and iOS.
Note: If you’re using a server like a DigitalOcean Droplet, be aware of potential bandwidth charges.
Prerequisites
You’ll need:
- An Ubuntu 22.04 server with a sudo-enabled non-root user and firewall. We’ll refer to this as the WireGuard Server.
- A client device to connect to the WireGuard server, referred to as the WireGuard Peer. Your local machine is recommended, but remote servers and mobile devices can also act as clients.
- To use IPv6 with WireGuard, ensure your server supports IPv6 traffic. If using a DigitalOcean Droplet, refer to their documentation on enabling IPv6 (opens in a new tab).
Step 1 — Installing WireGuard and Generating a Key Pair
To start, update your server's package index and install WireGuard:
sudo apt update
sudo apt install wireguard
Then, generate a private and public key pair for the server:
-
Create the private key and set permissions:
wg genkey | sudo tee /etc/wireguard/private.key sudo chmod go= /etc/wireguard/private.key
-
Generate the public key:
sudo cat /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key
Keep the public key for reference, as it will be shared with peers for encryption.
Step 2 — Choosing IPv4 and IPv6 Addresses
You’ll need to assign private IPv4 and IPv6 addresses for the WireGuard server and peers.
Step 2(a) — Choosing an IPv4 Range
For IPv4 addresses, you can use one of these private IP ranges:
- 10.0.0.0/8 (used in this guide as
10.8.0.0/24
) - 172.16.0.0/12
- 192.168.0.0/16
The server will use an IP like 10.8.0.1/24
from this range, with clients using IPs within the same subnet.
Step 2(b) — Choosing an IPv6 Range
To generate a unique IPv6 range based on RFC 4193 (opens in a new tab), you’ll create a private IPv6 prefix by combining a timestamp with your machine’s unique ID, hashing the combined value, and extracting a portion of the hash to form a prefix.
Steps to Generate a Unique IPv6 Prefix:
-
Collect the timestamp and machine ID
Run the following commands to generate a 64-bit timestamp and retrieve the machine ID, which provides a unique identifier for your system:date +%s%N cat /var/lib/dbus/machine-id
- Example Output:
- Timestamp:
1650301699497770167
- Machine ID:
610cef4946ed46da8f71dba9d66c67fb
- Timestamp:
- Example Output:
-
Generate a unique IPv6 prefix
Combine the timestamp and machine ID, then hash the result with SHA-1. After hashing, extract the last 5 bytes of the hash to create a unique 40-bit value, which you’ll use in your prefix.printf <timestamp><machine-id> | sha1sum printf <hash> | cut -c 31-
-
Example Commands and Outputs:
printf 1650301699497770167610cef4946ed46da8f71dba9d66c67fb | sha1sum
- Hash:
442adea1488d96388dae9ab816045b24609a6c18 -
printf 442adea1488d96388dae9ab816045b24609a6c18 -| cut -c 31-
- Last 5 bytes:
24609a6c18
- Hash:
-
-
Construct the IPv6 prefix
Use thefd
prefix and format your unique 40-bit value by inserting colons every two bytes. Set the prefix to a /64 subnet for simplicity.- Resulting IPv6 Prefix:
fd24:609a:6c18::/64
For your WireGuard configuration, assign
fd24:609a:6c18::1/64
to the server. Each peer can increment the last segment, such asfd24:609a:6c18::2/64
,fd24:609a:6c18::3/64
, and so on. - Resulting IPv6 Prefix:
This range is now ready for configuring WireGuard tunnel interfaces. Proceed to the next section to continue the setup.
Step 3 — Creating a WireGuard Server Configuration
Once you have the private key and IP address(es), create a configuration file and change the permissions:
sudo vim /etc/wireguard/wg0.conf
sudo chmod go= /etc/wireguard/wg0.conf
Add the following lines, replacing <base64_encoded_private_key_goes_here>
with your private key and the Address
line with your chosen IP(s):
[Interface]
PrivateKey = base64_encoded_private_key_goes_here
Address = 10.8.0.1/24, fd24:609a:6c18::1/64
ListenPort = 51820
SaveConfig = true
Save the configuration file by pressing ESC
, typing :wq
, and hitting Enter.
Step 4 — Adjusting the WireGuard Server’s Network Configuration
To route peer traffic through the WireGuard server, enable IP forwarding:
sudo vim /etc/sysctl.conf
Add these lines based on your setup:
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
Save and close the file, then apply the changes:
sudo sysctl -p
Your WireGuard server is now set to handle VPN connections and route traffic through its public IP address. Further firewall configuration is recommended to complete the setup, ensuring secure and efficient traffic handling between server and peer.
Step 5 — Configuring the WireGuard Server’s Firewall
In this section, you’ll update the WireGuard Server’s configuration to add firewall rules for correct routing of traffic to and from the server and clients. If your VPN setup is only for a machine-to-machine connection, skip this step.
To allow WireGuard VPN traffic through the server’s firewall, enable masquerading, a form of dynamic network address translation (NAT) that helps route client connections.
Start by identifying the public network interface of your WireGuard Server:
ip route list default
Look for the network interface after the dev
keyword. For example, in this output:
default via 198.51.100.1 dev ens3 proto static
The interface ens3
is your public network interface.
Open the /etc/wireguard/wg0.conf
file for editing:
sudo nano /etc/wireguard/wg0.conf
Add these lines at the end of the file, after SaveConfig = true
:
/etc/wireguard/wg0.conf
. . .
PostUp = ufw route allow in on wg0 out on ens3
PostUp = iptables -t nat -I POSTROUTING -o ens3 -j MASQUERADE
PostUp = ip6tables -t nat -I POSTROUTING -o ens3 -j MASQUERADE
PreDown = ufw route delete allow in on wg0 out on ens3
PreDown = iptables -t nat -D POSTROUTING -o ens3 -j MASQUERADE
PreDown = ip6tables -t nat -D POSTROUTING -o ens3 -j MASQUERADE
These PostUp
rules will activate when the WireGuard Server starts the VPN tunnel:
ufw route allow in on wg0 out on ens3
: Allows IPv4 and IPv6 forwarding fromwg0
toens3
.iptables -t nat -I POSTROUTING -o ens3 -j MASQUERADE
: Configures IPv4 masquerading to make traffic appear from the server's public IP.ip6tables -t nat -I POSTROUTING -o ens3 -j MASQUERADE
: Configures IPv6 masquerading similarly.
The PreDown
rules deactivate these settings when the VPN tunnel is closed.
Allow WireGuard Port Traffic in Firewall
If using the default WireGuard UDP port 51820, open it with UFW:
sudo ufw allow 51820/udp
sudo ufw allow OpenSSH
Restart UFW to load the new rules:
sudo ufw disable
sudo ufw enable
Confirm the rules are in place:
sudo ufw status
You should see output like:
Status: active
To Action From
-- ------ ----
51820/udp ALLOW Anywhere
22/tcp ALLOW Anywhere
51820/udp (v6) ALLOW Anywhere (v6)
22/tcp (v6) ALLOW Anywhere (v6)
Step 6 — Starting the WireGuard Server
To have WireGuard run as a systemd service, enable the wg-quick
service:
sudo systemctl enable wg-quick@wg0.service
sudo systemctl start wg-quick@wg0.service
Verify that WireGuard is running:
sudo systemctl status wg-quick@wg0.service
Example 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 Thu 2024-10-10 12:34:56 UTC; 2s ago
Docs: man:wg-quick(8)
man:wg(8)
Step 7 — Configuring a WireGuard Peer
-
Install WireGuard: On the peer system, update package sources and install WireGuard:
sudo apt update sudo apt install wireguard
-
Generate the Peer’s Key Pair: To create the private key:
wg genkey | sudo tee /etc/wireguard/private.key sudo chmod go= /etc/wireguard/private.key
To create the public key from the private key:
sudo cat /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key
Keep both the public and private keys secure. You’ll use the private key for the peer configuration and share the public key with the WireGuard server.
-
Create the Peer’s Configuration File:
-
Open
/etc/wireguard/wg0.conf
on the peer:sudo nano /etc/wireguard/wg0.conf
-
Add the following configuration, substituting
base64_encoded_peer_private_key_goes_here
with the peer’s private key andU9uE2kb/nrrzsEU58GD3pKFU3TLYDMCbetIsnV8eeFE=
with the server’s public key:[Interface] PrivateKey = base64_encoded_peer_private_key_goes_here Address = 10.8.0.2/24 Address = fd24:609a:6c18::2/64 [Peer] PublicKey = U9uE2kb/nrrzsEU58GD3pKFU3TLYDMCbetIsnV8eeFE= AllowedIPs = 10.8.0.0/24, fd24:609a:6c18::/64 Endpoint = 198.51.100.1:51820
If you want to route all traffic through the VPN, modify
AllowedIPs
as follows:AllowedIPs = 0.0.0.0/0, ::/0
-
-
(Optional) Add Routing Rules for All Traffic: If the peer should route all traffic over the VPN, add routing rules for remote access. For a home network setup with internal IPs, use your peer’s internal IP (
10.0.0.20
) and gateway (10.0.0.1
):PostUp = ip rule add table 200 from 10.0.0.20 PostUp = ip route add table 200 default via 10.0.0.1 PreDown = ip rule delete table 200 from 10.0.0.20 PreDown = ip route delete table 200 default via 10.0.0.1
-
(Optional) Port Forwarding for WireGuard: Since the peer is behind a home router, configure port forwarding on your router to ensure incoming connections from the WireGuard server reach the peer.
- Port Forwarding Steps:
- Log into your router’s administration panel (usually found at
http://10.0.0.1
in a browser). - Find the Port Forwarding section, typically under Advanced Settings or Firewall Settings.
- Create a new rule to forward UDP traffic on port
51820
(or the port specified in your WireGuard setup) to the internal IP of the peer device (10.0.0.20
). - Save the settings and test connectivity.
- Log into your router’s administration panel (usually found at
Note: Ensure the router’s firewall allows UDP traffic on the WireGuard port.
- Port Forwarding Steps:
-
(Optional) Configure Peer DNS: To secure DNS traffic, add your server’s DNS resolvers to the peer’s configuration:
DNS = 67.207.67.2 2001:4860:4860::8844
-
Add the Peer’s Public Key to the WireGuard Server: Log into the WireGuard server and run:
sudo wg set wg0 peer PeURxj4Q75RaVhBKkRTpNsBPiPSGb5oQijgJsTa29hg= allowed-ips 10.8.0.2/32, fd24:609a:6c18::2/128
-
Connect the Peer:
- To start the VPN tunnel on the peer, use:
sudo wg-quick up wg0
- Verify the connection with:
sudo wg
- To start the VPN tunnel on the peer, use:
-
Verification:
- Check routing:
ip route get 1.1.1.1 ip -6 route get 2606:4700:4700::1111
- Check routing:
-
Disconnecting: To stop the tunnel, use:
sudo wg-quick down wg0
Additional Notes for Peers Behind Home Routers
If the peer device is behind a home router that doesn’t allow advanced routing or NAT configuration, you may need to enable IP masquerading on the WireGuard server. This allows the server to rewrite the source IP of packets coming from the peer’s internal IP (10.8.0.0/24
) so that outgoing traffic from the VPN appears as coming from the server’s external IP.
On the WireGuard server’s /etc/wireguard/wg0.conf
, add the following:
PostUp = iptables -t nat -A POSTROUTING -o eth0 -s 10.8.0.0/24 -j MASQUERADE
PreDown = iptables -t nat -D POSTROUTING -o eth0 -s 10.8.0.0/24 -j MASQUERADE
This ensures that traffic from the peer (10.8.0.0/24) is correctly routed without requiring configuration changes on the home router.
Troubleshooting Tips:
- DNS Resolution Issues: If you can’t load websites, make sure the
DNS
setting in the WireGuard configuration points to DNS servers. - Testing Connectivity: Use
ping
ortraceroute
to confirm network reachability.
Step 8 — Adding the Peer’s Public Key to the WireGuard Server
Before connecting the peer to the server, you must add the peer’s public key to the WireGuard Server. This step enables the peer to connect and route traffic over the VPN. Without this, the WireGuard server won’t allow the peer to transmit or receive data over the tunnel.
Ensure you have the base64-encoded public key for the WireGuard Peer. You can retrieve it by running:
sudo cat /etc/wireguard/public.key
Example output:
PeURxj4Q75RaVhBKkRTpNsBPiPSGb5oQijgJsTa29hg=
Log into the WireGuard server, and use this command to add the peer:
sudo wg set wg0 peer PeURxj4Q75RaVhBKkRTpNsBPiPSGb5oQijgJsTa29hg= allowed-ips 10.8.0.2/32, fd24:609a:6c18::2/128
The allowed-ips
parameter takes a comma-separated list of IPv4 and IPv6 addresses. This restricts the IP addresses that the peer can assign itself. Ensure each peer has a unique allowed-ips
setting.
To update the allowed-ips
for an existing peer, rerun the command with modified IP addresses. For example, to add 10.8.0.100
:
sudo wg set wg0 peer PeURxj4Q75RaVhBKkRTpNsBPiPSGb5oQijgJsTa29hg= allowed-ips 10.8.0.2/32, 10.8.0.100/32, fd24:609a:6c18::2/128
To confirm the peer's configuration, run:
sudo wg
Example output:
interface: wg0
public key: U9uE2kb/nrrzsEU58GD3pKFU3TLYDMCbetIsnV8eeFE=
private key: (hidden)
listening port: 51820
peer: PeURxj4Q75RaVhBKkRTpNsBPiPSGb5oQijgJsTa29hg=
allowed ips: 10.8.0.2/32, fd24:609a:6c18::/128
Step 9 — Connecting the WireGuard Peer to the Tunnel
With the server and peer configurations complete, connect the peer to the VPN tunnel.
To manually start the tunnel, use the wg-quick
command:
sudo wg-quick up wg0
Example 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 fd24:609a:6c18::2/64 dev wg0
[#] ip link set mtu 1420 up dev wg0
If your peer’s AllowedIPs
setting covers all traffic (0.0.0.0/0
and ::/0
), the output will show routing rules for default routes:
[#] ip -4 route add 0.0.0.0/0 dev wg0 table 51820
[#] ip -4 rule add not fwmark 51820 table 51820
To verify the tunnel status on the peer, run:
sudo wg
Example output:
interface: wg0
public key: PeURxj4Q75RaVhBKkRTpNsBPiPSGb5oQijgJsTa29hg=
private key: (hidden)
listening port: 49338
fwmark: 0xca6c
peer: U9uE2kb/nrrzsEU58GD3pKFU3TLYDMCbetIsnV8eeFE=
endpoint: 203.0.113.1:51820
allowed ips: 10.8.0.0/24, fd24:609a:6c18::/64
Verifying Peer Routing
Run the following to check the route for external traffic, such as Cloudflare's DNS:
ip route get 1.1.1.1
Example output:
1.1.1.1 dev wg0 table 51820 src 10.8.0.2 uid 1000
For IPv6:
ip -6 route get 2606:4700:4700::1111
Example output:
2606:4700:4700::1111 from :: dev wg0 table 51820 src fd24:609a:6c18::2 metric 1024 pref medium
If the peer is routing all traffic over the VPN, websites like ipleak.net
and ipv6-test.com
will confirm the peer’s traffic is being routed correctly.
To disconnect from the VPN, use:
sudo wg-quick down wg0
Example output:
[#] ip link delete dev wg0
[#] resolvconf -d tun.wg0 -f
To reconnect, simply run wg-quick up wg0
.
Removing a Peer from the WireGuard Server
To remove a peer entirely, use:
sudo wg set wg0 peer PeURxj4Q75RaVhBKkRTpNsBPiPSGb5oQijgJsTa29hg= remove
This is typically only necessary if the peer is decommissioned or if its keys are compromised.
Conclusion
In this guide, you set up WireGuard on an Ubuntu 22.04 server and peer, created firewall rules, configured routing, and verified connectivity. You also learned how to limit VPN access by setting specific allowed-ips
for peers and how to configure WireGuard to handle all internet traffic from peers.
For more information on advanced configurations, consult the official WireGuard documentation (opens in a new tab).