Choisir ce qui passe par le tunnel
Recettes RouterOS facultatives pour un routeur ForestVPN — envoyer un groupe d'applications, tout envoyer, et empêcher le trafic de fuir quand le tunnel est indisponible.
Mis à jour le 8 octobre 2026
Tout ce qui figure sur cette page est facultatif. Un routeur ForestVPN fait transiter son propre trafic dès qu'il se connecte, et rien de tout cela n'est nécessaire pour cela. Voici l'autre rôle : décider quelle part du trafic de votre réseau local sort par la sortie, et ce qui se passe quand la sortie est injoignable.
La répartition des tâches ne change jamais. RouterOS décide quoi envoyer dans le tunnel, le conteneur fait transiter tout ce qu'on lui confie, et votre compte décide où cela ressort. Tout ceci n'est donc qu'une configuration RouterOS ordinaire — des marques mangle, une table de routage, une règle de pare-feu — et rien de tout cela ne touche au conteneur.
À lire en premier
Trois faits décident si tout ceci fonctionne. Les ignorer, c'est une soirée que vous ne récupérerez pas.
Collez ceci sur le boîtier qui route votre réseau local. La chaîne prerouting de RouterOS ne
voit que le trafic que le boîtier lui-même route. Sur un point d'accès situé en aval de votre
véritable passerelle, chaque règle ci-dessous est inerte — mesuré sur une cAP ax dont la route par
défaut est le routeur en amont : le conteneur faisait transiter son trafic parfaitement et aucun
trafic d'un client du réseau local n'en approchait jamais. Le conteneur peut vivre sur ce point
d'accès ; les règles vont sur la passerelle.
La sortie n'admet qu'une seule adresse source par appareil — le bail de recouvrement qu'elle a délivré. Un paquet arrivant avec toute autre source interne est abandonné, pas routé, aussi correctes que soient vos règles. Quelque chose doit réécrire votre réseau local vers ce bail, et ce qui s'en charge dépend du conteneur :
| Conteneur | Ce que vous devez faire |
|---|---|
suquant/fvpn — l'application gérée par le compte | Rien. Depuis la version 0.3.9, le conteneur masque tout ce que vous lui transférez sous son propre bail, et suit ce bail quand il change. La commande d'installation active cela. |
suquant/fvpnq — le tunnel brut, à partir d'un .conf que vous avez écrit | Ajoutez un src-nat vers l'Address de votre .conf, qui est aussi ce que vous mettez dans l'AllowedIPs de la sortie. Vous l'avez choisie, elle est donc stable et une règle peut la nommer. |
Vous faites tourner un conteneur antérieur à la 0.3.9 ? Relancez la commande d'installation — les règles ci-dessous marqueront et routeront parfaitement, mais la sortie rejettera chaque paquet, ce qui se lit comme le réseau local perdant purement et simplement l'accès à Internet dès que vous ajoutez la règle de routage.
Fasttrack contourne mangle. Le pare-feu d'usine de MikroTik met en fasttrack les connexions
établies, et une connexion en fasttrack n'atteint plus jamais la chaîne mangle — vos marques
s'appliquent donc au premier paquet d'un flux et à rien après lui. Chaque recette ci-dessous comporte
la règle unique qui garde les connexions marquées hors du fasttrack, et elle doit se placer
au-dessus de la règle fasttrack-connection.
Et la moitié IPv6, que ces règles ne peuvent pas faire pour vous
Tout ceci est en IPv4. Si votre routeur dispose d'un IPv6 fonctionnel, chaque destination que vous
sélectionnez ci-dessous est aussi joignable en v6, en contournant le tunnel, sans qu'aucun
avertissement n'apparaisse. Si au contraire le routeur s'annonce comme routeur IPv6 sans avoir de
route par défaut v6, les clients du réseau local lui envoient du v6 et n'obtiennent rien en retour —
pas même une erreur, car RouterOS 7 n'a pas de route « injoignable » pour le v6, seulement
un blackhole silencieux. Les appareils sans Happy Eyeballs — téléviseurs, montres, tout ce qui fait
une connexion brute sur un enregistrement AAAA — restent alors bloqués pendant tout le délai de
connexion sur chaque destination v6, ce qui se lit comme « Internet est parfois cassé » et
accuse le Wi-Fi. Cette seule ligne indique dans lequel des deux cas vous êtes :
# Does this router tell LAN clients it is their IPv6 router?
/ipv6/nd/print where ra-lifetime!=none
# Does it have somewhere to send their v6 traffic?
/ipv6/route/print where dst-address="::/0" and routing-table="main"Une réponse à la première commande et aucune à la seconde correspond au second cas. Donnez à IPv6
une véritable route par défaut, ou cessez d'en annoncer une avec
/ipv6/nd/set [find] ra-lifetime=none.
Étape 1 — l'échafaudage
La même chose pour les trois recettes. Remplacez 172.31.254.2 par votre propre adresse de conteneur
(celle par défaut de l'installation ; /interface/veth/print la donne)
et 192.168.88.0/24 par votre propre préfixe de réseau local.
Vérifiez d'abord /container/print detail. remote-image doit indiquer 0.3.9 ou une version
ultérieure, et cmd doit contenir --nat-lan. Les deux viennent de la commande
d'installation actuelle ; un conteneur installé avant cela n'a ni l'un ni
l'autre, et le symptôme est le réseau local perdant purement et simplement l'accès à Internet dès que
vous ajoutez la règle de routage de l'étape 2.
# A routing table of its own, so nothing here can disturb your normal
# default route.
/routing/table add name=via-fvpn fib
# Where marked traffic goes: the container, on the address RouterOS itself
# gave it.
/ip/route add dst-address=0.0.0.0/0 gateway=172.31.254.2 \
routing-table=via-fvpn comment="fvpn: traffic leaves via the container"
# Collapse the LAN to one source address on the way IN to the container. The
# exit never sees this one either -- the container masquerades again onto its
# own lease -- so this is about keeping your LAN's layout out of the
# container's connection table, not about being admitted.
/ip/firewall/nat add chain=srcnat out-interface=veth-fvpn action=masquerade \
comment="fvpn: hide LAN addressing from the container"
# The tunnel costs 80 bytes of MTU. Without this, large TCP flows stall
# rather than fail, which presents as "the internet is broken on Tuesdays".
/ip/firewall/mangle add chain=forward action=change-mss new-mss=clamp-to-pmtu \
protocol=tcp tcp-flags=syn connection-mark=via-fvpn \
comment="fvpn: clamp MSS on tunnelled TCP"
# Fasttrack bypasses mangle, so marked connections have to be accepted
# before they reach it. This rule is inert if it ends up below the fasttrack
# rule -- check with /ip/firewall/filter/print that it did not.
/ip/firewall/filter add chain=forward action=accept connection-mark=via-fvpn \
place-before=[find action=fasttrack-connection] \
comment="fvpn: marked flows skip fasttrack"Choisissez ensuite l'une des deux suivantes. Elles produisent toutes deux la même marque de
connexion via-fvpn, donc elles se disputeraient le même trafic si vous colliez les deux.
Étape 2a — facultatif : appels et messageries uniquement
La configuration qui tourne sur notre propre RB3011 depuis des mois. Elle découpe le problème comme le trafic se découpe réellement : la signalisation représente une poignée de noms d'hôtes d'éditeurs, le flux média représente une plage de ports sur des relais que personne ne publie.
# Signalling, by hostname. A hostname in a RouterOS address list is not a
# static entry -- the router resolves it and keeps the answers fresh, which
# is the only form that survives a CDN moving under you.
/ip/firewall/address-list
add list=fvpn-via address=g.whatsapp.net comment="fvpn: signalling"
add list=fvpn-via address=media.whatsapp.net comment="fvpn: signalling"
add list=fvpn-via address=mmg.whatsapp.net comment="fvpn: signalling"
add list=fvpn-via address=static.whatsapp.net comment="fvpn: signalling"
add list=fvpn-via address=web.whatsapp.com comment="fvpn: signalling"
add list=fvpn-via address=api.telegram.org comment="fvpn: signalling"
add list=fvpn-via address=core.telegram.org comment="fvpn: signalling"
add list=fvpn-via address=web.telegram.org comment="fvpn: signalling"
add list=fvpn-via address=chat.signal.org comment="fvpn: signalling"
add list=fvpn-via address=storage.signal.org comment="fvpn: signalling"
/ip/firewall/mangle
add chain=prerouting action=mark-connection new-connection-mark=via-fvpn \
dst-address-list=fvpn-via \
comment="fvpn: signalling by resolved vendor hostname"
# Media, by port -- the half an address list can never cover, because a call
# lands on whichever TURN relay the vendor picked that minute.
add chain=prerouting action=mark-connection new-connection-mark=via-fvpn \
protocol=udp dst-port=3478-3481 \
comment="fvpn: STUN/TURN media - calls in every major app"
add chain=prerouting action=mark-connection new-connection-mark=via-fvpn \
protocol=tcp dst-port=3478-3481,5349,5350 \
comment="fvpn: STUN/TURN over TCP and TLS"
add chain=prerouting action=mark-connection new-connection-mark=via-fvpn \
protocol=udp dst-port=5060,5061 comment="fvpn: SIP"
add chain=prerouting action=mark-connection new-connection-mark=via-fvpn \
protocol=tcp dst-port=5060,5061 comment="fvpn: SIP over TCP/TLS"
add chain=prerouting action=mark-connection new-connection-mark=via-fvpn \
protocol=tcp dst-port=5222,5223 comment="fvpn: XMPP signalling"
# One routing decision for the whole connection. Marking the connection
# first and the route second -- rather than marking the route directly -- is
# what keeps a call that started on the tunnel on the tunnel.
add chain=prerouting action=mark-routing new-routing-mark=via-fvpn \
passthrough=no src-address=192.168.88.0/24 connection-mark=via-fvpn \
comment="fvpn: route marked connections via the exit"Ces noms d'hôtes sont un point de départ, pas une autorité. Les éditeurs en ajoutent et en
retirent sans prévenir personne. Vérifiez /ip/firewall/mangle/print stats pour repérer les
compteurs qui restent à zéro — c'est une règle qui ne correspond à rien, pas une règle qui fait
discrètement son travail.
Étape 2b — facultatif : tout le trafic
/ip/firewall/mangle
# The container's own packets must never be marked, or its tunnel gets
# routed into itself. The install puts the container's interface in the LAN
# list, so the rule below WOULD match it. Substitute the container's
# address.
add chain=prerouting action=accept src-address=172.31.254.2 \
comment="fvpn: never mark the container's own traffic"
# Everything from the LAN that is not addressed to this router.
# `dst-address-type=!local` is what keeps DNS, WebFig and the status page
# off the tunnel; `in-interface-list=LAN` rather than a source prefix keeps
# the rule correct when the LAN is renumbered.
add chain=prerouting action=mark-connection new-connection-mark=via-fvpn \
in-interface-list=LAN dst-address-type=!local \
comment="fvpn: everything from the LAN"
# `dst-address-type=!local` on this rule too, and it is not decoration. The
# install puts the container's veth in the LAN list, so replies coming back
# OUT of the container also match `in-interface-list=LAN`, and they still
# carry the connection mark. Mangle prerouting runs before dstnat, so at
# this moment their destination is still the router's own srcnat address --
# local. Without the test they would take the routing mark and be sent back
# into the container instead of on to the client that asked.
add chain=prerouting action=mark-routing new-routing-mark=via-fvpn \
passthrough=no in-interface-list=LAN dst-address-type=!local \
connection-mark=via-fvpn \
comment="fvpn: route marked connections via the exit"Comptez ce que vous avez collé avant de tester. /ip/firewall/mangle/print doit afficher ces
trois règles. Un collage dans le terminal qui perd l'une des continuations de ligne vous laisse avec
les règles de marquage et sans règle de routage, ce qui ressemble exactement à « le tunnel est
ignoré » — les connexions portent connection-mark=via-fvpn, rien ne consulte jamais la table,
et chaque paquet repart par votre connexion normale.
Envoyer tout le trafic, c'est aussi envoyer le DNS — c'est le but, mais cela signifie que le
résolveur de la sortie répond à votre réseau local. Vérifiez que tout ce qui dépend de noms locaux
(une imprimante, un NAS, router.lan) résout encore avant de décider que c'est le mode que vous
voulez.
Étape 3 — facultatif : bloquer le trafic si le tunnel tombe
Le routage sélectif a un mode de défaillance qu'il vaut la peine de fermer : quand le tunnel s'arrête, le trafic marqué peut se remettre à sortir discrètement par votre connexion normale. Ces trois règles le bloquent à la place. Ajoutez-les après la recette que vous avez choisie.
Chaque commande de cette section a été exécutée sur RouterOS 7.24.1 avant d'être consignée ici. La syntaxe diffère de RouterOS 6 à un endroit, signalé ci-dessous.
# 1. The route to the container counts only while the container answers.
/ip/route/set [find routing-table=via-fvpn dst-address=0.0.0.0/0] \
check-gateway=ping
# 2. When it stops counting, drop rather than fall back. The higher distance
# keeps this route inactive for as long as the real one is up. `blackhole`
# is a bare flag here, not `type=blackhole` -- RouterOS 7 has no `type`
# property on a route at all, and rejects it with "bad parameter type".
/ip/route/add dst-address=0.0.0.0/0 blackhole distance=10 \
routing-table=via-fvpn comment="fvpn: kill switch - no exit, no traffic"
# 3. The leak the first two cannot see: a container that is alive and
# answering ping while its own tunnel is down forwards to its default
# gateway, which is you. Traffic wearing the address the srcnat above gave
# it must never reach the internet directly. Substitute your router's own
# address on the container's /30 if you changed it.
/ip/firewall/filter/add chain=forward action=drop src-address=172.31.254.1 \
out-interface-list=WAN \
place-before=[find comment="fvpn: marked flows skip fasttrack"] \
comment="fvpn: kill switch - overlay source must not leave over WAN"La règle 3 doit se placer au-dessus de la règle d'exemption fasttrack de l'étape 1, sinon cette
dernière accepte le trafic en premier et le rejet n'est jamais atteint. place-before s'en charge
ici ; confirmez avec /ip/firewall/filter/print.
La version plus stricte : des appareils qui ne doivent jamais utiliser autre chose que le tunnel
Si ce que vous voulez réellement, c'est « cet ordinateur portable n'a Internet que si son trafic passe par le tunnel », dites-le directement plutôt que de le déduire de l'état du routage :
/ip/firewall/address-list/add list=fvpn-only address=192.168.88.50 \
comment="fvpn: the work laptop"
/ip/firewall/filter/add chain=forward action=drop src-address-list=fvpn-only \
out-interface-list=WAN \
place-before=[find comment="fvpn: marked flows skip fasttrack"] \
comment="fvpn: kill switch - these devices are tunnel-only"Cet appareil n'atteint désormais Internet qu'à travers le conteneur, ou pas du tout, quoi que disent les tables de routage un matin donné.
Vérifier que ça fonctionne
# A rule sitting at zero packets is a rule matching nothing.
/ip/firewall/mangle/print stats
/ip/route/print where routing-table=via-fvpn
# The fasttrack-exemption rule has to be above the fasttrack rule.
/ip/firewall/filter/printDepuis un appareil du réseau local, chargez n'importe quelle page « quelle est mon IP ». Elle devrait montrer le pays de la sortie pour le trafic que vous avez sélectionné, et le vôtre pour tout le reste. Si elle montre le vôtre pour tout, la cause habituelle est le premier fait de cette page : les règles sont sur un boîtier qui ne route pas le réseau local.
Annuler tout ça
Chaque ligne ci-dessus porte un commentaire commençant par fvpn:, donc les retirer est exact — et
ne touchera pas aux objets propres du conteneur, que l'installeur commente forestvpn.
/ip/firewall/mangle/remove [find comment~"^fvpn:"]
/ip/firewall/filter/remove [find comment~"^fvpn:"]
/ip/firewall/nat/remove [find comment~"^fvpn:"]
/ip/firewall/address-list/remove [find comment~"^fvpn:"]
/ip/route/remove [find comment~"^fvpn:"]
/ip/address/remove [find comment~"^fvpn:"]
/routing/table/remove [find name="via-fvpn"]Le conteneur continue de tourner, conserve son association au compte, et revient à ne faire transiter que son propre trafic. Si autre chose ne va pas, voir dépannage.