Overview:
Author: Diyaa
Published date: August 3rd, 2024
Last updated: August 3rd, 2024
This article contains all of the WireGuard documentations I have made for myself. I use WireGuard heavily in my homelab network for Site to Site (S2S) and remote access VPNs.
Wireguard configuration generation:
Keys generation:
Generate client private, public keys and save them into files:
Files:
wg genkey | tee private-key-client | wg pubkey > public-key-client > /dev/null
Generate server and client key pairs:
SERV_PRIV_KEY = $( wg genkey ); \
SERV_PUB_KEY = $( echo "${ SERV_PRIV_KEY }" | wg pubkey ); \
CLIENT_PRIV_KEY = $( wg genkey ); \
CLIENT_PUB_KEY = $( echo "${ CLIENT_PRIV_KEY }" | wg pubkey ); \
PRESHARED_KEY = $( wg genpsk ); \
echo "Server private key: ${ SERV_PRIV_KEY }" ; \
echo "Server public Key: ${ SERV_PUB_KEY }" ; \
echo "Client private key: ${ CLIENT_PRIV_KEY }" ; \
echo "Client public Key: ${ CLIENT_PUB_KEY }" ; \
echo "Preshared Key: ${ PRESHARED_KEY }"
Generate client key pairs:
CLIENT_PRIV_KEY = $( wg genkey ); \
CLIENT_PUB_KEY = $( echo "${ CLIENT_PRIV_KEY }" | wg pubkey ); \
PRESHARED_KEY = $( wg genpsk ); \
echo "Client private key: ${ CLIENT_PRIV_KEY }" ; \
echo "Client public Key: ${ CLIENT_PUB_KEY }" ; \
echo "Preshared Key: ${ PRESHARED_KEY }"
Generate private and public keys only:
CLIENT_PRIV_KEY = $( wg genkey ); \
CLIENT_PUB_KEY = $( echo "${ CLIENT_PRIV_KEY }" | wg pubkey ); \
echo "Client private key: ${ CLIENT_PRIV_KEY }" ; \
echo "Client public Key: ${ CLIENT_PUB_KEY }"
Generate server private, public keys and save them into files:
wg genkey | tee private-key-server | wg pubkey > public-key-server > /dev/null
Generate a preshared key and save to file:
wg genpsk | tee preshared-key > /dev/null
Generate a preshared key and output to terminal:
wg genpsk
Configuration examples:
Example of all possible configuration options:
[Interface]
# Name = node1.example.tld
Address = 192.0.2.3/32
ListenPort = 51820
PrivateKey = localPrivateKeyAbcAbcAbc=
DNS = 1.1.1.1,8.8.8.8
Table = 12345
MTU = 1500
PreUp = /bin/example arg1 arg2 %i
PostUp = /bin/example arg1 arg2 %i
PreDown = /bin/example arg1 arg2 %i
PostDown = /bin/example arg1 arg2 %i
[Peer]
# Name = node2-node.example.tld
AllowedIPs = 192.0.2.1/24
Endpoint = node1.example.tld:51820
PublicKey = remotePublicKeyAbcAbcAbc=
PresharedKey = presharedkeyabcabcabc=
PersistentKeepalive = 25
Server configuration example:
[Interface]
Address = xx
ListenPort = xx
PrivateKey = xx
#
PreUp = echo 1 > /proc/sys/net/ipv4/ip_forward
PreUp = echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
#
PreDown = echo 0 > /proc/sys/net/ipv4/ip_forward
PreDown = echo 0 > /proc/sys/net/ipv6/conf/all/forwarding
#
[Peer]
PublicKey = xx
PresharedKey = xx
AllowedIPs = a.b.c.d/x,a.b.c.d/x
Client configuration example:
[Interface]
PrivateKey = xx
Address = xx
DNS = xx (optional)
[Peer]
PublicKey = server public key
PresharedKey = preshared key
Endpoint = < I P > : < Por t >
AllowedIPs = what to push up the tunnel
Server config:
[ Interface ]
# Name = server
Address = 10.0.0.254/24
ListenPort = 51820
PrivateKey = <private Key>
# Public key is not required in the config. I just like to have it here
# PublicKey = <Public Key>
DNS = 1.1.1.1
MTU = 1420
# Table is optional, not required for most deployments
Table = 12345
PreUp = <run before tunnel come up>
PreDown = <run before bringing the tunnel down>
PostUp = <run after tunnel come up>
PostDown = <run after tunnel go down>
[ Peer ]
# Name = Client-01
# All traffic without forcing default route through wireguard
AllowedIPs = 0.0.0.0/1, 128.0.0.0/1, ::/1, 8000::/1
# specific allowed route
AllowedIPs = 10.0.0.1/32
PublicKey = <Public key of peer node>
# Don't include endpoint for dynamic endpoint
Endpoint = domain.com:51820
# Keep alive isn't recommended, but can be used for NAT traversal
PersistentKeepalive = 25
# Preshared key is not required, but can be used for enhanced security
PresharedKey = <preshared key>
Client config:
[ Interface ]
# Name = server
Address = 10.0.0.1/24
# Don't include ListenPort to allow the client to use a random port
ListenPort = 51820
PrivateKey = <private Key>
# Public key is not required in the config. I just like to have it here
# PublicKey = <Public Key>
DNS = 1.1.1.1
MTU = 1420
# Table is optional, not required for most deployments
Table = 12345
PreUp = <run before tunnel come up>
PreDown = <run before bringing the tunnel down>
PostUp = <run after tunnel come up>
PostDown = <run after tunnel go down>
[ Peer ]
# Name = Client-01
AllowedIPs = 10.0.0.254/32
PublicKey = <Public key of peer node>
# Don't include endpoint for dynamic endpoint
Endpoint = domain.com:51820
# Keep alive isn't recommended, but can be used for NAT traversal
PersistentKeepalive = 25
# Preshared key is not required, but can be used for enhanced security
PresharedKey = <preshared key>
Wireguard troubleshooting:
Routing:
DNS routing:
DNS routing with wireguard
DNS can be setup with a server and a search domain as well:
[interface]
DNS = 10.0.0.2, internal.example.com
# or this way
PostUp = resolvectl dns %i 10.0.0.2 ; resolvectl domain %i ~internal.example.com
Avoid DNS from DHCP:
nmcli modify 'Network name' ipv4.ignore-auto-dns yes
show WireGuard routing table and peer connections:
wg show
wg show wg0 allowed-ips
show system routing table:
ip route show table main
ip route show table local
show system route to specific address:
ip route get 192.0.2.3
Bandwidth:
install iperf:
sudo apt install -y iperf
check bandwidth over public internet to relay server
iperf -s # start iperf in server mode
iperf -c 10.11.1.254 # connect from client to iperf server
DNS:
Lookup DNS:
dig wireguard.com A
or
nslookup wireguard.com
Custom routing table:
Add specific routes with ip rule
and ip route
:
The following commands can be used to specify Wireguard routes with specific routing tables:
Doing this leads to the use of Policy Based Routing (PBR)
[interface]
PreUp = ip rule add from 10.10.1.0/24 lookup 200
PostUp = ip route add default dev wg0 table 200
Setup custom routing tables:
source
[interface]
Table = 1234
Generate QR Code Config:
Install QR generator package:
sudo apt install -y qrencode
Generate QR picture of the configuration:
qrencode -r phone.conf -o client1.conf.png
Display QR image of the config on the CLI:
cat phone.conf | qrencode -t UTF8