Настройка Firewall, NAT,ALTQ на PF
Packet Filter (PF) — фаервол разработанный для OpenBSD и позже портированный на FreeBSD и NetBSD. По сравнению с тем же ipfw, имеет более понятный для чтения и написания правил синтаксис, имеет встроенный NAT, очереди и другие вкусности. Примеры конфигов можно увитеть тут: /usr/share/examples/pf.
В ОС FreeBSD он поставляется в виде подгружаемых модулей ядра, добавим его поддержку:
[root@router /]# cat /etc/rc.conf | grep pf
pf_enable="YES" pf_rules="/etc/pf.conf" pf_flags="" pflog_enable="YES" pflog_logfile="/var/log/pflog" pflog_flags="" gateway_enable="YES"
Если FreeBSD используется в качестве маршрутизатора, следует разрешить проброс пакетов, добавить в файл /etc/sysctl.conf:
net.inet.ip.forwarding=1 net.inet6.ip6.forwarding=1
Сам конфиг у нас находиться в /etc/pf.conf и имеет организованную структуру:
1. Макросы: Определяемые пользователем переменные, которые могут содержать адреса IP, имена интерфейсов, и т.д.
2. Таблицы: Применяются для хранения списков IP адресов.
3. Опции: Параметры, влияющие на работу pf.
4. Параметры нормализации Scrub: Подготовка пакета к нормализации и дефрагментации.
5. Приоретизация и очереди ALTQ: Обеспечивает управление полосой пропускания и установку приоритетов пакета.
6. Трансляции: Контроль NAT и перенаправление пакетов.
7. Правила фильтрации: Осуществляют выборочную фильтрацию пакетов на интерфейсах.
Для ясности происходящего приведу пример включения PF в сеть:
[root@router /]# cat /etc/pf.conf
####МАКРОСЫ#### # Внешний виртуальный сетевой интерфейс созданный PPPoE. ext_if="tun0"# WAN ISP int_isp="vr1"# Сетевой интерфейс который смотрит в мою домашнюю сеть. int_if="vr0"router="192.168.1.1" LAN="192.168.1.0/24"# Разрешенные типы icmp сообщений allowed_icmp_types="{ echoreq, unreach }" # Открытые порты со стороны интернет servises_ext = "{ 21 80 3389 4899 5900 }" # Cписок немаршрутизируемых адресов, с которых к нам будут долбиться на внешний интерфейс non_route_nets_inet="{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8, 169.254.0.0/16, 192.0.2.0/24, 0.0.0.0/8, 240.0.0.0/4 }" ####ТАБЛИЦЫ#### # Те, кто ходит у меня через NAT. table <it> persist { 192.168.1.5 } # Всем с сети 192.168.2.0/24 кроме 192.168.2.200. #table <clients> { 192.168.2.0/24, !192.168.2.200 } ####CONTROL PF#### # Тем, кто лезет туда куда не нужно вежливо сообщаем что нельзя #set block-policy return # Если Вас досят, есть смысл поставить вместо "return". set block-policy drop # Не проверяем на lo0 set skip on lo0 # Изменяем время для состояния установленного tcp соединения, которое по-умолчанию чересчур большое (24часа). set timeout { frag 10, tcp.established 3600 } # Собирать пакеты перед отправкой scrub in all #Очереди, полоса - 2мбит, режем исходящий трафик от сервера с стороны внешнего интерфейса tun0. altq on $ext_if cbq bandwidth 1980Kb queue { qssh, qhttp, qdns, qack, qftp } queue qhttp bandwidth 70% priority 6 cbq (default borrow) queue qssh bandwidth 15% priority 5 cbq (borrow) queue qdns bandwidth 5% priority 5 cbq (borrow) queue qack bandwidth 5% priority 6 cbq (borrow) queue qftp bandwidth 5% priority 2 cbq (red) #### NAT #### # Тем, кто в таблице <it> разрешаем ходить в интернет через NAT, кроме 25 порта. nat on $ext_if inet from <it> to any port != smtp -> ($ext_if) # Для примера, NAT всех разрешенных портов, кроме www #nat on $ext_if from $int_if:network to any port { ntp, nntp, domain } -> $ext_if nat on $ext_if inet from 192.168.1.100 to any port smtp -> ($ext_if) #DBSERV #### PORTMAPING #### # Указываем какие порты редиректить и куда. rdr on $ext_if inet proto tcp from any to any port 3389 -> 192.168.1.10 port 3389 #RDP rdr on $ext_if inet proto tcp from any to any port 4899 -> 192.168.1.11 port 4899 #RADMIN rdr on $ext_if inet proto tcp from any to $ext_if port 5900 -> 192.168.1.12 port 5900 #VNC #### ПРАВИЛА ФИЛЬТРАЦИИ #### # Блокируем всяких нехороших людей стандартный антиспуфинг средствами pf. antispoof log quick for { lo0, $int_if, $ext_if } #### $ext_if #### #Блокируем все входящие на внешнем интерфейсе (ext_if) tun0 block in on $ext_if #Рубаем Мультикастовые рассылки (Данные, предназначенные для приемом группой машин. В отличие от unicast и broadcast) block in on $ext_if from any to 240.0.0.0/4 #Блокируем приватные сети на внешний интерфейс block drop in quick on $ext_if from $non_route_nets_inet to any block drop out quick on $ext_if from any to $non_route_nets_inet #Разрешаем пинги на внешний интерфейс pass in on $ext_if inet proto icmp all icmp-type $allowed_icmp_types #Разрешаем ssh на внешнем интерфейсе pass in quick on $ext_if inet proto tcp from any to any port 2222 keep state #Разрешаем открытые порты на внешнем интерфейсе pass in on $ext_if inet proto { tcp,udp } from any to any port $servises_ext flags S/SA keep state #IN ALTQ pass in on $ext_if inet proto { tcp,udp } from any to $ext_if port 2222 queue ( qssh, qack ) pass in on $ext_if inet proto { tcp,udp } from any to $ext_if port 80 queue qhttp pass in on $ext_if inet proto { tcp,udp } from any to $ext_if port 53 queue qdns pass in on $ext_if inet proto { tcp,udp } from any to $ext_if port { 21 30000:35000 } queue qftp #OUT ALTQ pass out on $ext_if inet proto { tcp,udp } from $ext_if to $ext_if port 2222 queue ( qssh, qack ) pass out on $ext_if inet proto { tcp,udp } from $ext_if to $ext_if port 80 queue qhttp pass out on $ext_if inet proto { tcp,udp } from $ext_if to $ext_if port 53 queue qdns pass out on $ext_if inet proto { tcp,udp } from $ext_if to $ext_if port { 21 30000:35000 } queue qftp #Разрешить все исходящие на внешнем интерфейсе pass out on $ext_if keep state #### $int_isp #### # Разрешаем все на этом интерфейсе. pass in quick on $int_isp all pass out quick on $int_isp all #### $int_if #### # Наша локалка # Блокируем все входящие на внутр. интерфейсе (int_if) block in on $int_if all #Разрешаем пинги на внутр. интерфейсе pass in on $int_if inet proto icmp all icmp-type $allowed_icmp_types #Разрешаем открытые порты на внутр. интерфейсе pass in on $int_if inet proto { tcp,udp } from $LAN to $router port 21 flags S/SA keep state #ftp pass in on $int_if inet proto { tcp,udp } from $LAN to $router port 30000:35000 flags S/SA keep state #ftp-pasive pass in on $int_if inet proto { tcp,udp } from $LAN to $router port 25 flags S/SA keep state #smtp pass in on $int_if inet proto { tcp,udp } from $LAN to $router port 53 flags S/SA keep state #domain pass in on $int_if inet proto { tcp,udp } from $LAN to $router port 67 flags S/SA keep state #dhcps pass in on $int_if inet proto { tcp,udp } from $LAN to $router port 80 flags S/SA keep state #http pass in on $int_if inet proto { tcp,udp } from $LAN to $router port 110 flags S/SA keep state #pop3 pass in on $int_if inet proto { tcp,udp } from $LAN to $router port 123 flags S/SA keep state #synctime (ntp) pass in on $int_if inet proto { tcp,udp } from $LAN to $router port 137:139 flags S/SA keep state #samba pass in on $int_if inet proto { tcp,udp } from $LAN to $router port 143 flags S/SA keep state #imap pass in on $int_if inet proto { tcp,udp } from $LAN to $router port 445 flags S/SA keep state #microsoft-ds pass in on $int_if inet proto { tcp,udp } from $LAN to $router port 465 flags S/SA keep state #ssmtp pass in on $int_if inet proto { tcp,udp } from $LAN to $router port 993 flags S/SA keep state #imaps pass in on $int_if inet proto { tcp,udp } from $LAN to $router port 995 flags S/SA keep state #pop3s pass in on $int_if inet proto { tcp,udp } from $LAN to $router port 2222 flags S/SA keep state #SSH pass in on $int_if inet proto { tcp,udp } from $LAN to $router port 3128 flags S/SA keep state #proxy pass in on $int_if inet proto { tcp,udp } from $LAN to $router port 5222:5223 flags S/SA keep state #jabber pass in on $int_if inet proto { tcp,udp } from $LAN to $router port 8000 flags S/SA keep state #stream-radio pass in on $int_if inet proto { tcp,udp } from $LAN to $router port 9090 flags S/SA keep state #jabber-www-adminka #for NAT pass in on $int_if inet proto { tcp,udp } from <it> to any flags S/SA keep state #Разрешить все исходящие на внутр. интерфейсе pass out on $int_if keep state
PF имеет некоторые ключи для работы:
Включить pf:
[root@router /]# pfctl -e
Выключить pf:
[root@router /]# pfctl -d
Загрузить pf.sh:
[root@router /]# pfctl -f /etc/pf.conf
Анализировать, но не загружать конфиг:
[root@router /]# pfctl -nf /etc/pf.conf
Загрузить только правила NAT:
[root@router /]# pfctl -Nf /etc/pf.conf
Загрузить только правила фильтрации:
[root@router /]# pfctl -Rf /etc/pf.conf
Просмотр:
Показать текущие правила NAT:
[root@router /]# pfctl -sn
Показать текущие правила фильтрации:
[root@router /]# pfctl -sr
Показать текущее состояние таблиц:
[root@router /]# pfctl -ss
Показать статистику правил и состояние счетчиков:
[root@router /]# pfctl -si
Показать все:
[root@router /]# pfctl -sa
Просмотр очередей ALTQ в реалтайме:
[root@router /]# pfctl -vvsq
Подсчет трафика с помощью pf на определенных интерфейсах:
[root@router /]# pfctl -sI -vv -i tun0
Подсчет трафика с помощью pf на всех интерфейсах:
[root@router /]# pfctl -sI -vv
Сброс всех правил PF, полный клир:
[root@router /]# pfctl -F all
Логирование трафика
Для просмотра логов, которые находятся в /var/log/pflog и не читабельны простым редактором используют tcpdump:
[root@router /]# tcpdump -n -e -ttt -r /var/log/pf.log
В реальном времени:
[root@router /]# tcpdump -n -e -ttt -i pflog0
Для просмотра пакетов, которые прошли через определенный порт, в данном случае smtp порт:
[root@router /]# tcpdump -n -e -ttt -r /var/log/pflog port 25
Можно ограничить показ пакетов комбинацией указанных адреса хоста и порта:
[root@router /]# tcpdump -n -e -ttt -r /var/log/pflog port 80 and host 192.168.1.10
Такой же способ применим при чтении информации из интерфейса pflog0:
[root@router /]# tcpdump -n -e -ttt -i pflog0 host 192.168.1.10
Ставим в крон и отправляем себе на почту например каждый день в 8.00:
#!/bin/sh tcpdump -n -e -r /var/log/pflog | mail admin(at)adminunix.ru && cat /dev/null > /var/log/pflog
Теперь пробуем проанализировать ваш конфиг:
[root@router /]#pfctl -nf /etc/pf.conf
если ошибок нет, значит все в порядке и можна загружать его в PF:
[root@router /]#pfctl -f /etc/pf.conf
Для большей безопасности я пересобираю ядро с поддержкой PF:
# Package Filter options ALTQ options ALTQ_CBQ options ALTQ_RED options ALTQ_RIO options ALTQ_HFSC options ALTQ_PRIQ options ALTQ_NOPCC device pf device pflog device pfsync
Вот вроде и всё.