(Based on Chrispus Kamau's excellent Wireguard VPN tutorials for Typical Setup and Chained Setup, it appears I may have a solution (untested!) in a format that shows how somewhat unusual/complex setups could be handled—or at least give you an idea. Many thanks CK!)
Via: https://github.com/iamckn/chained-wireguard-ansible
How it works:
Client (vpn0
) → 10.200.200.0/24
→ (wg0
) → Middleman (gate0
) → 10.100.100.0/24
→ (wg0
) Gate (wg0
) → Public Internet
Assumes that Unbound is set up on both the Middleman and Gate for local DNS resolution.
Gate Configuration
Configure the gate's VPN interface (wg0
).
File: /etc/wireguard/wg0.conf
# SERVER
[Interface] # Gate
PrivateKey = GATE_PRIVATE_KEY
Address = 10.100.100.1/24
ListenPort = 53701
SaveConfig = false
# CLIENTS
[Peer] # Middleman
PublicKey = MIDDLEMAN_PUBLIC_KEY
PresharedKey = MIDDLEMAN_PRESHARED_KEY
AllowedIPs = 10.0.0.0/8
Firewall config. commands:
# Track VPN connection
## Track input chain
iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
## Track forward chain
iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# Allow incoming WireGuard connections/VPN traffic on the listening port
iptables -A INPUT -p udp -m udp --dport 53701 -m conntrack --ctstate NEW -j ACCEPT
# Allow both TCP and UDP recursive DNS traffic
iptables -A INPUT -s 10.100.100.0/24 -p tcp -m tcp --dport 53 -m conntrack --ctstate NEW -j ACCEPT
iptables -A INPUT -s 10.100.100.0/24 -p udp -m udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT
# Allow forwarding of packets that stay in the VPN tunnel
iptables -A FORWARD -i wg0 -o wg0 -m conntrack --ctstate NEW -j ACCEPT
# Set up NAT
iptables -t nat -A POSTROUTING -s 10.100.100.0/24 -o enp7s0 -j MASQUERADE
Bring up the gate's VPN interface, and enable the WireGuard service to automatically restart on boot:
wg-quick up wg0
systemctl enable wg-quick@wg0
Middleman Configuration
Configure the middleman's gate-facing interface (gate0
). Here middleman acts as the client.
File: /etc/wireguard/gate0.conf
[Interface] # Middleman
PrivateKey = MIDDLEMAN_PRIVATE_KEY
Address = 10.100.100.2/32
DNS = 10.100.100.1
SaveConfig = false
# PEERS
[Peer] # Gate
PublicKey = GATE_PUBLIC_KEY
PresharedKey = MIDDLEMAN_PRESHARED_KEY
Endpoint = GATE_PUBLIC_IP:53701
AllowedIPs = 0.0.0.0/0
#PersistentKeepalive = 21
Configure the middleman's client-facing interface (wg0
). Here middleman acts as the server.
File: /etc/wireguard/wg0.conf
# SERVER
[Interface] # Middleman
PrivateKey = MIDDLEMAN_PRIVATE_KEY
Address = 10.200.200.1/24
ListenPort = 53701
SaveConfig = false
# CLIENTS
[Peer] # PC
PublicKey = CLIENT_PUBLIC_KEY
PresharedKey = CLIENT_PRESHARED_KEY
AllowedIPs = 10.200.200.2/32
Firewall config. commands:
iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -p udp -m udp --dport 53701 -m conntrack --ctstate NEW -j ACCEPT
iptables -A INPUT -s 10.200.200.0/24 -p tcp -m tcp --dport 53 -m conntrack --ctstate NEW -j ACCEPT
iptables -A INPUT -s 10.200.200.0/24 -p udp -m udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT
iptables -A FORWARD -i wg0 -o wg0 -m conntrack --ctstate NEW -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.200.200.0/24 -o enp41s0 -j MASQUERADE
# Set up VPN chain NAT
iptables -t nat -A POSTROUTING -s 10.200.200.0/24 -j SNAT --to-source 10.100.100.2
Configure policy routing on the middleman to route traffic from the client to the gate.
echo "1 middleman" >> /etc/iproute2/rt_tables
# Forward all traffic to the gate
ip route add 0.0.0.0/0 dev gate0 table middleman
# OR only forward traffic to 4.2.2.2 (for e.g.), to the gate
#ip route add 4.2.2.2/32 dev gate0 table middleman
ip rule add from 10.200.200.0/24 lookup middleman
Bring up the middleman's WireGuard interfaces, and enable the WireGuard service to automatically restart on boot:
wg-quick up gate0
systemctl enable wg-quick@gate0
wg-quick up wg0
systemctl enable wg-quick@wg0
Client Configuration
File: /etc/wireguard/vpn0.conf
[Interface]
PrivateKey = CLIENT_PRIVATE_KEY
Address = 10.200.200.2/32
DNS = 10.200.200.1
# PEERS
[Peer] # Middleman
PublicKey = MIDDLEMAN_PUBLIC_KEY
PresharedKey = CLIENT_PRESHARED_KEY
Endpoint = MIDDLEMAN_PUBLIC_IP:53701
AllowedIPs = 0.0.0.0/0
#PersistentKeepalive = 21
Finally activate WireGuard on the client.