Lab 04-05 · Recursive routing and failover (optional)¶
MTCNA
Module 4 · Routing of the MikroTik MTCNA course, official slides p182–185 (routing in RouterOS 6
vs 7, the /routing route menu, and the optional LAB "Recursive Routing + Failover"), plus p165–166
(check-gateway and distance).
Your phone says it is connected to the WiFi: full bars. You open Instagram and... nothing loads. The phone was not lying: the link to the WiFi router is perfect. The problem is further away: the router's own Internet connection is down. The bars only measure the first metre of the journey.
A small office with two Internet providers has the same problem. The classic failover, "if the provider's router stops answering, use the other provider", only checks the first metre: the cable to the provider. If the provider breaks somewhere behind its router, the office keeps sending everything into a dead end. In this lab you build the cure taught on slide p184: test a real address on the Internet, through each provider, and switch only when that test fails. That trick is called recursive routing.
What you will learn
- Explain why a failover based on checking the provider's router misses failures upstream.
- Explain recursive routing: a route whose gateway is not directly connected and is found through another route.
- Use scope and target-scope to allow that, and apply the v7 rule from slide p185 (target-scope bigger than scope).
- Combine distance (1 = main, 2 = backup) with check-gateway=ping to switch provider automatically.
- Break the main provider upstream, prove that traffic moves to the backup, and that it comes back on its own.
- Read the v7 route menus:
/ip routeto configure,/routing routeto see everything.
The analogy: WiFi bars vs "does Instagram load?"¶
| Phone | Office router | What it means |
|---|---|---|
| Full WiFi bars | The cable to ISP1's router is up | Link-level check: the first metre only |
| "Connected, no Internet" | ISP1 lost its own Internet link | An upstream failure the bars cannot see |
| Opening a real website to test | Pinging 8.8.8.8 through ISP1 |
The recursive check: tests the whole path |
| Switching to mobile data | Using ISP2 (distance 2) | The backup route takes over |
Failover, distance and check-gateway¶
Failover is switching automatically to a backup path when the main one fails.
You already have all the pieces from the previous labs:
- Distance decides the order: the main route gets 1, the backup 2. While both are active, distance 1 wins (they are not equal, so this is not ECMP).
- check-gateway=ping makes a route inactive when its gateway misses two pings in a row (about 20 s). Then the distance-2 route is the best one left and becomes active.
The router you receive already has this naive failover:
0.0.0.0/0 gateway=10.1.1.1 distance=1 check-gateway=ping ← ISP1's router
0.0.0.0/0 gateway=10.2.2.1 distance=2 check-gateway=ping ← ISP2's router
It pings ISP1's router, 10.1.1.1. If the cable is cut, the ping fails and the backup takes over. But if
ISP1's router is alive and its link to the Internet is dead, 10.1.1.1 keeps answering, the route stays
active, and the office is offline. That is the failure "in an upper node" of slide p184.
Recursive routing¶
A recursive route is a route whose gateway is not in a directly connected network. The router finds out how to reach that gateway by looking it up in its routing table again: it recurses.
The trick of slide p184 in three lines:
- A probe route:
8.8.8.8/32(one single address) through ISP1's router10.1.1.1. Now 8.8.8.8 can only be reached through ISP1. Same for1.1.1.1/32through ISP2. - The main default route uses
8.8.8.8as its gateway, with check-gateway=ping and distance 1. The router resolves "how do I reach 8.8.8.8?" through the probe route: via10.1.1.1. So the traffic really goes to ISP1, but the health check pings 8.8.8.8, across ISP1's whole network. - The backup default route does the same with
1.1.1.1(ISP2), distance 2.
If anything between you and 8.8.8.8 breaks, inside ISP1 or beyond, the ping fails, the main route goes inactive, and the backup takes over.
flowchart LR
R1["<b>r1</b><br>default → 8.8.8.8 (d=1)<br>default → 1.1.1.1 (d=2)"]
ISP1["<b>isp1</b><br>10.1.1.1"]
ISP2["<b>isp2</b><br>10.2.2.1"]
NET["<b>internet</b><br>8.8.8.8 · 1.1.1.1<br>198.51.100.10"]
R1 -->|"8.8.8.8/32 via 10.1.1.1<br>ping every 10 s"| ISP1
R1 -->|"1.1.1.1/32 via 10.2.2.1"| ISP2
ISP1 -->|"this link breaks"| NET
ISP2 --> NET
Scope and target-scope: permission to recurse¶
By default RouterOS does not resolve a gateway through just any route; otherwise a mistake could create loops. Two numbers control it:
scope is a number on every route: how "close" it is. Connected routes have scope 10, static routes scope 30 by default.
target-scope is a number on a route that says which routes may be used to resolve its gateway: only routes whose scope is within the target-scope. Static routes have target-scope 10 by default.
So by default a static route can only find its gateway through connected routes (scope 10). To let the
default route find 8.8.8.8 through the probe route, you give the probe route scope=10 and the default
route a bigger target-scope. Slide p185 states the RouterOS v7 rule: target-scope must be bigger than
scope, so target-scope=11. We tested it on RouterOS 7.23: with target-scope=10 the route stays inactive
(its immediate-gw stays empty); with 11 it becomes active, with immediate-gw=10.1.1.1%ether2.
RouterOS 6 vs 7: where are my routes?
In v6 everything lived in /ip route. In v7 (slides p182–183) you still add static routes in
/ip route (and /ipv6 route), which now shows only the basic attributes. The new menu /routing
route shows every route of every address family, with all their attributes (scope, target-scope,
immediate gateway...). v7 also raised the limit on the number of routes and changed how routes go into
other routing tables.
The scenario¶
There is only one trainer's router in the classroom, so this lab builds its own small world: one office router
and two simulated Internet providers. 8.8.8.8 and 1.1.1.1 are famous public DNS servers (Google and
Cloudflare); here they are just two addresses on the internet node, and nothing leaves your computer.
flowchart LR
PC1["<b>pc1</b><br>office laptop<br>192.168.88.x"]
subgraph R1["r1 · office router"]
E3["ether3 · bridge1<br>192.168.88.1/24"]
E2["ether2 · WAN 1<br>10.1.1.2/24"]
E4["ether4 · WAN 2<br>10.2.2.2/24"]
end
ISP1["<b>isp1</b> (main)<br>10.1.1.1 · 172.16.1.1"]
ISP2["<b>isp2</b> (backup)<br>10.2.2.1 · 172.16.2.1"]
NET["<b>internet</b><br>8.8.8.8 · 1.1.1.1<br>web 198.51.100.10"]
PC1 --- E3
E2 --- ISP1
E4 --- ISP2
ISP1 ---|"172.16.1.0/30"| NET
ISP2 ---|"172.16.2.0/30"| NET
| Node | Role | Address |
|---|---|---|
r1 |
The office router (yours): two WANs, one LAN, NAT on both WANs | ether2 10.1.1.2/24, ether4 10.2.2.2/24, bridge1 192.168.88.1/24 |
isp1 |
Main provider's router (Linux) | 10.1.1.1 towards you, 172.16.1.1 towards the Internet |
isp2 |
Backup provider's router (Linux) | 10.2.2.1 towards you, 172.16.2.1 towards the Internet |
internet |
"The Internet": owns 8.8.8.8, 1.1.1.1 and the web server 198.51.100.10 |
172.16.1.2, 172.16.2.2 |
pc1 |
Office laptop | By DHCP from r1 |
Why ether2 and ether4?
On a real hAP the Internet port is ether1. In the virtual lab ether1 is reserved for the lab itself (containerlab uses it to manage the router), so the first Internet port is ether2 and the LAN starts at ether3. The second provider is plugged into ether4, taken out of the LAN as you would do on a real hAP. Never touch ether1 in these labs.
Start the lab¶
Download the lab files and unzip them: 04-05-recursive-failover.zip. Open a terminal inside the 04-05-recursive-failover folder.
Give RouterOS about two minutes to boot. Then:
ssh admin@clab-mtcna-04-05-r1 # password: admin
docker exec -it clab-mtcna-04-05-pc1 bash
docker exec -it clab-mtcna-04-05-isp1 bash # you will "break" ISP1 from here
At any moment you can run CLAB_EXEC="docker exec" ./check.sh. The check breaks ISP1's Internet link for
about half a minute and repairs it at the end.
The laptops ask for their address by themselves when the lab starts; if ip -br address show eth1 shows
no IPv4 address yet (the router was still booting), run dhclient -v eth1.
Step 1 · Test the naive failover (it works for a cut cable)¶
Look at the routes you received. On r1 (WinBox: IP → Routes):
Two default routes: via 10.1.1.1 (distance 1, active) and via 10.2.2.1 (distance 2). On pc1:
Hop 2 is 10.1.1.1: ISP1's router. Now pull the cable to ISP1. On r1:
The route via 10.1.1.1 becomes I immediately (its interface is down) and the backup is active. Repeat the
traceroute: hop 2 is now 10.2.2.1. Plug the cable back:
Check yourself
- Why did the switch happen immediately here, without waiting for check-gateway's 20 seconds?
Done when you have seen the traffic move to ISP2 and back.
Step 2 · Break ISP1 upstream (the naive failover fails)¶
Now the nasty failure: ISP1's router is fine, but it loses its Internet link. On isp1:
Wait 30 seconds, then on r1 and pc1:
The route via 10.1.1.1 is still active: ISP1's router answers every ping. But curl fails, and the
traceroute stops at 10.1.1.1 (with !N: ISP1 has no way to the Internet). The office is offline, and the backup sits unused. Repair ISP1 before going
on (Linux removes a route when its link goes down, so put it back too):
Check yourself
- Why did check-gateway not notice anything? What exactly was it testing?
Done when you have seen the office go offline while the main route stayed active.
Step 3 · Add the probe routes¶
Pin 8.8.8.8 to ISP1 and 1.1.1.1 to ISP2, with scope=10. WinBox: IP → Routes → +, Dst. Address
8.8.8.8/32, Gateway 10.1.1.1, Scope 10 (and the same for 1.1.1.1/32 via 10.2.2.1).
/ip route add dst-address=8.8.8.8/32 gateway=10.1.1.1 scope=10
/ip route add dst-address=1.1.1.1/32 gateway=10.2.2.1 scope=10
/ping 8.8.8.8 count=3
/ping 1.1.1.1 count=3
Both pings answer. Each address can now only be reached through its own provider.
Done when both probe routes are active and both pings work.
Step 4 · Add the recursive default routes¶
WinBox: IP → Routes → +, Dst. Address 0.0.0.0/0, Gateway 8.8.8.8, Check Gateway ping, Distance 1,
Target Scope 11. Then the backup with 1.1.1.1 and Distance 2.
First see the v7 rule in action. Add the main route without target-scope:
/ip route add dst-address=0.0.0.0/0 gateway=8.8.8.8 check-gateway=ping distance=1
/ip route print detail where gateway=8.8.8.8
It shows I (inactive), target-scope=10 and immediate-gw="": RouterOS is not allowed to resolve 8.8.8.8
through a route of scope 10. Fix it, and add the backup:
/ip route set [find where dst-address=0.0.0.0/0 and gateway=8.8.8.8] target-scope=11
/ip route add dst-address=0.0.0.0/0 gateway=1.1.1.1 target-scope=11 check-gateway=ping distance=2
/routing route print where dst-address=0.0.0.0/0
Expected: the route via 8.8.8.8 is active, with immediate gateway 10.1.1.1%ether2: it found its way
through the probe route. The one via 1.1.1.1 waits with distance 2.
Look closely: right now two default routes have distance 1 (the naive one via 10.1.1.1 and the new one
via 8.8.8.8), so RouterOS shows both with +: that is ECMP, not what you want. Finally remove the naive
routes:
Expected: two default routes (via 8.8.8.8, active; via 1.1.1.1, standby) and the two probe routes.
Check yourself
- In
/routing route print, which column shows the real next hop of the route via8.8.8.8? - Why must the probe route to
8.8.8.8be a/32and go through ISP1 only?
Done when the default route via 8.8.8.8 is active with immediate gateway 10.1.1.1.
Step 5 · Break ISP1 upstream again (now it works)¶
Repeat Step 2. On isp1: ip link set eth2 down. On r1, watch for about 30 seconds:
After two missed pings to 8.8.8.8 the main route becomes I and the route via 1.1.1.1 becomes A. On
pc1:
curl works again, and hop 2 is now 10.2.2.1: ISP2. Repair ISP1:
Within about 10 seconds the ping to 8.8.8.8 succeeds, the main route is active again, and the traceroute goes
back through 10.1.1.1. Nobody had to touch the office router.
Check yourself
- How long did the switch to ISP2 take? And the switch back?
- Your router also uses
8.8.8.8as a DNS server. During ISP1's failure, can it still reach that DNS server? Why does it also list1.1.1.1?
Done when the traffic moved to ISP2 and came back by itself. Run CLAB_EXEC="docker exec" ./check.sh:
every line must say PASS.
Traps in real networks
- The probe addresses are pinned to one provider. Any other traffic to
8.8.8.8(DNS queries, for example) also goes through ISP1, even when ISP1 is down. Use probe addresses you do not need for anything else, or list several DNS servers. - Pick probe addresses that answer ping reliably and belong to big, stable networks. If the probe host itself goes down, you switch provider for nothing.
If something goes wrong¶
| Symptom | Likely cause | Fix |
|---|---|---|
Default route via 8.8.8.8 stays I, immediate-gw="" |
target-scope not bigger than the probe route's scope |
target-scope=11 on the default route, scope=10 on the probe route |
Probe route active but pings to 8.8.8.8 fail |
ISP1 is still broken from Step 2 | On isp1: ip link set eth2 up; ip route replace default via 172.16.1.2 |
| Both default routes active at once, traffic split | Same distance on both: that is ECMP | Main distance=1, backup distance=2 |
| Failover never happens | No check-gateway=ping on the main route |
/ip route set [find gateway=8.8.8.8] check-gateway=ping |
| Traffic never comes back to ISP1 | ISP1 repaired without its default route | Add ip route replace default via 172.16.1.2 on isp1 |
| pc1 has no address | It started before r1 was ready | dhclient -v eth1 on pc1 |
Clean up¶
Key takeaways¶
- Failover with distance (1 main, 2 backup) and check-gateway only sees what it pings: pinging the provider's router misses upstream failures.
- A recursive route has a gateway that is not directly connected; RouterOS finds it through another route.
- scope and target-scope control which routes may resolve a gateway; in RouterOS v7 the target-scope must be bigger than the probe route's scope (
scope=10,target-scope=11). - Pinning a public address (
8.8.8.8) to each provider with a/32route turns check-gateway into an end-to-end test of that provider. - In v7 you add routes in
/ip routeand inspect every detail in/routing route.
Quick check¶
1. Why does a failover that pings the provider's own router miss some failures?
- Because providers block pings to their routers
- Because the provider's router can keep answering while its link to the Internet is down
- Because check-gateway only works with recursive routes
- Because ping is too slow to detect anything
check-gateway only tests what it pings. The provider's router is the first hop: it can be alive while the provider is broken upstream, so the route stays active and traffic goes into a dead end.
2. What makes a route recursive?
- It has a distance higher than 1
- It points at an interface instead of an address
- Its gateway is not directly connected and is resolved through another route
- It is repeated in several routing tables
A recursive route's gateway (here 8.8.8.8) is not in any connected network. RouterOS looks it up in
the routing table again and finds the probe route, which gives the real next hop 10.1.1.1.
3. The probe route 8.8.8.8/32 has scope=10. Which target-scope does the default route via 8.8.8.8 need in RouterOS v7?
- 5
- 10
- 11
- 30
In v7 the target-scope of the recursive route must be bigger than the scope of the route used to
resolve its gateway. With scope=10 on the probe route, target-scope=11 works; 10 leaves the route
inactive.
4. Main and backup default routes: which distances make one the main and the other the backup?
- Distance 1 for the main, distance 2 for the backup
- Distance 1 for both
- Distance 2 for the main, distance 1 for the backup
- Distance 0 for the main, distance 1 for the backup
The lower distance wins. With 1 and 2 the main route is used while it is active, and the backup takes over only when the main becomes inactive. Equal distances would create ECMP instead.
5. In RouterOS v7, where do you see a route's scope, target-scope and immediate gateway together with every other route?
- In /ip address
- In /routing route
- In /interface bridge
- In /system routerboard
RouterOS v7 introduced /routing route, which shows all routes of every address family with all their
attributes. /ip route is still where you add static routes, and it shows only the basic columns.
6. ISP1 loses its Internet link but its router keeps answering. With recursive routing, which two things happen?
- The pings to 8.8.8.8 through ISP1 fail and the main default route becomes inactive
- The probe route 8.8.8.8/32 is deleted from the configuration
- The default route via 1.1.1.1 becomes active and traffic leaves through ISP2
- The router reboots to reconnect to ISP1
check-gateway pings 8.8.8.8, which is only reachable through ISP1. When ISP1 breaks anywhere, two pings fail, the distance-1 route goes inactive, and the distance-2 route through ISP2 takes over. Nothing is deleted: when ISP1 recovers, the main route comes back by itself.
That closes the routing module. Next module: wireless, where the cable you have relied on so far is replaced by radio.