VPNs-On-Ubuntu
Wireguard Install and Configuration

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:

  1. Create the private key and set permissions:

    wg genkey | sudo tee /etc/wireguard/private.key
    sudo chmod go= /etc/wireguard/private.key
  2. 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:

  1. 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
  2. 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
  3. Construct the IPv6 prefix
    Use the fd 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 as fd24:609a:6c18::2/64, fd24:609a:6c18::3/64, and so on.

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 from wg0 to ens3.
  • 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

  1. Install WireGuard: On the peer system, update package sources and install WireGuard:

    sudo apt update
    sudo apt install wireguard
  2. 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.

  3. 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 and U9uE2kb/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
  4. (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
  5. (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.

    Note: Ensure the router’s firewall allows UDP traffic on the WireGuard port.

  6. (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
  7. 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
  8. Connect the Peer:

    • To start the VPN tunnel on the peer, use:
      sudo wg-quick up wg0
    • Verify the connection with:
      sudo wg
  9. Verification:

    • Check routing:
      ip route get 1.1.1.1
      ip -6 route get 2606:4700:4700::1111
  10. 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 or traceroute 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).