Connect Two WireGuard Peers Through MikroTik (Hub-and-Spoke)
This post summarizes a real debugging and configuration process to make two WireGuard peers ping each other through a MikroTik router acting as the central hub.
Context
Topology:
Peer A (Client) (10.10.0.10) --+
+--> WireGuard Interface (MikroTik) <-- hub
VPS (10.10.2.1) ---------------+
Environment:
- MikroTik router acts as the WireGuard hub, with
10.10.0.1/24on the WG interface. - Peer A (Client) connects to WG with
10.10.0.10/32. - VPS connects to WG with
10.10.2.1/32(on MikroTik,allowed-addressfor this peer is10.10.2.0/24). - Both peers use the same shared WireGuard interface on MikroTik.
Core problem
When two peers connect to the same WireGuard interface on MikroTik, traffic between them must be hairpin-forwarded. In other words, MikroTik receives packets from peer A and forwards them back out on that same interface to peer B. MikroTik does not do this automatically if required firewall rules and routes are missing.
On top of that, the client side also needs a valid kernel route to the VPS subnet. If this route is missing, packets take the wrong interface (LAN or internet) instead of the WG tunnel.
Configuration steps
Step 1: Make sure MikroTik has an IP on the WireGuard interface
/ip address print where interface~"Wire"
You should see:
10.10.0.1/24 WireGuard
If missing:
/ip address add address=10.10.0.1/24 interface=WireGuard
Step 2: Check peer allowed-address values on MikroTik
/interface wireguard peers print where allowed-address~"10.10"
Ensure:
- Peer A (Client) has
allowed-address=10.10.0.10/32. - VPS has
allowed-address=10.10.2.0/24(or10.10.2.1/32).
Step 3: Verify auto-generated routes
MikroTik auto-creates routes from each peer’s allowed-address:
/ip route print where dst-address~"10.10"
You should see:
10.10.0.10/32 WireGuard (reachable)
10.10.2.0/24 WireGuard (reachable)
Step 4: Add forward firewall rules on MikroTik
This is the most important step. MikroTik usually has a drop rule at the end of the forward chain, so add accept rules before those drops:
/ip firewall filter
add chain=forward src-address=10.10.0.10/32 dst-address=10.10.2.0/24 \
action=accept comment="WG: client->vps" place-before=0
add chain=forward src-address=10.10.2.0/24 dst-address=10.10.0.10/32 \
action=accept comment="WG: vps->client" place-before=1
Verify rule order:
/ip firewall filter print stats where chain=forward
These two rules should be at indexes 0 and 1, before drop rules.
Step 5: Set AllowedIPs on VPS
In /etc/wireguard/wg0.conf on VPS, the MikroTik [Peer] section must include the client subnet:
[Peer]
PublicKey = <mikrotik-pubkey>
Endpoint = <mikrotik-public-ip>:51820
AllowedIPs = 10.10.0.0/24, 10.10.2.0/24
PersistentKeepalive = 25
Step 6 (Critical): Add route on Client (Peer A)
This was the actual root cause in this case.
Even if client WireGuard AllowedIPs already includes 10.10.2.1/32, if that config was applied after wg0 was already up (using wg syncconf), the kernel route may not be created automatically.
Check:
ip route get 10.10.2.1
If it goes through the physical or LAN interface instead of wg0:
10.10.2.1 via 192.168.1.1 dev eth0 src 192.168.1.10 <- WRONG
Add a temporary manual route for testing:
ip route add 10.10.2.0/24 dev wg0
Test immediately:
ping 10.10.2.1
Step 7: Make the route persistent in wg0.conf
To recreate the route each time wg0 is brought up, add PostUp and PostDown under [Interface]:
[Interface]
Address = 10.10.0.10/32
PostUp = ip route add 10.10.2.0/24 dev wg0
PostDown = ip route del 10.10.2.0/24 dev wg0
[Peer]
PublicKey = <mikrotik-pubkey>
Endpoint = <mikrotik-public-ip>:51820
AllowedIPs = 10.10.0.0/24, 10.10.2.1/32
PersistentKeepalive = 21
Apply without restarting the tunnel:
wg syncconf wg0 <(wg-quick strip wg0)
Root cause and fix summary
| Problem | Cause | Fix |
|---|---|---|
| Packets are not forwarded between two WG peers | Missing forward firewall rules on MikroTik | Add explicit accept rules with correct src/dst |
| Accept rule counters stay at 0 even after adding rules | Packets never hit forward chain | Verify routing on the client |
| MikroTik can ping both ends but Peer A cannot ping VPS | Client route goes out wrong interface | Add ip route add 10.10.2.0/24 dev wg0 |
Route is not auto-created even with correct AllowedIPs |
wg syncconf does not update kernel routing table |
Use PostUp in wg0.conf |
Useful debug commands
# On MikroTik
/interface wireguard peers print detail # Tunnel status, last-handshake
/ip firewall filter print stats where chain=forward # Rule counters
/ip route print where dst-address~"10.10" # Route checks
/ping 10.10.2.1 # Ping VPS from MikroTik
# On Client (Linux)
wg show # WireGuard status
ip route get 10.10.2.1 # Route check to VPS
tcpdump -i wg0 icmp # Verify ICMP leaves via wg0