Build a WireGuard VPN
You may want to review the typographical conventions used on this site.
Install WireGuard
Install the WireGuard packages and dependencies.
On non-amd64 computers, adjust the linux-headers-amd64
package
to match your architecture.
apt-get install build-essential linux-headers-amd64 dkms
apt-get install wireguard-tools wireguard-dkms wireguard
Configure WireGuard
For the purposes of this tutorial, the following example network will be used:
- Site-1 and Site-2 need to securely communicate over the Internet.
- Alice works at Site-1. Her laptop establishes a VPN to Site-1 when she is traveling.
- Bob works at Site-2. His laptop establishes a VPN to Site-2 when he is traveling.
Generate Per-Peer Asymmetric Keys
Each WireGuard peer requires a unique public-private key pair. The following command pipeline will generate a private key, and then generate a public key for that private key. Execute these commands on each WireGuard peer to generate a unique key pair for that peer.
umask 077
wg genkey | tee private.key | wg pubkey > public.key
Since there are four WireGuard peers in this tutorial, four key pairs are required:
- Gateway-1
- Gateway-2
- Alice
- Bob
The private.key
and public.key
files can be deleted
once their contents have been copied into the relevant configuration files.
Generate Per-Tunnel Pre-Shared Keys
For additional security, each WireGuard tunnel can add a unique pre-shared key (PSK). Execute the following command to generate each PSK.
wg genpsk
Since there are three WireGuard tunnels in this tutorial, three PSKs are required:
- Gateway-1 – Gateway-2
- Alice – Gateway-1
- Bob – Gateway-2
Configuration Files
Gateway-1 (GW1)
Gateway-1: /etc/wireguard/wg0.conf
[Interface]
#PublicKey = GW1_PublicKey
PrivateKey = GW1_PrivateKey
ListenPort = 4510
Address = 192.168.11.1/24, fd1e:6fe0:5044:420b::1/64
# Peer: Gateway-2
[Peer]
PublicKey = GW2_PublicKey
PresharedKey = GW1_GW2_PSK
AllowedIPs = 192.168.20.0/23, fd1e:6fe0:5044:4214::/63
Endpoint = GW2_PUBLIC_IP:4510
# Peer: Alice's laptop
[Peer]
PublicKey = ALICE_PublicKey
PresharedKey = GW1_ALICE_PSK
AllowedIPs = 192.168.11.10/32, fd1e:6fe0:5044:420b::a/128
For the Gateway-2 peer, AllowedIPs
contains all IP address space at Site-2:
192.168.20.0/23
contains both 192.168.20.0/24
and 192.168.21.0/24
,
and fd1e:6fe0:5044:4214::/63
contains both fd1e:6fe0:5044:4214::/64
and fd1e:6fe0:5044:4215::/64
.
For simple endpoint peers, such as Alice’s laptop,
AllowedIPs
contains the specific IPv4 and IPv6 addresses for that peer.
Gateway-1 is also running a DNS recursive resolver that is listening
on addresses 192.168.11.1
and fd1e:6fe0:5044:420b::1
.
Gateway-2 (GW2)
Gateway-2: /etc/wireguard/wg0.conf
[Interface]
#PublicKey = GW2_PublicKey
PrivateKey = GW2_PrivateKey
ListenPort = 4510
Address = 192.168.21.1/24, fd1e:6fe0:5044:4215::1/64
# Peer: Gateway-1
[Peer]
PublicKey = GW1_PublicKey
PresharedKey = GW1_GW2_PSK
AllowedIPs = 192.168.10.0/23, fd1e:6fe0:5044:420a::/63
Endpoint = GW1_PUBLIC_IP:4510
# Peer: Bob's laptop
[Peer]
PublicKey = BOB_PublicKey
PresharedKey = GW2_BOB_PSK
AllowedIPs = 192.168.21.10/32, fd1e:6fe0:5044:4215::a/128
For the Gateway-1 peer, AllowedIPs
contains all IP address space at Site-1:
192.168.10.0/23
contains both 192.168.10.0/24
and 192.168.11.0/24
,
and fd1e:6fe0:5044:420a::/63
contains both fd1e:6fe0:5044:420a::/64
and fd1e:6fe0:5044:420b::/64
.
For simple endpoint peers, such as Bob’s laptop,
AllowedIPs
contains the specific IPv4 and IPv6 addresses for that peer.
Gateway-2 is also running a DNS recursive resolver that is listening
on addresses 192.168.21.1
and fd1e:6fe0:5044:4215::1
.
Alice
Alice’s laptop: /etc/wireguard/wg0.conf
[Interface]
#PublicKey = ALICE_PublicKey
PrivateKey = ALICE_PrivateKey
Address = 192.168.11.10/32, fd1e:6fe0:5044:420b::a/128
DNS = 192.168.11.1, fd1e:6fe0:5044:420b::1
# Peer: Gateway-1
[Peer]
PublicKey = GW1_PublicKey
PresharedKey = GW1_ALICE_PSK
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = GW1_PUBLIC_IP:4510
Bob
Bob’s laptop: /etc/wireguard/wg0.conf
[Interface]
#PublicKey = BOB_PublicKey
PrivateKey = BOB_PrivateKey
Address = 192.168.21.10/32, fd1e:6fe0:5044:4215::a/128
DNS = 192.168.21.1, fd1e:6fe0:5044:4215::1
# Peer: Gateway-2
[Peer]
PublicKey = GW2_PublicKey
PresharedKey = GW2_BOB_PSK
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = GW2_PUBLIC_IP:4510
Control WireGuard
On peers such as VPN gateways,
configure systemd to automatically start the wg0
interface.
systemctl daemon-reload
systemctl start wg-quick@wg0.service
systemctl enable wg-quick@wg0.service
On other peers, you can manually bring the wg0
interface
up and down on an as-needed basis.
wg-quick up wg0
wg-quick down wg0
To show the current status of all WireGuard interfaces:
wg show