MikroTik WireGuard Site to Site VPN for Multi Site ISPs
ISPs running more than one site, a main NOC and a secondary PoP, two peering points, a head office and a field site, eventually need a reliable way to link them over the public internet. IPsec and OpenVPN have handled this job for years, but MikroTik WireGuard site to site setups are faster to configure, lighter on CPU, and easier to reason about once you're past the basics. This guide covers a real two-site WireGuard tunnel, adding dual WAN load balancing with PCC on top of it, and the one gap that trips up almost everyone the first time: the tunnel comes up, routing works, and WinBox or WebFig still refuse to connect across it.
By the end you'll have a working site to site link between two RouterOS v7 routers, a PCC-based dual WAN setup riding on top of it, and a fix for the local-service access problem that shows up right after the handshake succeeds.
Why WireGuard for Multi Site ISP Links
WireGuard's appeal for ISP site to site links comes down to three things. The configuration surface is small, a handful of fields per peer instead of IPsec's policy and phase negotiation. The handshake is fast enough that a flapping WAN link recovers in seconds rather than the 30 to 60 second renegotiation windows IPsec sometimes needs. And CPU overhead is low enough that a modest CCR or even an RB4011 can carry real production traffic over several tunnels at once.
None of that makes WireGuard a drop-in replacement for every IPsec deployment; interoperability with third party firewalls and FIPS-mandated environments still lean IPsec, but for two MikroTik routers talking to each other, it's usually the simpler and faster choice.
Basic Site to Site Setup
Start with the interface and keys on each router. Generate a key pair on Site A:
/interface wireguard add name=wg-site-b listen-port=13231
/interface wireguard print
The print output shows the public key for this interface. Do the same on Site B, then exchange the public keys and configure the peer on each side:
# On Site A
/interface wireguard peers add interface=wg-site-b public-key="<site-b-public-key>" endpoint-address=<site-b-wan-ip> endpoint-port=13231 allowed-address=10.20.0.0/30,192.168.20.0/24 persistent-keepalive=25s
/ip address add address=10.20.0.1/30 interface=wg-site-b
/ip route add dst-address=192.168.20.0/24 gateway=10.20.0.2
# On Site B, mirrored
/interface wireguard peers add interface=wg-site-a public-key="<site-a-public-key>" endpoint-address=<site-a-wan-ip> endpoint-port=13231 allowed-address=10.20.0.0/30,192.168.10.0/24 persistent-keepalive=25s
/ip address add address=10.20.0.2/30 interface=wg-site-a
/ip route add dst-address=192.168.10.0/24 gateway=10.20.0.1
persistent-keepalive matters more than it looks. Without it, a NAT device sitting in front of either site can drop the UDP mapping during idle periods, and the tunnel silently stops passing traffic until the next outbound packet re-triggers a handshake. 25 seconds is the standard value and works for almost every consumer and carrier-grade NAT in front of a WAN link.
Confirm the tunnel with a ping across the allowed-address range before moving on. If it doesn't come up, check that UDP port 13231 is actually forwarded or not blocked on both WAN sides first, that's the most common reason a WireGuard handshake never completes.
Adding Dual WAN Load Balancing with PCC
A single WAN link at either site is a single point of failure for the whole tunnel. PCC (per connection classifier) based load balancing spreads traffic across two WAN links while keeping each individual connection sticky to one path, which matters for a UDP-based protocol that doesn't tolerate mid-session path changes well.
/ip firewall mangle add chain=prerouting in-interface=ether1-wan1 action=mark-connection new-connection-mark=wan1-conn passthrough=yes
/ip firewall mangle add chain=prerouting in-interface=ether2-wan2 action=mark-connection new-connection-mark=wan2-conn passthrough=yes
/ip firewall mangle add chain=output connection-mark=wan1-conn action=mark-routing new-routing-mark=to-wan1 passthrough=no
/ip firewall mangle add chain=output connection-mark=wan2-conn action=mark-routing new-routing-mark=to-wan2 passthrough=no
/ip route add dst-address=0.0.0.0/0 gateway=<wan1-gateway> routing-mark=to-wan1
/ip route add dst-address=0.0.0.0/0 gateway=<wan2-gateway> routing-mark=to-wan2
For the WireGuard endpoint traffic specifically, PCC classifies new connections based on source and destination address pairs, splitting outbound sessions roughly evenly across both links. If you want the tunnel itself pinned to a preferred WAN with automatic failover instead of load balancing, use a Netwatch script that swaps the WireGuard peer's endpoint on link failure, rather than PCC, since a single UDP tunnel session doesn't benefit from being split across two paths mid-stream the way many short-lived subscriber connections do.
Fixing Local Service Access After the Tunnel Is Up
This is the part that catches almost everyone the first time, and it's the exact problem showing up in current MikroTik forum threads on RouterOS v7.25: the WireGuard handshake succeeds, routing across the tunnel works, and WebFig or WinBox still can't reach the remote router's management interface over it.
Three things to check, in order:
/ip service print
If www or the API services show a restricted available-from address list that doesn't include the tunnel's subnet, management traffic arriving over WireGuard gets silently dropped before it reaches the service. Add the tunnel subnet to whatever address list those services are scoped to, or clear the restriction if you're relying on the firewall input chain instead.
/ip firewall filter print where chain=input
Check that nothing in the input chain is dropping traffic from the WireGuard peer's allowed-address range before it reaches the accept rules for established and related connections. A common cause is an input chain written before the WireGuard interface existed, so it never explicitly allows the new tunnel subnet and falls through to a default drop at the bottom.
/ip firewall filter add chain=input in-interface=wg-site-b action=accept place-before=0
Finally, confirm NAT masquerade isn't applying to tunnel traffic. A masquerade rule scoped too broadly (out-interface-list=all instead of out-interface-list=WAN) can rewrite the source address of traffic that should be routing natively across the WireGuard link, which breaks the return path for WebFig's session even though the initial connection looked fine.
Common Mistakes
- Reusing the same allowed-address range on both peers instead of mirroring the correct remote subnet, which causes asymmetric routing that looks like a working tunnel with broken return traffic.
- Skipping persistent-keepalive on links behind NAT, then troubleshooting intermittent drops as a routing problem when it's actually a NAT timeout.
- Forgetting the new WireGuard interface needs its own entry in any interface list used by firewall or routing rules written before the tunnel existed.
- Running PCC load balancing on the WireGuard endpoint traffic itself without considering that a single long-lived UDP session doesn't actually benefit from mid-stream path splitting, only new sessions riding over the tunnel do.
Frequently Asked Questions
Does WireGuard replace IPsec for ISP site to site links entirely?
Not universally. WireGuard is simpler to configure and lighter on CPU for MikroTik-to-MikroTik links, but IPsec remains the better choice when you need to interoperate with non-MikroTik firewalls or meet a compliance requirement that specifically calls for IPsec.
Why does the tunnel show a recent handshake but no traffic passes?
Check allowed-address on both peers first. A handshake can succeed even when the allowed address ranges don't actually cover the traffic you're trying to route, since the handshake only depends on the keys and endpoint, not the routing policy.
Can I run more than two sites with this same approach?
Yes, each additional site is another WireGuard interface and peer entry, effectively a full or partial mesh. Beyond four or five sites, a hub-and-spoke design through one central router is usually easier to manage than a full mesh.
Is persistent-keepalive needed on both sides or just one?
Only one side strictly needs it to keep the NAT mapping alive, but setting it on both sides is standard practice and costs almost nothing in overhead.
What MTU should the WireGuard interface use?
1420 is the common starting point for a WireGuard interface riding over a standard 1500-byte WAN link, accounting for the WireGuard header overhead. Lower it further if the WAN path has additional encapsulation, such as a PPPoE uplink.
Conclusion
A MikroTik WireGuard site to site VPN gets a two-site ISP link running with a fraction of the configuration IPsec needs, and PCC load balancing on top of it removes the single-WAN point of failure. The local service access gap after the tunnel comes up isn't a WireGuard bug; it's almost always an IP service restriction, a missing input chain rule, or an over-broad masquerade rule, all fixable in a few minutes once you know where to look.
Need a second set of eyes on a multi site MikroTik deployment, or want someone to set this up end to end? I'm available for remote MikroTik and ISP infrastructure work.
Top comments (0)