Вам бонус- начислено 1 монета за дневную активность. Сейчас у вас 1 монета

Файервол IPFW во FreeBSD - настраиваем с нуля, пример простого конфига

Практика



В этой заметке я расскажу и покажу основы одного из самых популярных файерволов Unix - IPFW. Это именно тот файервол, который считается "по-умолчанию" для FreeBSD.


Итак, я предполагаю, что Вам в целом понятно - для чего файервол нужен и как он работает. Если совсем по-простому: файерволы просматривают весь траффик, проходящий через компьютер (будь то простой домашний декстоп, маршрутизатор или сервер), сравнивают каждый пакет с правилами, заданными администратором, на основе того - откуда и с какого порта этот пакет идет и куда на какой порт, и принимают решение - что с этим пакетом делать.

Мы не будем здесь касаться ограничения пропускной способности через "трубы", ядерного NAT (обойдемся NATd) и других вещей, которые уже не попадают в категорию "первичной настройки". Здесь конфиг для настройки файервола человеком, который мало с этим файерволом знаком и которому нужен "толчек" для того, чтобы дальше уже понять - что и куда вписать, чтобы работало как он хочет.


1. Общие положения

Итак, у нас есть компьютер с 2мя (в нашем рассказе пойдет речь о двух) сетевыми картами. Для простоты мы их назовем eth0 и eth1, хотя увидеть такие названия сетевых интерфейсов во FreeBSD - это, как бы, редкость.

В нашем примере сетевая карта eth0 будет "глядеть" внутрь нашей, защищенной сети. А карта eth1 - во-вне, в интернет. Опять же здесь мы рассказываем на примере частного случая - когда роутер имеет выходной "дыркой" интернет, а не другую какую-то нашу-же сеть.

Теперь поговорим о том, как задаются правила в IPFW и как файервол их обходит.

Правила описываются одно за другим. Каждый пакет файервол прогоняет по правилам одно за другим, пока не найдет то, с условиями которого этот пакет совпадет. В большинстве случаев обработка после этого прекращается (т.е. первое совпавшее правило прекращает путь пакета по списку).

Например, если мы имеем два правила:

allow all from 192.168.0.1 to any dst-port 1000-2000
deny  all from 192.168.0.1 to any dst-port 1050

Второе правило в нашем случае не сработает. Казалось бы, если их сложить на уровне логики человека - то пакету, идущему с адреса 192.168.0.1 куда угодно разрешено проходить на порты с 1000го по 2000й, кроме порта 1050. А вот и нет - ведь правило allow (1е) сработает и на порт номер 1050 (этот порт находится в указанном диапазоне 1000-2000) и IPFW просто не проверит следуюее правило!

Каждое правило имеет свой уникальный номер, начинающийся с малого числа (по-умолчанию 100). Последний допустимый номер правила - 65535, который занят "правилом по-умолчанию". По-умолчанию "правило по-умолчанию" - это "запретить все".

При указании правил мы можем как указывать их номер, так и не указывать. В последнем случае IPFW самостоятельно будет инкрементировать номер следующего правила и мы получим список с автоматически проставленными номерами правил.

По большому счету, указывать номера правил явно имеет смысл только в случае, если Вы хотите в процессе обработки "прыгать" между правилами. Например, при совпадении пакета с условием правила - ему нужно перепрыгнуть некий набор запрещающих правил и оказаться ниже по списку. Другого способа, кроме как "прыгнуть" к определенному правилу нет в данном случае - а для этого нам нужно будет точно знать - какой номер у нужного условия.

Еще одна заметка про нумерацию. IPFW спокойно относится к разрывам в списке. Например, для него очень даже "нормально", если Вы сделаете нумерацию правил как-то так:

100 ...
200 ...
300 ...
10000 ...
10100 ...
10200 ...

Т.е. номера правил не обязаны идти с четким инкрементом. Можно даже делать так:

100 ...
200 ...
201 ...
202 ...
300 ...


2. Как строятся правила и основные команды файервола

Каждое правило состоит из:
а) Номера
б) Команды
в) Параметров команды, если они есть
г) Указания протокола (tcp, upd, icmp... слова all и ip означают - любой протокол)
д) Правила "откуда"
е) Правила "куда"
ж) Дополнительные условия

Правила "откуда" и "куда" состоят из:
а) слова "from" или "to" соответственно
б) IP-адреса или имени хоста (слово any означает любой IP, а слово me - любой IP адрес из текущих настроенных на этом компьютере)
в) порта(ов). если порт не указан - считается равным "любой порт".

Если перед IP адресом или портом поставить "not" - то это будет инвертировать условие.

Еще раз - это сильно усеченно. На самом деле, если Вы собираетесь считать трафик, помечать пакеты и т.д. - IPFW синтаксис еще расширяется, но это выходит за пределы данной статьи.

Вот пример:
allow tcp from 192.168.0.1 33333 to 192.168.0.5 dst-port 80

Здесь мы:
а) Не указываем номера правила - значит IPFW его присвоит сам
б) Указываем команду "allow" - разрешить правилу пройти через файервол
в) Дополнительных параметров у "allow" нет - потому их здесь не видно
г) Указываем условие, что пакет должен быть TCP-пакетом (не UDP, не ICMP - именно TCP)
д) Правило "откуда" - с компьютера 192.168.0.1 с порта 33333
е) Правило "куда" - на компьютер 192.168.0.5 на порт 80
ж) Доп-условий нет

Другой пример:
500 skip 10000 all from any to 192.168.0.100 dst-port 3389 out via eth1

Здесь мы:
а) Мы указываем IPFW, что данное правило имеет номер 500
б) Указываем команду "skip" - перейти на другое правило
в) Указываем параметр команды skip - номер правила, на которое нужно прыгнуть - 10000
г) Указываем условие протокола - любой протокол (all)
д) Откуда: с любого компьютера (any) с любого порта (порт не указан)
е) Куда: на компьютер с IP 192.168.0.100 на порт 3389
ж) Доп-условие - направление: задаем, что условие сработает только если пакет должен выйти через сетевую карту eth1 (out eth1)


При необходимости в одном правиле указания нескольких IP-адресов или портов - смотрим следующую подсказку.

а) Можно использовать диапазоны:
allow all from any to 192.168.0.1 dst-port 5000-9000
allow all from any to 192.168.0.1-192.168.0.100

б) Можно перечислять через запятую (и группировать с диапазонами)
allow all from any to 192.168.0.1,192.168.0.2 dst-port 25,110,143,1024-2048
allow all from any to 192.168.0.1-192.168.0.10, 192.168.0.15

в) Можно использовать фигурные скобки (только 1 уровень скобок!):
allow all from any to { 192.168.0.1 or not 192.168.0.5 or 192.168.0.10 }


Как указывать подсети (маску)?

а) Через "/":
allow all from any to 192.168.0.0/24

б) Через ":":
allow all from any to 192.168.0.0:255.255.255.0



Основные команды:

 allow или pass или accept или permit
Разрешить пакету прохождение и завершить проверку. Т.е. пакету дается "зеленый" свет.
allow tcp from 192.168.0.1 to 192.168.0.2
allow udp from 192.168.0.1 to 192.168.1.0/24 dst-port 80,443
allow all from 192.168.0.5 to any dst-port 80,443,25,110,143,8080

 deny или drop
Запретить пакету прохождение и завершить проверку. Пакет не пропускается через роутер.
deny tcp from 192.168.0.1 to not 192.168.0.1/24
deny all from any to 192.168.0.5

 divert
Передать пакет сокету перенаправления на указанный порт. Проверка завершается, пакет вместо указанного адресата попадает к демону на локальной машине, который "слушает" на указанном порту.
divert natd ip from 10.0.0.0/8 to any out via eth1
# тут мы передаем пакеты, выходящие через eth1 из сети 10.0.0.0/8 демону NATd

 fwd или forward
Перенаправить пакет на указанный IP адрес вместо того, куда пакет направлялся. Т.е. мы ловим пакет и указываем ему "катиться" к нужному нам компьютеру. Проверка завершается.
Сладует учесть, что IPFW не меняет сам пакет, потому принимающий компьютер таки увидит, что пакет направлялся нифига не ему и должен быть к этому готов.
fwd 10.0.0.1,3128 tcp from 10.0.0.0/8 to not me 80
# Тут мы передаем на прозрачный прокси по адресу 10.0.0.1 и на порт 3128 все, что идет из сети 10A куда угодно кроме самого роутера на порт 80

 reset
Отказать пакету в прохождении и, если это TCP-пакет, постараться послать отправителю TCP-сообщение "reset". Более "гуманный" ответ вместо "просто безответного отказа", но тратит трафик на обратный ответ. Проверка завершается.
reset all from any to 192.168.0.1 dst-port 25,110,143

 skipto
При совпадении с условием - перейти на указанный номер пакета. Проверка продолжается с того условия, на которое пакет был перенаправлен.
skipto 3000 tcp from 192.168.1.0/24 to 192.168.0.0/16

 tee
При совпадении с уловием - послать копию данного пакета на указанный порт сокета перенавления (divert socket). Оригинальный пакет продолжает прохождение списка условий.
tee 40000 tcp from 192.168.0.15 to any
# Например, на порту 40000 на роутере сидит демон, который записывает весь трафик, идущий с 192.168.0.15

 unreach
Отказать пакету в прохождении и послать в ответ ICMP-ответ "unreach" с указанным кодом. Прохождение пакета завершается.
unreach net all from any to 192.168.5.0/24


Дополнительные условия, которые ставятся в конце правила:

 bridged
Пакет является Layer2 пакетом.

 diverted
Пакет сгенерирован divert-сокетом

 diverted-loopback
Пакет сгенерирован divert-сокетом и положен обратно в стек IP input для доставки.

 diverted-output
Пакет сгенерирован divert-сокетом и положен обратно в стек IP output для доставки. 

 dst-ip ip-адреса
Пакет отправляется на один из указанных адресов IP.

 dst-port номера портов
Пакет отправляется на один из указанных портов.

 established
Пакет проходит по уже установленному TCP-соединению.

 frag
Пакет фрагментирован и является не первой частью фрагментированной датаграммы.

 jail ID-тюрьмы
Пакет послан или принимается "тюрьмой" - виртуальной машиной во FreeBSD.

 icmptypes типы
Пакет совпадает с одним из указанных ICMP-типов.

 in или out
Пакет является входящим или выходящим (взаимоисключающие условия).

 iplen размеры
Пакет имеет размер из списка "размеры", который задается так-же, как и список портов.

 layer2
Пакет является Layer2 пакетом.

 MAC исходящий MAC целевой MAC
Пакет отправлен с сетевого интерфейса с MAC-адресом "исходящий MAC" и должен поступить на сетевой интерфейс с MAC-адресом "целевой MAC".

 proto протокол
Пакет соответствует указанному протоколу.

 via интерфейс
Пакет входит или выходит через указанный интерфейс.

 setup
Пакет имеет флаг SYN протокола TCP, но не имеет ACK.

 dst-ip ip-адреса
Пакет приходит с одного из указанных адресов IP.

 dst-port номера портов
Пакет приходит с одного из указанных портов.

 tcpflags флаги
Пакет имеет указанные TCP-флаги.
Если перед флагом стоит восклицательный знак (!) - флаг не должен стоять чтобы правило сработало.


Здесь только основные условия. Намного больше Вы можете прочитать в справке

man ipfw.


3. Конфигурируем файервол

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

#!/bin/sh

# Команда для общения с ipfw
fwcmd="/sbin/ipfw -q"

# eth0 - это внутренний сетевой интерфейс
# с IP-адресом 192.168.0.1
iip="192.168.0.1"
imask="255.255.255.0"
inet="192.168.0.0"
iif="eth0"

# eth1 - это интерфейс интернета
# IP, маска, подсеть и т.д. - чисто для примера
oip="11.22.33.44"
omask="255.255.255.0"
onet="11.22.33.0"
oif="eth1"

# Очищаем текущий набор правил
${fwcmd} -f flush

### Правила до NAT

# Через eth1 не может быть трафика с серыми IP
${fwcmd} add deny all from 10.0.0.0/8 to any in via ${oif}
${fwcmd} add deny all from 172.16.0.0/12 to any in via ${oif}
${fwcmd} add deny all from 192.168.0.0/16 to any in via ${oif}

${fwcmd} add deny all from any to 10.0.0.0/8 via ${oif}
${fwcmd} add deny all from any to 172.16.0.0/12 via ${oif}
${fwcmd} add deny all from any to 192.168.0.0/16 via ${oif}

${fwcmd} add deny all from any to 0.0.0.0/8 via ${oif}
${fwcmd} add deny all from any to 169.254.0.0/16 via ${oif}
${fwcmd} add deny all from any to 192.0.2.0/24 via ${oif}
${fwcmd} add deny all from any to 224.0.0.0/4 via ${oif}
${fwcmd} add deny all from any to 240.0.0.0/4 via ${oif}

# Ну и на внутреннем интерфейсе - откуда взяться внешнему трафику
${fwcmd} add deny all from ${onet}:${omask} to any in via ${iif}

# Позволяем ходить трафику внутри наших сетей
${fwcmd} add allow all from ${inet}:${imask} to ${inet}:${imask}

### NAT
# Исходящий трафик в интернет - пропускаем через NAT
${fwcmd} add divert natd ip from ${inet}:${imask} to any out via ${oif}

# Входящий трафик на ${oip} - т.е. на IP адрес самого маршрутизатора
# тоже загоняем в NATD - для демаскировки
${fwcmd} add divert natd ip from any to ${oip} in via ${oif}


### Правила после NAT

# Весь трафик, исходящий с этого роутера - разрешен. Это же правило
# срабатывает при маскировке - если его отключить, что в интернет после
# NAT ничего улетать не будет
${fwcmd} add allow all from me to any



# Не проверяем пакеты, проходящие по уже установленному, соответственно,
# проверенному соединению TCP
${fwcmd} add allow all from any to any established

# Запрещаем длинные фрагментированые эхо-запросы
${fwcmd} add deny icmp from any to any frag

# Разрешаем проходить вторым и более частям фрагментированных пакетов
# (их заголовки мы уже проверили)
${fwcmd} add allow all from any to any frag


# Разрешаем пользователям ломиться на почту по SMTP и получать ее по
# POP3, IMAP
${fwcmd} add allow tcp from ${inet}:${imask} to any dst-port 25,110,143,465,995
${fwcmd} add allow tcp from any 25,110,143,465,995 to ${inet}:${imask}

# Разрешаем резолвить DNS-имена
${fwcmd} add allow all from any to any dst-port 53
${fwcmd} add allow all from any 53 to any

# Разрешаем ходить по SSH
${fwcmd} add allow all from any to any dst-port 22
${fwcmd} add allow all from any 22 to any

# Разрешаем обновление времени через NTP
${fwcmd} add allow all from any to any dst-port 123
${fwcmd} add allow all from any 123 to any

# Разрешаем ходить по FTP только определенным IP
${fwcmd} add allow all from 192.168.0.5 to any dst-port 20,21,49152-65535
${fwcmd} add allow all from any 20,21,49152-65535 to 192.168.0.5

# Разрешаем подключаться через RDP (Windows Terminals)
${fwcmd} add allow all from any to any dst-port 3389
${fwcmd} add allow all from any 3389 to any

# Разрешаем ходить по HTTP/S
${fwcmd} add allow all from any to any dst-port 80,443
${fwcmd} add allow all from any 80,443 to any

# Разрешаем все пинги изнутри
${fwcmd} add allow icmp from any to any via ${iif}

# Запрещаем остальные пинги
${fwcmd} add deny icmp from any to any

# И запрещаем некоторые типы пингов снаружи
${fwcmd} add allow icmp from any to any icmptypes 0,3,4,8,11,12 via ${oif}

# Разрешаем ICQ
${fwcmd} add allow all from any to any dst-port 5190
${fwcmd} add allow all from any 5190 to any

#Разрешаем UDP
${fwcmd} add allow udp from ${inet}:${imask} to any

# Запрещаем IDENT
${fwcmd} add reset tcp from any to any 113 in via ${oif} setup

# Запрещаем все установления связи из-вне
${fwcmd} add deny tcp from any to any in via ${oif} setup

# Запрещаем broadcast через внешний интерфейс
${fwcmd} add deny ip from any to 0.0.0.255:0.0.0.255 in via ${oif}

# Запрещаем SMB соединения из-вне
${fwcmd} add deny udp from any to any 137-139 via ${oif}

# Запрещаем все остальное из-вне
${fwcmd} add deny ip from any to any via ${oif}


4. Разжевываем про NAT - двойное хождение пакетов

Итак, что же происходит когда пакет в процессе обработки IPFW встречает на своем пути правило "идика ты через NAT"? Т.е. срабатывает команда "divert natd"?

Давайте разберем по шагам. Начнем с пакета, который вылетает из локальной сети в интернет.
1) Пакет залетает в IPFW с серым IP и проходит все проверки вплоть до правила с NATD.
2) Пакет перенаправляется демону NATD и проверка IPFW заканчивается.
3) Пакет преобразуется (маскируется) демоном NATD и IP пакета принимает значение IP-адреса выходного интерфейса роутера.
4) Демон NATD заново выкидывает пакет в поток IPFW и файервол начинает проверку пакета С ПЕРВОГО ПРАВИЛА! Т.е. для IPFW это новый пакет, который он еще не смотрел и который не имеет ничего общего с тем пакетом, который изначально залетел из локальной сети.
5) Правило NATD уже не срабатывает, т.к. пакет не имеет локального IP и должен выйти через внешнюю сетевую карту (out via eth1).
6) Пакет доходит до места, где ему разрешается выйти, т.к. он якобы отправлен самим роутером (allow all from me to any). Ну и вылетает в интернет.

Теперь о пакете, который залетает из интернета и ломится на внутреннюю машину:
1) Пакет залетает в IPFW с белым IP компьютера-отправителя и начинает проходить по правилам.
2) Пакет доходит до правила NATD, где говорится, что если пакет прилетел именно на внешний IP-адрес роутера и зашел через внешнюю сетевую карту - то его надо прогнать через NATD.
3) Пакет перенаправляется на NATD и проверка IPFW завершается - этот пакет больше файервол не интересует.
4) NATD демаскирует пакет (если может) и направляет его обратно в IPFW, который начинает проверку демаскированного пакета С САМОГО НАЧАЛА ПРАВИЛ - для него это уже новый пакет, ничего общего с первым не имеющий.
5) IPFW производит свои обычные проверки уже с учетом того, что пакет летит не на белый адрес самого роутера, а на серый адрес внутри локальной сети. Потому правило NATD не срабатывает и пакет продолжает свой путь по правилам.

Вот так мы и видим, что каждый пакет, который проходит маскировку - проходит через файервол дважды - как он сам и потом как маска. А также мы видим, что каждое повторное такое прохождение начинается не за правилом NATD, а с самого первого правила IPFW.


5. Включаем файервол во FreeBSD

1) Создайте файл со списком правил, например, из примера выше, и положите его в:

/usr/local/etc/ipfw.conf

2) Сделайте файл исполняемым:

# cd /usr/local/etc
# chmod +x ipfw.conf

3) Откройте /etc/rc.conf и допишите вот такие строчки:

...
firewall_enable="YES"
firewall_script="/usr/local/etc/ipfw.conf"
...

4) Перезапустите роутер

# reboot

ВНИМАНИЕ! Будьте рядом с роутером на случай, если Вы где-то что-то забыли указать правильно (какой-нибудь IP) и связь с роутером после загрузки окажется закрытой. Т.е. будьте перед консолью.


6. А если нам надо DIVERT или FORWARD?

В ядро по-умолчанию не включены divert и forward. Их можно добавить пересобрав ядро (заодно и безусловно включите IPFW - не подгружаемым модулем, а как часть ядра).

# cd /usr/src/sys/i386/conf

Здесь копируете нужное Вам ядро (по-умолчанию используется ядро GENERIC) в другой файл и добавляете следующие строчки после всех опций:

options       IPFIREWALL
options       IPFILTER
options       IPDIVERT
options       IPFIREWALL_FORWARD

И пересобирываете ядро с его установкой:

# cd /usr/src
# make buildkernel KERNCONF=MYKERNEL && make installkernel KERNCONF=MYKERNEL

вместо MYKERNEL, конечно, ставьте название файла конфигурации Вашего ядра.

Все, перезагружаемся и Divert и Forward - работают через IPFW.


7. Что еще умеет IPFW?

Много. Он умеет делать "трубы", внутри которых ограничивать пропускную способность трафика, эмулировать потери пакетов; он умеет считать трафик по заданным правилам; он умеет работать с таггированными пакетами... Поверьте, файл конфигурации выше - это всего минимальный конфиг.

Многое Вы можете прочитать по "man ipfw". Многое - в handbook по FreeBSD (кстати, на русском она тоже есть). Эта заметка не предназначалась для описания всех возможностей IPFW - она для тех, кто только начинает с этим файерволом работать и кому нужно начальное понимание - где, что и как прописать чтобы получить тот или иной результат.


8. А почему не ядерный NAT?

А потому что на момент FreeBSD 8.1 ядерный NAT глючил - имел очень небольшой командный буфер, который не позволял использовать большое количество правил проброса портов (D-NAT). А патчить исходники ядерного NAT с пересборкой этого всего удовольствия мне не улыбнулось (без того хватает работы), потому я лично до сих пор (даже на 8.2) живу с не-ядерным NAT. Может быть сейчас уже поправили - я еще не тестил.

В любом случае, если ядерный NAT заработал как надо - я опишу его использование.
создано: 2017-05-10
обновлено: 2024-11-12
3789



Рейтиг 9 of 10. count vote: 2
Вы довольны ?:


Поделиться:

Найди готовое или заработай

С нашими удобными сервисами без комиссии*

Как это работает? | Узнать цену?

Найти исполнителя
$0 / весь год.
  • У вас есть задание, но нет времени его делать
  • Вы хотите найти профессионала для выплнения задания
  • Возможно примерение функции гаранта на сделку
  • Приорететная поддержка
  • идеально подходит для студентов, у которых нет времени для решения заданий
Готовое решение
$0 / весь год.
  • Вы можите продать(исполнителем) или купить(заказчиком) готовое решение
  • Вам предоставят готовое решение
  • Будет предоставлено в минимальные сроки т.к. задание уже готовое
  • Вы получите базовую гарантию 8 дней
  • Вы можете заработать на материалах
  • подходит как для студентов так и для преподавателей
Я исполнитель
$0 / весь год.
  • Вы профессионал своего дела
  • У вас есть опыт и желание зарабатывать
  • Вы хотите помочь в решении задач или написании работ
  • Возможно примерение функции гаранта на сделку
  • подходит для опытных студентов так и для преподавателей

Комментарии


Оставить комментарий
Если у вас есть какое-либо предложение, идея, благодарность или комментарий, не стесняйтесь писать. Мы очень ценим отзывы и рады услышать ваше мнение.
To reply

Компьютерные сети

Термины: Компьютерные сети