СЕРГЕЙ СУПРУНОВ
FreeBSD tips: NAT по старинке
В наши дни, когда свободных IP-адресов становится все меньше и меньше, трансляция сетевых адресов (Network Address Translation – NAT) становится все более актуальной. Трудно найти провайдера, который, не сопротивляясь, даст вам нужное количество реальных адресов. Наиболее типичная ситуация – когда в «комплекте» с подключением к сети Интернет выделяется один-единственный IP-адрес. В результате внутреннюю сеть приходится строить на одной из приватных подсетей (что это такое, мы рассмотрим немного позже), и эти «левые», как их называют в народе, адреса нужно каким-то образом транслировать в тот единственный реальный, данный провайдером. Cразу стоит указать и на определенное преимущество такого подхода – в большинстве случаев локальная сеть становится невидимой снаружи, то есть любой внешний хост может общаться только с сервером NAT, ничего не подозревая о наличии (не говоря уже о структуре) вашей внутренней сети. В данной статье будет показано, как настроить NAT-сервер на базе FreeBSD. В качестве инструмента будет использоваться демон natd в связке с ipfw. В современных версиях системы такая схема считается не самой лучшей в плане гибкости и нагрузки на систему, и более предпочтительным является вариант на базе IPFilter – ipnat (этот NAT будет рассмотрен в одной из следующих статей). Тем не менее старый добрый natd до сих пор честно служит на просторах Сети, и оставлять его без внимания было бы, по меньшей мере, невежливо.
Сначала – немного теории. Как известно, в сети Интернет каждый хост, взаимодействующий с другими, должен иметь уникальный IP-адрес, по которому он и распознается. Несколько сетей (10.0.0.0/8, 172.16.0.0/12 и 192.168.0.0/16) выделяются в так называемый «нерегистрируемый» диапазон, то есть они могут использоваться для нужд внутренних сетей без какой-либо регистрации. Эти адреса именуют также приватными, или «серыми». Чтобы избежать конфликтов адресов в глобальной сети, пакеты с такими адресами не должны выходить за пределы шлюза, ограничивающего соответствующую внутреннюю сеть. Поэтому такие адреса иногда называют немаршрутизируемыми (хотя внутри локальной сети они замечательно маршрутизируются). Вообще нужно заметить, что деление на реальные и приватные весьма условно. Я, например, учитывая дефицит «настоящих» адресов, выданных на наш узел, широко практикую раздачу клиентам адресов из сети 192.168.x.x, «пряча» их за NAT. Таким образом, с точки зрения клиента эти адреса будут реальными.
Суть NAT заключается в том, что в процессе преобразования адрес отправителя (который может быть любым, в том числе принадлежать немаршрутизируемой подсети) заменяется адресом NAT-сервера (он должен быть «реальным», то есть входить в диапазон адресов, предоставленный вам провайдером). В отличие от прокси-серверов, которые берут на себя обработку запросов в соответствии с тем или иным протоколом, сервер NAT просто заменяет адрес и, как правило, порт отправителя (или получателя). Он не пытается разбираться в сути передаваемых данных, и благодаря этому использование NAT не ограничено списком поддерживаемых протоколов.
Говоря упрощенно, NAT работает так: клиент, имеющий адрес «A», отправляет через порт «a» пакет на некоторый удаленный сервер. Этот пакет заворачивается (пока не будем уточнять, как именно) на сервер NAT, который вместо адреса «A» подставляет свой адрес «B» и отправляет этот пакет уже от своего имени через порт «b». Одновременно с этим в памяти сервера делается запись о выполненной подстановке, чтобы при получении ответного пакета на порт «b» знать, на кого из клиентов его пересылать. Описанная схема работы носит название «маскарадинг» (masquarading).
Помимо маскарадинга существуют также понятия SNAT и DNAT (особенно хорошо известные пользователям Linux). Первый из них (Source NAT) отвечает за преобразования адреса-источника и во многом подобен маскарадингу, с тем исключением, что работает только со статическими адресами источников, и потому менее требователен к ресурсам. DNAT (Destination NAT) осуществляет преобразование адреса назначения, что используется для проброса внешних соединений, приходящих на конкретный порт (например, 80-й) на внутренние хосты, не имеющие реального адреса. Общий случай DNAT – статический NAT, когда все внешние соединения, поступающие на указанный адрес, перенаправляются на внутренний хост.
Более полную информацию по технологии NAT можно найти в Интернете, а сейчас приступим к рассмотрению natd. Эта программа включена в систему FreeBSD, и потому никакая инсталляция не требуется. Перед началом ее использования должно быть выполнено следующее:
- Ядро должно быть собрано с опциями IPFIREWALL и IPDIVERT – это необходимо для перенаправления пакетов на сервер natd.
- Должна быть включена маршрутизация между интерфейсами, что можно сделать, добавив в /etc/rc.conf следующую опцию: «gateway_enable=YES».
- Должен быть разрешен брандмауэр опцией «firewall_ enable=YES» в том же rc.conf.
Теперь можно запускать и сам сервер. Как было сказано выше, пакеты, нуждающиеся в трансляции адреса, должны быть перенаправлены на сервер NAT. При использовании natd это выполняется с помощью правила divert брандмауэра ipfw. Например, чтобы вывести в Интернет внутреннюю сеть 192.168.0.0/24, имея один реальный адрес 190.190.190.190 на интерфейсе ed0, «смотрящем» наружу, нужно сделать следующее:
- Запустить сервер natd (ключ -interface означает, что в качестве внешнего адреса будет использоваться адрес указанного интерфейса):
# natd –interface ed0
- Перенаправить на демон natd пакеты, адресованные с внутренних адресов во внешнюю сеть, то есть нуждающиеся в трансляции:
# ipfw add 100 divert natd ip from 192.168.0.0 to any out via ed0
- Завернуть на NAT входящие пакеты, адресованные непосредственно на внешний интерфейс (поскольку именно сюда будут приходить ответы):
# ipfw add 110 divert natd ip from any to 190.190.190.190 in via ed0
В результате произойдет следующее: демон natd запустится с параметрами по умолчанию, то есть будет ждать пакеты на порту 8668 и в качестве внешнего IP-адреса использовать адрес указанного интерфейса, в данном случае – ed0. Отправленные клиентами пакеты ipfw будет заворачивать на порт 8668 (в /etc/services для него задано имя natd, поэтому можно использовать и его). Сервер NAT отправит эти пакеты по адресу назначения, но уже с адреса 190.190.190.190. Получив пакеты в ответ, NAT перенаправит их клиенту.
Если вы хотите использовать в качестве внешнего адреса какой-то другой, вместо ключа -interface при запуске сервера следует использовать опцию -alias_address с указанием нужного адреса в качестве параметра. Какая-то из этих опций должна быть задана обязательно, но не обе одновременно.
Дополнительно при запуске natd может быть задано достаточно большое количество опций, получить информацию по которым можно на страницах руководства man natd. Здесь рассмотрим только наиболее интересные.
Например, можно задавать отличный от используемого по умолчанию номер divert-порта, с которым будет связан сервер natd. Для этого предназначен ключ -port . Это свойство часто используется, если необходимо запустить несколько демонов natd. К сожалению, этот инструмент может обрабатывать пакеты только в соответствии с одним правилом. Поэтому, если вам нужно использовать свои параметры для различных клиентов, приходится запускать отдельные демоны на разных для каждой группы клиентов портах. Соответственно, в правилах ipfw перенаправление должно выполняться на те же порты, которые связаны с natd. Кроме того, с помощью опций -in_port и -out_port можно задавать отдельные порты для входящих и исходящих пакетов соответственно.
Иногда может быть полезно, чтобы NAT пересылал пакеты с того же порта, с которого их отправлял клиент. Для этого можно использовать опцию -same_ports, однако не забывайте, что при этом NAT не обязуется сохранять номер порта, а будет делать это по возможности. То есть в принципе порт может и поменяться (например, если нужный номер уже используется другим соединением, NAT «забудет» про ключ -same_ports и будет работать как обычно).
Если natd запущен с опцией -interface, то есть привязывается к адресу конкретного интерфейса, то при изменении IP-адреса интерфейса IP-адрес, используемый демоном natd, останется прежним. Чтобы NAT отслеживал и автоматически учитывал изменения IP-адреса интерфейса, используется опция -dynamic.
Опция -unregistered_only указывает, что NAT должен обрабатывать только пакеты, адрес источника которых входит в указанные выше «нерегистрируемые» сети.
Ключи -redirect_port, -redirect_proto и -redirect_address служат для реализации «проброса» внешних соединений на внутренний адрес в зависимости от номера порта, протокола или адреса назначения входящих пакетов соответственно. Например, если во внутренней сети имеется HTTP-сервер 192.168.0.125, к которому нужно предоставить доступ снаружи, это можно сделать с помощью опции «-redirect_port tcp 192.168.0.125:80 80».
Все опции можно вынести в конфигурационный файл, где в каждой строчке указывается одна опция с параметрами либо с пометкой «yes / no» для непараметрических опций. При запуске natd этот файл следует указать с помощью опции -config.
Теперь, чтобы natd запускался автоматически при старте системы, в /etc/rc.conf можно указать следующие строки (показан конкретный пример):
natd_enable = “YES”
natd_interface = “ed0”
natd_flags = “-config /etc/natd.conf”
При этом параметр «natd_interface» при запуске демона natd «превратится» в параметр -nterface, остальные параметры можно задать в строке natd_flags. Обычно здесь указывается только путь к конфигурационному файлу, в который выносятся все остальные настройки.
Ну и как обычно – если режим работы сервера позволяет перезагрузку, то лучше это сделать, чтобы лишний раз убедиться в правильности всех настроек и отсутствии опечаток в конфигурационных файлах.
В заключение отмечу несколько недостатков natd. Прежде всего это все-таки демон, и, следовательно, по производительности он несколько проигрывает тому же ipnat, который более тесно интегрирован с ядром. Реализация сложной политики предоставления доступа в Интернет, дифференцированная по различным группам пользователей, может потребовать запуска нескольких демонов natd, что через rc.conf уже не получится, и потребуется писать свой стартовый сценарий.
Тем не менее в большинстве случаев natd вполне справляется с возложенными на него обязанностями, и если в системе уже работает ipfw, то такая схема может оказаться наиболее простым способом построения NAT-сервера. Дополнительная информация, как обычно, в man natd(8), divert(4), rc.conf(5), ipfw(8).