Локальные сервисы — веб-сервер, камера видеонаблюдения, RDP на рабочую станцию — часто нужно сделать доступными из интернета, при этом не выдавая устройству реальный публичный IP. Для этого в RouterOS используется destination NAT (dst-nat), более известный как проброс портов. Отдельная и не менее важная тема — hairpin NAT, который позволяет обращаться к этим же сервисам по внешнему адресу изнутри локальной сети, где без него запросы просто не находят дорогу обратно. Разберём обе задачи на примере роутера rtr-edge01 и сети 192.168.10.0/24.

Прежде чем настраивать проброс портов, важно понимать, что NAT — это не замена firewall, а механизм трансляции адресов. Проброшенный порт без ограничений firewall — это прямой путь внутрь сети для любого желающего, поэтому в этой статье мы сразу сочетаем dst-nat с точечными правилами forward.

Стоит также разделять два принципиально разных вида NAT в RouterOS: srcnat меняет исходный адрес пакета (используется для выхода локальной сети в интернет через один публичный IP) и dstnat меняет адрес назначения (используется для проброса портов снаружи внутрь). Оба типа правил живут в одном разделе /ip firewall nat, но обрабатываются на разных этапах прохождения пакета через роутер, и порядок правил внутри каждого типа так же важен, как и в filter.

Базовый masquerade для выхода в интернет

Если у тебя ещё не настроен исходящий NAT из предыдущих статей серии, начни с него — без masquerade локальные адреса 192.168.10.0/24 не смогут выйти в интернет вообще, а проброс портов без masquerade не имеет смысла:

/ip firewall nat add chain=srcnat out-interface=pppoe-out1 action=masquerade comment="masquerade LAN to WAN"

Проброс порта для веб-сервера

Допустим, в локальной сети на адресе 192.168.10.50 работает веб-сервер, и его нужно сделать доступным на 80 и 443 портах извне:

/ip firewall nat add chain=dstnat protocol=tcp dst-port=80 in-interface=pppoe-out1 action=dst-nat to-addresses=192.168.10.50 to-ports=80 comment="web http"
/ip firewall nat add chain=dstnat protocol=tcp dst-port=443 in-interface=pppoe-out1 action=dst-nat to-addresses=192.168.10.50 to-ports=443 comment="web https"

Указание in-interface=pppoe-out1 важно: без него правило может неожиданно сработать и для трафика, приходящего изнутри сети, что часто приводит к путанице при диагностике.

Проброс с изменением порта

Иногда удобно вынести сервис на нестандартный внешний порт — например, чтобы не светить стандартный RDP-порт 3389 напрямую и хотя бы немного снизить шум от автоматического сканирования:

/ip firewall nat add chain=dstnat protocol=tcp dst-port=33890 in-interface=pppoe-out1 action=dst-nat to-addresses=192.168.10.60 to-ports=3389 comment="rdp workstation"

Внешний порт 33890 транслируется во внутренний стандартный 3389 — снаружи подключаются на нестандартный порт, а конечное устройство ничего не замечает. Само по себе это не защита от атак, а лишь снижение шума в логах — полноценную защиту всё равно обеспечивает firewall и, желательно, VPN вместо прямого доступа по RDP.

Разрешение проброшенного трафика в forward

Правило dst-nat само по себе не открывает доступ — трафик всё ещё должен пройти цепочку forward. Добавь разрешение именно для проброшенных соединений:

/ip firewall filter add chain=forward connection-nat-state=dstnat protocol=tcp dst-port=80,443 action=accept comment="allow forwarded web"
/ip firewall filter add chain=forward connection-nat-state=dstnat protocol=tcp dst-port=3389 src-address-list=trusted_remote action=accept comment="allow forwarded rdp from trusted"

Для чувствительных сервисов вроде RDP разумно дополнительно ограничить источник конкретным списком доверенных адресов (trusted_remote) — не всякий проброшенный сервис должен быть доступен вообще всему интернету.

Hairpin NAT: доступ к сервису изнутри сети

Представь ситуацию: сотрудник в офисе, находящийся в той же сети 192.168.10.0/24, пытается открыть веб-сервер по внешнему адресу или по доменному имени, которое резолвится во внешний IP. Без hairpin NAT запрос уходит на WAN-интерфейс роутера и не возвращается — потому что источник и назначение оказываются в одном сегменте с точки зрения маршрутизации, и обратный пакет от сервера 192.168.10.50 идёт напрямую клиенту, минуя NAT, а клиент ждёт ответ именно от внешнего адреса. Решается это дополнительным правилом src-nat специально для внутреннего обращения к самому себе:

/ip firewall nat add chain=srcnat action=masquerade src-address=192.168.10.0/24 dst-address=192.168.10.50 protocol=tcp dst-port=80 comment="hairpin nat web"
/ip firewall nat add chain=srcnat action=masquerade src-address=192.168.10.0/24 dst-address=192.168.10.50 protocol=tcp dst-port=443 comment="hairpin nat web https"

Это правило должно стоять после dst-nat правил в списке nat, потому что RouterOS обрабатывает dstnat раньше srcnat, и к моменту применения hairpin-правила адрес назначения уже должен быть транслирован из внешнего в 192.168.10.50.

Альтернатива hairpin NAT: локальный DNS

Более чистое архитектурное решение — вместо hairpin NAT настроить локальный DNS-сервер (или DNS static-запись на самом роутере), который для внутренних клиентов резолвит доменное имя сервиса сразу во внутренний адрес 192.168.10.50, минуя NAT вообще:

/ip dns static add name=web.itpages.lab.local address=192.168.10.50 type=A

Такой подход называют split-horizon DNS: снаружи имя резолвится во внешний IP через публичный DNS-провайдера, а изнутри сети — сразу во внутренний адрес через локальный DNS-сервер роутера. Он снижает нагрузку на NAT и обычно работает надёжнее hairpin NAT, особенно при большом числе одновременных подключений.

Netmap для проброса целого диапазона портов

Когда сервис использует не один порт, а диапазон (например, пассивный FTP или некоторые видеорегистраторы с десятками потоков), правило netmap удобнее, чем перечислять каждый порт отдельным dst-nat:

/ip firewall nat add chain=dstnat protocol=tcp dst-port=50000-50100 in-interface=pppoe-out1 action=netmap to-addresses=192.168.10.70 to-ports=50000-50100 comment="nvr port range"

Netmap сохраняет соответствие портов один в один внутри диапазона, что удобно для протоколов, которые сами договариваются о номерах портов в динамическом диапазоне и ожидают их без изменений.

NAT loopback для нескольких сервисов на одном порту

Если за одним внешним IP скрывается несколько внутренних серверов, каждый на своём порту, но с одним и тем же портом снаружи различить их можно только с помощью reverse-proxy (например, Nginx) на входе — сам NAT не умеет маршрутизировать по содержимому запроса вроде HTTP Host-заголовка. RouterOS в этом случае обычно используется просто как транзитный dst-nat на адрес прокси-сервера, а уже прокси разбирает, какому внутреннему сервису передать запрос:

/ip firewall nat add chain=dstnat protocol=tcp dst-port=80,443 in-interface=pppoe-out1 action=dst-nat to-addresses=192.168.10.55 comment="forward to reverse proxy"

Такая связка NAT плюс reverse-proxy — стандартный паттерн, когда за одним публичным адресом нужно спрятать несколько веб-сервисов с разными доменными именами.

UPnP и автоматический проброс

RouterOS поддерживает UPnP — протокол, который позволяет приложениям (торрент-клиентам, играм, некоторым мессенджерам) самостоятельно открывать себе порты без ручной настройки. Для домашней сети это удобно, но для офисной или продакшен-инфраструктуры лучше держать выключенным — иначе любое приложение внутри сети сможет само пробросить порт наружу без ведома администратора:

/ip upnp set enabled=no

Если всё же нужен UPnP, ограничь его конкретным внутренним интерфейсом и не включай на сегментах с недоверенными устройствами вроде гостевого Wi-Fi.

Проверка работы проброса

После настройки проверь трансляцию с внешнего хоста (не из локальной сети — оттуда результат будет зависеть уже от hairpin NAT или DNS):

/ip firewall nat print stats
/ip firewall connection print

Счётчики в nat print stats должны расти при каждом новом подключении к проброшенному порту. Если счётчик не растёт вообще, проблема на уровне провайдера (блокировка портов) или в самом правиле dst-nat; если растёт, но соединение не устанавливается — смотри правила forward.

Диагностика типичных проблем проброса

Если снаружи сервис не открывается, а внутри всё работает, проверяй по порядку: во-первых, действительно ли внешний IP на pppoe-out1 публичный, а не серый адрес провайдера за его собственным CGNAT — в этом случае проброс портов физически невозможен без выделенного публичного IP, и придётся договариваться с провайдером отдельно. Во-вторых, проверь, что порт не заблокирован firewall на самом целевом устройстве внутри сети — Windows и большинство Linux-дистрибутивов по умолчанию блокируют входящие подключения собственным firewall, даже если MikroTik всё сделал правильно. В-третьих, убедись, что порт не заблокирован на стороне провайдера — некоторые операторы связи закрывают стандартные порты вроде 25 или 445 для конечных пользователей независимо от настроек оборудования.

/ip address print detail
/tool fetch url="https://api.ipify.org" as-value output=user

Команда fetch к внешнему сервису покажет реальный публичный адрес, под которым роутер виден в интернете — если он отличается от адреса на pppoe-out1, значит между роутером и интернетом есть ещё один уровень NAT со стороны провайдера.

NAT-хелперы для протоколов с динамическими портами

Некоторые протоколы договариваются о номерах портов прямо внутри своих данных, а не только на уровне заголовков TCP/UDP — классический пример это активный и пассивный FTP, а также SIP для VoIP-телефонии. Обычный NAT не заглядывает внутрь полезной нагрузки пакета и не умеет транслировать такие адреса и порты автоматически, поэтому RouterOS использует специальные NAT-хелперы, которые разбирают протокол и подменяют адреса там, где это нужно. Проверить список включённых хелперов:

/ip firewall service-port print

Хелпер для FTP включён по умолчанию, и именно благодаря ему клиент за NAT может успешно скачивать и загружать файлы по пассивному FTP, хотя сервер отвечает динамическим портом, о котором роутер заранее ничего не знает. Если в сети есть внутренний FTP-сервер, который нужно пробросить наружу, хелпер для FTP стоит на время диагностики отключить и посмотреть, не он ли ломает соединение с нестандартными клиентами:

/ip firewall service-port disable ftp

Для SIP-телефонии похожая история: хелпер отслеживает согласование медиапотоков внутри сигнального SIP-трафика и подменяет адреса в SDP-сообщениях, чтобы голосовой поток из внешней сети правильно долетал до IP-телефона за NAT. Если в офисе используется SIP-транк от провайдера телефонии и звук пропадает в одну сторону, первое, что стоит проверить — включён ли и корректно ли работает соответствующий service-port, либо не мешает ли он, наоборот, работе современной АТС, которая сама умеет обрабатывать NAT через STUN.

Частые ошибки и как их избежать

  • Забытое разрешение в forward для connection-nat-state=dstnat. Само правило dst-nat транслирует адрес, но если цепочка forward целиком закрыта финальным drop без исключения для проброшенного трафика, соединение до конечного устройства не дойдёт, хотя NAT формально настроен верно.
  • Неверный порядок hairpin-правила относительно dst-nat. Hairpin NAT должен идти после правил dst-nat в списке — если поставить его раньше, RouterOS применит src-nat до трансляции адреса назначения, и трюк не сработает.
  • Проброс RDP или SSH без ограничения по адресу. Открытый наружу порт администрирования без списка доверенных адресов быстро становится целью брутфорса. Комбинируй dst-nat с ограничением src-address-list или, ещё лучше, вообще не пробрасывай такие сервисы наружу — используй VPN.
  • Включённый UPnP на сети с недоверенными устройствами. Автоматический проброс портов удобен, но полностью обходит ручной контроль администратора — заражённое устройство или вредоносное приложение может само открыть себе порт наружу. На офисных и продакшен-роутерах UPnP лучше держать выключенным по умолчанию.

Что дальше

Продолжить тему сетевого оборудования Cisco можно так: