# Wireguard
Simplest way to create a private network, with minimal setup.
Steps:
- Install Wireguard through the package manager.
- Generate the certificate.
- Setup Server/Client wireguard config.
- Start the service.
- Add health check to Client.
1. Install Wireguard through the package manager.
# For Ubuntu/Debian
sudo apt update
sudo apt install wireguard -y
# For CentOS/RHEL
sudo yum install epel-release -y
sudo yum install wireguard-tools -y
# Check command
wg --version
2. Generate the certificate.
All Wireguard instances need genrerate it's certificate.
mkdir -p /etc/wireguard
cd /etc/wireguard
sudo wg genkey | sudo tee private.key | wg pubkey | sudo tee public.key
3. Setup Server/Client Wireguard config.
Both Server/Client would set up the config in path /etc/wireguard/wg0.conf.
Server
# Setup network interface, basic using wg0
[Interface]
PrivateKey = <server_private_key> # Private key generated from previous step
Address = 10.0.0.1/24 # VPN subnet (10.0.0.1 is the ip of this instance)
ListenPort = 51820 # UDP port for VPN
# Enable IP forwarding
PostUp = sysctl -w net.ipv4.ip_forward=1
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
# Set MTU to 1280
PostUp = ip link set mtu 1280 dev %i
PostDown = ip link set mtu 1500 dev %i
# A client setting like this, add whole `[Peer]` when adding new client.
[Peer]
PublicKey = <client_public_key> # Public key genereated from client instance.
AllowedIPs = 10.0.0.2/32
Client
# Setup network interface, basic using wg0
[Interface]
PrivateKey = <client_private_key> # Private key generate from previous step
Address = 10.0.0.2/24 # VPN subnet (10.0.0.2 is the ip of this instance)
# Setup MTU to 1280
PostUp = ip link set mtu 1280 dev %i
PostDown = ip link set mtu 1500 dev %i
# Setup Server IP and whether the connection needs to use this Network interface
[Peer]
PublicKey = <server_public_key> # Public key generated from Server.
Endpoint = <server_public_ip>:51820 # The public ip of Server.
AllowedIPs = 10.0.0.0/16 # The subnet of server (This means only 10.0.X.X connection would go through wg0 network interaface.)
PersistentKeepalive = 25 # Setup keep Alive
Tip
This setup all networks would go through the server side, if you want more efficiency,
setting all clients as servers and use allowedIps to determine the network mesh.
Eample in a 3-node cluster:
Node A – set up a server ip 10.1.0.1 with peer Node B 10.1.0.2 and peer Node C 10.1.0.3.
Node B - set up a server ip 10.1.0.2 with peer Node A 10.1.0.1 with public endpoint and peer Node C 10.1.0.3.
Node C - set up a server ip 10.1.0.3 with peer Node A 10.1.0.1 with public endpoint and peer Node B 10.1.0.2 with public endpoint.
4. Start the service
Note
The config wg0.conf defined as interface wg0.
So the using interface should use wg0.
# manual start
sudo wg-quick up wg0
sudo wg-quick down wg0
# using `systemctl`
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0
sudo systemctl status wg-quick@wg0
sudo systemctl is-enabled wg-quick@wg0
# check current connection status (Client Only)
sudo wg show
Tip
Using sudo wg show can check the last handshake time.
The time should less than around 120 seconds by default.
It would restart handshake time when read 120, so it's useful to check the time to know if it's disconnected.
5. Add health check to Client.
In sometimes, Wireguard does not reconnect to the server. We add a health check for better mantainance.
Add a health check script
We use 140 seconds threashold to determine the disconnect state,
since Wireguard should restart handshake at 120 seconds.
/usr/local/bin/wg-healthcheck.sh
# !bin/bash
HANDSHAKE=$(sudo wg show wg0 latest-handshakes | awk '{print $2}')
NOW=$(date +%s)
if [ "$HANDSHAKE" -eq 0 ] || [ $((NOW - HANDSHAKE)) -gt 140 ]; then
logger -t wg-check "WireGuard stale. Restarting..."
sudo systemctl restart wg-quick@wg0
else
logger -t wg-check "WireGuard is OK, handshake: $HANDSHAKE, now: $NOW, diff: $((NOW - HANDSHAKE))"
fi
Add +x to the script.
sudo chmod +x /usr/local/bin/wg-healthcheck.sh
Add the script to the crontab
Use sudo crontab -e to edit the cron tab, and add the following lines.
* * * * * /usr/local/bin/wg-healthcheck.sh
Tip
Because of use sudo with crontab, the script it's run under root user.
Show logs
sudo journalctl -t wg-check
Tip
The script uses the logger function, and writes with the wg-check tag.
Add service depend on the Wireguard
For example, the K3s-agent service, make K3s restart when Wireguard restart.
/etc/systemd/system/k3s-agent.service.d/wg0-wait.conf
[Unit]
After=wg-quick@wg0.service
Requires=wg-quick@wg0.service
Tip
When updating service definition, should reload the config.
sudo systemctl daemon-reexec
Check current MTU
ip link show dev eth0