Wireguard creates point-to-point VPN tunnels over UDP by creating a virtual network interface and encapsulating IP packets on that interface and transmitting them to the other side. Wireguard is integrated into the Linux kernel as a module.
Key Setup for Client and Server
sudo su # become root user
cd /etc/wireguard
mkdir vpn
wg genkey | tee vpn/private.key
chmod go-r vpn/private.key # secure private key by removing read access
cat vpn/private.key | wg pubkey | tee vpn/public.key # generate public key
Server Setup
# Do Key Setup from Above First
# virtual network interface with example ip 192.168.254.1
tee vpn.conf <<EOF
[Interface]
Address = 192.168.254.1/24
SaveConfig = true
PostUp = nft add table ip vpn; nft add chain ip vpn vpn_chain {type nat hook postrouting priority srcnat\; policy accept\;}; nft add rule ip vpn vpn_chain counter packets 0 bytes 0 masquerade; nft add table ip6 vpn; nft add chain ip6 vpn vpn_chain {type nat hook postrouting priority srcnat\; policy accept\;}; nft add rule ip6 vpn vpn_chain counter packets 0 bytes 0 masquerade
PostDown = nft delete table ip vpn; nft delete table ip6 vpn
ListenPort = 51820
PrivateKey = $(cat vpn/private.key)
EOF
# enable ipv4 and ipv6 forwarding
tee /etc/sysctl.d/10-ip-forwarding.conf <<EOF
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
EOF
# load and apply ip forwarding settings
sysctl --system
# check forwarding has been enabled
cat /proc/sys/net/ipv4/ip_forward
cat /proc/sys/net/ipv6/conf/all/forwarding
# start server vpn interface
systemctl enable wg-quick@vpn
systemctl start wg-quick@vpn
Client Setup
# Do Key Setup from Above First
# virtual network interface with example ip 192.168.254.2
tee vpn2.conf <<EOF
[Interface]
Address = 192.168.254.2/24
SaveConfig = true
PreUp = ip route add "SERVER_IP"/32 via \$(ip r l default | cut -f "3,4,5" -d " ")
PostDown = ip route del \$(ip r l SERVER_IP)
PrivateKey = $(cat vpn/private.key)
EOF
# start client vpn interface
systemctl enable wg-quick@vpn
systemctl start wg-quick@vpn
Server Add Client
# replace CLIENT_PUBLIC_KEY with the client's public key
wg set vpn peer "CLIENT_PUBLIC_KEY" allowed-ips 192.168.254.2/32
# check that the client's public key has been added
wg show vpn
Client Add Server
# replace SERVER_PUBLIC_KEY with the server's public key
# replace SERVER_IP and SERVER_PORT with the server's IP and port
# the server's IP and port MUST BE internet accessible
wg set vpn peer "SERVER_PUBLIC_KEY" \
endpoint "SERVER_IP:SERVER_PORT" \
allowed-ips 192.168.254.0/24 \
persistent-keepalive 30
# check that the server's public key has been added and that connection has been established
wg show vpn
# test pinging the server through the vpn tunnel
ping 192.168.254.1
You can incrementally add clients to the server by incrementing the IP address by one for each client, eg, replacing 192.168.254.2 with 192.168.254.3, 192.168.254.4, …until the subnet max 192.168.254.254. If you want more than 253 clients, you need to use a bigger subnet.