Селективная маршрутизация — трафик через VPN
Селективная маршрутизация на MikroTik — определённый трафик через VPN
Селективная маршрутизация (policy-based routing) позволяет направлять через VPN-туннель только определённый трафик, а остальной отправлять напрямую через основного провайдера. Это полезно, когда нужно использовать VPN для конкретных устройств, доменов или сервисов, не снижая скорость остальной сети. В этой статье разберём три метода реализации, предотвращение DNS Leak, автоматическое обновление списков IP-адресов и типичные ошибки.
Описание
Задача
Типичные сценарии селективной маршрутизации:
- Определённые устройства через VPN — рабочий ноутбук через корпоративный VPN, остальные устройства напрямую
- Определённые сайты через VPN — заблокированные ресурсы через VPN, остальной трафик напрямую
- Определённые порты через VPN — HTTPS-трафик через VPN, остальное напрямую
- Комбинация — конкретные устройства + конкретные сайты + конкретные порты
Принцип работы
Селективная маршрутизация на MikroTik реализуется через связку:
- Mangle — маркировка трафика, который должен идти через VPN
- Routing Table — отдельная таблица маршрутизации для VPN-трафика
- Route — маршрут по умолчанию через VPN в этой таблице
- NAT — masquerade для VPN-интерфейса
Поток обработки пакета:
codeПакет от устройства → Mangle (prerouting) — проверяет src/dst/port → Если совпадение → mark-routing = "vpn-route" → Routing decision — ищет маршрут в таблице "vpn-route" → Route "vpn-route" → gateway = VPN-интерфейс → NAT (masquerade) → пакет уходит через VPN
Предварительные требования
Предполагается, что у вас уже настроен VPN-туннель (WireGuard, OpenVPN, L2TP/IPsec или другой). Проверьте:
[admin@MikroTik] ># Для WireGuard /interface/wireguard/print /interface/wireguard/peers/print # Для OpenVPN /interface/ovpn-client/print # Для L2TP /interface/l2tp-client/print
VPN-интерфейс должен быть активен (running=yes). Проверьте связность:
[admin@MikroTik] >/ping 10.0.0.1 src-address=10.0.0.2 count=5
Где 10.0.0.1 — адрес VPN-сервера на его стороне туннеля, 10.0.0.2 — ваш адрес в VPN.
Настройка
Шаг 0: Создание routing table
В RouterOS 7 маршрутные таблицы создаются явно:
[admin@MikroTik] >/routing/table/add name=vpn-route fib comment="Routing table for VPN traffic"
Параметр fib означает, что таблица будет использоваться для реальной пересылки пакетов (а не только для BGP/OSPF).
Шаг 1: Маршрут по умолчанию через VPN
Добавьте default route в таблицу vpn-route:
[admin@MikroTik] ># Для WireGuard /ip/route/add dst-address=0.0.0.0/0 gateway=wireguard1 \ routing-table=vpn-route comment="Default route via VPN" # Для OpenVPN /ip/route/add dst-address=0.0.0.0/0 gateway=ovpn-client \ routing-table=vpn-route comment="Default route via VPN" # Для L2TP /ip/route/add dst-address=0.0.0.0/0 gateway=l2tp-client \ routing-table=vpn-route comment="Default route via VPN"
Шаг 2: NAT для VPN-интерфейса
Добавьте masquerade для VPN:
[admin@MikroTik] >/ip/firewall/nat/add chain=srcnat \ out-interface=wireguard1 \ action=masquerade \ comment="Masquerade VPN traffic"
Замените wireguard1 на имя вашего VPN-интерфейса.
Метод 1: Маршрутизация по устройству (src-address)
Направляем весь трафик конкретного устройства (или подсети) через VPN:
[admin@MikroTik] ># Один компьютер через VPN /ip/firewall/mangle/add chain=prerouting \ src-address=192.168.88.100 \ action=mark-routing new-routing-mark=vpn-route \ passthrough=yes \ comment="PC-work via VPN" # Несколько устройств через address-list /ip/firewall/address-list add list=vpn-devices address=192.168.88.100 comment="Рабочий ноутбук" add list=vpn-devices address=192.168.88.101 comment="Рабочий телефон" add list=vpn-devices address=192.168.88.102 comment="Smart TV" /ip/firewall/mangle/add chain=prerouting \ src-address-list=vpn-devices \ action=mark-routing new-routing-mark=vpn-route \ passthrough=yes \ comment="VPN devices via address-list"
Для исключения локального трафика (чтобы обращения к локальной сети не шли через VPN):
[admin@MikroTik] >/ip/firewall/mangle/add chain=prerouting \ src-address-list=vpn-devices \ dst-address=192.168.88.0/24 \ action=accept \ comment="Exclude LAN from VPN routing" \ place-before=0 /ip/firewall/mangle/add chain=prerouting \ src-address-list=vpn-devices \ action=mark-routing new-routing-mark=vpn-route \ passthrough=yes \ comment="VPN devices via address-list"
Важно: правило accept для LAN должно стоять выше правила mark-routing.
Метод 2: Маршрутизация по домену (dst-address-list)
Направляем трафик к определённым доменам/IP через VPN. Это сложнее, потому что MikroTik работает с IP-адресами, а не с доменами. Нужно предварительно разрешить домены в IP-адреса.
Шаг 2.1: Ручное добавление IP-адресов
Для сервисов с известными IP-диапазонами:
[admin@MikroTik] >/ip/firewall/address-list add list=vpn-destinations address=157.240.0.0/16 comment="Facebook" add list=vpn-destinations address=31.13.24.0/21 comment="Facebook" add list=vpn-destinations address=31.13.64.0/18 comment="Facebook" add list=vpn-destinations address=69.171.224.0/19 comment="Facebook" add list=vpn-destinations address=69.63.176.0/20 comment="Facebook" add list=vpn-destinations address=173.252.64.0/18 comment="Facebook" add list=vpn-destinations address=204.15.20.0/22 comment="Facebook"
Шаг 2.2: Автоматическое разрешение доменов через скрипт
Создайте скрипт, который периодически разрешает домены в IP и обновляет address-list:
[admin@MikroTik] >/system/script/add name=vpn-dns-resolve source={ :local domains { "www.example.com"; "api.example.com"; "cdn.example.com"; "streaming.example.com" } :local listName "vpn-destinations" :local listComment "auto-resolved" # Удаляем старые автоматические записи :local oldEntries [/ip/firewall/address-list/find where list=$listName comment=$listComment] :if ([:len $oldEntries] > 0) do={ /ip/firewall/address-list/remove $oldEntries } # Разрешаем домены и добавляем IP :foreach domain in=$domains do={ :do { :local ip [:resolve $domain] :log info "VPN-route: $domain -> $ip" /ip/firewall/address-list/add list=$listName address=$ip \ comment=$listComment timeout=1d } on-error={ :log warning "VPN-route: не удалось разрешить $domain" } } :log info "VPN-route: обновление DNS завершено" }
Настройте автоматический запуск каждые 30 минут:
[admin@MikroTik] >/system/scheduler/add name=vpn-dns-update \ interval=30m \ on-event="/system/script/run vpn-dns-resolve" \ comment="Update VPN destination IPs"
Шаг 2.3: Mangle-правило для dst-address-list
[admin@MikroTik] >/ip/firewall/mangle/add chain=prerouting \ dst-address-list=vpn-destinations \ src-address=192.168.88.0/24 \ action=mark-routing new-routing-mark=vpn-route \ passthrough=yes \ comment="Route specific destinations via VPN"
Метод 3: Маршрутизация по порту
Направляем определённые протоколы/порты через VPN:
[admin@MikroTik] ># Весь HTTPS через VPN /ip/firewall/mangle/add chain=prerouting \ protocol=tcp dst-port=443 \ src-address=192.168.88.0/24 \ action=mark-routing new-routing-mark=vpn-route \ passthrough=yes \ comment="HTTPS via VPN" # Торренты (типичные порты) через VPN /ip/firewall/mangle/add chain=prerouting \ protocol=tcp dst-port=6881-6889 \ src-address=192.168.88.0/24 \ action=mark-routing new-routing-mark=vpn-route \ passthrough=yes \ comment="Torrent TCP via VPN" /ip/firewall/mangle/add chain=prerouting \ protocol=udp dst-port=6881-6889 \ src-address=192.168.88.0/24 \ action=mark-routing new-routing-mark=vpn-route \ passthrough=yes \ comment="Torrent UDP via VPN"
Комбинирование методов
Можно комбинировать все три метода. Порядок правил в mangle имеет значение:
[admin@MikroTik] ># 1. Исключаем локальный трафик (всегда первое!) /ip/firewall/mangle/add chain=prerouting \ dst-address=192.168.88.0/24 \ action=accept \ comment="Exclude LAN" \ place-before=0 # 2. Конкретные устройства — всё через VPN /ip/firewall/mangle/add chain=prerouting \ src-address-list=vpn-devices \ action=mark-routing new-routing-mark=vpn-route \ passthrough=no \ comment="All traffic from VPN devices" # 3. Конкретные сайты — со всех устройств через VPN /ip/firewall/mangle/add chain=prerouting \ dst-address-list=vpn-destinations \ src-address=192.168.88.0/24 \ action=mark-routing new-routing-mark=vpn-route \ passthrough=no \ comment="Specific sites via VPN" # 4. Конкретные порты — со всех устройств через VPN /ip/firewall/mangle/add chain=prerouting \ protocol=tcp dst-port=443 \ src-address=192.168.88.0/24 \ action=mark-routing new-routing-mark=vpn-route \ passthrough=no \ comment="HTTPS via VPN"
Обратите внимание на passthrough=no — после совпадения с правилом пакет не проверяется следующими правилами в mangle. Это важно, если вы хотите, чтобы устройства из vpn-devices не проверялись правилами по dst-address-list.
Предотвращение DNS Leak
DNS Leak — одна из главных проблем селективной маршрутизации. Даже если трафик идёт через VPN, DNS-запросы могут уходить через основного провайдера, раскрывая, какие сайты вы посещаете.
Решение 1: Перенаправление DNS для VPN-устройств
[admin@MikroTik] ># DNS-запросы от VPN-устройств → через VPN /ip/firewall/mangle/add chain=prerouting \ src-address-list=vpn-devices \ protocol=udp dst-port=53 \ action=mark-routing new-routing-mark=vpn-route \ passthrough=no \ comment="DNS from VPN devices via VPN" \ place-before=0 /ip/firewall/mangle/add chain=prerouting \ src-address-list=vpn-devices \ protocol=tcp dst-port=53 \ action=mark-routing new-routing-mark=vpn-route \ passthrough=no \ comment="DNS TCP from VPN devices via VPN" \ place-before=1
Решение 2: Split DNS — разные DNS-серверы для разного трафика
Настройте MikroTik так, чтобы он использовал DNS-сервер на стороне VPN для определённых доменов:
[admin@MikroTik] ># DNS-сервер VPN-провайдера (на стороне туннеля) /ip/dns/static/add name=example.com type=FWD forward-to=10.0.0.1 comment="via VPN DNS" /ip/dns/static/add name=api.example.com type=FWD forward-to=10.0.0.1 comment="via VPN DNS"
Где 10.0.0.1 — DNS-сервер на стороне VPN.
Решение 3: Принудительный DNS через VPN для всех
Если хотите, чтобы все DNS-запросы шли через VPN:
[admin@MikroTik] >/ip/dns/set servers=10.0.0.1
Но это замедлит DNS-разрешение для всей сети. Используйте только если VPN быстрый и стабильный.
Скрипт автообновления address-list из файла
Для больших списков доменов удобнее хранить их в файле и обновлять через скрипт:
[admin@MikroTik] >/system/script/add name=vpn-update-destinations source={ :local listName "vpn-destinations" :local listComment "auto-resolved" # Список доменов для разрешения :local domains [:toarray ""] :set ($domains->[:len $domains]) "www.example1.com" :set ($domains->[:len $domains]) "www.example2.com" :set ($domains->[:len $domains]) "api.example3.com" :set ($domains->[:len $domains]) "cdn.example4.com" :set ($domains->[:len $domains]) "stream.example5.com" :log info "VPN destinations: начало обновления" # Удаляем устаревшие записи :foreach entry in=[/ip/firewall/address-list/find where list=$listName comment=$listComment] do={ /ip/firewall/address-list/remove $entry } :local count 0 :foreach domain in=$domains do={ :do { :local resolvedIP [:resolve $domain] /ip/firewall/address-list/add list=$listName address=$resolvedIP \ comment=$listComment timeout=2h :set count ($count + 1) :log info "VPN destinations: $domain -> $resolvedIP" } on-error={ :log warning "VPN destinations: ошибка разрешения $domain" } } :log info "VPN destinations: обновлено $count записей" }
[admin@MikroTik] >/system/scheduler/add name=vpn-destinations-update \ interval=1h \ on-event="/system/script/run vpn-update-destinations" \ comment="Hourly update of VPN destination IPs"
Отказоустойчивость: проверка VPN-туннеля
Если VPN-туннель падает, трафик с routing-mark vpn-route перестанет ходить. Добавьте проверку через Netwatch:
[admin@MikroTik] >/tool/netwatch/add host=10.0.0.1 \ type=icmp interval=30s timeout=2s \ up-script="/ip/route/enable [find where routing-table=vpn-route comment~\"VPN\"]" \ down-script={ /ip/route/disable [find where routing-table=vpn-route comment~"VPN"] :log warning "VPN tunnel is down, disabling VPN routing" } \ comment="Monitor VPN tunnel"
При падении VPN маршрут в таблице vpn-route отключается, и трафик пойдёт по обычному маршруту (через основного провайдера). При восстановлении VPN маршрут включается обратно.
Проверка
Проверка routing table
[admin@MikroTik] >/routing/table/print
Должна быть таблица vpn-route.
Проверка маршрутов
[admin@MikroTik] >/ip/route/print where routing-table=vpn-route
Должен быть default route через VPN-интерфейс.
Проверка mangle-правил
[admin@MikroTik] >/ip/firewall/mangle/print stats
Посмотрите счётчики packets и bytes — если они растут, правила работают.
Проверка address-list
[admin@MikroTik] >/ip/firewall/address-list/print where list=vpn-destinations /ip/firewall/address-list/print where list=vpn-devices
Traceroute для проверки маршрута
С устройства, которое должно ходить через VPN:
codetracert 8.8.8.8
Первые хопы должны показывать адреса из VPN-туннеля, а не адреса провайдера.
С устройства, которое должно ходить напрямую — в traceroute должны быть адреса провайдера.
Проверка из RouterOS (с указанием routing-table):
[admin@MikroTik] >/tool/traceroute address=8.8.8.8 routing-table=vpn-route count=1
Проверка DNS Leak
Используйте сайт dnsleaktest.com с устройства, маршрутизируемого через VPN. Результат должен показывать DNS-серверы на стороне VPN, а не вашего провайдера.
Из RouterOS проверьте, через какой DNS разрешается домен:
routeros:put [:resolve "whoami.akamai.net"]
Мониторинг нагрузки на VPN
[admin@MikroTik] >/interface/monitor-traffic wireguard1 once
Это покажет текущую скорость tx/rx через VPN-интерфейс.
Типичные ошибки
1. DNS Leak — DNS-запросы идут мимо VPN
Самая частая ошибка. Вы настроили маршрутизацию HTTP/HTTPS через VPN, но забыли про DNS. DNS-запросы (порт 53) уходят через основного провайдера, раскрывая домены, которые вы посещаете.
Решение: добавьте mangle-правила для DNS-трафика (описано выше в разделе «Предотвращение DNS Leak»).
2. Routing loop — трафик к VPN-серверу тоже идёт через VPN
Если VPN-сервер находится в интернете и его IP попадает под mangle-правило (например, dst-port=443), трафик к самому VPN-серверу тоже пойдёт через VPN, создавая петлю. VPN-туннель разорвётся.
Решение: добавьте исключение для IP VPN-сервера:
[admin@MikroTik] >/ip/firewall/mangle/add chain=prerouting \ dst-address=<VPN_SERVER_IP> \ action=accept \ comment="Exclude VPN server from policy routing" \ place-before=0
Замените <VPN_SERVER_IP> на реальный IP вашего VPN-сервера.
3. Забыли masquerade для VPN-интерфейса
Без NAT на VPN-интерфейсе пакеты уйдут с локальным src-address (192.168.88.x), и VPN-сервер не сможет вернуть ответ.
Решение:
[admin@MikroTik] >/ip/firewall/nat/add chain=srcnat out-interface=wireguard1 action=masquerade
4. Локальный трафик идёт через VPN
Если mangle-правило маркирует весь трафик от устройства (src-address=192.168.88.100), то обращения к локальным ресурсам (NAS, принтер, другие ПК) тоже пойдут через VPN и не будут работать.
Решение: добавьте исключение для LAN перед правилом маркировки:
[admin@MikroTik] >/ip/firewall/mangle/add chain=prerouting \ dst-address=192.168.88.0/24 \ action=accept \ comment="Exclude LAN" \ place-before=0
5. VPN упал — трафик не ходит
Если VPN-туннель разрывается, маршрут в таблице vpn-route становится unreachable, и маркированный трафик просто пропадает.
Решения:
- Используйте Netwatch для мониторинга VPN (описано выше)
- Добавьте fallback-маршрут с большей distance:
[admin@MikroTik] >/ip/route/add dst-address=0.0.0.0/0 gateway=192.168.88.1 \ routing-table=vpn-route distance=10 \ comment="Fallback route if VPN is down"
Где 192.168.88.1 — шлюз вашего провайдера в основной таблице. Distance=10 означает, что этот маршрут будет использоваться только если VPN-маршрут (distance=1 по умолчанию) недоступен.
6. passthrough=yes вместо passthrough=no
При passthrough=yes пакет продолжает проверяться следующими mangle-правилами и может быть перемаркирован. Если у вас несколько правил и вы хотите, чтобы первое совпавшее было финальным:
[admin@MikroTik] ># Правильно: passthrough=no — после маркировки пакет выходит из mangle /ip/firewall/mangle/set [find where comment="All traffic from VPN devices"] passthrough=no
7. Address-list для домена содержит устаревшие IP
CDN-сервисы (Cloudflare, Akamai, AWS) часто меняют IP-адреса. Статический address-list быстро устаревает.
Решение: используйте скрипт автообновления с коротким timeout (1–2 часа) и частым запуском через scheduler (каждые 30–60 минут).
8. Неправильный порядок правил в mangle
Mangle обрабатывает правила сверху вниз. Если правило accept для LAN стоит ниже правила mark-routing, локальный трафик будет маркирован и пойдёт через VPN.
Проверьте порядок:
[admin@MikroTik] >/ip/firewall/mangle/print
Правильный порядок:
accept— исключения (LAN, VPN-сервер)mark-routing— маркировка VPN-трафика
Используйте place-before=0 или drag-and-drop в WinBox для перемещения правил.
9. Не работает с FastTrack
FastTrack обходит mangle. Если у вас включён FastTrack для established/related-соединений, mangle-правила не будут применяться к этим соединениям.
Решение: для connection-mark работа с FastTrack возможна, но routing-mark через mangle несовместим с FastTrack. Если селективная маршрутизация не работает, проверьте:
[admin@MikroTik] >/ip/firewall/filter/print where action=fasttrack-connection
Для соединений, маршрутизируемых через VPN, FastTrack нужно отключить или добавить исключение:
[admin@MikroTik] >/ip/firewall/filter/add chain=forward \ src-address-list=vpn-devices \ action=accept \ comment="Skip FastTrack for VPN devices" \ place-before=[find where action=fasttrack-connection]
Полный пример: устройства + сайты через WireGuard
[admin@MikroTik] ># === Routing Table === /routing/table/add name=vpn-route fib # === Route === /ip/route/add dst-address=0.0.0.0/0 gateway=wireguard1 routing-table=vpn-route # === NAT === /ip/firewall/nat/add chain=srcnat out-interface=wireguard1 action=masquerade # === Address Lists === /ip/firewall/address-list add list=vpn-devices address=192.168.88.100 comment="Рабочий ноутбук" add list=vpn-devices address=192.168.88.101 comment="Рабочий телефон" add list=vpn-destinations address=157.240.0.0/16 comment="Facebook" # === Mangle === # 1. Исключение VPN-сервера /ip/firewall/mangle/add chain=prerouting \ dst-address=203.0.113.1 action=accept \ comment="Exclude VPN server" # 2. Исключение LAN /ip/firewall/mangle/add chain=prerouting \ dst-address=192.168.88.0/24 action=accept \ comment="Exclude LAN" # 3. DNS от VPN-устройств через VPN /ip/firewall/mangle/add chain=prerouting \ src-address-list=vpn-devices protocol=udp dst-port=53 \ action=mark-routing new-routing-mark=vpn-route passthrough=no \ comment="DNS via VPN" # 4. Все VPN-устройства через VPN /ip/firewall/mangle/add chain=prerouting \ src-address-list=vpn-devices \ action=mark-routing new-routing-mark=vpn-route passthrough=no \ comment="VPN devices" # 5. Конкретные сайты через VPN (для всех) /ip/firewall/mangle/add chain=prerouting \ dst-address-list=vpn-destinations src-address=192.168.88.0/24 \ action=mark-routing new-routing-mark=vpn-route passthrough=no \ comment="VPN destinations" # === Netwatch === /tool/netwatch/add host=10.0.0.1 type=icmp interval=30s \ down-script="/ip/route/disable [find where routing-table=vpn-route]" \ up-script="/ip/route/enable [find where routing-table=vpn-route]"
Заключение
Селективная маршрутизация — мощный инструмент MikroTik, позволяющий гибко управлять потоками трафика. Ключевые принципы: правильный порядок mangle-правил, обязательные исключения для LAN и VPN-сервера, предотвращение DNS Leak и мониторинг состояния VPN-туннеля. Комбинация методов (по устройству + по домену + по порту) покрывает большинство практических сценариев.
Пакет от устройства
→ Mangle (prerouting) — проверяет src/dst/port
→ Если совпадение → mark-routing = "vpn-route"
→ Routing decision — ищет маршрут в таблице "vpn-route"
→ Route "vpn-route" → gateway = VPN-интерфейс
→ NAT (masquerade) → пакет уходит через VPN
# Для WireGuard
/interface/wireguard/print
/interface/wireguard/peers/print
# Для OpenVPN
/interface/ovpn-client/print
# Для L2TP
/interface/l2tp-client/print
/ping 10.0.0.1 src-address=10.0.0.2 count=5
/routing/table/add name=vpn-route fib comment="Routing table for VPN traffic"
# Для WireGuard
/ip/route/add dst-address=0.0.0.0/0 gateway=wireguard1 \
routing-table=vpn-route comment="Default route via VPN"
# Для OpenVPN
/ip/route/add dst-address=0.0.0.0/0 gateway=ovpn-client \
routing-table=vpn-route comment="Default route via VPN"
# Для L2TP
/ip/route/add dst-address=0.0.0.0/0 gateway=l2tp-client \
routing-table=vpn-route comment="Default route via VPN"
/ip/firewall/nat/add chain=srcnat \
out-interface=wireguard1 \
action=masquerade \
comment="Masquerade VPN traffic"
# Один компьютер через VPN
/ip/firewall/mangle/add chain=prerouting \
src-address=192.168.88.100 \
action=mark-routing new-routing-mark=vpn-route \
passthrough=yes \
comment="PC-work via VPN"
# Несколько устройств через address-list
/ip/firewall/address-list
add list=vpn-devices address=192.168.88.100 comment="Рабочий ноутбук"
add list=vpn-devices address=192.168.88.101 comment="Рабочий телефон"
add list=vpn-devices address=192.168.88.102 comment="Smart TV"
/ip/firewall/mangle/add chain=prerouting \
src-address-list=vpn-devices \
action=mark-routing new-routing-mark=vpn-route \
passthrough=yes \
comment="VPN devices via address-list"
/ip/firewall/mangle/add chain=prerouting \
src-address-list=vpn-devices \
dst-address=192.168.88.0/24 \
action=accept \
comment="Exclude LAN from VPN routing" \
place-before=0
/ip/firewall/mangle/add chain=prerouting \
src-address-list=vpn-devices \
action=mark-routing new-routing-mark=vpn-route \
passthrough=yes \
comment="VPN devices via address-list"
/ip/firewall/address-list
add list=vpn-destinations address=157.240.0.0/16 comment="Facebook"
add list=vpn-destinations address=31.13.24.0/21 comment="Facebook"
add list=vpn-destinations address=31.13.64.0/18 comment="Facebook"
add list=vpn-destinations address=69.171.224.0/19 comment="Facebook"
add list=vpn-destinations address=69.63.176.0/20 comment="Facebook"
add list=vpn-destinations address=173.252.64.0/18 comment="Facebook"
add list=vpn-destinations address=204.15.20.0/22 comment="Facebook"
/system/script/add name=vpn-dns-resolve source={
:local domains {
"www.example.com";
"api.example.com";
"cdn.example.com";
"streaming.example.com"
}
:local listName "vpn-destinations"
:local listComment "auto-resolved"
# Удаляем старые автоматические записи
:local oldEntries [/ip/firewall/address-list/find where list=$listName comment=$listComment]
:if ([:len $oldEntries] > 0) do={
/ip/firewall/address-list/remove $oldEntries
}
# Разрешаем домены и добавляем IP
:foreach domain in=$domains do={
:do {
:local ip [:resolve $domain]
:log info "VPN-route: $domain -> $ip"
/ip/firewall/address-list/add list=$listName address=$ip \
comment=$listComment timeout=1d
} on-error={
:log warning "VPN-route: не удалось разрешить $domain"
}
}
:log info "VPN-route: обновление DNS завершено"
}
/system/scheduler/add name=vpn-dns-update \
interval=30m \
on-event="/system/script/run vpn-dns-resolve" \
comment="Update VPN destination IPs"
/ip/firewall/mangle/add chain=prerouting \
dst-address-list=vpn-destinations \
src-address=192.168.88.0/24 \
action=mark-routing new-routing-mark=vpn-route \
passthrough=yes \
comment="Route specific destinations via VPN"
# Весь HTTPS через VPN
/ip/firewall/mangle/add chain=prerouting \
protocol=tcp dst-port=443 \
src-address=192.168.88.0/24 \
action=mark-routing new-routing-mark=vpn-route \
passthrough=yes \
comment="HTTPS via VPN"
# Торренты (типичные порты) через VPN
/ip/firewall/mangle/add chain=prerouting \
protocol=tcp dst-port=6881-6889 \
src-address=192.168.88.0/24 \
action=mark-routing new-routing-mark=vpn-route \
passthrough=yes \
comment="Torrent TCP via VPN"
/ip/firewall/mangle/add chain=prerouting \
protocol=udp dst-port=6881-6889 \
src-address=192.168.88.0/24 \
action=mark-routing new-routing-mark=vpn-route \
passthrough=yes \
comment="Torrent UDP via VPN"
# 1. Исключаем локальный трафик (всегда первое!)
/ip/firewall/mangle/add chain=prerouting \
dst-address=192.168.88.0/24 \
action=accept \
comment="Exclude LAN" \
place-before=0
# 2. Конкретные устройства — всё через VPN
/ip/firewall/mangle/add chain=prerouting \
src-address-list=vpn-devices \
action=mark-routing new-routing-mark=vpn-route \
passthrough=no \
comment="All traffic from VPN devices"
# 3. Конкретные сайты — со всех устройств через VPN
/ip/firewall/mangle/add chain=prerouting \
dst-address-list=vpn-destinations \
src-address=192.168.88.0/24 \
action=mark-routing new-routing-mark=vpn-route \
passthrough=no \
comment="Specific sites via VPN"
# 4. Конкретные порты — со всех устройств через VPN
/ip/firewall/mangle/add chain=prerouting \
protocol=tcp dst-port=443 \
src-address=192.168.88.0/24 \
action=mark-routing new-routing-mark=vpn-route \
passthrough=no \
comment="HTTPS via VPN"
# DNS-запросы от VPN-устройств → через VPN
/ip/firewall/mangle/add chain=prerouting \
src-address-list=vpn-devices \
protocol=udp dst-port=53 \
action=mark-routing new-routing-mark=vpn-route \
passthrough=no \
comment="DNS from VPN devices via VPN" \
place-before=0
/ip/firewall/mangle/add chain=prerouting \
src-address-list=vpn-devices \
protocol=tcp dst-port=53 \
action=mark-routing new-routing-mark=vpn-route \
passthrough=no \
comment="DNS TCP from VPN devices via VPN" \
place-before=1
# DNS-сервер VPN-провайдера (на стороне туннеля)
/ip/dns/static/add name=example.com type=FWD forward-to=10.0.0.1 comment="via VPN DNS"
/ip/dns/static/add name=api.example.com type=FWD forward-to=10.0.0.1 comment="via VPN DNS"
/ip/dns/set servers=10.0.0.1
/system/script/add name=vpn-update-destinations source={
:local listName "vpn-destinations"
:local listComment "auto-resolved"
# Список доменов для разрешения
:local domains [:toarray ""]
:set ($domains->[:len $domains]) "www.example1.com"
:set ($domains->[:len $domains]) "www.example2.com"
:set ($domains->[:len $domains]) "api.example3.com"
:set ($domains->[:len $domains]) "cdn.example4.com"
:set ($domains->[:len $domains]) "stream.example5.com"
:log info "VPN destinations: начало обновления"
# Удаляем устаревшие записи
:foreach entry in=[/ip/firewall/address-list/find where list=$listName comment=$listComment] do={
/ip/firewall/address-list/remove $entry
}
:local count 0
:foreach domain in=$domains do={
:do {
:local resolvedIP [:resolve $domain]
/ip/firewall/address-list/add list=$listName address=$resolvedIP \
comment=$listComment timeout=2h
:set count ($count + 1)
:log info "VPN destinations: $domain -> $resolvedIP"
} on-error={
:log warning "VPN destinations: ошибка разрешения $domain"
}
}
:log info "VPN destinations: обновлено $count записей"
}
/system/scheduler/add name=vpn-destinations-update \
interval=1h \
on-event="/system/script/run vpn-update-destinations" \
comment="Hourly update of VPN destination IPs"
/tool/netwatch/add host=10.0.0.1 \
type=icmp interval=30s timeout=2s \
up-script="/ip/route/enable [find where routing-table=vpn-route comment~\"VPN\"]" \
down-script={
/ip/route/disable [find where routing-table=vpn-route comment~"VPN"]
:log warning "VPN tunnel is down, disabling VPN routing"
} \
comment="Monitor VPN tunnel"
/routing/table/print
/ip/route/print where routing-table=vpn-route
/ip/firewall/mangle/print stats
/ip/firewall/address-list/print where list=vpn-destinations
/ip/firewall/address-list/print where list=vpn-devices
tracert 8.8.8.8
/tool/traceroute address=8.8.8.8 routing-table=vpn-route count=1
:put [:resolve "whoami.akamai.net"]
/interface/monitor-traffic wireguard1 once
/ip/firewall/mangle/add chain=prerouting \
dst-address=<VPN_SERVER_IP> \
action=accept \
comment="Exclude VPN server from policy routing" \
place-before=0
/ip/firewall/nat/add chain=srcnat out-interface=wireguard1 action=masquerade
/ip/firewall/mangle/add chain=prerouting \
dst-address=192.168.88.0/24 \
action=accept \
comment="Exclude LAN" \
place-before=0
/ip/route/add dst-address=0.0.0.0/0 gateway=192.168.88.1 \
routing-table=vpn-route distance=10 \
comment="Fallback route if VPN is down"
# Правильно: passthrough=no — после маркировки пакет выходит из mangle
/ip/firewall/mangle/set [find where comment="All traffic from VPN devices"] passthrough=no
/ip/firewall/mangle/print
/ip/firewall/filter/print where action=fasttrack-connection
/ip/firewall/filter/add chain=forward \
src-address-list=vpn-devices \
action=accept \
comment="Skip FastTrack for VPN devices" \
place-before=[find where action=fasttrack-connection]
# === Routing Table ===
/routing/table/add name=vpn-route fib
# === Route ===
/ip/route/add dst-address=0.0.0.0/0 gateway=wireguard1 routing-table=vpn-route
# === NAT ===
/ip/firewall/nat/add chain=srcnat out-interface=wireguard1 action=masquerade
# === Address Lists ===
/ip/firewall/address-list
add list=vpn-devices address=192.168.88.100 comment="Рабочий ноутбук"
add list=vpn-devices address=192.168.88.101 comment="Рабочий телефон"
add list=vpn-destinations address=157.240.0.0/16 comment="Facebook"
# === Mangle ===
# 1. Исключение VPN-сервера
/ip/firewall/mangle/add chain=prerouting \
dst-address=203.0.113.1 action=accept \
comment="Exclude VPN server"
# 2. Исключение LAN
/ip/firewall/mangle/add chain=prerouting \
dst-address=192.168.88.0/24 action=accept \
comment="Exclude LAN"
# 3. DNS от VPN-устройств через VPN
/ip/firewall/mangle/add chain=prerouting \
src-address-list=vpn-devices protocol=udp dst-port=53 \
action=mark-routing new-routing-mark=vpn-route passthrough=no \
comment="DNS via VPN"
# 4. Все VPN-устройства через VPN
/ip/firewall/mangle/add chain=prerouting \
src-address-list=vpn-devices \
action=mark-routing new-routing-mark=vpn-route passthrough=no \
comment="VPN devices"
# 5. Конкретные сайты через VPN (для всех)
/ip/firewall/mangle/add chain=prerouting \
dst-address-list=vpn-destinations src-address=192.168.88.0/24 \
action=mark-routing new-routing-mark=vpn-route passthrough=no \
comment="VPN destinations"
# === Netwatch ===
/tool/netwatch/add host=10.0.0.1 type=icmp interval=30s \
down-script="/ip/route/disable [find where routing-table=vpn-route]" \
up-script="/ip/route/enable [find where routing-table=vpn-route]"