Hairpin NAT

Hairpin NAT — примерно 10% запросов в нашу техподдержку так или иначе связаны с темой этой статьи.
20 августа 2015
Hairpin
Примерно 10% запросов в нашу техподдержку таки или иначе связаны с темой этой статьи.
Итак, что такое Hairpin NAT и зачем он нужен.
Данная конфигурация обычно требуется, если Вы опубликовали на внешнем адресе (dst-nat) сервер, и Вам необходимо чтобы он был доступен по внешнему адресу изнутри сети.
Начнем с базовой конфигурации сети.
Вы имеете IP адрес 1.1.1.1/24 на интерфейсе WAN вашего маршрутизатора.
Вы имеете IP адрес 192.168.0.1/24 на интерфейсе LAN вашего маршрутизатора.
Вы имеете www‑сервер с адресом 192.168.0.10 в LAN сегменте.
Адрес вашего компьютера находится в диапазоне адресов LAN. Для примера пусть это будет 192.168.0.5

Вполне логично, что для того, чтобы опубликовать web‑сервер на внешнем интерфейсе, вы создаёте правило dst‑nat следующего вида:
/ip firewall nat add action=dst-nat chain=dstnat dst-address=1.1.1.1 dst-port=80 protocol=tcp \
to-addresses=192.168.0.10Обратите внимание, что в правиле не указан in-interface, так как правило должно срабатывать при обращении на 80 порт адреса 1.1.1.1 с любого интерфейса.
Вы это делаете и у вас все замечательно работает снаружи сети (при обращении из Интернет), но обращение с вашего компьютера по адресу http://1.1.1.1 говорит «Нет ответа от сервера». Для того, чтобы понять, что же происходит, рисуем схему прохождения и преобразования пакета:

Теперь распишем что происходит на каждом этапе.
Исходная попытка (без Hairpin)
Этап 1
Компьютер с адреса 192.168.0.5 пытается установить соединение с адресом 1.1.1.1 по 80 порту и отправляет пакет на маршрутизатор.
Этап 2
На маршрутизаторе срабатывает правило dst-nat, в результате чего адрес назначения пакета меняется на 192.168.0.10, и пакет отправляется на www‑сервер 192.168.0.10.
Этап 3
Узел 192.168.0.10, получив пакет с адресом источника 192.168.0.5, определяет, что они оба находятся в одной локальной сети и отвечает ему напрямую, минуя маршрутизатор.
Проблема
Компьютер, отправив пакет на адрес 1.1.1.1, вдруг получает ответ с адреса 192.168.0.10. Этот пакет он игнорирует и соединение не устанавливается.
Решение: добавить src‑nat (маскарадинг)
Необходимо, чтобы www‑сервер получил пакет, у которого адрес источника будет равен адресу маршрутизатора. Добавляем правило, которое заменит адрес отправителя адресом интерфейса маршрутизатора:
/ip firewall nat
add action=dst-nat chain=dstnat dst-address=1.1.1.1 dst-port=80 protocol=tcp to-addresses=192.168.0.10
add action=masquerade chain=srcnat dst-address=192.168.0.10 dst-port=80 protocol=tcp src-address=192.168.0.0/24После этого схема работает правильно:

Работа схемы (после добавления masquerade):
Этап 1
Компьютер с адреса 192.168.0.5 пытается установить соединение с адресом 1.1.1.1 по 80 порту и отправляет пакет на маршрутизатор.
Этап 2
На маршрутизаторе срабатывает правило dst-nat, в результате чего адрес назначения пакета меняется на 192.168.0.10 и правило src-nat, где адрес источника пакета меняется на адрес интерфейса маршрутизатора (192.168.0.1). После чего пакет отправляется на www‑сервер 192.168.0.10.
Этап 3
Узел 192.168.0.10, получив пакет с адресом источника 192.168.0.1 (адрес маршрутизатора), определяет, что они находятся в одной локальной сети и отвечает маршрутизатору.
Этап 4
Connection tracker маршрутизатора, получив ответный пакет, выполняет обратное преобразование адресов. Компьютер получает ожидаемый ответ с адреса 1.1.1.1.
Вот такая схема трансляции адресов и является Hairpin NAT.
Недостаток схемы: публикуемый сервер будет получать запросы от хостов локальной сети с адреса маршрутизатора. Это не всегда хорошо — например, при публикации прозрачного proxy‑сервера вы не сможете собрать нормальную статистику по реальным клиентским IP.
Альтернативы этой схеме:
Вынос публикуемых или вообще всех серверов в отдельную подсеть.
Использование split‑DNS: при обращении извне на www.mydomain.com возвращается 1.1.1.1, а внутри сети на тот же домен — 192.168.0.10.
Последнее обновление