Мы — долго запрягаем, быстро ездим, и сильно тормозим.
www.lissyara.su —> статьи —> FreeBSD —> настройка —> ng_nat

Описание работы с ng_nat

Автор: terminus.


Версия статьи: 0.0.1

Возник интерес к подсистеме netgraph. Решил начать изучать ее с наиболее актуальной и нужной лично мне возможности - с ната реализованного в ноде ng_nat. За время использования ipfw nat выяснилось, что у него есть некоторые недостатки, а ответственные за него люди из проекта FreeBSD что-то не спешат исправлять найденные проблемы. Поэтому захотелось освоить параллельно еще и ng_nat чтобы применять его при случае там, где ipfw nat не дает нужного результата. Да и просто ng_nat (как и сам netgraph) - это прикольная штука играться с которой уже само по себе интересно!

С того времени как ng_nat впервые был закоммичен в FreeBSD в нем многое изменилось. В первых реализациях не было некоторых важных функций (типа проброса портов), а теперь его функционал даже больше чем у ipfw nat! Нода ng_nat построена все на той же библиотеке libalias на которой работают как ipfw nat, так и natd и все что мы знаем о natd применимо к ng_nat. К слову сказать - даже модули протоколов libalias (alias_ftp.ko, alias_irc.ko, etc...) работают с ng_nat так же как они работали с ipfw nat.

Если провести сравнение с ipfw nat, то на вскидку получится следующий список фич в пользу ng_nat:
- работают правила проксирования proxy_rule, proxy_only
- менее "глючен" в работе, позволяет налету изменять правила проброса портов
- нет неприятных ошибок типа ограничений на количество редиректов (NAT_BUF_LEN)
- возможность добавлять к правилам проброса портов текстовые описания
- дополнительные, интересные настройки не реализованные в ipfw nat

Я планирую позже оформить эту статью по такому же принципу как было с обзором ipfw nat - с кучей примеров и детальных описаний. Пока же только самое основное и один интересный пример.

В процессе освоения ng_nat возникли некоторые вопросы по его настройке. Хотелось бы выразить благодарность Вадиму Гончарову ака nuclight за то, что он дал полезную информацию о принципах настройки ng_nat, а так же за то, что он подготовил специальный rc.d скрипт ng_nat.sh для настройки экземпляров ng_nat - этот скрипт значительно облегчает работу с netgraph для тех кто с ним никогда не имел дела. Примеры в заметке будут использовать ng_nat.sh
Скрипт этот был сделан уже давно, но по непонятным причинам в базовую систему не вошел (снова хотелось бы передать ПРЕВЕД людям отвечающим за ipfw в FreeBSD - почему ng_nat принят, а этот полезный дополнительный функционал к нему не принят?!)


Ручное создание ноды ng_nat и связь ее с ipfw

Для того чтобы вручную создать экземпляр ng_nat и связать его с ipfw, надо проделать следующие шаги:

- загрузить через kldload (или /boot/loader.conf) модули netgraph.ko, ng_ipfw.ko и ng_nat.ko
- создать с помощью ngctl экземпляр ноды ng_nat и связать ее своими хуками с нодой ng_ipfw и ее хуками
- с помощью управляющих сообщений netgraph, настроить ноду ng_nat
- с помощью ipfw настроить пересылку входящего и исходящего трафика в netgraph через соответствующие хуки

Создание ноды ng_nat под именем nat1 и связь ее с ipfw:

ngctl mkpeer ipfw: nat 100 in
ngctl name ipfw:100 nat1
ngctl connect ipfw: nat1: 200 out
ngctl msg nat1: setaliasaddr 192.168.1.1

Была создана нода ng_nat под именем nat1, и в качестве первичной настройки ей было указано использовать IP адрес 192.168.1.1 для алиасинга. Нода под именем nat1 имеет два хука. Хук in, через который в ноду поступает трафик для демаскировки, соединен с хуком под номером 100 у ноды ipfw. Хук out, через который в ноду поступает трафик для маскировки, соединен с хуком под номером 200 у ноды ipfw.


Настройка ipfw для пересылки трафика в ng_nat:


ipfw add netgraph 100 all from any to any in via fxp0
ipfw add netgraph 200 all from any to any out via fxp0

Правила пересылают весь трафик приходящий к нам через внешний интефейс fxp0 в netgraph через хук 100, а весь исходящие трафик пересылается в netgraph через хук 200. Таким образом трафик из ipfw перенаправляется на обработку в экземпляр ng_nat.


Показанный выше пример дает общее представление о принципах настройки связки ipfw + ng_nat. Ниже будут приводиться примеры более детальной ручной настройки ng_nat, а в конце заметки будет пример использования rc.d скрипта ng_nat.sh с помощью которого можно отказаться от рутины и автоматизировать настройку через /etc/rc.conf


Возможности ng_nat и опции конфигурации.

Ниже приводятся ключевые слова используемые при настройке ng_nat через сообщения netgraph, примеры сообщений netgraph, а так же их эквиваленты применяемые для настройки ноды ng_nat через rc.d интерфейс реализованный в ng_nat.sh.

Сообщения netgraph для настройки ng_nat:

setaliasaddr

Параметр указывает IP адрес используемый при
маскировании и демаскировании.

Пример сообщения netgraph:
ngctl msg nat1: setaliasaddr 192.168.1.1

Пример настройки через rc.conf/ng_nat.sh:
ng_nat_nat1_interface="192.168.1.1"
ng_nat_nat1_interface="fxp0"


setmode

Устанавливает режимы работы экземпляра ната.
Для настройки доступны следующие опции (опция - шестнадцатеричное
значение - [десятичный эквивалент]):

NG_NAT_LOG 0x01 [1]
NG_NAT_DENY_INCOMING 0x02 [2]
NG_NAT_SAME_PORTS 0x04 [4]
NG_NAT_UNREGISTERED_ONLY 0x10 [16]
NG_NAT_RESET_ON_ADDR_CHANGE 0x20 [32]
NG_NAT_PROXY_ONLY 0x40 [64]
NG_NAT_REVERSE 0x80 [128]

Каждое из этих значений в бинарном виде выражается с помощью установки одного разряда. Например NG_NAT_PROXY_ONLY [64]= 01000000. Комбинация этих значений задает режим работы экземпляра ната. Например для установки режимов NAT_LOG + DENY_INCOMING + SAME_PORTS + UNREGISTERED_ONLY + RESET_ON_ADDR_CHANGE мы должны передать управляющее сообщение содержащее десятичное значение 1+2+4+16+32=55

Пример сообщения netgraph:
ngctl msg nat1: setmode { flags=55 mask=55 }

Пример настройки через rc.conf/ng_nat.sh:
ng_nat_nat1_set_mode="log deny_incoming same_ports unregistered_only reset_on_addr_change"

settarget

Устанавливает адрес по-умолчанию на который должна происходить передача
входящего трафика, когда в таблице переадресации нет полного совпадения
для какой-либо из ранее установленных сессий или правил пересылки
установленных вручную. Функционал аналогичный режиму "natd -t".

Пример сообщения netgraph:
ngctl msg nat1: settarget 172.16.0.100

Пример настройки через rc.conf/ng_nat.sh:
ng_nat_nat1_set_target="172.16.0.100"

redirectport

Проброс входящих TCP/UDP соединений на внутренние хосты.

Пример сообщения netgraph:
ngctl msg nat1: redirectport { local_addr=172.16.0.100 alias_addr=192.168.1.1 remote_addr=8.8.8.8 local_port=8080 alias_port=80 remote_port=12345 proto=6 description="this is test" }

Пример настройки через rc.conf/ng_nat.sh:
ng_nat_nat1_redirect_port0="tcp 172.16.0.100:8080 192.168.1.1:80 8.8.8.8:12345"
ng_nat_nat1_redirect_port0_description="this is test"

redirectaddr

Проброс входящих TCP/UDP соединений на внутренние хосты.

Пример сообщения netgraph:
ngctl msg nat1: redirectaddr { local_addr=172.16.0.100 alias_addr=192.168.1.1 description="this is test" }

Пример настройки через rc.conf/ng_nat.sh:
ng_nat_nat1_redirect_address0="172.16.0.100 192.168.1.1"
ng_nat_nat1_redirect_address0_description="this is test"

redirectproto

Проброс входящих TCP/UDP соединений на внутренние хосты.

Пример сообщения netgraph:
ngctl msg nat1: redirectproto { local_addr=172.16.0.100 alias_addr=192.168.1.1 remote_addr=8.8.8.8 proto=6 description="this is test" }

Пример настройки через rc.conf/ng_nat.sh:
ng_nat_nat1_redirect_proto0="tcp 172.16.0.100 192.168.1.1 18.8.8.8"
ng_nat_nat1_redirect_proto0_description="this is test"

redirectdynamic

Делает ранее установленное правило редирекции динамическим.
После первого обмена пакетами через динамическое правило,
оно будет автоматически удалено

Пример сообщения netgraph:
ngctl msg nat1: redirectdynamic 1

redirectdelete

Удаляет правило редирекции

Пример сообщения netgraph:
ngctl msg nat1: redirectdelete 1

Пример настройки через ng_nat.sh:
ng_nat.sh delete_redirect nat1 1

addserver

Реализация LSNAT - распределения коннекций на несколько
серверов по round-robin. Сообщение netgraph принимает id
номер ранее установленной редирекции и адрес + порт
назначения которые надо добавить для данной редирекции.

Пример сообщения netgraph:
ngctl msg nat1: addserver { id=1 addr=1.2.3.4 port=8080}

Пример настройки через rc.conf/ng_nat.sh:
ng_nat_nat1_redirect_port0="tcp 172.16.0.100:80,172.16.0.102:80 192.168.1.1:80"

listredirects

Показывает список со всеми сконфигурированными статическими
редирекциями для конкретной ноды.

Пример сообщения netgraph:
ngctl msg nat1: listredirects

Пример настройки через rc.conf/ng_nat.sh:
ng_nat.sh list_redirects nat1

proxyrule

Конфигурация правила проксирования проходящего трафика.
Правила применяются к трафику полученному через хук in.
Возможные значения type: encode_ip_hdr | encode_tcp_stream | no_encode

Пример сообщения netgraph:
msg nat1: proxyrule "type no_encode port 81 server
172.16.1.1:8080 proto tcp dst 7.7.7.7"

Пример настройки через rc.conf/ng_nat.sh:
ng_nat_nat1_proxy_rule0="type no_encode port 80 server 172.16.1.1:8080 proto tcp dst 7.7.7.7"

Дополнительная информация о способах конфигурации режимов работы ng_nat

В примере использования сообщения setmode была показана конструкция такого вида:
ngctl msg nat1: setmode { flags=55 mask=55 }

Про способ подбора значения параметра flags было сказано (плюсуются десятичные значения соответствующих опций), но не было сказано про второй параметр - mask. Маска используется для указания какие именно биты конфигурации необходимо изменить. Как объяснил nuclight - в C коде есть такая часть в которой и происходит обработка флагов и маски. Там-то как раз и задается режим работы ноды ng_nat:

la->packetAliasMode = (flags & mask) | (la->packetAliasMode & ~mask);

Это значит, что когда заданы как флаги так и маска, между ними проводится логическая операция AND после чего в качестве конфигурации ноды ng_nat применяется полученное значение. В нашем случае применение AND между  flags=55 и mask=55 даст то же самое 55 - режим который мы хотим установить. С тем же успехом можно было применять flags=55 mask=0xffffffff - это бы дало те же самые 55. Если задать flags=55 и mask=54 то будет отключен режим логирования (убрали единицу в последнем разряде).

Маску можно использовать для управления режимом работы ната, когда не известно эталонное значение flags. Скажем, если мы хотим отключить режим DENY_INCOMING [2] то можно послать такое сообщение:
ngctl msg nat1: setmode { flags=0 mask=2 }

так как флаги равны 0 (false), то сработает вторая часть кода в которой будет взято теперешнее значение флагов, инвертирована переданная нами маска, и между ними будет проведена операция AND. В итоге флаги станут 53 и это значение будет применено к ноде ng_nat.


Примеры и сценарии применения механизма ng_nat

Пример 1

Случай использования правил проксирования для передачи http трафика на прозрачный прокси сервер. Прокси сервер работает на машине 192.168.1.80 у которой свое подключение к интернету. Весь проходящий через наш рутер трафик адресованный на 80 порт любого адреса получателя надо пересылать на 192.168.1.80:8080. Наш нат рутер имеет адреса 192.168.1.1 со стороны локальной сети и 1.2.3.4 со стороны интернета.

онфигурация:

/etc/rc.conf

gateway_enable="YES"
ifconfig_em0="inet 1.2.3.4 netmask 255.255.255.0 -rxcsum"
ifconfig_fxp0="inet 192.168.1.1 netmask 255.255.255.0"
defaultrouter="1.2.3.254"
firewall_enable="YES"
firewall_type="/etc/firewall"

ng_nat_enable="YES"
ng_nat_nodes="nat1"
ng_nat_nat1_interface="em0"
ng_nat_nat1_cookies="1 2" # in out
ng_nat_nat1_ipfw_rules="20005 20008" # in out
ng_nat_nat1_ipfw_rule0="20005 netgraph 1 ip from any to me in recv em0"
ng_nat_nat1_ipfw_rule1="20008 netgraph 2 ip from any to any out xmit em0"
ng_nat_nat1_set_mode="same_ports reset_on_addr_change log deny_incoming"
ng_nat_nat1_proxy_rule0="type no_encode port 80 server 192.168.1.80:8080 proto tcp"



/etc/sysctl.conf

net.inet.ip.fw.one_pass=1



/etc/firewall

# разрешаем все через интерфейс локальной сети
add 1040 allow ip from any to any via fxp0

# непонятное нам не нужно
add 1050 deny ip from any to 192.168.0.0/16 in recv em0
add 1060 deny ip from 192.168.0.0/16 to any in recv em0
add 1070 deny ip from any to 172.16.0.0/12 in recv em0
add 1080 deny ip from 172.16.0.0/12 to any in recv em0
add 1090 deny ip from any to 10.0.0.0/8 in recv em0
add 10100 deny ip from 10.0.0.0/8 to any in recv em0
add 10110 deny ip from any to 169.254.0.0/16 in recv em0
add 10120 deny ip from 169.254.0.0/16 to any in recv em0

# здесь в правилах с номерами 20005 и 20008 автоматически появятся
# директивы пересылающие трафик в ng_nat

add 65534 deny all from any to any



Файл ng_nat.sh надо скачать от сюда, поместить в /usr/local/etc/rc.d/ и сделать выполняемым через chmod 555 ng_nat.sh

Более подробно о ng_nat можно прочитать в манах

Так же про настройку различных режимов libalias тоже в манах

Подробное описание использования ng_nat.sh можно прочитать сдесь



размещено: 2011-03-13,
последнее обновление: 2011-03-30,
автор: terminus


vadim64, 2011-03-26 в 19:03:16

шикарно!
респект и уважуха!
ложка дёгтя: мля, теперь и с этой штукой не буду разбераться сам, раз такой ман заимелся

chel, 2011-06-25 в 11:46:24

а для pf есть настройки?

terminus, 2011-06-26 в 12:51:34

pf не соеденяем с netgraph напрямую.

ХУЙ, 2011-11-18 в 23:13:51

Полная хуйня.
А чтоб правила чуть поменять надо машину перезагружать, да?

На PF собирайте фаервол и не занимайтесь хуйнёй!

terminus, 2011-11-19 в 17:45:38

Не будьте мудаком. Чтобы поменять режим работы ng_nat есть два способа и оба правельные:
1) послать управляющее сообщение через ngctl.
2) поменять настройки rc.conf (ng_nat_) и сделать /usr/local/etc/rc.d/ng_nat.sh restart.

пф головного мозга, да.

Иван Зимин, 2013-09-19 в 1:07:39

Для интерфейса IFx можно создать файлик /etc/start_if_IFx, который является штатным местом донастройки сетевых параметров, вызываемым скриптами конфигурации как "/bin/sh /etc/start_if_IFx IFx" (или чё-та типа того). Т. е. исполняемым файлик делать не надо. Имхо ng_nat'у там самое место. У меня на 8 с чем-то оттуда ng_car заводился. Где я нашёл про /etc/start_if* уже не помню, но это было в системе, а не в инете. Выполняется он вроде после выполнения директив из /etc/rc.conf

'" <b>, 2013-10-16 в 12:24:50

 



 

  Этот информационный блок появился по той простой причине, что многие считают нормальным, брать чужую информацию не уведомляя автора (что не так страшно), и не оставляя линк на оригинал и автора — что более существенно. Я не против распространения информации — только за. Только условие простое — извольте подписывать автора, и оставлять линк на оригинальную страницу в виде прямой, активной, нескриптовой, незакрытой от индексирования, и не запрещенной для следования роботов ссылки.
  Если соизволите поставить автора в известность — то вообще почёт вам и уважение.

© lissyara 2006-10-24 08:47 MSK

Время генерации страницы 0.1456 секунд
Из них PHP: 48%; SQL: 52%; Число SQL-запросов: 77 шт.
Исходный размер: 32937; Сжатая: 9375