Wireguard
Modern state-of-the-art VPN designed to be simpler and faster that IPsec and openVPN.
Migrated to ansible collection
Only the server endpoint needs to be exposed publicly. Clients can globally roam as long as they have working Internet connections and can send UDP traffic to the given port.
Key Generation
Warning
The private key will enable anyone to impersonate that client on the VPN.
Public/Private keys need to be generated for each machine using wireguard. A bare bones utility is provided. Generated keys are not OS specific.
/usr/local/bin/wggen
0755 root:root
#!/bin/bash
# Generate wireguard keys.
WG=/usr/bin/wg
TEE=/usr/bin/tee
if [ -z "$1" ]; then
echo "Requires name for output files."
exit 1
else
name=$1
fi
${WG} genkey | ${TEE} ${1}.key | ${WG} pubkey > ${1}.pub
chmod 0400 ${1}.{key,pub}
Examples
This setup enables a private network connection to the server, preventing other clients on that network from communicating to other clients. DNS and any network access not directly addressed to the private network will egress through the client's standard network stack.
This creates a /24 network that all machines use, while only allowing point to point communications from each client to the server.
Server
/etc/wireguard/server.conf
0600 root:root
[Interface]
Address = 172.31.255.254/24
SaveConfig = False
ListenPort = 51820
PrivateKey = {SERVER PRIVATE KEY}
# Client #1
[Peer]
PublicKey = {CLIENT PUBLIC KEY}
AllowedIPs = 172.31.255.250/32
# Bring up the tunnel for testing.
systemctl enable wg-quick@server
Clients
Warning
Windows clients do not use the SaveConfig option. Remove this line if configuring a Windows client.
/etc/wireguard/client.conf
0600 root:root
[Interface]
Address = 172.31.255.250/24
PrivateKey = {CLIENT PRIVATE KEY}
SaveConfig = False
# Wireguard server
[Peer]
PublicKey = {SERVER PUBLIC KEY}
EndPoint = {SERVER PUBLIC IP}:51820
AllowedIPs = 172.31.255.254/32
# Bring up the tunnel for testing.
systemctl enable wg-quick@client
Testing
# Show server network status and ping a client.
wg
ping 172.31.255.250
# Show client network status and ping server. Pinging other clients should fail.
wg
ping 172.31.255.254
ping 172.31.255.100
Behaves like a traditional VPN network. All traffic and DNS lookups are routed through the connection to be resolved in the VPN server location.
Server
# Enable IP traffic forwarding on iptables.
echo 1 > /proc/sys/net/ipv4/ip_forward
echo 1 > /proc/sys/net/ipv6/ip_forward
/etc/sysctl.conf
0644 root:root
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
/etc/wireguard/server.conf
0600 root:root
[Interface]
Address = 172.31.255.254/24
SaveConfig = False
ListenPort = 51820
PrivateKey = {SERVER PRIVATE KEY}
# Automatically adjust iptables rules to allow forwarded traffic when VPN up.
PostUp = iptables -A FORWARD -i {WIREGUARD TUNNEL} -j ACCEPT; iptables -t nat -A POSTROUTING -o {INTERFACE} -j MASQUERADE; ip6tables -A FORWARD -i {WIREGUARD TUNNEL} -j ACCEPT; ip6tables -t nat -A POSTROUTING -o {INTERFACE} -j MASQUERADE
PostDown = iptables -D FORWARD -i {WIREGUARD TUNNEL} -j ACCEPT; iptables -t nat -D POSTROUTING -o {INTERFACE} -j MASQUERADE; ip6tables -D FORWARD -i {WIREGUARD TUNNEL} -j ACCEPT; ip6tables -t nat -D POSTROUTING -o {INTERFACE} -j MASQUERADE
# Client #1
[Peer]
PublicKey = {CLIENT PUBLIC KEY}
AllowedIPs = 172.31.255.250/32
# Bring up the tunnel for testing.
systemctl enable wg-quick@server
Client
Tip
Set a custom DNS server if needed. DNS is resolved at the VPN server.
/etc/wireguard/client.conf
0600 root:root
# Route all traffic through VPN connection.
[Interface]
Address = 172.31.255.250/24
PrivateKey = {CLIENT PRIVATE KEY}
DNS = 1.1.1.1,1.1.2.2
SaveConfig = False
# Wireguard server
[Peer]
PublicKey = {SERVER PUBLIC KEY}
EndPoint = {SERVER PUBLIC IP}:51820
AllowedIPs = 0.0.0.0/0
# Bring up the tunnel for testing.
systemctl enable wg-quick@vpn-client
From the client access the Internet and verify that your data is routed through the VPN server.
A quick test can be verifying different IP's from https://www.whatismyip.com.
InitRAMFS
Enable wireguard during boot process allowing for remote unlocks anywhere in the world.
Migrated to ansible collection
This enables the used of Dropbear and related unlock utilities over a wireguard network before a system has booted.
Install
Install Wireguard first, then install the latest package from https://github.com/r-pufky/wireguard-initramfs:
wget https://github.com/r-pufky/wireguard-initramfs/archive/refs/tags/2025-03-02.tar.gz
tar xvf 2025-03-02.tar.gz
cd wireguard-initramfs-2025-03-02
make install
Configure
/etc/wireguard/initramfs.conf
0600 root:root
[Interface]
Address = 172.31.255.10/32
PrivateKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
[Peer]
PublicKey = gyW39I9bAiOBXyhL8LWw9qwiTZgMmtAbsWtLUv8uKTc=
AllowedIPs = 172.31.255.254/32
PresharedKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
PersistentKeepalive = 25
Endpoint = {SERVER INTERFACE IP}:51820
/etc/wireguard/initramfs
0644 root:root
ADAPTER=/etc/wireguard/initramfs.conf
# Enable wg-quick for adapter management?
ENABLE_QUICK=
# URL to send a web request to set the local datetime.
#
# Raspberry Pi's should enable this feature for wireguard-initramfs to work.
#
# Skipped if blank.
DATETIME_URL=
# Persist (do not down) interface after initramfs exits? Any value enables.
PERSISTENT=
# Enable debug logging (will expose key material)? Any value enables.
DEBUG=
Note
Most systems do not encrypt /boot so private key material is exposed and considered compromised/untrusted. Boot wireguard network should be different & untrusted, versus the network used after booting. Always restrict ports and access on the wireguard server.
# Add wireguard to initramfs.
update-initramfs -u
update-grub
reboot
Dropbear Remote Unlock
Unlock an encrypted root filesystem remotely on boot over wireguard.
Ensure that both Dropbear and Wireguard are setup and working correctly. Then set dropbear to only listen over wireguard network:
/etc/dropbear-initramfs/config
0644 root:root
DROPBEAR_OPTIONS='... -p 172.31.255.10:22 ...'
# Update dropbear config in initramfs.
update-initramfs -u
update-grub
reboot
- The boot wireguard network should be separate from your normal wireguard network. Protect the server endpoint and restrict all ports not needed.
- The boot and running wireguard networks should have different keys.
- Set UFW on the host as well for further protection.