Mikrotik: site-to-site WireGuard между филиалами
Когда в двух филиалах уже стоят Mikrotik на границе сети, тянуть VPN через отдельный сервер избыточно — RouterOS 7 умеет WireGuard нативно, и связать две локальные сети можно прямо на роутерах, без промежуточного хоста. Сложность не в самом WireGuard (это по-прежнему одна команда на интерфейс), а в том, что происходит вокруг него: allowed-address нужно указывать не на адрес, а на всю чужую подсеть, NAT норовит подменить адреса межфилиального трафика, а если у одного филиала нет статического IP — endpoint придётся держать в актуальном состоянии отдельно. Ниже — полная схема на двух Mikrotik с конкретными командами RouterOS и разбором мест, где обычно теряется трафик.
Содержание
- Что нужно подготовить перед стартом
- Схема сети и план адресации
- Создаём WireGuard-интерфейс на каждом Mikrotik
- Peer и allowed-address: пробрасываем подсеть, а не адрес
- Маршрутизация между офисами и NAT-исключение
- Firewall: forward, input и защита туннеля
- Если у филиала нет статического IP: DDNS и переподключение
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Что нужно подготовить перед стартом
- RouterOS 7.x на обоих роутерах — нативная поддержка WireGuard есть только в седьмой ветке, архитектура (ARM, ARM64, MIPS, x86) значения не имеет. Версия проверяется командой
/system resource print, апгрейд — через/system package update check-for-updates. - Непересекающиеся локальные подсети в обоих филиалах. Если в обоих на роутере из коробки стоит одна и та же подсеть по умолчанию (частый случай на новом оборудовании) — сначала перенумеруйте один из офисов, иначе маршрутизация станет неоднозначной.
- Хотя бы один статический публичный IP — на стороне, которая будет endpoint. Второй филиал может сидеть за динамическим IP провайдера, ниже об этом отдельный раздел.
- Административный доступ к обоим роутерам через Winbox, WebFig или SSH.
- Открытый UDP-порт на границе сети статического филиала — либо публичный IP висит прямо на WAN-интерфейсе Mikrotik, либо провайдер пробрасывает нужный порт на него через NAT выше по цепочке.
Все команды ниже вводятся в терминале RouterOS на каждом из двух роутеров — Winbox: New Terminal, WebFig: раздел Terminal, либо просто SSH-сессия.
Схема сети и план адресации
Возьмём для примера филиал в Москве со статическим IP и филиал в Новосибирске за динамическим адресом провайдера — сценарий чуть менее удобный, чем два статических IP, зато более частый в жизни:
| Филиал А (Москва) | Филиал Б (Новосибирск) | |
|---|---|---|
| Локальная подсеть | 192.168.10.0/24 | 192.168.20.0/24 |
| Mikrotik, LAN-интерфейс | bridge, 192.168.10.1 | bridge, 192.168.20.1 |
| Публичный IP | 203.0.113.10 (статический) | динамический, через DDNS |
| Адрес в тоннеле (wg) | 10.100.0.1/30 | 10.100.0.2/30 |
| Имя интерфейса WireGuard | wg-b | wg-a |
| UDP-порт WireGuard | 13231 | 13231 |
Тоннельная подсеть 10.100.0.0/30 нужна только для связи двух роутеров между собой, реальный трафик офисов по ней не ходит — он идёт между 192.168.10.0/24 и 192.168.20.0/24. Оба Mikrotik должны быть шлюзом по умолчанию для своей локальной сети (или иметь корректный статический маршрут со стороны LAN-коммутатора, если шлюз — не сам Mikrotik).
Арендуйте сервер под свои задачи!
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверСоздаём WireGuard-интерфейс на каждом Mikrotik
На роутере филиала А:
/interface wireguard add name=wg-b listen-port=13231 comment="tunnel to office B (Novosibirsk)"
На роутере филиала Б — то же самое, только имя и комментарий зеркальные:
/interface wireguard add name=wg-a listen-port=13231 comment="tunnel to office A (Moscow)"
Приватный ключ генерируется автоматически при создании интерфейса, если не задать его вручную. Публичный ключ, который нужно передать на другую сторону, смотрится командой:
/interface wireguard print
Колонка public-key — это то значение, которое пойдёт в конфигурацию peer на противоположном роутере. Скопируйте оба публичных ключа (А и Б) перед следующим шагом — они понадобятся сразу на обеих сторонах.
Peer и allowed-address: пробрасываем подсеть, а не адрес
Это ключевое отличие site-to-site от обычного клиентского подключения — в клиентской схеме (например, настройка WireGuard-клиента на Mikrotik) allowed-address обычно стоит 0.0.0.0/0 — весь трафик роутера в один туннель. Здесь же в allowed-address указывается конкретная подсеть удалённого филиала — это одновременно и маршрут, и фильтр: пакеты с адресами вне этого диапазона от peer будут отброшены.
На роутере филиала А:
/interface wireguard peers add interface=wg-b public-key="<публичный_ключ_Б>" \
endpoint-address=office-nsk.sn.mynetname.net endpoint-port=13231 \
allowed-address=192.168.20.0/24 persistent-keepalive=25s
/ip address add address=10.100.0.1/30 interface=wg-b
/ip route add dst-address=192.168.20.0/24 gateway=wg-b comment="LAN office B via VPN"
На роутере филиала Б — зеркально, но endpoint-address теперь статический IP филиала А:
/interface wireguard peers add interface=wg-a public-key="<публичный_ключ_А>" \
endpoint-address=203.0.113.10 endpoint-port=13231 \
allowed-address=192.168.10.0/24 persistent-keepalive=25s
/ip address add address=10.100.0.2/30 interface=wg-a
/ip route add dst-address=192.168.10.0/24 gateway=wg-a comment="LAN office A via VPN"
persistent-keepalive=25s обязателен на стороне динамического IP — без него сессия за NAT провайдера может "засыпать" на простое, и первый пакет после паузы теряется, пока туннель не переустановится. Проверка рукопожатия:
/interface wireguard peers print
Свежая дата в колонке current-handshake подтверждает, что стороны видят друг друга. Если рукопожатия нет — сначала проверьте системное время обоих роутеров (/system clock print, включите NTP: /system ntp client set enabled=yes) — WireGuard использует временные метки в протоколе, и разъехавшиеся часы после перезагрузки без синхронизации ломают хендшейк без явной ошибки в логе.
Маршрутизация между офисами и NAT-исключение
Маршруты до чужих подсетей уже добавлены на предыдущем шаге, но на большинстве Mikrotik "из коробки" есть правило NAT-маскарадинга для выхода в интернет — и если его не ограничить, оно перехватит и межфилиальный трафик, подменив адреса, из-за чего пакеты будут доходить, а обратная маршрутизация на другой стороне — ломаться (адрес отправителя окажется адресом самого роутера, а не реального хоста в LAN).
Стандартное правило обычно выглядит так:
/ip firewall nat print
;;; 0 chain=srcnat action=masquerade out-interface=ether1
Перед ним нужно вставить правило-исключение — на обоих роутерах, для своей пары подсетей:
/ip firewall nat add chain=srcnat src-address=192.168.10.0/24 dst-address=192.168.20.0/24 \
action=accept place-before=0 comment="no NAT: office A <-> office B"
и на роутере Б — зеркально, с обратными адресами. place-before=0 ставит правило перед первой существующей записью (обычно перед masquerade), а action=accept останавливает дальнейшую обработку в NAT-таблице для этого трафика — до маскарадинга он просто не доходит, и хосты офисов видят друг друга по реальным адресам напрямую, без подмены.
Firewall: forward, input и защита туннеля
Открываем входящий UDP-порт WireGuard на WAN-интерфейсе (нужно на обеих сторонах — как на статической, так и на динамической, если она сама принимает подключения; в этой схеме филиал Б только инициирует соединение, но правило на всякий случай не помешает):
/ip firewall filter add chain=input protocol=udp dst-port=13231 in-interface=ether1 \
action=accept place-before=0 comment="WireGuard site-to-site"
Форвардинг между тоннелем и локальной сетью нужно явно разрешить в обе стороны — по умолчанию в типовых конфигах Mikrotik forward-трафик с "чужих" интерфейсов часто попадает под общее drop-правило:
/ip firewall filter add chain=forward in-interface=wg-b out-interface=bridge action=accept place-before=0 comment="office B -> LAN A"
/ip firewall filter add chain=forward in-interface=bridge out-interface=wg-b action=accept place-before=0 comment="LAN A -> office B"
Если в перспективе филиалов станет больше двух, вместо точечных правил под каждую пару интерфейсов удобнее завести address-list с подсетями всех офисов и написать одно правило forward на весь список — иначе при росте числа филиалов количество правил быстро станет неуправляемым:
/ip firewall address-list add address=192.168.20.0/24 list=branch-networks comment="office B"
/ip firewall filter add chain=forward src-address-list=branch-networks dst-address-list=branch-networks action=accept
Не ограничивайте доступ только forward-правилами — стоит также решить на уровне бизнеса, каким именно хостам в филиале Б разрешён доступ к ресурсам филиала А (файловый сервер, 1С, домен), и в идеале сузить allowed-address и firewall-правила не до всей /24, а до конкретных серверов, если полный доступ "все со всеми" не нужен.
Если у филиала нет статического IP: DDNS и переподключение
В нашей схеме филиал Б сидит за динамическим адресом провайдера, поэтому в его сторону endpoint-address указан не как IP, а как имя DDNS. Проще всего поднять его через встроенный Mikrotik Cloud:
/ip cloud set ddns-enabled=yes ddns-update-interval=00:01:00
/ip cloud print
В выводе появится dns-name вида xxxxxxxxxxxx.sn.mynetname.net — именно его и указывают в endpoint-address на роутере филиала А вместо статического IP.
Честная оговорка: RouterOS резолвит имя в IP при создании или изменении записи peer, но не отслеживает смену адреса в реальном времени. Если провайдер филиала Б поменяет внешний IP, а сессия сама не переустановится, туннель на стороне А будет продолжать стучаться по старому адресу до тех пор, пока запись peer не обновится вручную или по расписанию. Рабочий вариант — периодически пересобирать endpoint-address скриптом планировщика:
/system scheduler add name=wg-ddns-refresh interval=5m on-event={
:local newip [:resolve "xxxxxxxxxxxx.sn.mynetname.net"]
:local peerid [/interface wireguard peers find interface=wg-b]
:local curip [/interface wireguard peers get $peerid endpoint-address]
:if ($newip != $curip) do={
/interface wireguard peers set $peerid endpoint-address=$newip
:log info "wg-b endpoint updated to $newip"
}
}
Если для филиала критична стабильность связи, а провайдер часто меняет IP, разумная альтернатива — арендовать недорогой VPS со статическим адресом как постоянную "точку встречи": оба Mikrotik подключаются к нему как к hub-серверу (схема, близкая к классическому site-to-site VPN между офисами, только с сервером вместо прямого линка), и тогда endpoint у каждой стороны всегда один и тот же статический IP, без DDNS и скриптов обновления. Для контроля состояния тоннеля в любом случае стоит настроить внешний мониторинг доступности порта и алерты по пропаданию хендшейка — подробнее в статье про мониторинг доступности VPN-сервера через Uptime Kuma.
Арендуйте сервер под свои задачи!
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Можно ли связать так больше двух филиалов?
Да, но каждая пара роутеров требует отдельного [Peer] с подсетью именно этого филиала в allowed-address — при трёх и более офисах это уже mesh, а не строго site-to-site, и конфиги проще поддерживать через address-list, как описано выше.
Нужен ли NAT, если подсети филиалов пересекаются?
Тогда прямая маршрутизация не сработает, подсети придётся перенумеровать заранее — это решается планированием адресации, а не постфактум через NAT44/NAT66 между дублирующимися сетями, что на практике выходит хрупким и сложным в поддержке.
Почему туннель поднят (хендшейк свежий), а пинг между офисами не идёт?
Чаще всего — забытое NAT-исключение (маскарадинг подменяет адрес до того, как пакет уйдёт в тоннель) или отсутствующее forward-правило. Разбор похожих ситуаций — в статье про типичные проблемы WireGuard на Mikrotik и Keenetic.
Обязательно ли использовать RouterOS 7 на обеих сторонах?
Да, нативная реализация WireGuard есть только в седьмой ветке; RouterOS 6.x требует стороннего пакета с другим синтаксисом команд, и смешивать версии в одной схеме не стоит — лучше обновить обе стороны заранее.
Как проверить, что трафик реально идёт через тоннель, а не в обход?
traceroute до адреса из подсети другого филиала — первым хопом после локального шлюза должен быть тоннельный адрес соседнего роутера (10.100.0.x), а не публичный маршрут провайдера.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →