Wireguard
Updated: September 28, 2024
WireGuard securely encapsulates IP packets over UDP.
You add a WireGuard interface, configure it with your private key and your peers' public keys, and then you send packets across it. Both parties have each other’s public keys, and then they’re simply able to begin exchanging packets through the interface. WireGuard works by adding a network interface (or multiple), like eth0 or wlan0, called wg0 (or wg1, wg2, wg3, etc). This network interface can then be configured normally using ifconfig(8) or ip-address(8), with routes for it added and removed using route(8) or ip-route(8), and so on with all the ordinary networking utilities. The specific WireGuard aspects of the interface are configured using the wg(8) tool. This interface acts as a tunnel interface. Wireguard can be used for containers. Use only one interface in the container.
Table of Contents
ARGUMENTS
wg
show { <interface> | all | interfaces } [public-key | private-key | preshared-key | listen-port | peers | endpoints | allowed-ips | latest-handshake | persistent-keepalive | bandwidth]
# Shows current WireGuard configuration of specified <interface>. If no <interface> is specified, <interface> defaults to all. If interfaces is specified, prints a list of all WireGuard interfaces, one per line, and quit. If no options are given after the interface specification, then prints a list of all attributes in a visually pleasing way meant for the terminal. Otherwise, prints specified information grouped by newlines and tabs, meant to be used in scripts.
showconf <interface>
# Shows the current configuration of <interface> in the format described by CONFIGURATION FILE FORMAT below.
set <interface> [listen-port <port>] [private-key <file-path>] [preshared-key <file-path>] [peer <base64-public-key> [remove] [endpoint <ip>:<port>] [persistent-keepalive <interval seconds>] [allowed-ips <ip1>/<cidr1>[,<ip2>/<cidr2>]...] ]...
# Sets configuration values for the specified <interface>. Multiple peers may be specified, and if the remove argument is given for a peer, that peer is removed, not configured. If listen-port is not specified, the port will be automatically generated when the interface comes up. Both private-key and preshared-key must be a files, because command line arguments are not considered private on most systems but if you are using bash(1), you may safely pass in a string by specifying as private-key or preshared-key the expression: <(echo PRIVATEKEYSTRING). If /dev/null is specified as the filename for either private-key or preshared-key, the key is removed from the device. The use of preshared-key is optional, and may be omitted; it adds an additional layer of symmetric-key cryptography to be mixed into the already existing public-key cryptography, for post-quantum resistance. If allowed-ips is specified, but the value is the empty string, all allowed ips are removed from the peer. The use of persistent-keepalive is optional and is by default off; setting it to 0 or "off", disables it. Otherwise it represents, in seconds, between 10 and 3600 inclusive, how often to send an empty UDP packet to the peer, for the purpose of keeping a stateful firewall or NAT mapping valid persistently. For example, if the interface very rarely sends traffic, but it might at anytime receive traffic from a peer, and it is behind NAT, the interface might benefit from having a persistent keepalive interval of 25 seconds.
setconf <interface> <configuration-filename>
# Sets the current configuration of <interface> to the contents of <configuration-filename>, which must be in the format described by CONFIGURATION FILE FORMAT below.
addconf <interface> <configuration-filename>
# Appends the contents of <configuration-filename>, which must be in the format described by CONFIGURATION FILE FORMAT below, to the current configuration of <interface>.
genkey
# Generates a random private key in base64 and prints it to standard output.
genpsk
# Generates a random preshared key in base64 and prints it to standard output.
pubkey
# Calculates a public key and prints it in base64 to standard output from a corresponding private key (generated with genkey) given in base64 on standard input.
# A private key and a corresponding public key may be generated at once by calling:
$ umask 077
$ wg genkey | tee private.key | wg pubkey > public.key
help
Show usage message.
INSTALLATION
Create /etc/wireguard in each machine where wireguard is installed and run:
umask 077 # This makes sure credentials don't leak in a race condition.
wg genkey | tee privatekey | wg pubkey > publickey
Will also need to open UDP port for any machine behind a NAT. default 51820
SETUP
Eaxmple Server
[Interface]
Address = 192.168.2.1
PrivateKey = <server's privatekey>
ListenPort = 51820
[Peer]
PublicKey = <client's publickey>
AllowedIPs = 192.168.2.2/32
Example Client
[Interface]
Address = 192.168.2.2
PrivateKey = <client's privatekey>
ListenPort = 21841
[Peer]
PublicKey = <server's publickey>
Endpoint = <server's ip>:51820
AllowedIPs = 192.168.2.0/24
# This is for if you're behind a NAT and
# want the connection to be kept alive.
PersistentKeepalive = 25
HOME LAN
Under server Interface place:
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
On Client add LAN’s subnet under AllowedIPs
AllowedIPs = 192.168.2.0/24, 192.168.1.0/24
To forward all traffic though VPN
AllowedIPs = 0.0.0.0/0, ::/0
So entire client might look something like:
[Interface]
Address = 192.168.2.2
PrivateKey = <client's privatekey>
ListenPort = 21841
[Peer]
PublicKey = <server's publickey>
Endpoint = <server's ip>:51820
AllowedIPs = 0.0.0.0/0, ::/0
PERSISTENCE
Secure the folders
sudo chown -R root:root /etc/wireguard/
sudo chmod -R og-rwx /etc/wireguard/*
Initialization of wireguard is controlled by systemd
sudo systemctl enable wg-quick@wg0.service
To start and stop use:
sudo systemctl start wg-quick@wg0.service
sudo systemctl stop wg-quick@wg0.service
Non-persistent
wg-quick up wg0
wg-quick down wg0