Вибір того, що йде через тунель
Необов'язкові рецепти RouterOS для роутера ForestVPN — надсилати одну групу застосунків, надсилати все, і зупиняти витік трафіку, коли тунель не працює.
Оновлено 8 жовтня 2026 р.
Усе на цій сторінці необов'язкове. Роутер ForestVPN тунелює власний трафік у момент підключення, і ніщо з цього для цього не потрібне. Це інше завдання: вирішити, який трафік вашої локальної мережі виходить через вихідний сервер, і що відбувається, коли вихідний сервер недоступний.
Розподіл праці не змінюється ніколи. RouterOS вирішує, що йде в тунель, контейнер тунелює все, що йому передано, а ваш акаунт вирішує, де це виходить. Тож усе це — звичайне налаштування RouterOS: позначки mangle, таблиця маршрутизації, правило файрвола — і ніщо з цього не торкається контейнера.
Прочитайте це спершу
Три факти визначають, чи спрацює хоч щось із цього. Пропустити їх — це вечір, який вам не повернути.
Вставляйте це на пристрій, який маршрутизує вашу локальну мережу. Ланцюжок prerouting у
RouterOS бачить лише трафік, який маршрутизує сам пристрій. На точці доступу, що стоїть нижче за
течією від вашого справжнього шлюзу, кожне правило нижче бездіяльне — перевірено на cAP ax, чий
власний маршрут за замовчуванням веде на роутер вище за нього: контейнер тунелював ідеально, і
трафік жодного клієнта локальної мережі так і не наблизився до нього. Контейнер може жити на цій
точці доступу; правила йдуть на шлюз.
Вихідний сервер приймає одну адресу джерела на пристрій — оверлейну оренду, яку він видав. Пакет, що прибуває з будь-яким іншим внутрішнім джерелом, буде відкинутий, а не маршрутизований, хоч би якими правильними були ваші правила. Щось має переписувати вашу локальну мережу на цю оренду, і що саме — залежить від контейнера:
| Контейнер | Що потрібно зробити |
|---|---|
suquant/fvpn — застосунок, керований акаунтом | Нічого. Починаючи з версії 0.3.9 контейнер маскує все, що ви в нього перенаправляєте, під власну оренду, і слідує за цією орендою, коли вона змінюється. Команда встановлення вмикає це. |
suquant/fvpnq — сирий тунель із написаного вами .conf | Додайте src-nat до Address у своєму .conf, це ж значення ви вказуєте і в AllowedIPs вихідного сервера. Ви обрали його самі, тож воно стабільне, і правило може посилатися на нього. |
У вас контейнер старіший за 0.3.9? Перезапустіть команду встановлення — правила нижче позначатимуть і маршрутизуватимуть ідеально, а вихідний сервер відкидатиме кожен пакет, що виглядатиме як повна втрата інтернету в локальній мережі в ту саму мить, коли ви додасте правило маршрутизації.
Fasttrack пропускає mangle. Заводський файрвол MikroTik прискорює (fasttrack) встановлені
з'єднання, і прискорене з'єднання більше ніколи не потрапляє в ланцюжок mangle — тож ваші позначки
застосовуються лише до першого пакета потоку і ні до чого після нього. Кожен рецепт нижче містить
одне правило, яке тримає позначені з'єднання поза fasttrack, і воно має стояти вище за правило
fasttrack-connection.
І половина з IPv6, яку ці правила зробити за вас не можуть
Усе тут — IPv4. Якщо у вашого роутера є робочий IPv6, кожен пункт призначення, який ви оберете
нижче, також досяжний через v6, в обхід тунелю, і вас про це ніщо не попередить. Якщо ж роутер
оголошує себе IPv6-роутером, не маючи маршруту за замовчуванням для v6, клієнти локальної мережі
надсилають v6-трафік на нього і не отримують нічого назад — навіть помилки, бо в RouterOS 7 немає
маршруту «недосяжно» для v6, лише мовчазний blackhole. Пристрої без Happy Eyeballs — телевізори,
годинники, будь-що, що робить звичайне підключення за записом AAAA, — тоді зависають на повний
тайм-аут підключення для кожного пункту призначення v6, що виглядає як «інтернет часом ламається»
і звинувачує Wi-Fi. Цей один рядок повідомляє, у якому з двох станів ви перебуваєте:
# 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"Є відповідь на перше і немає на друге — це і є другий випадок. Дайте IPv6 справжній маршрут за
замовчуванням, або перестаньте його оголошувати командою /ipv6/nd/set [find] ra-lifetime=none.
Крок 1 — базові налаштування
Однаково для всіх трьох рецептів. Підставте власну адресу контейнера замість 172.31.254.2
(значення за замовчуванням з встановлення; його показує
/interface/veth/print) і власний префікс локальної мережі замість 192.168.88.0/24.
Спершу перевірте /container/print detail. remote-image має показувати 0.3.9 або новішу
версію, а cmd має містити --nat-lan. Обидва значення походять з поточної команди
встановлення; контейнер, встановлений до цього, не матиме жодного з них, і
симптомом буде повна втрата інтернету в локальній мережі в ту саму мить, коли ви додасте правило
маршрутизації в кроці 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"Тепер оберіть один із наступних двох. Обидва створюють ту саму позначку з'єднання via-fvpn,
тож вони конфліктуватимуть за той самий трафік, якщо вставити обидва.
Крок 2a — необов'язково: лише дзвінки та месенджери
Налаштування, яке місяцями працює на нашому власному RB3011. Воно розділяє задачу так, як насправді розділяється трафік: сигналізація — це жменька хостнеймів постачальників, медіа — це діапазон портів на релеях, які ніхто не публікує.
# 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"Хостнейми — це відправна точка, а не остаточний авторитет. Постачальники додають і виводять
їх з ужитку, нікого не попереджаючи. Перевіряйте /ip/firewall/mangle/print stats на лічильники,
що лишаються на нулі, — це правило, яке нічому не відповідає, а не правило, що тихо робить свою
роботу.
Крок 2b — необов'язково: усе
/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"Порахуйте, що ви вставили, перш ніж тестувати це. /ip/firewall/mangle/print має показати всі
три ці правила. Вставлення в термінал, яке губить продовження одного з рядків, лишає вас із
правилами позначення й без правила маршрутизації, що виглядає точнісінько як «тунель ігнорується»
— з'єднання несуть connection-mark=via-fvpn, ніхто ніколи не звертається до таблиці, і кожен
пакет виходить через ваше звичайне з'єднання.
Надішлете все — надішлете і DNS, у цьому й суть, але це означає, що на вашу локальну мережу
відповідає резолвер вихідного сервера. Перевірте, що все, що залежить від локальних імен
(принтер, NAS, router.lan), все ще розв'язується, перш ніж вирішити, що це саме той режим, який
вам потрібен.
Крок 3 — необов'язково: блокування трафіку без тунелю
У вибіркової маршрутизації є режим відмови, який варто закрити: коли тунель зупиняється, позначений трафік може тихо повернутися до виходу через ваше звичайне з'єднання. Ці три правила натомість це зупиняють. Додайте їх після того рецепта, який ви обрали.
Кожна команда в цьому розділі була виконана на RouterOS 7.24.1, перш ніж її записали тут. Синтаксис відрізняється від RouterOS 6 в одному місці, позначеному нижче.
# 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"Правило 3 має стояти вище за правило-виняток fasttrack із кроку 1, інакше те правило прийме
трафік першим, і до відкидання справа так і не дійде. Тут це робить place-before; підтвердьте це
командою /ip/firewall/filter/print.
Суворіший варіант: пристрої, яким дозволено виходити лише через тунель
Якщо насправді ви хочете сказати «цей ноутбук не має інтернету, якщо трафік не йде через тунель», скажіть це прямо, а не виводьте це зі стану маршрутизації:
/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"Тепер цей пристрій виходить в інтернет лише через контейнер або не виходить узагалі, хоч би що казали таблиці маршрутизації в будь-який конкретний ранок.
Перевірка, що це спрацювало
# 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З пристрою в локальній мережі відкрийте будь-яку сторінку «який мій IP». Вона має показувати країну вихідного сервера для трафіку, який ви обрали, і вашу власну — для всього іншого. Якщо вона показує вашу власну для всього, зазвичай причина — перший факт на цій сторінці: правила стоять на пристрої, який не маршрутизує локальну мережу.
Скасування
Кожен рядок вище має коментар, що починається з fvpn:, тож видалити їх можна точно — і це не
торкнеться власних об'єктів контейнера, які інсталятор позначає коментарем 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"]Контейнер продовжує працювати, зберігає прив'язку до акаунта і повертається до тунелювання лише власного трафіку. Якщо щось інше не так, див. усунення несправностей.