понедельник, 29 декабря 2008 г.

IPFW



Собираем ядро с опциямы для фаервола

options IPFIREWALL # встраиваем поддержку файрволла в ядро
options IPFIREWALL_VERBOSE # проходящие пакеты записываются в лог-файл, при использовании опции log в правилах
options IPFIREWALL_VERBOSE_LIMIT=100 # ограничение, чтоб весь /var логами не забили (количества записей в лог-файл по одному правилу, в правилах IPFW значение можно изменить через опцию logamount)
options IPFIREWALL_FORWARD # включаем поддержку перенаправления чтобы можно было сделать позрачный прокси-сервер TCP пакетов ядром( одновременно работает IPFW и прокси-сервер (например SQUID или FROX)
options IPDIVERT # поддержка IP-маскарадинга (natd)
options DUMMYNET # поддержка DUMMYNET (искуственное ограничение пропускной способности сети

allow ip from any to any- если включена опция
options IPFIREWALL_DEFAULT_TO_ACCEPT
либо, deny ip from any to any- если отсутствует.


/etc/rc.conf пишем
firewall_enable="YES"
firewall_script="/usr/local/etc/ipfw.rules" путь к файлу с правилами
natd_enable="YES"
natd_interface="de0" на каком интерфейсе будет nat
natd_flags="-same_ports"


Пример набора правил для IPFW (находится в “/etc/rc.firewall”)


IPFW составлен из семи компонентов,

1. первичный компонент - брэндмауэр управляющий списком правил на уровне ядра и интегрированная в него возможность пакетного учета,
2. возможность ведения логов,
3. "divert" правила которые взаимодействуют с NAT, и улучшенные специальные средства,
4. траффик dummynet, возможность шейпинга,
5. возможность перенаправления "fwd rule",
6. возможность бриджа,
7. возможность ipstealth.


Можна и не включать поддержку IPFW в ядро, пока вам не потребуется включить функцию NAT.
на сервере лучше включать.
------------------------------------------------------------------------------------------------------------------

ipfw list - показывает список правил
ipfw show - тоже показывает список правил, но вместе с числом пакетов и байт, что попали под эти правила. Очень удобно при отдладке - смотрим на чём зарубаются пакеты.
sysctl -a | grep ip.fw
ipfw zero - обнуление всех счётчиков. Если вести в виде ipfw zero №_правила то будет обнулён только счётчик правила с этим номером.
Чтобы применилось внесенное правилу - нужно перегрузить скрипт с правилами


синтаксис правил
CMD RULE_NUMBER ACTION LOGGING SELECTION STATEFUL
где
CMD............add | del
RULE_NUMBER....00001
ACTION.........allow | accept | pass | permit | check-state | deny | drop
LOGGING........log или logamount (в логе с именем SECURITY)
SELECTION......udp | tcp | icmp или любые имена протоколов, из /etc/protocols
STATEFUL.......from откуда to куда
-------------------------------------------------------------------------------------------------------------------
from и to используются для сопоставления с IP адресом. Правила должны быть определены для обоих параметров, источника и приемника. any специально ключевое слово, которое совпадает с IP адресом. me - специальное ключевое слово которое совпадает с любым IP адресом заданным на интерфейсе вашей FreeBSD для представления PC где запущен файрволл (то есть как коробки) как "от меня к любому" или от "от любого ко мне", или "от 0.0.0.0/0 к любому" или "от 0.0.0.0/0 ко мне", или "от 0.0.0.0 к любому" или "от 0.0.0.0 ко мне", IP адреса определены как адреса через точку, цифровая форма/длина маски или как один IP адрес без маски. Это обязательное требование.

port number


Для протоколов которые поддерживают номера (такие как TCP или UDP). Обязательно нужно написать номер порта сервиса для совпадения. Имена сервисов (из “/etc/services”) могут использоваться вместо значений номеров портов. in | out

Совпадения для входящих или исходящих пакетов соответственно. in и out - ключевые слова и обязательное написание одного или другого как часть критерия совпадения.via IF(интерфейс)
Совпадающие пакеты проходящие через определенное имя интерфейса интерфейс. via - ключевое слово которое означает интерфейс который будет всегда проверяться как часть процесса совпадения.setup

Обязательное ключевое слово, которое распознает запрос о начале сессии для TCP пакетов.keep-state

Обязательное ключевое слово. После совпадения файрволл создаст динамическое правило, чье поведение по умолчанию состоит в том, что бы было совпадение двунаправленного траффика между IP адресом или портом источника и приемника по тому же самому протоколу.limit {src-addr | src-port | dst-addr | dst-port}

Файрволл будет позволять только N соединений с тем же набором параметров, какие определены в правилах. Один или больше исходных и приемных адрессов может быть определено. "limit" и "keep-state" не могут быть использованы в том же правиле. "limit" дает ту же самую функцию состояния как и "keep-state" плюс собственные функции.


примеры правил
ipfw add deny icmp from me to ukr.net #закрывает пинг от меня на укр.нет
ipfw add deny tcp from site.ua to site.ru telnet #отвергает перенаправление текущим хостом всех tcp-пакетов от хоста site.ua на порт telnet хоста site.ru
ipfw add deny ip from 123.45.67.0/24 to my.host.org#запрещает любое подключение из сети взломщиков к моему хосту
ipfw divert 5000 ip from 192.168.2.0/24 to any in #перенаправляет все входящие пакеты от 192.168.2.0/24 на порт 5000:
00600 allow tcp from any to any 80 out via bge0 setup keep-state
00601 allow tcp from any to any 110 out via bge0 setup keep-state
00602 allow tcp from any to any 143 out via bge0 setup keep-state
00603 allow tcp from any to any 25 out via bge0 setup keep-state
правила 600-603 позволяют вам работать только с WWW (порт 80) и e-mail (порты 25, 110, 143)
00700 allow tcp from any to XX.XX.XX.XX 53 out via bge0 setup keep-state
00701 allow udp from any to XX.XX.XX.XX 53 out via bge0 keep-state
00702 allow tcp from any to YY.YY.YY.YY 53 out via bge0 setup keep-state
00703 allow udp from any to YY.YY.YY.YY 53 out via bge0 keep-state
Правила 700-703 аналогичны предыдущим, они позволяют вам работать с DNS, причём только с легальными DNS вашего провайдера. Замените XX.XX.XX.XX и YY.YY.YY.YY на адреса ваших DNS

ipfw add 510 divert natd ip from any to any via em0 - роздает инет на подсети


Как известно после перезагрузки системы правила в ipfw сбрасываются
Поэтому необходимо эти самые правила где-то хранить, что бы при загрузке системы происходила настройка фаервола
Это достигается следующими вариантами
************************************************************************************************************
1)Используя /etc/rc.conf и /etc/ipfw.rules - метод №1
1.1) В /etc/rc.conf пишем:
firewall_enable="YES"
firewall_type="/etc/ipfw.rules"
1.2) Создаём /etc/ipfw.rules:
# ee /etc/ipfw.rules
1.3) Вписываем в /etc/ipfw.rules нужные нам правила:
1.4) Перезагружаемся.
Замечание: прописывать в /etc/rc.conf строку firewall_enable="YES" - ОБЯЗАТЕЛЬНО, даже если ядро собиралось с поддежкой IPFW.
*************************************************************************************************************
2) Используя /etc/rc.conf и /etc/ipfw.rules - метод №2
2.1) В /etc/rc.conf пишем:
firewall_enable="YES"
firewall_script="/etc/ipfw.script"
2.2) Создаём /etc/ipfw.script
# ee /etc/ipfw.script
2.3) Вписываем в/etc/ipfw.script нужное нам содержание:
#!/bin/sh
……..
2.4) Даём право на запуск /etc/ipfw.script:
# chmod +x /etc/ipfw.script
2.5) Перезагружаемся.
*****************************************************************************************************
3) Используя /etc/rc.d/ipfwrules метод 3
3.1) Создаём файл /etc/rc.d/ipfwrules:
# ee /etc/rc.d/ipfwrules
3.2) Даём право на запуск /etc/rc.d/ipfwrules:
# chmod +x /etc/rc.d/ipfwrules
3.3) Вписываем нужное нам содержимое в /etc/rc.d/ipfwrules:
……..
3.4) Перезагружаемся.
******************************************************************************************************
4) Используя /usr/local/etc/rc.d/ipfw.sh метод 4
4.1) Создаём файл /usr/local/etc/rc.d/ipfw.sh:
# ee /usr/local/etc/rc.d/ipfw.sh
4.2) Даём право на запуск /usr/local/etc/rc.d/ipfw.sh:
# chmod +x /usr/local/etc/rc.d/ipfw.sh
4.3) Вписываем нужное нам содержимое в /usr/local/etc/rc.d/ipfw.sh:
……..
4.4) Перезагружаемся.
**************************************************************************************************************

если после перезагрузки скрипта не применяються правила или пишет not found чтото значит синтаксическая ошибка в скрипте
делаем /etc/rc.d/ipfw start и смотрим что и в какой строке не так.



А вот то, что следует вписать в конфигурационном файле: (я использую 2-й способ)

#!/bin/sh

# Создание переменных
ipfw="/sbin/ipfw"
lan_out="rl0"
lan_in="rl1"

#Создание pipe
${ipfw} pipe 1 config bw 384Kbit/s
${ipfw} pipe 2 config bw 128Kbit/s

#Сброс всех существующих правил
${ipfw} -f flush

#Проверка на соответствие дирамическим правилам
${ipfw} add check-state

#Разрешение работать через петлю
${ipfw} add allow ip from any to any via lo0

#Запрет на принятие/отправку пакетов петли
${ipfw} add deny ip from any to 127.0.0.0/8
${ipfw} add deny ip from 127.0.0.0/8 to any

#Запрет принятия пакетов с частных сетей
${ipfw} add deny ip from any to 0.0.0.0/8 in via ${lan_out}
${ipfw} add deny ip from any to 10.0.0.0/8 in via ${lan_out}
${ipfw} add deny ip from any to 172.16.0.0/16 in via ${lan_out}
${ipfw} add deny ip from any to 192.168.0.0/24 in via ${lan_out}

#Ограничение скорости канала
${ipfw} add pipe 1 ip from me to 192.168.10.20 out via ${lan_in}
${ipfw} add pipe 2 ip from me to 192.168.10.0/24 out via ${lan_in}

#Правила для ната с машины 192.168.10.20
${ipfw} add divert natd tcp from 192.168.10.20 to any 22 via ${lan_out}
${ipfw} add divert natd ip from any to me in via ${lan_out}

#Разрешение для устновленных соединений
${ipfw} add allow tcp from any to any via ${lan_out} established

# Разрешение на подключение по SSH c наружи
${ipfw} add allow tcp from any to me 22 in via ${lan_out}

# Разрешение на подключение по SMTP c наружи
${ipfw} add allow tcp from any to me 25 in via ${lan_out}

# Разрешение DNS
${ipfw} add allow udp from me to any 53 out via ${lan_out}
${ipfw} add allow udp from any 53 to me in via ${lan_out}

# Разрешение SSH –правило для NAT
${ipfw} add allow tcp from me to any 22 out via ${lan_out}

# Разрешение HTTP
${ipfw} add allow tcp from me to any 80 out via ${lan_out}

# Разрешение HTTPS
${ipfw} add allow tcp from me to any 443 out via ${lan_out}

# Разрешение FTP
${ipfw} add allow tcp from me to any 21 out via ${lan_out}
${ipfw} add allow tcp from any to me 49152-65535 in via ${lan_out}

# Разрешение SMTP
${ipfw} add allow tcp from me to any 25 out via ${lan_out}

# Local
${ipfw} add allow icmp from any to any via ${lan_in}
${ipfw} add allow udp from any to any via ${lan_in}
${ipfw} add allow tcp from any to any via ${lan_in}

# LOG
${ipfw} add deny log ip from any to any
**********************************************************************************************************
С такими настройками у нас получается что:
Шлюз имеет доступ на сервисы DNS, SSH, HTTP, HTTPS, FTP, SMTP
С мира можно подключиться на 22 и 25 порт
Для машины 192.168.10.20 открыт NAT только на SSH
Т.е. придеться побегать по машинам и вручную прописать в настройках соединения адрес и порт прокси.
Для маленькой сетки больше и не надо :)
Добавил в конфиг ограничения по скорости канала: сделал 2 трубы - на 384к и 128к -
В трубу на 384к мы засунули директора (192.168.10.20), а в трубу 128к мы засунули всех остальных
-----------------------------------------------------------------------------
natd_enable="YES"
natd_interface=""
natd_flags="-dynamic"