Dokumentation

Auswählen, was durch den Tunnel geht

Optionale RouterOS-Rezepte für einen ForestVPN-Router — eine Gruppe von Apps senden, alles senden und ein Durchsickern von Datenverkehr stoppen, wenn der Tunnel ausfällt.

Aktualisiert am 8. Oktober 2026

Alles auf dieser Seite ist optional. Ein ForestVPN-Router tunnelt seinen eigenen Datenverkehr in dem Moment, in dem er sich verbindet, und nichts davon ist dafür nötig. Das hier ist die andere Aufgabe: zu entscheiden, welcher Teil des Datenverkehrs Ihres LANs über den Exit hinausgeht, und was passiert, wenn der Exit nicht erreichbar ist.

Die Arbeitsteilung ändert sich nie. RouterOS entscheidet, was zum Tunnel geht, der Container tunnelt, was immer ihm übergeben wird, und Ihr Konto entscheidet, wo es herauskommt. All das ist also gewöhnliche RouterOS-Konfiguration — Mangle-Markierungen, eine Routingtabelle, eine Firewall-Regel — und nichts davon berührt den Container.

Lesen Sie dies zuerst

Drei Tatsachen entscheiden, ob überhaupt etwas davon funktioniert. Sie zu überspringen, ist eine Nacht, die Sie nicht zurückbekommen.

Fügen Sie dies auf der Box ein, die Ihr LAN routet. Die prerouting-Chain von RouterOS sieht nur Datenverkehr, den die Box selbst routet. Auf einem Access Point, der einem echten Gateway nachgeschaltet ist, ist jede Regel unten wirkungslos — gemessen an einem cAP ax, dessen eigene Standardroute der Router davor ist: Der Container hat einwandfrei getunnelt, und kein Datenverkehr eines LAN-Clients kam ihm je nahe. Der Container kann auf diesem Access Point laufen; die Regeln gehören auf das Gateway.

Der Exit lässt pro Gerät nur eine Quelladresse zu — die von ihm vergebene Overlay-Lease. Ein Paket mit einer anderen inneren Quelladresse wird verworfen, nicht geroutet, wie korrekt Ihre Regeln auch sind. Irgendetwas muss Ihr LAN auf diese Lease umschreiben, und was das ist, hängt vom Container ab:

ContainerWas Sie deswegen tun müssen
suquant/fvpn — die kontoverwaltete AppNichts. Ab Version 0.3.9 maskiert der Container alles, was Sie in ihn weiterleiten, auf seine eigene Lease und folgt dieser Lease, wenn sie sich ändert. Der Installationsbefehl schaltet das ein.
suquant/fvpnq — der rohe Tunnel, aus einer selbst geschriebenen .confFügen Sie ein src-nat zu der Address in Ihrer .conf hinzu, dieselbe Adresse, die Sie auch in die AllowedIPs des Exits eintragen. Sie haben sie gewählt, also ist sie stabil, und eine Regel kann sie benennen.

Läuft bei Ihnen ein Container älter als 0.3.9? Führen Sie den Installationsbefehl erneut aus — sonst markieren und routen die Regeln unten einwandfrei, und der Exit verwirft jedes Paket, was sich anfühlt, als hätte das LAN in dem Moment, in dem Sie die Routing-Regel hinzufügen, komplett das Internet verloren.

Fasttrack überspringt Mangle. Die werksseitige Firewall von MikroTik beschleunigt (fasttrack) etablierte Verbindungen, und eine beschleunigte Verbindung erreicht die Mangle-Chain nie wieder — Ihre Markierungen gelten also nur für das erste Paket eines Flows und für nichts danach. Jedes Rezept unten enthält die eine Regel, die markierte Verbindungen aus dem Fasttrack heraushält, und sie muss über der fasttrack-connection-Regel stehen.

Und die IPv6-Hälfte, die diese Regeln nicht für Sie erledigen können

Alles hier ist IPv4. Hat Ihr Router funktionierendes IPv6, ist jedes von Ihnen unten ausgewählte Ziel zusätzlich über v6 erreichbar, am Tunnel vorbei, und nichts warnt Sie davor. Gibt sich der Router stattdessen als IPv6-Router aus, ohne eine v6-Standardroute zu haben, senden LAN-Clients v6-Verkehr an ihn und bekommen nichts zurück — nicht einmal einen Fehler, weil RouterOS 7 für v6 keine erreichbare Route kennt, nur ein stilles blackhole. Geräte ohne Happy Eyeballs — Fernseher, Uhren, alles, was einen reinen Connect auf einen AAAA-Eintrag macht — hängen dann für den vollen Verbindungs-Timeout an jedem v6-Ziel fest, was sich anfühlt wie „das Internet ist manchmal kaputt" und dem WLAN die Schuld gibt. Diese eine Zeile verrät, welcher der beiden Fälle bei Ihnen vorliegt:

# 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"

Antworten auf die erste Frage und keine auf die zweite ist der zweite Fall. Geben Sie IPv6 eine echte Standardroute, oder hören Sie auf, eine anzukündigen, mit /ipv6/nd/set [find] ra-lifetime=none.

Schritt 1 — das Gerüst

Gleich für alle drei Rezepte. Ersetzen Sie 172.31.254.2 (den Standardwert aus der Installation; /interface/veth/print zeigt ihn) durch die Adresse Ihres eigenen Containers und 192.168.88.0/24 durch Ihr eigenes LAN-Präfix.

Prüfen Sie zuerst /container/print detail. remote-image muss 0.3.9 oder neuer anzeigen, und cmd muss --nat-lan enthalten. Beides stammt aus dem aktuellen Installationsbefehl; ein Container, der vorher installiert wurde, hat keins von beidem, und das Symptom ist, dass das LAN in dem Moment, in dem Sie die Routing-Regel in Schritt 2 hinzufügen, komplett das Internet verliert.

# 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"

Wählen Sie dann eines der beiden nächsten Rezepte. Beide erzeugen dieselbe via-fvpn-Verbindungsmarkierung, sie würden also um denselben Datenverkehr konkurrieren, wenn Sie beide einfügen.

Schritt 2a — optional: nur Anrufe und Messenger

Das Setup, das seit Monaten auf unserem eigenen RB3011 läuft. Es teilt das Problem so, wie der Datenverkehr sich tatsächlich teilt: Signalisierung ist eine Handvoll Anbieter-Hostnamen, Medien sind ein Portbereich auf Relays, die niemand veröffentlicht.

# 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"

Die Hostnamen sind ein Ausgangspunkt, keine Autorität. Anbieter fügen sie hinzu und entfernen sie, ohne jemanden zu informieren. Prüfen Sie /ip/firewall/mangle/print stats auf Zähler, die bei null bleiben — das ist eine Regel, die nichts trifft, keine Regel, die still ihren Dienst tut.

Schritt 2b — optional: alles

/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"

Zählen Sie nach, was Sie eingefügt haben, bevor Sie es testen. /ip/firewall/mangle/print muss alle drei dieser Regeln zeigen. Ein Terminal-Einfügevorgang, der einen der Zeilenumbrüche verschluckt, lässt Sie mit den Markierungsregeln, aber ohne Routing-Regel zurück, was sich genau anfühlt wie „der Tunnel wird ignoriert" — die Verbindungen tragen connection-mark=via-fvpn, aber nichts fragt jemals die Tabelle ab, und jedes Paket verlässt das Netz über Ihre normale Verbindung.

Senden Sie alles, senden Sie auch DNS mit — das ist der Sinn der Sache, aber es bedeutet, dass der Resolver des Exits Ihr LAN beantwortet. Prüfen Sie, ob alles, was von lokalen Namen abhängt (ein Drucker, ein NAS, router.lan), weiterhin auflöst, bevor Sie sich für diesen Modus entscheiden.

Schritt 3 — optional: ein Kill-Switch

Selektives Routing hat einen Fehlerfall, den es sich zu schließen lohnt: Stoppt der Tunnel, kann markierter Datenverkehr still wieder über Ihre normale Verbindung nach draußen gehen. Diese drei Regeln lassen ihn stattdessen stoppen. Fügen Sie sie nach dem von Ihnen gewählten Rezept hinzu.

Jeder Befehl in diesem Abschnitt wurde auf RouterOS 7.24.1 ausgeführt, bevor er hier aufgeschrieben wurde. Die Syntax weicht an einer Stelle von RouterOS 6 ab, unten markiert.

# 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"

Regel 3 muss über der Fasttrack-Ausnahmeregel aus Schritt 1 stehen, sonst nimmt jene Regel den Datenverkehr zuerst an, und der Drop wird nie erreicht. place-before erledigt das hier; bestätigen Sie es mit /ip/firewall/filter/print.

Die strengere Version: Geräte, die ausschließlich den Tunnel nutzen dürfen

Wenn Sie eigentlich wollen, dass „dieser Laptop kein Internet hat, außer wenn er getunnelt wird", sagen Sie das direkt, statt es aus dem Routing-Zustand abzuleiten:

/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"

Dieses Gerät erreicht das Internet nun entweder über den Container oder gar nicht, unabhängig davon, was die Routingtabellen an einem beliebigen Morgen gerade sagen.

Prüfen, ob es funktioniert hat

# 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/print

Laden Sie von einem LAN-Gerät aus eine beliebige „Wie ist meine IP"-Seite. Sie sollte für den von Ihnen ausgewählten Datenverkehr das Land des Exits zeigen und für alles andere Ihr eigenes. Zeigt sie durchgehend Ihr eigenes, liegt die übliche Ursache in der ersten Tatsache dieser Seite: Die Regeln sitzen auf einer Box, die das LAN nicht routet.

Rückgängig machen

Jede Zeile oben trägt einen mit fvpn: beginnenden Kommentar, sodass das Entfernen präzise ist — und die eigenen Objekte des Containers, die der Installer mit forestvpn kommentiert, nicht anrührt.

/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"]

Der Container läuft weiter, behält seine Kontoverknüpfung und tunnelt wieder nur seinen eigenen Datenverkehr. Ist etwas anderes nicht in Ordnung, siehe Problembehandlung.

Zurück zur Hilfe

Deutsch
Fragen Sie uns alles