Ключевые слова:freebsd, nat, ipfilter, firewall, proxy, ftp, howto, (найти похожие документы)
From: Evgueni V. Gavrilov <aquatique at rusunix.org>
Date: Mon, 17 May 2004 18:21:07 +0000 (UTC)
Subject: NAT во FreeBSD с помощью IPFilter (ipnat)
Оригинал: http://aquatique.rusunix.org/ipnat.html
NAT во FreeBSD с помощью IPFilter (ipnat)
Содержание
* Введение
* Подготовка
* Простенький stateful NAT
* Перенаправление (redirect)
* FTP proxy
* Использование отдельного IP-адреса для трансляций на внешнем интерфейсе
* Безусловная полная трансляция
* Контроль над трансляцией
Введение
--------
Синдром гамака является одним из ключевых моментов деградации
сисадмина. Он начинается с того, что стабильность и неподвижность
становятся синонимами. Когда-то, до того, как IPFilter включили в
состав FreeBSD, единственным нормальным способом сделать NAT во
FreeBSD был natd. Это извращение работало через divert socket и висело
демоном. natd до сих пор может быть в некоторых случаях актуален. Мы
же рассмотрим использование ipnat из IPFilter в качестве средства для
Network Address Translation (NAT).
Этот документ не является пошаговым howto for dummies -
подразумевается, что не нужно объяснять, что например после изменения
/etc/syslog.conf ему нужно послать сигнал HUP, а файлы, куда он будет
писать, создавать нужно самостоятельно и как "применять" изменённые
правила. Если Вы считаете, что ещё не совсем освоились с *nix и с
FreeBSD в частности, то по этой теме можно почитать:
ipnat(1), ipnat(5), ipnat(8)
ipf(5), ipf(8), ipfstat(8), ipftest(1), ipmon(8)
Здесь и далее будет считаться, что IPFilter у нас как минимум версии
3.4.29. Если в Вашем случае это не так - то Вы ещё не совсем вылезли
из гамака, хотя уже тот факт, что Вы читаете этот текст, является
доказательством Вашего на то желания.
Подготовка
----------
Итак, рассмотрим ситуацию: мы имеем 2 интерфейса - fxp0
(200.200.200.1), смотрящий в большой и злой интернет, и dc0
(192.168.0.1), смотрящий во внутреннюю сеть.
Задача: сделать возможность пользователям внутренней сети открывать
TCP/UDP соединения к внешним хостам без использования socks5/http
proxy и т.п.
В ядре нам понадобятся всего 2 строчки:
options IPFILTER
options IPFILTER_LOG
После этого IPFilter доступен нам во всей своей красе.
Также в /etc/rc.conf нужно добавить строчку gateway_enable="yes" или в
/etc/sysctl.conf добавить строчку net.inet.ip.forwarding=1.
Теперь всё готово - пакеты перебрасываются между интерфейсами.
Осталось контролировать их переброс и заменять в них IP адрес с
внутреннего на внешний и наоборот.
Простенький stateful NAT
------------------------
Начнём с простого stateful NAT т.е. IP пакеты с внешнего интерфейса
для получателя во внутренней сети будут транслироваться только в том
случае, если пользователь сам установил это соединение. Все остальные
пакеты, пришедшие на внешний интерфейс для получателя во внутренней
сети бы будем блокировать (см. redirect далее, если какие-то пакеты
извне нужно всегда пробрасывать внутрь).
Для соединений, установленных пользователем, мы будем создавать
запись в state table с помощью простого правила IPFilter:
pass out quick on fxp0 proto tcp from 192.168.1.149 to any flags S/FSRA keep state
(для TCP-соединений) и
pass out quick on fxp0 proto udp from 192.168.1.149 to any keep state
(для UDP-соединений).
Можно вместо двух правил сделать одно общее как для TCP, так и для UDP:
pass out quick on fxp0 proto tcp/udp from 192.168.1.149 to any keep state
однако в таком правиле мы не сможем отслеживать tcp-пакеты с флагом SYN с
помощью flags, в результате чего любой пакет из внутренней сети будет
создавать запись в state table (если её не было), а не те пакеты,
которые являются первыми в установке TCP-соединения (с флагом SYN).
Что удобнее/лучше/больше подходит - решайте сами.
Следом за этим правилом мы поместим правило, блокирующее все пакеты
для внутренней сети: block in quick on fxp0 from any to 192.168.0/16.
Под это правило будут попадать пакеты, не являющиеся частью
соединений, запрошенных из внутренней сети либо пакеты из соединений,
которых нет в state table
Теперь сама трансляция. Занесём в файл трансляций (по умолчанию это
/etc/ipnat.rules) правило:
map fxp0 192.168.1.149/32 -> 200.200.200.1/32 portmap tcp/udp 20000:20099
В результате мы получаем следующую картину: при установке
TCP-соединения самый первый пакет (с флагом SYN) из внутренней сети с
хоста 192.168.1.149 при уходе в большой и злой интернет будет
подвержен простому преобразованию - адрес хоста, запросившего
установку соединения будет изменён с 192.168.1.149 на 200.200.200.1.
Порт будет также изменён на первый доступный из диапазона от 20000 до
20099. Как можно заметить, в данном случае хост 192.168.1.149 может
открыть наружу не более 100 соединений.
Всё что осталось - применить правила. ;-)
Для удобства отслеживания работы NAT можно добавить строчку в
syslog.conf:
local0.* /var/log/ipmon.log
и запустить утилиту мониторинга работы IPFilter - ipmon с ключами -Dvas
(стать демоном, показывать более детальную информацию, отслеживать все
утройства IPFilter (NAT, state table и сам IPFilter) и работать через syslog).
Если получаемый log-файл кажется сумбурным - не торопитесь включать
только NAT опцией -o N. Правила IPFilter попадающие в лог можно туда
направлять с другой facility. Для этого достаточно в каждое правило с
флагом log добавить facilty:
block in log level local2.info quick on fxp0 from any to 192.168.0/16
а в syslog.conf добавить ещё одну строку:
local2.* /var/log/ipfilter.block.log. В результате сего деяния
в /var/log/ipmon.log будет попадать информация о NAT (созданные
трансляции, закрытые трансляции) и state table (создание записи и её
удаление), а в файл /var/log/ipfilter.block.log пакеты, которые были
блокированы.
Если не желаете, чтобы в большом количестве правил была указана
facility и правила были короче - можно отвергнуть возможность работы
ipmon через syslog и заставить его писать прямо в файл; например так:
ipmon -Dv -o NS /var/log/NAT.log
(трансляции и state table протоколируем в файл /var/log/NAT.log) и
ipmon -Dv -o I /var/log/ipfilter.log
(работу самого фильтра протоколируем в файл /var/log/ipfilter.log).
Стоит заметить, что одним правилом можно транслировать несколько
хостов. Например заменив в правилах ipnat и IPFilter 192.168.1.149/32
на 192.168.128/25 мы будем транслировать пакеты хостов из внутренней
сети из диапазона от 192.168.1.128 до 192.168.1.254.
Перенаправление (редирект)
--------------------------
Если существует необходимость безусловно транслировать какие-то
пакеты, пришедшие извне (например чтобы WWW/SMTP сервер из внутренней
сети) был доступен снаружи - используется редирект (redirect).
Простой вариант: транслировать пакеты от любого хоста.
rdr fxp0 200.200.200.1/32 port 8080 -> 192.168.1.17 port 80 tcp
В данном случае любой пакет, пришедший на порт 8080 внешнего
интерфейса 200.200.200.1 будет "проброшен" на 192.168.1.18 порт 80.
Естественно, что хост 192.168.1.17 лучше поместить в таблицу
трансляций как было описано в "Простеньком stateful NAT" и с учётом
того, что инициироваться соединение будет снаружи - добавить правила
IPFilter, которые бы разрешали их. В случае, если ipmon протоколирует
работу IPFilter, допущенную ошибку можно будет легко увидеть.
Редирект можно делать не всех пакетов, а выборочно на основании их
отправителя:
rdr fxp0 from 212.118.165.100/32 to 200.200.200.1/32 port = 6000 -> 192.168.1.89 port 6000
Этим правилом будут транслироваться пакеты, пришедшие на 200.200.200.1
порт 6000 только с хоста 212.118.165.100
Не стоит забывать создавать правила IPFilter, разрешающие прохождение
таких пакетов. Хотя, если ipmon настроен и запущен, то он быстро об
этом напомнит. ;-)
FTP proxy
---------
Итак, всё работает замечательно, за исключением FTP. Это обусловлено
тем, что в ходе установки соединения, по которому будут передаваться
данные, указывается IP-адрес клиента, который в нашем случае
принадлежит частной сети.
ipnat способен в таких случаях быть "прокси-сервером" - то есть
"ковыряться" в данных, передаваемых FTP-серверу и от него, и
транслировать адреса из внутренних во внешние и наоборот. Для этого
используется такое правило:
map fxp0 192.168.1.149/32 -> 200.200.200.1/32 proxy port ftp ftp/tcp
proxy-правило должно обязательно стоять перед другими правилами (за
исключением redirect).
Использование отдельного IP-адреса для трансляций на внешнем интерфейсе
-----------------------------------------------------------------------
Если у Вас имеется в наличии не 1 IP-адрес, а сегмент сети, может быть
удобным транслировать не с тех адресов, которые установлены на внешнем
интерфейсе (fxp0), а с других. При этом важным является то, что на
самом внешнем интерфейсе (fxp0) этот IP-адрес устанавливать нет
никакой необходимости. ipnat делая трансляцию не открывает сокетов -
об этом нужно помнить.
Допустим, что сеть 200.200.200.0/24 полностью принадлежит нам. В таком
случае, во всех правилах трансляции мы можем ставить не реальный
IP-адрес, установленный на внешнем интерфейсе (fxp0), а другой,
например 200.200.200.200 (также можно по желанию сделать PTR запись
для этого хоста в зоне 200.200.200.in-addr.arpa).
Безусловная полная трансляция
-----------------------------
Если существует необходимость транслировать абсолютно все пакеты,
пришедшие на какой-либо адрес (не забывайте, что этот IP-адрес
необязательно должен быть установлен на внешнем интерфейсе fxp0) -
используется правило bimap.
bimap fxp0 192.168.1.66/32 -> 200.200.200.100/32
и/или
bimap fxp0 192.168.1.66/32 -> 200.200.200.100/32 portmap tcp/udp
Контроль над трансляцией
------------------------
Безусловно глупо настраивать NAT не глядя в протоколы, генерируемые
ipmon'ом. Также возможно будет полезным ограничивать способность
устанавливать соединения изнутри к привилегированным портам внешних
хостов. Всё это можно и нужно настроить по желанию.
Могут ли быть одновременно включены опции IPFILTER и IPFIREWALL? Если natd уже работает (т.е. natd_enable="YES"), то может ли одновременно с ним работать ipnat (i.e. ipnat_enable="YES")?
Здравствуйте! 8)
Без всяких прелюдий, прямо к делу! Необходимо фильтровать и считать трафик!
ADSL Router (192.168.0.100)
Сетевой интерфейс1, далее rl1 (192.168.0.10)
Сетевой интерфейс2, далее rl0 (192.168.1.10)
Оба интерфейса сидят в серваке под управлением FreeBSD 4.6.2
Интерфейс1 подключен к ADSL Router-у.
Интерфейс2 подключен к общему свитчу.
Я уже пару дней маюсь с этим. Ничего не получается. Поэтому опишу всё.
Пересобираю ядро со следующими опциями:
options IPFILTER
options IPFILTER_LOG
options IPFILTER_DEFAULT_BLOCK
options IPFIREWALL
options IPFIREWALL_FORWARD
options IPFIREWALL_DEFAULT_TO_ACCEPT
options DUMMYNET
Создаём ipf.rules:
pass in quick on lo0 all
pass out quick on lo0 all
pass in quick on rl0 all
pass out quick on rl0 all
pass in quick on rl1 all
pass out quick on rl1 all
А вот здесь не совсем всё понимаю, поэтому поправьте, (фактически
192.168.1.10 у меня гейт для всех пользователей)
ipnat.rules:
map rl0 192.168.1.0/24 -> 0/32 proxy port 21 ftp/tcp
map rl0 192.168.1.0/24 -> 192.168.0.10/32 portmap tcp/udp 20001:40000
map rl0 192.168.1.0/24 -> 192.168.0.10/32
Всё правильно сделал?
Не работает почему-то NAT ;( В настройках у юзеров прописываю гейт
192.168.1.10, днс провайдера. Не идёт ничего.
Щас заметил, что машины из 192.168.1.0 не пингуют 192.168.1.10
А сам сервер не слышит 192.168.0.100 - то есть роутера
>Могут ли быть одновременно включены опции IPFILTER и IPFIREWALL? Если natd уже
>работает (т.е. natd_enable="YES"), то может ли одновременно с ним работать ipnat
>(i.e. ipnat_enable="YES")?
Mogut. Tolko v etom slu4ae ipnat ne budet vlijat na NAT, t.e. vsem zapravliat budet natd.
Sobstvenno uspeshno ispolzuju sistemu: ipf-ipnat-ipfw.
Вопрос
Пробрасываю порт
В ipnat
rdr ale0 from xxx.xxx.xxx.xxx/32 to yyy.yyy.yyy.yyy/32 port = 2223 -> 192.168.1.2 port 2223
в ipf
block in on ale0 all
pass in quick proto tcp from xxx.xxx.xxx.xxx to yyy.yyy.yyy.yyy port = 2223
пакеты не ходят
Подскажите пожалуйста где проблема?