François' Blog

Simple WireGuard on Linux

Published on 2024-03-01

We'll describe how to set up a simple WireGuard VPN server between two Debian 12 systems. One acting as a "server", and one as a "client". If you follow the steps below, this will survive reboots and aims to be safe to run in production. It can also be used to create a simple WireGuard server test setup on a cheap VM somewhere.

Trees next to Werbellinsee, Germany

Keys

WireGuard uses private and public keys using the PrivateKey and PublicKey fields in the configuration file. Each "peer" needs to have their own pair.

In the examples below we'll use the following keys, this makes it easy to match them with the various configuration snippets below.

NOTE: you MUST generate your own keys as shown below and use them, NOT these example keys!

A private key can be generated using the wg command, from the wireguard-tools package, we'll install it below in the Server section.

$ wg genkey

To extract the public key from a private key, you can use e.g. this:

$ echo 'xLV2NAqYpJWLO5Og2uJuXcaMuW0Wk+wycGwD+4fOQPY=' | wg pubkey

It will show WAhc6YSytsbaRbgsrOx7++FkSOHTG3rAYuUbQXV8vV4= as output, matching what was shown above.

Server

Install the required Debian packages:

$ sudo apt -y install wireguard-tools nftables

Put this in /etc/wireguard/wg0.conf:

[Interface]
Address = 10.43.43.1/24,fd43::1/64
ListenPort = 51820
PrivateKey = xLV2NAqYpJWLO5Og2uJuXcaMuW0Wk+wycGwD+4fOQPY=

[Peer]
PublicKey = THmB/OI2kWvlnsATLN59LtXYIL3rfshAWXGKVSZ0Dhg=
AllowedIPs = 10.43.43.2/32,fd43::2/128

Enable and start the interface:

$ systemctl enable --now wg-quick@wg0

Now to configure the firewall, we use the following /etc/nftables.conf:

table inet filter {
    chain input {
        type filter hook input priority filter; policy drop;
        ct state vmap { invalid : drop, established : accept, related : accept }
        iifname "lo" accept

        # if you want to restrict SSH access to certain IP ranges, comment the
        # next line, and uncomment line(s) below
        tcp dport 22 accept
        #ip saddr { 192.0.2.0/24 } tcp dport 22 accept
        #ip6 saddr { 2001:db8::/32 } tcp dport 22 accept

        udp dport 51820 accept
        icmp type echo-request limit rate 5/second accept
        icmpv6 type { echo-request limit rate 5/second, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept
    }

    chain forward {
        type filter hook forward priority filter; policy drop;
        ct state vmap { invalid : drop, established : accept, related : accept }
        iifname "wg0" accept
    }

    chain postrouting {
        type nat hook postrouting priority srcnat; policy accept;
        masquerade
    }
}

Enable and start the firewall:

$ sudo systemctl enable --now nftables

Create a file /etc/sysctl.d/70-vpn.conf:

net.ipv4.ip_forward = 1
net.ipv6.conf.eth0.accept_ra = 2
net.ipv6.conf.all.forwarding = 1

Replace eth0 with your server's external interface name. Now enable these changes:

$ sudo sysctl --system

NOTE: the line net.ipv6.conf.eth0.accept_ra = 2 is needed in case your server receives its IPv6 address via "Router Advertisement". If you have a static IPv6 address on your server this is not necessary and should be removed.

Client

If you are running a Debian desktop installation with e.g. GNOME or KDE, you most likely have NetworkManager installed, in that case see NetworkManager for a simpler approach.

On a "CLI only" install, install the required Debian packages:

$ sudo apt -y install wireguard-tools openresolv

Put this in /etc/wireguard/wg0.conf and replace vpn.example with the IP address or hostname of your VPN server:

[Interface]
PrivateKey = O2sDxac/5XRbVMx2QoSabqfj248Pc2MuOV5SivSfGQQ=
Address = 10.43.43.2/24,fd43::2/64
DNS = 9.9.9.9,2620:fe::fe

[Peer]
PublicKey = WAhc6YSytsbaRbgsrOx7++FkSOHTG3rAYuUbQXV8vV4=
AllowedIPs = 0.0.0.0/0,::/0
Endpoint = vpn.example:51820

Enable and start the interface:

$ systemctl enable --now wg-quick@wg0

You should be online through the VPN now!

NetworkManager

If you are running a Debian desktop with GNOME or KDE you can simply use NetworkManager.

Put this in vpn.conf and replace vpn.example with the IP address or hostname of your VPN server:

[Interface]
PrivateKey = O2sDxac/5XRbVMx2QoSabqfj248Pc2MuOV5SivSfGQQ=
Address = 10.43.43.2/24,fd43::2/64
DNS = 9.9.9.9,2620:fe::fe

[Peer]
PublicKey = WAhc6YSytsbaRbgsrOx7++FkSOHTG3rAYuUbQXV8vV4=
AllowedIPs = 0.0.0.0/0,::/0
Endpoint = vpn.example:51820

Now you can import this configuration file:

$ nmcli con import type wireguard file vpn.conf

This should configure and immediately activate the VPN.

You should be online through the VPN now!

To stop the VPN, e.g. in case something does not work:

$ nmcli con down vpn

To delete the configuration:

$ nmcli con delete vpn

History