Использование pf для фильтрации трафика по сигнатурам ОС во FreeBSD


Сетевая фильтрация по типу операционной системы.

(Перевод. Оригинал - http://www.onlamp.com/pub/a/bsd/2006/02/16/os_fingerprint_filtering.html by Avleen Vig).

Вы управляете гетерогенной сетью и хотите предоставить различное качество обслуживания и полномочия в сети, в зависимости от типа операциооной системы клиента. С помощью pf и altq Вы можете ограничить величину пропускной способности канала, достпного пользователям различных ОС, или же принудительно направлять трафик на прозрачный кеширующий прокси-сервер. Эта статья описывает, как установить pf, altq и Squid на Ваш FreeBSD-маршрутизатор и веб-прокси для достижения этих целей.
Цели миссии.

В идеальном окружении не существует необходимости для шейпинга пропускной способности, фильтрации по отпечаткам ОС или даже качества обслуживания. некотрые факторы реального мира требуют изменения плана игры. За пропускную способность требуется платить, и множество ISP получают плату от своих клиентов за увеличение пропускной способности предоставляемых ими каналов. Черви, вирусы и скомпрометированные системы могут вести к увеличению занятости канала. При действии червя W32.Slammer, увеличивавшего количество соединений в инфицированных сетях, многие компании увидели космический рост счетов за трафик. Фильтрация соединений на основе анализа типа ОС отчасти поможет избежать выхода таких ситуаций из-под контроля. несмотря на то, что я фокусируюсь на фильрации трафика Windows-систем, это можно с тем же успехом применять для BSD, Linux, MacOS и ряда других ОС, перечисленных в файле pf.os в вашей системе. Это может быть особенно полезно для тех, кто запускает более старые версии ОС, которые не были или не могут быть пропатчены, но, тем не менее, подключены к сети. Как расширение прозрачной фильтрации, также возможна фильтрация контента с использованием таких утилит, как SquidGuard, позволяющим как детям, так и корпоративным пользователям просматривать сайты в относительной безопасности.
Необходимые утилиты.

Во время исследований при написании статьи, некоторые спрашивали меня, почему я решил использовать BSD, pf, altq и Squid для решения этой задачи. Другие утилиты имеют подобную функциональность, но никто более не предлагает сходную по полноте функциональность, как эти. Linux и iptables могут работать с Squid для обеспечения прозрачного проксирования, но не могут фильтровать соединения по типам ОС. Несмотря на многообразие прокси-серверов, Squid - один из лучших, доступных сегодня.

Важно отметить, что фильтрация по типу ОС может быть применена только к TCP SYN-пакетам, инициирующим TCP-сессию, а не к пакетам, идущим в течение установленного TCP-соединения, или udp-сессии.Тогда как это не является проблемой для большинства систем и сетевых администраторов, Вы можете захотеть уделить больше внимания Вашим правилам для фильтрации udp-пакетов.
Установка pf и altq.

pf и altq предоставляют возможности фильтрации пакетов и шейпинга соответственно. Их взаимосвязь неотличима от IPFIREWALL и DUMMYNET, тогда как один и тот же файл с правилами конфигурирует как pf, так и altq. В то время как pf является универсально использующимся, для работы altq требуется поддерживаемая сетевая карта. Хорошей новостью является то, что поддерживается большинство сетевых карт. Взгляните на секцию "Поддерживаеые устройства" интерактивных страниц справочника man 4 altq для того, чтобы найти список сетевых карт. Убедившись, что Вы обладаете поддерживаемой сетевой картой, добавьте поддержку pf и altq в файл конфигурации ядра. Вам понадобится пересобрать ядро, как описано в руководстве FreeBSD. Сперва добавьте несколько опций в конец файла конфигурации ядра :
device pf
options ALTQ
options ALTQ_CBQ
options ALTQ_RED
options ALTQ_RIO
options ALTQ_HFSC
options ALTQ_CDNR
options ALTQ_PRIQ

Примечание : при установке altq в многопроцессорной системе добавьте "options ALTQ_NOPPC" в конфигурацию Вашего ядра перед его пересборкой.

После пересборки, установки ядра и перезапуска машины протестируйте pf для того, чтобы убедиться, что pf установлен корректно, с помощью команды pfctl -s rules. Если Вы видите ошибку "pfctl: /dev/pf: No such file or directory", это означает, что pf не был установлен корректно. Если же Вы видите сообщение "No ALTQ support in kernel ALTQ related functions disabled", то pf работает, но altq - нет. В последнем случае Вы сможете заставить пользователей использовать прозрачный прокси, но не сможете ограничивать пропускную способность канала с помощью altq.
Установка Squid с поддержкой прозрачного прокси.

Установите squid командой
% cd /usr/ports/www/squid && make config install clean

Это ознакомит Вас со списком опций для сборки Squid. Для добавления поддержки прозрачного прокси выберите SQUID_PF. Вы также можете выбрать или исключить из предпочтений любую другую опцию. Я зачастую нахожу опцию SQUID_SNMP полезной для сборки и графической визуализации статистики при помощи RRDTool. Установив Squid, отредактируйте файл /usr/local/etc/squid/squid.conf. Установите по крайней мере следующие опции:
http_port YOUR_PROXY_IP:3128
http_access deny to_localhost
acl our_networks src YOUR_NETWORK/24
http_access allow our_networks
visible_hostname YOUR_HOSTNAME
httpd_accel_host virtual
httpd_accel_port 80
httpd_accel_with_proxy on
httpd_accel_uses_host_header on

Замените "YOUR_PROXY_IP" адресом, на котором будет принимать входящие запросы прокси-сервер, "YOUR_NETWORK/24" - внутренним диапазоном сетевых адресов (например, 192.168.0.0/24), и "YOUR_HOSTNAME" - именем хоста, которое будет видно пользователям в сообщениях об ошибке. "YOUR_HOSTNAME" не является обязательным, но чрезвычайно полезно, если Вы обладаете кластером прокси-серверов, разделяющий единый фронт-энд, например, балансировщик нагрузки.

Несмотря на то, что Вы можете использовать такую конфигурацию, Вам следует уделить больше времени на исследование оставшейся части файла squid.conf и настройки его для своих нужд. Через некоторое время Вам может стать необходимо настроить другие опции, например, размер кэша или тайм-аутов соединения. Файл конфигурации squid огромен, трата времени на изучение может позволить Вам ознакомиться с различными опциями и сэкономить время в будущем.
Фильтрация контента с помощью squidGuard.

Этот необязательный раздел посвящен желающим осуществлять фильтрацию контента. Я использую squidGuard в моей домашней сети для предотвращения просмотра моими детьми сайтов, которые я считаю неподходящими. Существует бесчисленное множество программ для этого, но squidGuard предлагает черные списки сайтов с нежелательным ПО, контентом для взрослых, пропагандой наркотиков, азартных игр, ненависти и так далее.

Установка и конфигурирование squidGuard.

После установки squid squidGuard кажется простым в настройке, что, вероятно, хорошо, ведь Вы потратили два последних часа на конфигурацию Squid, верно ?

Скопируйте /usr/local/etc/squid/squidGuard.conf.sample в /usr/local/etc/squid/squidGuard.conf и отредактируйте его своим любимым редактором. Если Вы хотитие осуществлять фильтрацию по времени дня, прочитайте руководство "Configuring squidGuard". Для начала оставьте фильтры включенными постоянно. Удалите существующий блок "source sample-clients", а затем создайте новый на его месте, прописав собственную сеть :
source localnet {
ip 192.168.0.0/24
}

В конце файла замените существующую секцию на следующую:
acl {
default {
pass !ads !drugs !gambling !porn all
redirect http://YOUR_WEBSERVER/cgi-bin/squidGuard.cgi?
clientaddr=%a&clientname=%n&clientuser=%i&clientgroup=%s&url=%u
}
}

Примечание : не включайте перевод строки в строке, задаваемой параметром redirect.

Эти ACL будут отвергать доступ к любым url, перечисленным в базах данных. Другие базы данных также доступны (их список находится в конфигурационном файле перед секцией acl), Вы можете выбрать любую. Обратите особое внимание на на инструкцию redirect, осуществляющую перенаправление на CGI. В момент попытки перехода на запрещенный url пользователь будет перенаправлен на этот адрес. Пример squidGuard.cgi доступен для загрузки. Поместите его на веб-сервер и измените опцию redirect так, чтобы вместо "YOUR_WEBSERVER" находилось имя вашего сервера.

Вы также должны сконфигурировать squid для использования squidGuard директивой redirect_program в usr/local/etc/squid/squid.conf. Откройте этот файл и найдите строку
# TAG: redirect_program.

Под ней напишите команду :
redirect_program /usr/local/bin/squidGuard
Конфигурация pf и altq.

Теперь - самое время собрать сконфигурированные программы воедино посредством конфигурации пакетного фильтра и шейпера пропускной способности. По умолчанию FreeBSD хранит конфигурационный файл pf в /etc/pf.conf. Файл с примером конфигурации хорошо документирован. Для начала рассмотрим пример фильтрации с преобразованием сетевых адресов (NAT). Этот пример предполагает интернет-соединение с доступной полосой в 3 Мбит/с (входящая) и 512 Кбит/с (исходящая):
ext_if = "fxp0"
external_addr = "1.2.3.4"
int_if = "fxp1"
internal_net = "192.168.0.0/24"
proxy_server = "192.168.0.10"

altq on $ext_if bandwidth 512Kb cbq queue { windows_out, trusted_out }
queue windows_out bandwidth 20%
queue trusted_out bandwidth 80%
altq on $int_if bandwidth 3Mb cbq queue { windows_in, trusted_in }
queue windows_in bandwidth 20%
queue trusted_in bandwidth 80%

rdr on $int_if inet proto tcp from $internal_net os "Windows" to any
port www -> $proxy_server port 3128
nat on $ext_if from $internal_net to any -> ($ext_if)

pass out quick on $ext_if inet proto tcp from $proxy_server
to any port www keep state queue windows_out
pass out quick on $ext_if inet proto tcp from $internal_net os "Windows"
to any keep state queue windows_out
pass out quick on $ext_if inet proto tcp from $internal_net os "unknown"
to any keep state queue windows_out
pass out on $ext_if inet proto tcp from $internal_net
to any keep state queue trusted_out
pass out quick on $int_if proto tcp from any to $proxy_server
queue windows_in
pass out on $int_if proto tcp from any to $internal_net queue trusted_in

Первые пять строк объявляют переменные, чтобы набор правил мог использовать их повторно. Переменные весьма полезны в конфигурационных файлах. Используя их корректно, Вы сможете сэкономить много времени при попытке изменить ip-адреса, сетевые интерфейсы, протоколы и все остальное. Объявив пеерменную, Вы сможете получить ее значение, используя запись вида $имя_переменной.

Шесть последующих строк, конфигурирующих altq, количественно определяют размеры полосы пропускания канала. Она контролируется на внешнем интерфейсе, где пакеты покидают маршрутизатор. Исходящие пакеты, идущие наружу, исходят из интерфейса $ext_if, так что мы устанавливаем $ext_if в 512 Кбит. Аналогично, пакеты, приходящие снаружи, исходят из интерфейса $int_f, поэтому мы устанавливаем 3 Mb. pf различает "b", "Kb", "Mb" и "Gb", что означает "бит", "килобит", "мегабит" и "гигабит" соответственно.

Затем директива altq определяет тип планировщика очередей для построения пакетов в очереди. В настоящем примере используется cbq. Планировщики определяют, в каком порядке следует обрабатывать очереди. Постановка в очередь на основе классов (class based queuing, cbq), разделяет доступную ширину канала на две или более очереди, пакет соответствует каждой из с помощью адреса источника или приемника, портом или другим идентифицирующим методом (в данном случае - операционной системой). Очереди также могут обладать приоритетом над другими. Страница "OpenBSD Packet Queuing" подробно рассматривает различные типы планировщиков.

Конец строки определяет лимит очередей.

Следующие две строки определяют собственно очереди, которые будут обрабатываться altq. Формат вполне понятен и явно определяет соответствие ширины очереди. Вы можете указать этот параметр также как процентное соотношение или же как заданный численно. Если Вы представите Ваш канал как дорогу, очередь определяет, по скольки полосам может осуществляться движение. Чем больше полос используется, тем больше данных передается. Затем конфигурация используется для определения входящей ширины пропускания.

Строка, содержащая директиву rdr - ключевая в процессе фильтрации. Она указывает, что весь TCP-трафик (proto tcp) из внутренней сети ($internet_net), исходящий от Windows-систем к другим системам на 80-й порт (os "Windows" to any port www), должен быть перенаправлен на прокси сервер, принимающий запросы на 3128-м порту (? $proxy_server port 3128).

Директива nat устанавливает трансляцию сетевых адресов, позволяющую внутренне сети взаимодействовать с сетью Internet.

Заметьте, что каждая строка набора правил pf заканчивается переменными windows_in, windows_out, trusted_in или trusted_out. Эти четыре очереди предварительно установлены как часть правил altq, что позволяет pf "знать", какие очереди следует использовать при обработке пакетов. Эти очереди полностью опциональны, удаление их из наброра правил pf не позволит altq лимитировать пропускную способность пакетами, соответствующими этим правилам.

Простейший вид правил pf выглядит следующим образом :
<pass|block> <in|out> on <interface> from <src> to <dst>
[keep state] [queue <queue_name>]

Также Вы можете указать номера портов и протоколов.

Этот набор правил включает специальное правило для фильтрации трафика от неизвестной ОС. Патчи для ОС и tcp/ip-стека могут изменить "отпечатки" (fingerprints) пакетов. Фильтрация всего нераспознанного трафика с использованием очередей для Windows-машин позволит избежать проблем в будущем.

Последние две строчки контролируют входящий трафик. Так как невоможно определить, является ли Windows-машина хостом-получателем, pf не может фильтровать входящий трафик, основываясь на информации об операционной системе, не использующей прокси. На практике, это не является серьезной проблемой, так как весь web-трафик проходит через прокси-сервер с ограниченным каналом. Если на Windows-системе будет произведена попытка запуска приложения, использующего прямое соединение "точка-точка" (peer-to-peer), такого как BitTorrent, трафик такого типа не будет пропущен через прокси. В этом случае ограничьте такой трафик с помощью очереди, указывая номера портов :
bittorrent_ports = "6881:6999"
pass out quick on $int_if proto { tcp, udp } from any to any
port $bittorrent_ports queue windows_in

http://wiki.bsdportal.ru/doc:pf1
Обновлено: 12.03.2015