Основы NAT на MikroTik: srcnat, dstnat и проброс портов

20 минут чтенияАвтор: Евгений Коржиков, сертифицированный тренер MikroTik
Основы NAT на MikroTik: srcnat, dstnat и проброс портов

Что такое NAT и зачем он нужен, чем srcnat отличается от dstnat и как открыть сервер из локальной сети наружу: проброс порта шаг за шагом с проверкой «до и после», hairpin NAT для доступа из своей сети и ответ на вопрос, заменяет ли NAT firewall.

Нет роутера под рукой? На открытом уроке стенд уже включён и ждёт вас. Подробнее ↓

Зачем нужен NAT

Внутри сети используются частные адреса. Их выделили для локальных сетей, и в интернете они не маршрутизируются: провайдер не передаст пакет с таким отправителем, а ответить на такой адрес просто некуда. Частных диапазонов три (RFC 1918):

ДиапазонРазмерГде встречается
10.0.0.0/816 млн адресовКрупные сети, корпоративные сети
172.16.0.0/121 млн адресовРеже: часть диапазона занимают контейнеры и VPN
192.168.0.0/1665 тыс. адресовДом и малый офис, в том числе 192.168.88.0/24 у MikroTik

Публичных адресов IPv4 тоже не хватает на всех, поэтому дому или офису обычно выдают один, часто динамический. NAT (Network Address Translation) решает обе задачи: роутер на границе подменяет адреса в проходящих пакетах и запоминает, кому что вернуть. За одним внешним адресом работают десятки устройств.

Серый адрес на WAN. Иногда провайдер сам выдаёт вам адрес из частного диапазона или из 100.64.0.0/10: так выглядит CGNAT, NAT на стороне провайдера. Выход в интернет при этом работает, а проброс портов снаружи нет: внешний адрес принадлежит не вам. Заранее посмотрите адрес на внешнем интерфейсе и, если он «серый», закажите у провайдера услугу «белый» адрес.

В IPv6 адресов хватает, поэтому NAT там, как правило, не нужен: доступом управляют правилами firewall.

Виды NAT: srcnat и dstnat

В RouterOS правила NAT живут в двух цепочках, и разница между ними сводится к вопросу «что менять»:

  • srcnat меняет адрес отправителя. Применяется к пакетам, которые выходят из сети: «кто отправил».
  • dstnat меняет адрес и порт получателя. Применяется к пакетам, которые приходят снаружи: «куда доставить».
Схема двух видов NAT: srcnat заменяет адрес отправителя 192.168.88.254 на 203.0.113.99 при выходе в интернет, dstnat заменяет адрес и порт назначения 203.0.113.99:8080 на 192.168.88.254:8000 при входе к серверу в локальной сети

Названия «динамический», «статический» и «проброс портов» из учебников в RouterOS не отдельные режимы. Это разные сочетания цепочки и действия (action):

Что нужноЦепочкаДействие
Много устройств за одним адресом, выход в интернетsrcnatmasquerade или src-nat
Открыть сервер из локальной сети наружу (проброс порта)dstnatdst-nat
Один локальный адрес соответствует одному внешнему (1:1)dstnat и srcnatnetmap
Перехватить трафик на самом роутере (например, прозрачный прокси)dstnatredirect

Правила NAT, как и правила firewall, читаются сверху вниз, и срабатывает первое подходящее. Важная деталь: правила проверяются только для первого пакета нового соединения. Решение запоминается, и остальные пакеты идут по записи в таблице соединений.

Как роутер помнит соединения

Запись в таблице соединений (connection tracking) связывает пару направлений одного соединения. Именно по ней роутер знает, что ответ от 192.168.88.254 нужно вернуть клиенту из интернета, а не отправить дальше как есть. Таблица доступна в IP → Firewall → Connections и в терминале:

/ip firewall connection print detail where dst-address~"203.0.113.99"

Для нас важны три поля и два флага:

  • src-address и dst-address показывают соединение глазами отправителя: адрес клиента и тот адрес, на который он обращался.
  • reply-src-address и reply-dst-address показывают его глазами получателя: откуда реально отвечает сервер и куда ответ уйдёт. Разница между парами и есть результат NAT.
  • Флаг s (srcnat) означает, что у соединения подменён адрес отправителя, флаг d (dstnat) означает, что подменён адрес назначения. У соединений, прошедших оба вида подмены (мы встретим такое в разделе про hairpin), стоят оба: sd.
Фильтр по адресу назначения на разных версиях записывается чуть по-разному, потому что на RouterOS 6.49 порт входит в поле адреса (203.0.113.99:8080), а на 7.22 это отдельное поле dst-port. Условие where dst-address~"203.0.113.99" по одному адресу работает в обеих версиях.

Выход в интернет: masquerade

Самое частое правило srcnat выглядит так. Все пакеты, которые уходят через внешний интерфейс, получают адрес этого интерфейса:

/ip firewall nat add chain=srcnat out-interface-list=WAN action=masquerade comment="Masquerade to ISP"

Здесь WAN — список интерфейсов, в который входит внешний порт. Если списка у вас ещё нет, создайте его (в конфигурации по умолчанию он уже есть, и команда add ответит ошибкой already have interface list with such name, а это не повод для беспокойства):

/interface list add name=WAN
/interface list member add list=WAN interface=ether2

Masquerade берёт адрес с исходящего интерфейса сам, поэтому подходит для динамических адресов: DHCP, PPPoE, LTE. Если адрес статический, вместо него можно использовать src-nat с явным to-addresses. Пошаговая настройка, проверка «до и после» и сравнение с src-nat разобраны в отдельной статье: «Masquerade на MikroTik: как выпустить сеть в интернет и чем он отличается от src-nat». Здесь нам достаточно того, что в списке NAT появится такое правило:

Как это выглядит в WinBox 3 (Windows)

Проброс порта: что понадобится

Теперь обратная задача. В локальной сети стоит сервер, и к нему нужно подключаться из интернета. Снаружи виден только один адрес, адрес роутера, поэтому сервер «прячут» за портом: запросы на порт 8080 внешнего адреса роутер переадресует на сервер. Это и есть проброс порта, или dst-nat.

В статье используется такая схема:

  • роутер MikroTik: внешний порт ether2 с адресом 203.0.113.99, локальная сеть 192.168.88.0/24 на bridge с адресом 192.168.88.1;
  • сервер в локальной сети: 192.168.88.254, веб-сервер слушает порт 8000 (для проверки хватит python3 -m http.server 8000); если у вас обычный веб-сервер на порту 80, подставьте 80;
  • роутер «провайдера» 203.0.113.1 в роли клиента из интернета;
  • в настройках сервера в качестве шлюза указан 192.168.88.1, то есть наш роутер.
Важно. Сервер обязан отправлять ответы через роутер, то есть шлюзом у него должен быть 192.168.88.1. Если шлюз другой, ответ уйдёт мимо роутера, и соединение не установится.

Выход в интернет (masquerade из предыдущего раздела) для проброса сам по себе не нужен: входящее соединение возвращается по записи в таблице, а не через srcnat. Это проверено: при проверке счётчик masquerade остался нулевым, а страница открылась.

Команды в статье проверены на RouterOS 7.22 и 6.49. Где версии различаются, это сказано в тексте.

Шаг 1. Убедитесь, что порт закрыт

Начните с проверки «до». С роутера «провайдера» (или любого устройства снаружи) обратитесь на внешний адрес и порт 8080. Правила ещё нет, поэтому роутер сам отвечает отказом:

/tool fetch url="http://203.0.113.99:8080/" output=user

Ответ failure: Connection refused означает, что на внешнем адресе по этому порту никто не слушает. Это нормальная отправная точка: после настройки ответ изменится.

Как это выглядит в WinBox 3 (Windows)

Шаг 2. Создайте правило dst-nat

Откройте IP → Firewall, вкладку NAT, нажмите «+» и заполните:

  • на вкладке General: Chain — dstnat, Protocol — tcp, Dst. Port — 8080, In. Interface List — WAN (или In. Interface — ether2);
  • на вкладке Action: Action — dst-nat, To Addresses — 192.168.88.254, To Ports — 8000.

То же командой:

/ip firewall nat add chain=dstnat in-interface-list=WAN protocol=tcp dst-port=8080 action=dst-nat to-addresses=192.168.88.254 to-ports=8000 comment="Web server"

Правило читается так: «пакеты по TCP на порт 8080, которые пришли со стороны WAN, доставить на адрес 192.168.88.254, порт 8000». Несколько уточнений:

  • protocol обязателен: без него RouterOS не примет dst-port.
  • Если порт на сервере совпадает с внешним, to-ports можно не указывать.
  • Привязка по in-interface-list=WAN не требует знать внешний адрес, поэтому правило работает и при динамическом адресе. Вместо него допустим in-interface=ether2; на обеих версиях проверены оба варианта.
  • Если пробросить нужно диапазон портов, укажите его в dst-port через дефис, например 8081-8089, а в to-ports оставьте нужный порт или диапазон.
Как это выглядит в WinBox 3 (Windows)
На кадрах сервером служит компьютер с Python-сервером, поэтому в поле To Ports стоит 8000, а адрес сервера может отличаться от адреса в тексте. В своей сети подставьте адрес и порт своего сервера.

Шаг 3. Проверьте проброс

Повторите запрос с роутера «провайдера»:

/tool fetch url="http://203.0.113.99:8080/" output=user

Теперь вместо отказа приходит ответ сервера: status: finished, code: 200 и начало страницы в поле data. Затем убедитесь, что это работа именно вашего правила.

  1. Сервер видит настоящий адрес клиента. Dst-nat меняет только адрес и порт назначения, отправитель остаётся прежним. В журнале веб-сервера в строке GET будет адрес 203.0.113.1, а не адрес роутера. Это удобно для журналов, но и опасно (см. раздел про firewall).
  2. Счётчики правила. В WinBox они видны в списке NAT (колонки Bytes и Packets), в терминале: /ip firewall nat print stats. Счётчик растёт на каждое новое соединение, а не на каждый пакет: правила проверяются только для первого пакета.
  3. Таблица соединений. У записи стоит флаг d (dstnat), а адрес reply-src-address равен адресу сервера.
/ip firewall nat print stats
/ip firewall connection print detail where dst-address~"203.0.113.99"

В выводе второй команды видно, как устроена подмена: dst-address содержит внешний адрес и порт, на которые пришёл клиент, а reply-src-address содержит адрес и порт сервера. Клиент по-прежнему «разговаривает» с 203.0.113.99:8080 и не знает о существовании 192.168.88.254.

Как это выглядит в WinBox 3 (Windows)

Записи в таблице живут недолго: у закрытого соединения TCP остаётся несколько секунд в состоянии time-wait. Если print пуст, повторите запрос и сразу выведите таблицу. Чтобы записи жили дольше при проверке, можно временно увеличить срок: /ip firewall connection tracking set tcp-time-wait-timeout=1m, а после проверки вернуть значение по умолчанию.

Hairpin NAT: доступ по внешнему адресу из локальной сети

Проброс работает снаружи, а вот коллега из локальной сети, открыв http://203.0.113.99:8080/, видит ошибку. У этого два разных объяснения, и оба стоит знать.

Почему не работает

  1. Правило из шага 2 привязано к in-interface-list=WAN, а запрос из локальной сети приходит с bridge. Правило не срабатывает, пакет попадает на сам роутер, и клиент получает Connection refused.
  2. Если заменить привязку на «любой пакет, адресованный самому роутеру» (dst-address-type=local), запрос дойдёт до сервера, но связь всё равно не установится. Сервер видит клиента с локальным адресом (например, 192.168.88.20) и отвечает ему напрямую, минуя роутер. Клиент ждал ответ от 203.0.113.99, а получил от 192.168.88.254, поэтому он молча отбрасывает такой пакет, и по истечении времени запрос обрывается с ошибкой timeout.

Проверка на практике подтверждает оба сценария: сначала отказ, затем после замены условия таймаут.

Как это выглядит в WinBox 3 (Windows)

Как исправить

Нужно сделать так, чтобы ответ сервера всё-таки проходил через роутер. Для этого запросы из локальной сети к серверу дополнительно маскируются: сервер видит отправителем роутер и отвечает ему. Сначала замените условие основного правила, чтобы оно срабатывало и для обращений из локальной сети. В RouterOS 7 это делается так:

/ip firewall nat set [find comment="Web server"] !in-interface-list dst-address-type=local

На RouterOS 6.49 команда с !in-interface-list выдаёт ошибку ambiguous value of interface-list. Там проще создать правило заново (команда ниже) и удалить старое. Правило с условием dst-address-type=local целиком:

/ip firewall nat add chain=dstnat dst-address-type=local protocol=tcp dst-port=8080 action=dst-nat to-addresses=192.168.88.254 to-ports=8000 comment="Web server"

Затем добавьте правило hairpin в цепочку srcnat:

/ip firewall nat add chain=srcnat src-address=192.168.88.0/24 dst-address=192.168.88.0/24 action=masquerade comment="Hairpin"

После этого запрос из локальной сети открывается, а в таблице соединений у него два флага: sd. Адрес reply-dst-address теперь 192.168.88.1: ответ возвращается на роутер. Цена решения в том, что сервер видит у всех клиентов из локальной сети один адрес, адрес роутера. Для журналов это неудобно.

Hairpin NAT нужен не всегда. Если у вас есть локальный DNS (например, на роутере), проще добавить статическую запись, по которой имя сервера для локальных клиентов указывает на 192.168.88.254, и обращаться к серверу напрямую: /ip dns static add name=server.example.com address=192.168.88.254.

Диапазон адресов и перенаправление: netmap и redirect

Два других действия dstnat пригодятся реже, поэтому разберём их коротко.

netmap сопоставляет адреса «один в один»: адрес 203.0.113.10 целиком соответствует серверу 192.168.88.254, а не отдельному порту. Для работы в обе стороны нужна пара правил: dstnat для входящих соединений и srcnat, чтобы сервер сам выходил наружу с этого же адреса:

/ip firewall nat add chain=dstnat dst-address=203.0.113.10 action=netmap to-addresses=192.168.88.254
/ip firewall nat add chain=srcnat src-address=192.168.88.254 out-interface-list=WAN action=netmap to-addresses=203.0.113.10

Проверка: при таком правиле ping 203.0.113.10 с внешней стороны отвечает сервер (в ответе TTL на единицу меньше, потому что пакет прошёл через роутер), а не сам роутер. Для одного сервера обычно хватает проброса портов из предыдущих разделов.

redirect перенаправляет трафик на сам роутер, на указанный порт. Классический пример: все веб-запросы из локальной сети направить на прозрачный прокси или страницу авторизации на роутере:

/ip firewall nat add chain=dstnat in-interface-list=LAN protocol=tcp dst-port=80 action=redirect to-ports=8080

NAT — не firewall

Эти механизмы часто путают, потому что у обоих «правила» и «цепочки». Но задачи разные: NAT решает, какие адреса стоят в пакете, а firewall решает, пропускать ли пакет вообще. Закрытость сети для входящих соединений — побочное следствие NAT, а не защита.

Проброс порта делает эту разницу осязаемой. Правило dst-nat открывает доступ к серверу для всего интернета, а не только для вас:

  • Сервер получит запросы от любого адреса, в том числе от сканеров, которые перебирают открытые порты в любой сети.
  • Не пробрасывайте административные порты: WinBox (8291), SSH (22), Telnet (23), веб-интерфейс RouterOS (80). Для удалённого управления используйте VPN, например WireGuard (см. ссылку внизу).
  • Меняйте порт снаружи на нестандартный (например, 2222 вместо 22) только как мелкую меру. Это не защита, а способ уменьшить шум в журналах.
  • Если сервис нужен только известным адресам, ограничьте их прямо в правиле NAT: добавьте src-address (один адрес, список или подсеть).

Решение по существу принимает цепочка forward фильтра. По документации RouterOS, в конфигурации по умолчанию в ней есть правило «drop all from WAN not DSTNATed»: оно сбрасывает всё, что пришло из WAN и не прошло через dst-nat, а пакеты, подпавшие под проброс, пропускает. Поэтому на роутере с настройками по умолчанию правила NAT достаточно, а любой проброс сразу становится доступен всем. Если вы хотите, чтобы проброс был виден только вашему адресу, разрешите именно его перед запрещающим правилом:

/ip firewall filter add chain=forward action=accept connection-state=established,related
/ip firewall filter add chain=forward action=accept connection-nat-state=dstnat in-interface-list=WAN src-address=203.0.113.1 comment="Web server: only office"
/ip firewall filter add chain=forward action=drop in-interface-list=WAN comment="Drop other from WAN"

Проверено на практике: пока перед запрещающим правилом нет разрешения, запрос на пробрасываемый порт обрывается по таймауту (счётчик drop растёт); когда в src-address указан адрес клиента, запрос проходит, а чужие адреса по-прежнему отбрасываются. Не вставляйте такой набор в рабочий роутер «как есть»: правила читаются сверху вниз, и неверный порядок отрежет вам доступ. Сначала сделайте резервную копию и настраивайте из локальной сети, а не через внешний порт. Полноценный firewall подробно разбирается на курсе MTCNA.

Не работает: разбор проблем

СимптомПричинаЧто сделать
Connection refused снаружиПравило не срабатывает: счётчик в nat print stats равен нулю. Неверный порт, протокол или интерфейс (например, ether1 вместо ether2 или PPPoE)Сравните dst-port, protocol и in-interface-list с реальным запросом. Для PPPoE во внешнем списке должен быть pppoe-out1
Таймаут снаружи, счётчик NAT растётПакет доходит до сервера, но ответ не возвращается: у сервера другой шлюз, либо запрещающее правило forward режет пакетыУкажите шлюзом сервера адрес роутера. Проверьте /ip firewall filter print stats: растёт ли счётчик drop
Таймаут снаружи, счётчик NAT равен нулюЗапрос не доходит до роутера: ему мешает провайдер (CGNAT, «серый» адрес) или firewall на входе (input)Посмотрите адрес на WAN: если он частный или из 100.64.0.0/10, проброс снаружи невозможен без «белого» адреса
Снаружи работает, из локальной сети нетНет hairpin NAT: ответ сервера обходит роутерПравило srcnat с src-address и dst-address локальной сети (см. раздел про hairpin) или DNS-запись для локальных клиентов
Правило есть, но не срабатываетВыше стоит другое правило dstnat, которое перехватывает этот трафик, или правило отключено (серая строка в WinBox)Проверьте порядок и флаг X. Конкретное правило ставьте выше общего: place-before=0
Страница не открывается, а роутер и NAT в порядкеСервис на сервере слушает только 127.0.0.1 либо блокирует соединение его собственный firewallОткройте страницу с компьютера в локальной сети по адресу сервера. Проверьте, что сервис принимает соединения с других адресов
Нужно открыть порт, а он «уже занят»На роутере уже используется этот порт: например, 80 у веб-интерфейса, 8291 у WinBoxВыберите другой внешний порт или смените порт службы в /ip service

Частые вопросы

Нужен ли masquerade для проброса порта? Нет. Ответ сервера возвращается по записи в таблице соединений. Masquerade нужен для выхода в интернет и для hairpin NAT.

Чем dst-nat отличается от redirect? Dst-nat отправляет пакет на другой адрес, а redirect заменяет адрес назначения адресом самого роутера. Первое — это проброс к серверу, второе — перехват трафика на роутере.

Можно ли пробросить один порт на несколько серверов? Нет, на один внешний адрес и порт приходится один сервер. Для нескольких серверов используйте разные внешние порты или несколько внешних адресов.

Работает ли проброс при динамическом адресе от провайдера? Да, если правило привязано к интерфейсу (in-interface-list), а не к адресу. При смене адреса правило переписывать не нужно. Для доступа по имени понадобится динамический DNS.

Замедляет ли NAT работу роутера? Для обычной офисной нагрузки заметной разницы нет, но каждое соединение занимает запись в таблице. При очень большом числе соединений важно, чтобы роутер справлялся с таблицей.

Нужен ли NAT для IPv6? Как правило, нет: адресов достаточно, а доступ ограничивается правилами firewall.

Открытый урок · бесплатно

Пробросьте порт руками на живом стенде

Свой роутер не нужен. На каждом открытом уроке стенды уже прогреты: RouterOS загружена, доступ выдан. Вы настраиваете masquerade и проброс порта, проверяете доступ «снаружи» и по счётчикам убеждаетесь, что правило работает, а тренер отвечает на вопросы по ходу.

Стенд онлайн

Подключение за пару минут

Практика

Шаги 1–3 из этой статьи

Тренер рядом

Разбор ваших вопросов вживую

Ближайший урок: [ДАТА И ВРЕМЯ УРОКА]

Читайте также