I was planning on writing out an example, so just for your reading pleasure: the official “rabbit hole solution” to multi-wan wireguard hosting.
We have two WANS. For this example, the two WAN connections are actually EoIP tunnels to another router. The base configuration is:
Interfaces:
/interface eoip
add name=eoip-wan1 remote-address=[other_router] tunnel-id=10
add name=eoip-wan2 remote-address=[other_router] tunnel-id=20
Addresses:
/ip address
add address=192.168.111.10/24 interface=eoip-wan1
add address=192.168.112.10/24 interface=eoip-wan2
Routes:
/routing table
add fib name=wan2
/ip route
add distance=1 dst-address=0.0.0.0/0 gateway=192.168.111.1
add distance=20 dst-address=0.0.0.0/0 gateway=192.168.112.1
add disabled=no dst-address=0.0.0.0/0 gateway=192.168.112.1 routing-table=wan2
WAN masquerade:
add action=masquerade chain=srcnat out-interface=eoip-wan1
add action=masquerade chain=srcnat out-interface=eoip-wan2
And a wireguard “server” with a single peer: (The other side has a 10s persistent keepalive configured.)
/interface wireguard
add listen-port=13231 mtu=1420 name=wireguard1
/interface wireguard peers
add allowed-address=192.168.50.0/24 interface=wireguard1 name=peer1 public-key="22SMLvYh7cQzj3/sGFeFLn7l0xVePXM59DLms3qnNUY=" responder=yes
And now the interesting bit.
Create a bridge with a /30 address:
/interface bridge
add name=br-wg protocol-mode=none
/ip address
add address=172.16.10.1/30 interface=br-wg
Mark connections according to their origins, add routing for wan2 and nat them:
/ip firewall mangle
add action=mark-connection chain=prerouting connection-mark=no-mark dst-address=192.168.111.10 dst-port=13231 in-interface=eoip-wan1 new-connection-mark=wg-wan1 protocol=udp
add action=mark-connection chain=prerouting connection-mark=no-mark dst-address=192.168.112.10 dst-port=13231 in-interface=eoip-wan2 new-connection-mark=wg-wan2 protocol=udp
add action=mark-routing chain=output connection-mark=wg-wan2 new-routing-mark=wan2
/ip firewall nat
add action=dst-nat chain=dstnat connection-mark=wg-wan1 to-addresses=172.16.10.1
add action=dst-nat chain=dstnat connection-mark=wg-wan2 to-addresses=172.16.10.1
add action=src-nat chain=input connection-mark=wg-wan1 to-addresses=172.16.10.2
add action=src-nat chain=input connection-mark=wg-wan2 to-addresses=172.16.10.2
A packet capture:
(The capture is done on the opposing router where the corresponding interfaces are eoip-test1 and eoip-test2)
# TIME INTERFACE SRC-ADDRESS DST-ADDRESS IP-PROTOCOL SIZE CPU
0 3.367 eoip-test1 192.168.33.1:13231 192.168.111.10:13231 udp 190 0
1 3.373 eoip-test1 192.168.111.10:13231 192.168.33.1:13231 udp 134 1
2 3.374 eoip-test1 192.168.33.1:13231 192.168.111.10:13231 udp 74 1
3 13.542 eoip-test1 192.168.33.1:13231 192.168.111.10:13231 udp 74 1
4 23.784 eoip-test1 192.168.33.1:13231 192.168.111.10:13231 udp 74 1
5 47.754 eoip-test2 192.168.33.1:13231 192.168.112.10:13231 udp 190 0
6 47.761 eoip-test2 192.168.112.10:13231 192.168.33.1:13231 udp 134 1
7 47.761 eoip-test2 192.168.33.1:13231 192.168.112.10:13231 udp 74 2
8 58.342 eoip-test2 192.168.33.1:13231 192.168.112.10:13231 udp 74 2
This shows a connection first over wan1, then over wan2. The handshake initiations are the 190 byte packets, size 134 are the handshake responses and the 74 byte ones are keepalives. All is well.
A ping test was then conducted over the wg tunnel. The pings are 3s apart, and during the test, the wan1 connection was severed for about 10s.
9 63.476 eoip-test2 192.168.33.1:13231 192.168.112.10:13231 udp 138 2
10 63.476 eoip-test2 192.168.112.10:13231 192.168.33.1:13231 udp 138 1
11 66.484 eoip-test2 192.168.33.1:13231 192.168.112.10:13231 udp 138 2
12 66.485 eoip-test2 192.168.112.10:13231 192.168.33.1:13231 udp 138 1
13 69.479 eoip-test2 192.168.33.1:13231 192.168.112.10:13231 udp 138 2
14 69.48 eoip-test2 192.168.112.10:13231 192.168.33.1:13231 udp 138 1
15 72.479 eoip-test2 192.168.33.1:13231 192.168.112.10:13231 udp 138 2
16 72.48 eoip-test2 192.168.112.10:13231 192.168.33.1:13231 udp 138 1
17 75.486 eoip-test2 192.168.33.1:13231 192.168.112.10:13231 udp 138 2
18 75.487 eoip-test2 192.168.112.10:13231 192.168.33.1:13231 udp 138 1
19 78.486 eoip-test2 192.168.33.1:13231 192.168.112.10:13231 udp 138 2
20 78.487 eoip-test2 192.168.112.10:13231 192.168.33.1:13231 udp 138 1
21 81.495 eoip-test2 192.168.33.1:13231 192.168.112.10:13231 udp 138 2
22 81.496 eoip-test2 192.168.112.10:13231 192.168.33.1:13231 udp 138 1
23 84.498 eoip-test2 192.168.33.1:13231 192.168.112.10:13231 udp 138 2
24 84.499 eoip-test2 192.168.112.10:13231 192.168.33.1:13231 udp 138 1
25 87.502 eoip-test2 192.168.33.1:13231 192.168.112.10:13231 udp 138 2
26 87.503 eoip-test2 192.168.112.10:13231 192.168.33.1:13231 udp 138 1
27 90.499 eoip-test2 192.168.33.1:13231 192.168.112.10:13231 udp 138 2
28 90.5 eoip-test2 192.168.112.10:13231 192.168.33.1:13231 udp 138 1
29 93.506 eoip-test2 192.168.33.1:13231 192.168.112.10:13231 udp 138 2
30 93.507 eoip-test2 192.168.112.10:13231 192.168.33.1:13231 udp 138 1
31 96.512 eoip-test2 192.168.33.1:13231 192.168.112.10:13231 udp 138 2
32 96.513 eoip-test2 192.168.112.10:13231 192.168.33.1:13231 udp 138 1
33 99.51 eoip-test2 192.168.33.1:13231 192.168.112.10:13231 udp 138 2
34 99.511 eoip-test2 192.168.112.10:13231 192.168.33.1:13231 udp 138 1
35 102.512 eoip-test2 192.168.33.1:13231 192.168.112.10:13231 udp 138 2
36 102.513 eoip-test2 192.168.112.10:13231 192.168.33.1:13231 udp 138 1
37 112.742 eoip-test2 192.168.33.1:13231 192.168.112.10:13231 udp 74 2
38 112.742 eoip-test2 192.168.33.1:13231 192.168.112.10:13231 udp 74 2
39 122.982 eoip-test2 192.168.33.1:13231 192.168.112.10:13231 udp 74 2
40 133.222 eoip-test2 192.168.33.1:13231 192.168.112.10:13231 udp 74 2
41 143.462 eoip-test2 192.168.33.1:13231 192.168.112.10:13231 udp 74 2
42 153.702 eoip-test2 192.168.33.1:13231 192.168.112.10:13231 udp 74 2
43 163.942 eoip-test2 192.168.33.1:13231 192.168.112.10:13231 udp 74 2
44 174.182 eoip-test2 192.168.33.1:13231 192.168.112.10:13231 udp 74 2
Traffic flows without interruption. (This is the problem with dst-natting to the primary wan address, there the traffic is interrupted if the address is lost.)
If you would also want to initiate wg connections from the router side and do it over wan2, even if wan1 is available, this is the additional rule you’ll need: (Traffic may be interrupted for at most keepalive time when wan1 goes down.)
/ip firewall mangle
add action=mark-connection chain=output connection-mark=no-mark new-connection-mark=wg-wan2 protocol=udp src-port=13231