WireGuard example setup

Not a deep dive into WireGuard itself, but how to setup and use it.

Scope of this blog post is to have an easy understandable how to guide to quickly setup a WireGuard VPN with dualstack support through NAT.

Less blah blah, more commands and configs.

Requirements:

  • Debian 11 (Linux 5.10+ kernel)
  • At least either a public IPv4 or IPv6 address
  • Around 30 minutes of your time and somewhat useful Linux skills

Step 1: Setting up the server side

Install wireguard-tools by using apt like this:

apt install wireguard-tools

For each device you’ll need a private public keypair.

Use the following command to generate both private and public keys:

wg genkey | tee privatekey | wg pubkey > publickey

That way you have a fresh pair of it in your current directory.

In case you are in an IDGAF about security mode, take these values:

  • Private: qKTH2AX0wCTYC315UOdzf1eUs6+1F1UI7yBGA21hEUc=
  • Public: LQA8GIRJAjeN0NweVSSnYxmV5DwP74JpDyu/jT1vCSY=

I highly effing recommend you dicing your own keys, though.

Moving on to the WireGuard config itself. We are going to create a config file and let systemd manage it as a service through the [email protected].

By this point you’ll need a private IPv4 subnet and a ULA IPv6 prefix.

For the sake of simplicity, I chose both for you:

  • IPv4: 100.123.42.0/24
  • IPv6: fd4e:80e:2adc::/64

Create the following file as /etc/wireguard/wg0.conf:

[Interface]
Address = 100.123.42.1/24
Address = fd4e:80e:2adc::1/64
PrivateKey = qKTH2AX0wCTYC315UOdzf1eUs6+1F1UI7yBGA21hEUc=
ListenPort = 51280

PostUp = iptables -t nat -I POSTROUTING -s 100.123.42.0/24 -j MASQUERADE
PreDown = iptables -t nat -D POSTROUTING -s 100.123.42.0/24 -j MASQUERADE

PostUp = ip6tables -t nat -I POSTROUTING -s fd4e:80e:2adc::/64 -j MASQUERADE
PreDown = ip6tables -t nat -D POSTROUTING -s fd4e:80e:2adc::/64 -j MASQUERADE

Next up you’ll need some sysctl tuning to allow your Linux server to act as a router.

Please create the following file as /etc/sysctl.d/50-forwarding.conf:

net.ipv4.conf.all.forwarding = 1
net.ipv4.conf.default.forwarding = 1
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.default.forwarding = 1
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0

Apply it by using this command: sysctl -p /etc/sysctl.d/50-forwarding.conf

Please make sure your iptables and ip6tables rules are in yolo mode which means the default policy for FORWARD is ACCEPT. That’s usually the default configuration anyway.

Enable and start the service: systemctl enable --now wg-quick@wg0

Step 2: Setup a client

Prerequisites for each client:

  1. Repeat the private and public key dance from above.
    1. The public key goes into the [Peer] section of your server config.
    2. The private key goes into the [Interface] section of your client config.
  2. Allocate an IP address per address family.
    1. The address with its prefix length goes in the AllowedIPs in your [Peer] section of your server config.
    2. The address with its prefix length goes in the Address in your [Interface] section of your client config.

Make sure you pick a unique key pair and IP addresses for each client.

Example values:

  • IPv4 address: 10.123.42.2/32
  • IPv6 address: fd4e:80e:2adc::2/128
  • Private key: gKqGRcQOCVhVqmN5e0QYkj7K7lhNStYig8EntNjDDEM=
  • Public key: 8Yku08ytK+3OGVi8RC2K5opM4PqF84VPZmW4xFH52CY=

Now go back to the /etc/wireguard/wg0.conf from step one and add the following lines:

[Peer]
PublicKey = 8Yku08ytK+3OGVi8RC2K5opM4PqF84VPZmW4xFH52CY=
AllowedIPs = 10.123.42.2/32, fd4e:80e:2adc::2/128

Restart the service: systemctl restart wg-quick@wg0

Get the hostname or the public IPv6 or public IPv4 address of your server. We need that now.

Now assemble the client config:

[Interface]
PrivateKey = gKqGRcQOCVhVqmN5e0QYkj7K7lhNStYig8EntNjDDEM=
Address = 100.123.42.2/32, fd4e:80e:2adc::2/128
MTU = 1280

[Peer]
PublicKey = LQA8GIRJAjeN0NweVSSnYxmV5DwP74JpDyu/jT1vCSY=
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = wg0.example.net:51280
#Endpoint = [2001:db8::1]:51280
#Endpoint = 192.0.2.1:51280

Make sure to use the server’s public key in PublicKey in the [Peer] section and the correct address (again: the public one of your server) in Endpoint in the [Peer] section as well.

You can use the wireguard-tools and wg-quick on your Linux client as well. Just adapt the steps from step one without the sysctl things.

You can encode your config as a QR code and scan it in the official WireGuard Android app as well.

Good to know

  • On the client side: Instead of 0.0.0.0/0 and ::/0 you can use whatever and as many prefixes as you like and only route a few prefixes through the VPN.
  • On the server side: If you have prefixes routed to your WireGuard server, you can skip the NAT (iptables/ip6tables) configuration.
  • You can change the MTU, 1280 is recommended in unpredictable environments. To calculate it yourself: MTU = Outside MTU – 80. So on a 1500 Internet uplink you can use 1420 as MTU for the WireGuard interface. Consult the configuration or/and documentation your Internet connection to find the right value.
  • Make sure to properly safe guard your server using a firewall only allowing outbound connections. Theoretically your clients are exposed under certain circumstances.
  • Check out wg(8) for more information. It can do more things than outlined here.