WireGuard VPN

I decided to finally get a WireGuard VPN set up on my Hetzner server recently. Why now… no reason.

The protocol is natively part of the Linux kernel, and is also supported by systemd which makes setting up a VPN fairly simple. There’s still a few moving parts to the setup, so let’s go through them.

I have an nftables firewall, but we only need to open the WireGuard port. Nftables can do a lot more, but I don’t need it to. Systemd provides systemd-networkd which is configured to create the WireGuard network and allow clients to connect. The VPN gets its own subnet with the private 10.0.0.0 address space, with the server getting address 10.0.0.1. I then set the DNS of my clients to 10.0.0.1 so they will use my server’s DNS.

Step 1 is setting up my firewall, my configuration does slightly differ as I have a couple more ports than web and WireGuard open:

#!/usr/bin/nft -f
# IPv4/IPv6 Simple & Safe Firewall for WireGuard VPN
# Simplified configuration for systemd-networkd setup

define wg_port = 51820
define vpn_if = wg0

table inet firewall {
  chain input {
    ...

    udp dport $wg_port accept comment "allow wireguard"

    iifname $vpn_if udp dport 53 accept comment "allow dns from vpn clients"
    iifname $vpn_if tcp dport 53 accept comment "allow dns from vpn clients"
  }

  chain forward {
    type filter hook forward priority filter
    policy drop

    ct state {established, related} accept
    ct state invalid drop
    iifname $vpn_if accept comment "allow forwarding from vpn clients"
  }
}

Now to setup a WireGuard network with systemd. The network itself is defined with two files. One at /etc/systemd/network/wg0.netdev:

[NetDev]
Name=wg0
Kind=wireguard
Description=WireGuard VPN tunnel

[WireGuard]
PrivateKey=<server-private-key>
ListenPort=51820

[WireGuardPeer]
PublicKey=<client-1-public-key>
AllowedIPs=10.0.0.2/32,fd00::2/128

[WireGuardPeer]
PublicKey=<client-2-public-key>
AllowedIPs=10.0.0.3/32,fd00::3/128

Then also /etc/systemd/network/wg0.network:

[Match]
Name=wg0

[Network]
Address=10.0.0.1/24
Address=fd00::1/64
IPv4Forwarding=yes
IPv6Forwarding=yes
IPMasquerade=both

[Route]
Destination=10.0.0.0/24
Scope=link

[Route]
Destination=fd00::/64
Scope=link

Notice the lines setting up IP forwarding and IP masquerading. This could be done with rules in the nftables firewall, but is much simpler set within systemd I find.

Then a client config will look like:

[Interface]
PrivateKey = <client-1-private-key>
Address = 10.0.0.2/24, fd00::2/64
DNS = 10.0.0.1, fd00::1

[Peer]
PublicKey = <server-public-key>
Endpoint = example.com:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25

And now I can turn on a VPN tunnel with the WireGuard app on my computer and access the internet via my Hetzner server. I can also access IPv6 only sites from home now, which doesn’t have v6 connectivity natively!

It took a little bit of playing around with different configurations to get this all working, first time round I tried this and failed I didn’t know I could use systemd; or support hadn’t landed in systemd yet.

Just finished Love & Death starring Elizabeth Olsen from a few years ago, really quite enjoyable, a solid 7/10

Did the nice cliche of biopics of showing real pictures of the people at the end of the show.

Well that was an awful performance

Woop woop premier league is back baby! Now let’s go an beat Hull please

Well, I think summer might be over here in Manchester

Episode 2 of Ted Lasso was so much better than episode 1! But guess we needed episode 1 to set up this new season

I genuinely don’t know how people use macOS without a clipboard manager like Pastebot. Which by the wya has had an excellent v3 release recently.

I am liking the look of the new Man Utd 3rd kit. It’s different with the logos stacked.

Was weird sitting outside during the eclipse today. Definitely got darker even though we only had 91% totality in Manchester.

Spider-man, Spider-man, does whatever a spider can — with Sophie

My name is Jonny Barnes, and jonnybarnes.uk is my site. I’m from Manchester, UK .

I am active to varying degrees on several silos:

My usual online nickname is normally jonnybarnes. Here’s a profile pic. You can email me at hi@jonnybarnes.uk, or message me on Matrix: @jonnybarnes:matrix.org.