Configuring a two hop Wireguard VPN
Disclaimer
This is not a tutorial, just brief description of a working configuration. You should be at least vaguely familiar with wireguard before attempting to do something like this. That being said, I am a networking novice, so please do not blindly copy and paste these configs.
Setup
IP | Name |
---|---|
192.168.10.0/24 | The private network for the VPN |
192.168.10.1 | The public server S |
192.168.10.2 | The Gateway device G |
192.168.10.3-n | The other clients C |
100.100.20.0/24 | G’s local network (This has to be different to the network above) |
Routing
By setting AllowedIPs = 0.0.0.0/0, ::0/0
for $G$ on $S$, all traffic will by default be routed through $G$. But this also means, that all of $S$’s traffic will be routed through $G$, making $S$ inaccessible from
outside $G$. To avoid this, we configure a separate routing table.
IP forwarding
For this to work, S and G need ip forwarding to be enabled.
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.all.forwarding=1" >> /etc/sysctl.conf
sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv6.conf.all.forwarding=1
Or alternatively, use the PreUp
command specified below
Configuration
The configuration files below should be put into /etc/wireguard/wg0.conf
and the connection can be automatically started by systemctl enable --now wg-quick@wg0.service
.
Gateway config
[Interface]
Address = 192.168.10.3/32
PrivateKey = <...>
# IP forwarding (see section above)
PreUp = sysctl -w net.ipv4.ip_forward=1
# IP masquerading
PreUp = iptables -t mangle -I PREROUTING -i wg0 -j MARK --set-mark 0x30
PreUp = iptables -t nat -I POSTROUTING ! -o wg0 -m mark --mark 0x30 -j MASQUERADE
PostDown = iptables -t mangle -D PREROUTING -i wg0 -j MARK --set-mark 0x30
PostDown = iptables -t nat -D POSTROUTING ! -o wg0 -m mark --mark 0x30 -j MASQUERADE
# Server S
[Peer]
PublicKey = <...>
Endpoint = domain.of.server.s.example.com:51820
AllowedIPs = 192.168.10.0/24
PersistentKeepalive = 20
Server config
[Interface]
Address = 192.168.10.1/24
ListenPort = 51820
PrivateKey = <...>
# Do not pass the server's traffic through G, only other wg0 traffic
Table = 123
PreUp = ip rule add iif wg0 table 123 priority 456
PostDown = ip rule del iif wg0 table 123 priority 456
PreUp = ip -6 rule add iif wg0 table 123 priority 456
PostDown = ip -6 rule del iif wg0 table 123 priority 456
# Gateway
[Peer]
PublicKey = <...>
AllowedIPs = 0.0.0.0/0, ::0/0
# Client C_1
[Peer]
PublicKey = <...>
AllowedIPs = 192.168.10.3/32
# Client C_2
[Peer]
PublicKey = <...>
AllowedIPs = 192.168.10.4/32
...
Client C_1 config
[Interface]
PrivateKey = <...>
Address = 192.168.10.3/32
[Peer]
PublicKey = <...>
Endpoint = domain.of.server.s.example.com:51820
AllowedIPs = 0.0.0.0/0, ::0/0
PersistentKeepalive = 20