A working RouterOS v7 configuration for PCC load balancing across two internet lines, with recursive failover that notices when a line’s internet dies - not just when its cable is pulled - and switches back by itself.
New connections from the LAN are split between the two lines by PCC (the per-connection classifier). Each connection stays on the line it started on, so logins and video calls do not break. If either line loses its internet, every connection moves to the other one within about twenty seconds - two missed pings - and the split resumes when the line comes back. This is the configuration running on our own office router, written out for any MikroTik on RouterOS v7.
The example assumes ether1 is line 1 with gateway 203.0.113.1, ether2 is line 2 with gateway 198.51.100.1, both lines already have a masquerade NAT rule, and your LAN ports are in the interface list LAN (as in the default configuration). Replace the gateways with your own.
Changing routing on a remote router can cut you off from it. Before anything else, arm a scheduler that removes every rule below after five minutes. If you lose access, wait five minutes and the router puts itself back.
/system scheduler add name=LB-revert interval=5m on-event="/ip firewall mangle remove [find comment~\"^LB-\"]; /ip route remove [find comment~\"^LB-\"]; /routing table remove [find name~\"^to_wan\"]; /system scheduler remove [find name=LB-revert]"/routing table
add name=to_wan1 fib
add name=to_wan2 fibThe usual mistake is check-gateway=ping on the ISP gateway itself. The ISP’s modem keeps answering pings when the internet behind it has gone, so the router never fails over. Instead, give each line a public monitor host reachable only through that line, and route through the monitor host. When the line’s internet fails, the monitor host stops answering, the route goes inactive, and traffic moves.
/ip route
# Monitor hosts: each is reachable ONLY through its own line.
add dst-address=1.0.0.1/32 gateway=203.0.113.1 scope=10 comment=LB-mon-wan1
add dst-address=8.8.4.4/32 gateway=198.51.100.1 scope=10 comment=LB-mon-wan2
# Each routing table prefers its own line and falls back to the other.
add dst-address=0.0.0.0/0 gateway=1.0.0.1@main target-scope=11 routing-table=to_wan1 distance=1 check-gateway=ping comment=LB-wan1
add dst-address=0.0.0.0/0 gateway=8.8.4.4@main target-scope=11 routing-table=to_wan1 distance=2 check-gateway=ping comment=LB-wan1-backup
add dst-address=0.0.0.0/0 gateway=8.8.4.4@main target-scope=11 routing-table=to_wan2 distance=1 check-gateway=ping comment=LB-wan2
add dst-address=0.0.0.0/0 gateway=1.0.0.1@main target-scope=11 routing-table=to_wan2 distance=2 check-gateway=ping comment=LB-wan2-backup
# The router's own traffic (DNS, VPN, updates) uses the main table.
add dst-address=0.0.0.0/0 gateway=1.0.0.1 target-scope=11 distance=1 check-gateway=ping comment=LB-main-wan1
add dst-address=0.0.0.0/0 gateway=8.8.4.4 target-scope=11 distance=2 check-gateway=ping comment=LB-main-wan2Do not use 1.0.0.1 or 8.8.4.4 as the router’s DNS servers - each is now pinned to one line. Use 1.1.1.1 and 8.8.8.8 instead. If your router already has its own default route for line 1, raise its distance (for example to 5) so the new routes win.
/ip firewall address-list
add list=LB-bypass address=10.0.0.0/8
add list=LB-bypass address=172.16.0.0/12
add list=LB-bypass address=192.168.0.0/16
/ip firewall mangle
# Replies to connections that came IN on a line must go back out on it.
add chain=prerouting in-interface=ether1 connection-mark=no-mark action=mark-connection new-connection-mark=WAN1 passthrough=yes comment=LB-in-wan1
add chain=prerouting in-interface=ether2 connection-mark=no-mark action=mark-connection new-connection-mark=WAN2 passthrough=yes comment=LB-in-wan2
# Local and VPN networks are never load-balanced.
add chain=prerouting dst-address-list=LB-bypass action=accept comment=LB-bypass
# New LAN connections are split in two by PCC.
add chain=prerouting in-interface-list=LAN connection-mark=no-mark dst-address-type=!local per-connection-classifier=both-addresses:2/0 action=mark-connection new-connection-mark=WAN1 passthrough=yes comment=LB-pcc-1
add chain=prerouting in-interface-list=LAN connection-mark=no-mark dst-address-type=!local per-connection-classifier=both-addresses:2/1 action=mark-connection new-connection-mark=WAN2 passthrough=yes comment=LB-pcc-2
# Each marked connection follows its routing table.
add chain=prerouting in-interface-list=LAN connection-mark=WAN1 action=mark-routing new-routing-mark=to_wan1 passthrough=no comment=LB-route-1
add chain=prerouting in-interface-list=LAN connection-mark=WAN2 action=mark-routing new-routing-mark=to_wan2 passthrough=no comment=LB-route-2
add chain=output connection-mark=WAN1 action=mark-routing new-routing-mark=to_wan1 passthrough=no comment=LB-out-1
add chain=output connection-mark=WAN2 action=mark-routing new-routing-mark=to_wan2 passthrough=no comment=LB-out-2Add your own public subnets to LB-bypass as well, and if a remote system only accepts your office from one known IP address, mark connections to it as WAN1 before the PCC rules so they always leave by line 1.
From a LAN computer, browse and check that both lines carry traffic (Interfaces, Tx/Rx). Unplug the upstream side of line 1 - not the router port - and confirm browsing continues; plug it back and confirm line 1 returns. When everything works, remove the safety scheduler within the five minutes:
/system scheduler remove [find name=LB-revert]If a line gets its address by DHCP, its gateway can change. Point the monitor-host route at the new gateway from the DHCP client’s script, or ask the ISP for a fixed address.
Most scripts online are v6, with routing-mark on routes. On v7 they fail or do nothing. Tables are created under /routing table and routes use routing-table.
With a hotspot, the PCC rules must match the hotspot interface’s traffic as LAN traffic, and the hotspot’s own RADIUS and portal traffic should be pinned to one line so authentication is not split across two public addresses.
PCC, the per-connection classifier, splits new connections between internet lines by a hash of their addresses and ports. Each connection stays on the line it started on, so websites and banking sessions do not break, while the total traffic is spread across both lines.
No. A single connection uses one line, so one download still tops out at one line's speed. What doubles is the capacity for many users at once - which is exactly the situation in a hotel, hostel or office.
Because the ISP's modem or gateway usually keeps answering pings when the internet behind it is down. A recursive route resolves through a public host reached only via that line, so the route fails when the internet fails, not only when the cable is unplugged - and comes back by itself when the line recovers.
Not as written. The configuration on this page is RouterOS v7 syntax - routing tables are created under /routing table and routes use routing-table rather than routing-mark. A v6 router needs the older syntax, or an upgrade to v7 first.
Yes. iberry configures PCC load balancing with recursive failover on MikroTik routers remotely, including the hotspot and VPN side of the same router, and keeps watching both lines afterwards.
Test any change on your own network before relying on it; you apply this configuration at your own risk. MikroTik and RouterOS are trademarks of their owner; iberry is independent and not affiliated with MikroTik.
iberry sets up load balancing, failover, hotspot and VPN on MikroTik routers remotely, in India and abroad. See MikroTik services and captive portal software.
Talk to an Engineer