Failover multi-WAN sur RouterOS 7 — netwatch, sondes et filets
Failover multi-WAN sur RouterOS 7 — netwatch, sondes et filets Documentation de référence. Permet de comprendre, dépanner ou reconstruire le système à l'identique. Testé en…
Sommaire
- Failover multi-WAN sur RouterOS 7 — netwatch, sondes et filets
- 1. Le problème à résoudre
- Pourquoi pas check-gateway sur des routes récursives
- 2. Architecture
- Pourquoi deux jeux d'IP (sondes ≠ cibles netwatch)
- Le rôle du blackhole
- Choix des IP
- 3. Configuration complète
- 3.1 Neutraliser les routes automatiques des clients WAN
- 3.2 Étage 2 — les sondes
- 3.3 Étage 1 — les routes par défaut
- 3.4 Étage 3 — cibles netwatch et blackholes
- 3.5 La supervision netwatch
- 3.6 Étage 4 — les filets
- 3.7 Le rollback
- 4. Failover des tables de policy-routing
- 5. Vérification et tests
- État nominal
- Test de bascule (sans débrancher quoi que ce soit)
- Diagnostic d'une route récursive inactive
- 6. Règles d'or (résumé des leçons payées)
Failover multi-WAN sur RouterOS 7 — netwatch, sondes et filets#
Documentation de référence. Permet de comprendre, dépanner ou reconstruire le système à l'identique. Testé en production sur RouterOS 7.23 (CCR1036) avec trois liens : fibre A (box opérateur), fibre B (PPPoE), satellite (DHCP).
1. Le problème à résoudre#
Trois accès internet, un ordre de préférence, et une exigence : **la bascule doit
se déclencher sur une panne opérateur**, pas seulement quand l'interface tombe.
Le cas vicieux est la box qui répond au ping pendant que la fibre derrière est
morte — un check-gateway=ping vers l'IP de la box ne détecte rien.
Pourquoi pas check-gateway sur des routes récursives#
Première tentative : des routes par défaut récursives (gateway = IP de sonde)
portant check-gateway=ping. Échec en production : le ping de supervision
d'une route récursive interagit avec la résolution de sa propre gateway, et la
route oscille (monte/descend en boucle) ou tombe sans raison. Par ailleurs,
check-gateway=ping sur une route dont la gateway est une interface (PPPoE)
a un comportement indéfini.
Leçon retenue, devenue règle d'architecture :
Les sondes aiguillent, netwatch surveille, les filets garantissent. Aucun
check-gatewaysur aucune route récursive, jamais.
2. Architecture#
Quatre étages indépendants. Chacun peut tomber sans emporter les autres.
ETAGE 1 — routes par défaut "intelligentes" (pilotées par netwatch)
distance 1 WAN-A (fibre box) gateway = IP-sonde-A
distance 3 WAN-B (PPPoE) gateway = IP-sonde-B
distance 5 WAN-C (satellite) gateway = IP-sonde-C
ETAGE 2 — routes de sonde (aiguillage pur, un /32 par WAN)
IP-sonde-A/32 → gateway box A scope=10
IP-sonde-B/32 → interface PPPoE scope=10
IP-sonde-C/32 → gw-satellite%interface scope=10
ETAGE 3 — supervision netwatch (une cible dédiée par WAN + blackhole)
cible-A/32 → box A + blackhole distance=20
cible-B/32 → PPPoE + blackhole distance=20
cible-C/32 → satellite + blackhole distance=20
netwatch A/B/C : ping 10s, timeout 3s → disable/enable la route de l'étage 1
ETAGE 4 — filets (aucune dépendance, aucune supervision)
distance 11 WAN-A direct
distance 13 WAN-B direct
distance 15 tunnel de dernier recours (le cas échéant)Et une route de rollback : l'ancienne route par défaut d'origine, conservée désactivée, jamais supprimée. La réactiver restaure l'état d'avant-chantier en une commande.
Pourquoi deux jeux d'IP (sondes ≠ cibles netwatch)#
- Les IP de sonde (étage 2) servent de gateway récursive aux routes de l'étage 1. Elles ne sont jamais surveillées : une route de sonde ne tombe que si son interface tombe.
- Les cibles netwatch (étage 3) sont des IP distinctes, dédiées à la supervision, chacune forcée sur son WAN. Elles ne servent de gateway à rien.
Séparer les deux rôles élimine toute interaction entre la surveillance et la résolution des routes — la cause racine des oscillations.
Le rôle du blackhole#
Chaque cible netwatch a une route /32 vers son WAN et une route blackhole
à distance 20. Si l'interface du WAN tombe, la route /32 tombe, la blackhole
prend : le ping netwatch meurt au lieu de fuir par la route par défaut d'un
autre WAN. Sans ce blackhole, netwatch verrait la cible répondre via un autre
lien et conclurait à tort que le WAN est sain.
Choix des IP#
Une IP publique stable et pingable par jeu, jamais réutilisée ailleurs dans
la configuration (ni dans une address-list de policy-routing, ni comme DNS
configuré). Exemple de répartition : 1.1.1.1 / 208.67.222.222 / 9.9.9.10
pour les sondes, 1.0.0.1 / 208.67.220.220 / 149.112.112.112 pour les
cibles netwatch. Trois opérateurs différents par jeu : la panne d'un service
d'anycast ne fait pas tomber plusieurs étages.
Piège vécu : une IP de sonde qui figure aussi dans une address-list de policy-routing voit son trafic détourné par le mangle — la sonde teste alors le mauvais chemin. Vérifier avant de choisir :
/ip firewall address-list print where address=<IP>
3. Configuration complète#
Remplacer : <gw-box-A> (ex. 192.168.4.250), <if-pppoe> (ex. WAN2),
<gw-sat> (ex. 192.168.100.1), <if-sat> (nom du VLAN/interface satellite).
3.1 Neutraliser les routes automatiques des clients WAN#
Les clients PPPoE/DHCP/L2TP injectent leurs propres routes par défaut, qui entreraient en concurrence avec le montage :
/interface pppoe-client set [find name=<if-pppoe>] add-default-route=no
/ip dhcp-client set [find interface=<if-sat>] add-default-route=no
# pour un tunnel gardé en dernier recours, le garder mais au bon rang :
/interface l2tp-client set [find name=<tunnel>] default-route-distance=15Piège vécu : oublier un client avec
add-default-route=yesà distance basse. Le jour où les routes intelligentes tombent, c'est LUI qui prend tout le trafic — panne difficile à diagnostiquer car "ça marche", mais par le mauvais lien. Inventaire :/ip route print where dynamic and dst-address="0.0.0.0/0"
3.2 Étage 2 — les sondes#
/ip route
add dst-address=1.1.1.1/32 gateway=<gw-box-A> scope=10 comment="Sonde WAN-A"
add dst-address=208.67.222.222/32 gateway=<if-pppoe> scope=10 comment="Sonde WAN-B"
add dst-address=9.9.9.10/32 gateway=<gw-sat>%<if-sat> scope=10 comment="Sonde WAN-C"scope=10 est indispensable : c'est ce qui rend la sonde utilisable comme cible
de résolution récursive. Aucun check-gateway.
La syntaxe <gw-sat>%<if-sat> force la résolution par une interface précise —
nécessaire quand le préfixe de la gateway n'est routé nulle part ailleurs.
3.3 Étage 1 — les routes par défaut#
/ip route
add dst-address=0.0.0.0/0 gateway=1.1.1.1 distance=1 target-scope=10 \
comment="Defaut 1 - WAN-A (via sonde)"
add dst-address=0.0.0.0/0 gateway=208.67.222.222 distance=3 target-scope=10 \
comment="Defaut 2 - WAN-B (via sonde)"
add dst-address=0.0.0.0/0 gateway=9.9.9.10 distance=5 target-scope=30 \
comment="Defaut 3 - WAN-C (via sonde)"Aucun check-gateway — netwatch s'en charge.
Règle des target-scope, apprise à la dure : une route récursive résout sa gateway via une route dont le scope est ≤ à son target-scope. Dans
main,target-scope=10suffit (les sondes sont à scope=10). Mais une route dans une table de policy-routing qui vise une IP de sonde a besoin detarget-scope=30— la résolution inter-table est plus exigeante. Symptôme du défaut : routeI(inactive) avecimmediate-gw=""alors que la sonde est active. En cas de doute,target-scope=30partout ne casse rien.
3.4 Étage 3 — cibles netwatch et blackholes#
/ip route
add dst-address=1.0.0.1/32 gateway=<gw-box-A> scope=10 comment="Cible netwatch WAN-A"
add dst-address=1.0.0.1/32 blackhole distance=20 comment="Blackhole netwatch WAN-A"
add dst-address=208.67.220.220/32 gateway=<if-pppoe> scope=10 comment="Cible netwatch WAN-B"
add dst-address=208.67.220.220/32 blackhole distance=20 comment="Blackhole netwatch WAN-B"
add dst-address=149.112.112.112/32 gateway=<gw-sat>%<if-sat> scope=10 comment="Cible netwatch WAN-C"
add dst-address=149.112.112.112/32 blackhole distance=20 comment="Blackhole netwatch WAN-C"Syntaxe v7 :
blackholeest un flag sans valeur. Letype=blackholede RouterOS 6 renvoiebad parameter type.
3.5 La supervision netwatch#
/tool netwatch
add host=1.0.0.1 interval=10s timeout=3s comment="Supervision WAN-A" \
down-script="/ip route set [find comment=\"Defaut 1 - WAN-A (via sonde)\"] disabled=yes" \
up-script="/ip route set [find comment=\"Defaut 1 - WAN-A (via sonde)\"] disabled=no"
add host=208.67.220.220 interval=10s timeout=3s comment="Supervision WAN-B" \
down-script="/ip route set [find comment=\"Defaut 2 - WAN-B (via sonde)\"] disabled=yes" \
up-script="/ip route set [find comment=\"Defaut 2 - WAN-B (via sonde)\"] disabled=no"
add host=149.112.112.112 interval=10s timeout=3s comment="Supervision WAN-C" \
down-script="/ip route set [find comment=\"Defaut 3 - WAN-C (via sonde)\"] disabled=yes" \
up-script="/ip route set [find comment=\"Defaut 3 - WAN-C (via sonde)\"] disabled=no"Temps de bascule : ~13 s (un intervalle + timeout). Le retour est automatique.
Les scripts pilotent par commentaire, pas par numéro : les numéros de route changent à chaque ajout/suppression, les commentaires survivent. Ne jamais renommer un commentaire de route sans mettre à jour le netwatch correspondant.
3.6 Étage 4 — les filets#
/ip route
add dst-address=0.0.0.0/0 gateway=<gw-box-A> distance=11 comment="Filet WAN-A (sans sonde)"
add dst-address=0.0.0.0/0 gateway=<if-pppoe> distance=13 comment="Filet WAN-B (sans sonde)"
add dst-address=0.0.0.0/0 gateway=<gw-sat>%<if-sat> distance=14 comment="Filet WAN-C (sans sonde)"Gateway directe, aucune sonde, aucune supervision : ces routes ne tombent que si l'interface tombe. Si toute la supervision déraille, le trafic passe ici — dégradé (pas de détection de panne opérateur) mais jamais coupé.
3.7 Le rollback#
L'ancienne route par défaut d'origine (gateway box, check-gateway=ping
historique) est conservée désactivée :
/ip route set [find comment="<ancienne route>"] disabled=yesEn cas de comportement incompréhensible : enable dessus, disable sur les
Defaut 1/2/3, et l'état d'avant-chantier est restauré. Ce bouton a servi.
4. Failover des tables de policy-routing#
Les tables de policy (sortie forcée par tel WAN pour telles destinations)
bénéficient du même principe : deux routes par table, distances différentes,
gateways = IP de sonde, target-scope=30.
# exemple : table "via_wanB" — principal WAN-B, secours WAN-A
/ip route
add dst-address=0.0.0.0/0 gateway=208.67.222.222 distance=1 target-scope=30 \
routing-table=via_wanB comment="via_wanB principal"
add dst-address=0.0.0.0/0 gateway=1.1.1.1 distance=10 target-scope=30 \
routing-table=via_wanB comment="via_wanB - secours WAN-A"Quand netwatch désactive Defaut 2, la sonde WAN-B reste active (elle ne dépend
que de l'interface) — donc la route principale de la table reste active aussi.
La bascule de la table se produit si l'interface tombe. Pour une bascule de
table sur panne opérateur, ajouter un second couple de scripts au netwatch
concerné, pilotant la route de la table.
Réflexion avant d'ajouter un secours : certaines tables existent parce que l'IP de sortie compte (services liés à l'opérateur, IP whitelistée). Un secours par un autre WAN ne "sauvera" pas ces destinations — mais si le lien principal est mort, elles sont mortes de toute façon ; le secours sauve tout le reste de la liste. À trancher table par table.
Piège vécu : une table de routage vide (ou dont toutes les routes sont inactives) jette les paquets marqués — pas de repli sur main. Une table de policy doit toujours contenir au moins une route active, sinon le trafic marqué disparaît silencieusement.
5. Vérification et tests#
État nominal#
/ip route print detail where dst-address="0.0.0.0/0" and routing-table=main| Route | Distance | Flag attendu |
|---|---|---|
| Defaut 1 | 1 | As — porte le trafic |
| Defaut 2 | 3 | s — prête |
| Defaut 3 | 5 | X si le WAN est down (netwatch l'a coupée) |
| Filets | 11/13/14 | s |
| Dernier recours | 15 | s |
| Ancienne route | 1 | X — rollback |
/tool netwatch printstatus=up sur les WAN sains, down sur les WAN morts, since cohérent.
Test de bascule (sans débrancher quoi que ce soit)#
/ip route disable [find comment="Cible netwatch WAN-A"]La cible devient injoignable (blackhole) → netwatch passe down en ~13 s →
Defaut 1 désactivée → le trafic bascule sur WAN-B. Vérifier :
/tool netwatch print
/ip route print where dst-address="0.0.0.0/0" and routing-table=mainPuis enable la cible : retour automatique. **Tant que ce test n'est pas passé,
le failover doit être considéré comme non fonctionnel** — la structure sans le
test ne prouve rien.
Diagnostic d'une route récursive inactive#
Symptôme : route I, immediate-gw="".
- La route de sonde correspondante est-elle active ?
/ip route print detail where dst-address="<IP-sonde>/32" - Le
target-scopeest-il suffisant ? (30 pour les tables de policy) - Une connexion établie garde son ancien chemin — purger après tout
changement :
/ip firewall connection remove [find dst-address~"<IP>"] - Un ping depuis le routeur (
chain=output) ne traverse pas le mangle prerouting : il ne teste pas le policy-routing. Tester avec/ping <IP> routing-table=<table>ou depuis un poste du LAN.
6. Règles d'or (résumé des leçons payées)#
- Jamais de check-gateway sur une route récursive. Oscillations garanties. La surveillance vit dans netwatch, point.
- Jamais de check-gateway sur une route dont la gateway est une interface (PPPoE) : comportement indéfini.
- Une IP surveillée ne sert qu'à ça. Sondes et cibles netwatch sont des jeux disjoints, et aucune ne figure dans une address-list de policy.
- Chaque cible netwatch a son blackhole — sinon le ping fuit par un autre WAN et la supervision ment.
- Les filets d'abord. Ne jamais désactiver le mécanisme existant avant d'avoir prouvé que le nouveau fonctionne (test de bascule inclus).
- target-scope=30 pour toute route de table de policy visant une sonde.
- Désactiver, pas supprimer. Une route désactivée commentée est un rollback ; une route supprimée est une reconstruction.
- Export avant/après chaque chantier, récupéré hors du routeur :
/export compact file=stable-<date>. - Les scripts netwatch pilotent par commentaire : renommer un commentaire de route casse silencieusement la supervision.
- Après tout changement de routage, purger les connexions concernées — le conntrack fige le chemin à la première trame.