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:
- Repeat the private and public key dance from above.
- The public key goes into the
[Peer]
section of your server config. - The private key goes into the
[Interface]
section of your client config.
- The public key goes into the
- Allocate an IP address per address family.
- The address with its prefix length goes in the
AllowedIPs
in your[Peer]
section of your server config. - The address with its prefix length goes in the
Address
in your[Interface]
section of your client config.
- The address with its prefix length goes in the
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.