dadv: (chuck)
[personal profile] dadv

Стандартная ситуация: локальная сеть с маршрутизатором, один публичный IP, для выхода в мир используется NAT. Плюс на маршрутизаторе работает кеширующий DNS-сервер для локальной сети. Всё работает.

Однажды на одном из хостов локальной сети поселяется сервис, которому требуется пробросить статический диапазон портов UDP с внешнего IP. Казалось бы, какие могут быть проблемы?

А ведь DNS-сервер, выполняя запросы к внешним серверам, для исходящих запросов сам использует динамические UDP-порты и ожидает ответ на них. Например, ISC BIND под FreeBSD использует sysctl net.inet.ip.portrange.hifirst и net.inet.ip.portrange.hilast для определения диапазона таких эфемерных портов, по умолчанию это 49152-65535. Пока этот диапазон не пересекается с диапазоном проброшенных внутрь локалки портов, всё будет в порядке. Но стоит лишь пробросить, скажем, порты 40000-65535, и наступает катастрофа. В случае FreeBSD проброс портов "имеет приоритет выше" (выполняется раньше, чем доставка локальным приложениям) и проброс-то работать будет, но DNS-сервер остается без DNS-ответов на свои запросы, которые теперь уходят по пробросу локальному хосту, которому они и не нужны вовсе. И вся локальная сеть остаётся без локального DNS-сервиса.

Решением будет либо изменить диапазон проброшенных портов, если это допустимо для сервера в локальной сети, а если нет - изменить диапазон эфемерных портов для DNS-сервера. Кроме изменения системного дефолта, ISC BIND позволяет задать этот диапазон в собственной конфигурации:

use-v4-udp-ports { range 10000 30000; };

Аналогично для IPv6. Для защиты от некоторых типов атак, BIND каждый раз выбирает случайный порт из диапазона и рекомендуется, чтобы диапазон был достаточно большим, минимум 16384 портов (14 бит энтропии).

Date: 2016-10-04 09:35 (UTC)
From: [identity profile] filonov.livejournal.com
Проблем с DNS-запросами, очевидно, не наблюдается.

Date: 2016-10-04 09:38 (UTC)
From: [identity profile] http://users.livejournal.com/_slw/
а почему она должна быть?
проблема будет с отсутвием ответов от некоторых серверов, если делать запросы с порта 53.

Date: 2016-10-04 09:39 (UTC)
From: [identity profile] filonov.livejournal.com
Это совсем другая проблема.

PS: Слава, уболтал, ты зануднее :)

Date: 2016-10-04 09:41 (UTC)
From: [identity profile] http://users.livejournal.com/_slw/
да как же другая, если именно про это я и сказал?
http://dadv.livejournal.com/207897.html?thread=844569&style=mine#t844569

а, я тебя прочитал неправильно.
всё равно у тебя плохой вариант -- из локалки нельзя будет к внешним dns серверам обращаться, даже для тестирования.

Date: 2016-10-04 09:47 (UTC)
From: [identity profile] filonov.livejournal.com
всё равно у тебя плохой вариант -- из локалки нельзя будет к внешним dns серверам обращаться, даже для тестирования.
То, что мы не пробрасываем определенные пакеты, не отменяет обычной работы NAT.

Date: 2016-10-04 09:50 (UTC)
From: [identity profile] http://users.livejournal.com/_slw/
ты такой загадочный...
можешь более конкретно высказаться?

Date: 2016-10-04 09:53 (UTC)
From: [identity profile] filonov.livejournal.com
А что собственно мешает "из локалки к внешним dns серверам обращаться"?

Date: 2016-10-04 09:57 (UTC)
From: [identity profile] dadv.livejournal.com
Он имеет в виду, что NAT engine для входящих пакетов сначала ищет существующий максимально специфичный стейт и если он есть, то транслирует пакет по нему. Таким образом, трансляция для ответов на запросы из локалки будет выполнена. И только если такого стейта нет, трансляция идёт по менее специфичному стейту, созданному статическим правилом форвардинга портов, в котором не специфицирован порт источника. И вот NAT теоретически мог бы на этом этапе проверить, а не равен ли порт источника 53 в случае udp и если да - выпустить пакет без трансляции и тогда он доставился бы локально.

Практически ipfw nat такого не умеет.

Date: 2016-10-04 10:15 (UTC)
From: [identity profile] filonov.livejournal.com
ipfw nat надо два nat instance - один для проброса портов, второй для остального траффика.
Впрочем могу ошибаться - я туда уже лет десять не смотрел.
У pfnat все проще -
rdr on $ext_if proto udp from any port != 53 to ....
Edited Date: 2016-10-04 10:26 (UTC)

Date: 2016-10-04 10:37 (UTC)
From: [identity profile] dadv.livejournal.com
Да, верно, если вынести портфорвардинг во второй инстанс и отключить однопроходность - сработает и c ipfw nat, хотя и громоздко вышло бы.

Profile

dadv: (Default)
Choose your future

July 2024

M T W T F S S
12 34567
891011121314
15161718192021
22232425262728
293031    

Tags

Style Credit

Powered by Dreamwidth Studios