Skip to content

Instantly share code, notes, and snippets.

@enginefeeder101
Last active September 15, 2023 14:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save enginefeeder101/fcdd205f85d123f3cc90e5ec94206698 to your computer and use it in GitHub Desktop.
Save enginefeeder101/fcdd205f85d123f3cc90e5ec94206698 to your computer and use it in GitHub Desktop.
WireGuard VPN network

WireGuard VPN network

This example shows how to setup a WireGuard VPN network with a Linux server that is publicly accessible and serveral OpenWRT nodes that are not. One of these client nodes is used as network wide 'exit node'. This makes it possible to easily configure network with an exit node which is a network that is not under your control or cannot be (easily) configured to setup port forwarding.

Preparation

Generate private keys for all clients and a pre-shared key (PSK) for every connection pair.

(umask 0377; wg genkey > peerA.key)
wg pubkey < peerA.key > peerA.pub
(umask 0377; wg genpsk > peerA-peerB.psk)
(umask 0377; wg genpsk > peerA-peerC.psk)

To be able to more easily recognize keys in status overviews it might be benificial to use a vanity address.

wireguard-vanity-address --in 3 bob

Decide the RFC1918 IPv4 subnet you are going to use. For this a generator can be used. This example only implements IPv4 on the WireGuard layer. The underlying carrier network can, but does not need to, be IPv6.
The examples below uses 192.0.2.0/24 (RFC 5737).

Configure the middleman

Consult your distributions documentation on how to install wireguard on your Linux server.

Create the configuration file /etc/wireguard/wg0.conf

[Interface]
Address = 192.0.2.1/24
ListenPort = 443
PrivateKey = PrivateKeyOfPeerA
# Disable automatic routing
Table = off
# Insert manual routing and rule after device creation
PostUp = ip route add 192.0.2.0/24 dev wg0 scope link table 51820
PostUp = ip route add default via 192.0.2.2 dev wg0 table 51820
PostUp = ip rule add from 192.0.2.0/24 priority 30000 lookup 51820
PostUp = ip route flush cache
# Delete manual routes and rule on device removal
PreDown = ip rule del from 192.0.2.0/24 priority 30000 lookup 51820
PreDown = ip route del default via 192.0.2.2 dev wg0 table 51820
PreDown = ip route del 192.0.2.0/24 dev wg0 scope link table 51820
PreDown = ip route flush cache

[Peer]
PublicKey = PublicKeyOfPeerB
PresharedKey = PSKpeerApeerB
AllowedIPs = 192.0.2.2/32, 0.0.0.0/0

[Peer]
PublicKey = PublicKeyOfPeerC
PresharedKey = PSKpeerApeerC
AllowedIPs = 192.0.2.3/32

[Peer]
PublicKey = PublicKeyOfPeerD
PresharedKey = PSKpeerApeerD
AllowedIPs = 192.0.2.4/32

[Peer]
PublicKey = PublicKeyOfPeerE
PresharedKey = PSKpeerApeerE
AllowedIPs = 192.0.2.5/32

# Configure more peers as required

This configuration file setups WireGuard with an isolated routing table, separate from the rest of the default and possible other routes (eg. docker).

Start and enable the WireGuard service

systemctl start wg-quick@wg0.service
systemctl enable wg-quick@wg0.service

Configure your firewall to allow incomming traffic to the WireGuard service.

# When using iptables: (make sure to store permanently in eg /etc/iptables/rules.v4; consult your distros docs)
iptables -I INPUT -p udp –dport 443 -j ACCEPT
iptables -I FORWARD -i wg0 -j ACCEPT
# When using UFW:
ufw allow 443/udp
ufw route allow in on wg0

Configure your kernel to allow forwarding.

echo net.ipv4.ip_forward=1 >> /etc/sysctl.d/99-forward.conf 
sysctl --system

Setup the OpenWRT exit node

Setup interface

uci set network.wg=interface
uci set network.wg.proto='wireguard'
uci set network.wg.private_key='PrivateKeyOfPeerB'
uci set network.wg.listen_port='51820'
uci set network.wg.addresses='192.0.2.2/24'
uci set network.wg.nohostroute='1'
uci set network.wg.defaultroute='0'
uci set network.wg.fwmark='0xca6c'
uci set network.wg.ip4table='51820'

Add peer

uci add network wireguard_wg
uci set network.@wireguard_wg[-1].description='Middleman'
uci set network.@wireguard_wg[-1].public_key='PublicKeyOfPeerA'
uci set network.@wireguard_wg[-1].preshared_key='PSKpeerApeerB'
uci set network.@wireguard_wg[-1].allowed_ips='192.0.2.0/24'
uci set network.@wireguard_wg[-1].endpoint_host='fqdn.example.org'
uci set network.@wireguard_wg[-1].endpoint_port='443'
uci set network.@wireguard_wg[-1].persistent_keepalive='25'

Add WireGuard to the "LAN" zone (usualy this is zone 0)

ZONE=$(uci show firewall | grep ".name='lan'" | grep -oE '[0-9]+')
uci add_list firewall.@zone[$ZONE].network='wg'

Commit

uci commit firewall
uci commit network

Setup the other OpenWRT nodes

Setup interface

uci set network.wg=interface
uci set network.wg.proto='wireguard'
uci set network.wg.private_key='PrivateKeyOfPeerC'
uci set network.wg.listen_port='51820'
uci set network.wg.addresses='192.0.2.3/24'
uci set network.wg.nohostroute='1'
uci set network.wg.defaultroute='0'
uci set network.wg.fwmark='0xca6c'
uci set network.wg.ip4table='51820'

Add peer

uci add network wireguard_wg
uci set network.@wireguard_wg[-1].description='Middleman'
uci set network.@wireguard_wg[-1].public_key='PublicKeyOfPeerA'
uci set network.@wireguard_wg[-1].preshared_key='PSKpeerApeerC'
uci set network.@wireguard_wg[-1].allowed_ips='0.0.0.0/0'
uci set network.@wireguard_wg[-1].endpoint_host='fqdn.example.org'
uci set network.@wireguard_wg[-1].endpoint_port='443'
uci set network.@wireguard_wg[-1].persistent_keepalive='25'

Route traffic through wireguard

uci add network rule
uci set network.@rule[-1].priority='30000'
uci set network.@rule[-1].lookup='main'
uci set network.@rule[-1].suppress_prefixlength='0'

uci add network rule
uci set network.@rule[-1].priority='30001'
uci set network.@rule[-1].lookup='51820'
uci set network.@rule[-1].mark='0xca6c'
uci set network.@rule[-1].invert='1'

uci add network route
uci set network.@route[-1].interface='wg'
uci set network.@route[-1].target='0.0.0.0/0'
uci set network.@route[-1].table='51820'
uci set network.@route[-1].gateway='192.0.2.2'

Add WireGuard to the "WAN" zone (usualy this is zone 1)

ZONE=$(uci show firewall | grep ".name='wan'" | grep -oE '[0-9]+')
uci add_list firewall.@zone[$ZONE].network='wg'

Allow management via WireGuard

uci add firewall rule
uci set firewall.@rule[-1].name='Allow SSH via wg'
uci set firewall.@rule[-1].family='ipv4'
uci set firewall.@rule[-1].src='wan'
uci set firewall.@rule[-1].src_ip='192.0.2.0/24'
uci set firewall.@rule[-1].target='ACCEPT'
uci set firewall.@rule[-1].dest_port='22'

Commit

uci commit firewall
uci commit network
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment