WireGuard¶
The strange VPN that is pretty fast at everything.
Basic setup¶
Server side:
[Interface]
PrivateKey = <server-private-key>
Address = 10.0.0.1/24, 2001:db8::1/64
ListenPort = 51820
[Peer]
PublicKey = <client-public-key>
AllowedIPs = 10.0.0.2/32, 2001:db8::2/128
Client side:
[Interface]
PrivateKey = <client-private-key>
Address = 10.0.0.2/32, 2001:db8::2/128
[Peer]
PublicKey = <server-public-key>
AllowedIPs = 10.0.0.0/24, 2001:db8::/64
Endpoint = server.example.com:51820
Note: You can reverse roles by adding ListenPort to the clients Interface and Endpoint to the server Peer section, though this may complicate IPv4 NAT traversal.
Extra functionality¶
Behind IPv4 NAT¶
If you're behind NAT, the connection may timeout due to inactivity.
Add PersistentKeepalive to maintain the connection:
DNS¶
DNS configuration only works with wg-quick, systemd-networkd, or GUI tools - not with the basic wg command.
When routing all traffic through WireGuard (0.0.0.0/0), you may lose DNS access on some networks. Add DNS servers to your client configuration:
PostUp/PreDown scripts¶
PostUp and PreDown allow running commands when the interface comes up or goes down. These only work with wg-quick, systemd-networkd, or GUI tools - not with the basic wg command.
Common use cases (server side - NAT/forwarding):
[Interface]
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PreDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
Client side examples:
[Interface]
PostUp = echo "Connected to VPN"
PostUp = /home/you/vpn-connect-script.sh
PreDown = echo "Disconnected from VPN"
Multiple commands can be separated with semicolons or using multiple PostUp/PreDown lines.
Note: %i is replaced with the interface name. Scripts run with root privileges, so be careful with security.
AllowedIPs¶
AllowedIPs serves dual purposes
Server side: Defines which source IPs are allowed from this peer (access control)
Client side: Defines which destinations to route through the tunnel (routing table)
The peer's Interface address must always be included in AllowedIPs.
Just other WG clients (mesh network)¶
WireGuard network + home LAN access¶
Full tunnel (all traffic)¶
Routes all traffic through WireGuard:
Allow DNS¶
If you're using a weird OS like MacOS, you may need to specificly include routes for your DNS servers. Why? idk, it should already be covered.. Might be some security stuff.
Split tunnel (internet only, preserve local access)¶
Routes internet traffic through WireGuard while keeping local network access:
[Peer]
AllowedIPs = 2000::/3, 1.0.0.0/8, 2.0.0.0/8, 3.0.0.0/8, 4.0.0.0/6, 8.0.0.0/7, 11.0.0.0/8, 12.0.0.0/6, 16.0.0.0/4, 32.0.0.0/3, 64.0.0.0/2, 128.0.0.0/3, 160.0.0.0/5, 168.0.0.0/6, 172.0.0.0/12, 172.32.0.0/11, 172.64.0.0/10, 172.128.0.0/9, 173.0.0.0/8, 174.0.0.0/7, 176.0.0.0/4, 192.0.0.0/9, 192.128.0.0/11, 192.160.0.0/13, 192.169.0.0/16, 192.170.0.0/15, 192.172.0.0/14, 192.176.0.0/12, 192.192.0.0/10, 193.0.0.0/8, 194.0.0.0/7, 196.0.0.0/6, 200.0.0.0/5, 208.0.0.0/4
Additional considerations¶
IP forwarding: Enable on the server with net.ipv4.ip_forward=1 and net.ipv6.conf.all.forwarding=1 for routing to work.
Key generation: Use wg genkey | tee private.key | wg pubkey > public.key to generate keypairs securely.