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/24 on 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-address for this peer is 10.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 (or 10.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