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.
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!
-
Server
- SecretKey:
xLV2NAqYpJWLO5Og2uJuXcaMuW0Wk+wycGwD+4fOQPY=
- PublicKey:
WAhc6YSytsbaRbgsrOx7++FkSOHTG3rAYuUbQXV8vV4=
- SecretKey:
-
Client
- SecretKey:
O2sDxac/5XRbVMx2QoSabqfj248Pc2MuOV5SivSfGQQ=
- PublicKey:
THmB/OI2kWvlnsATLN59LtXYIL3rfshAWXGKVSZ0Dhg=
- SecretKey:
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