среда, 29 августа 2007 г.

Спор отцов: pf vs. iptables

На новой работе активно применяют BSD-решения, так что воленс, как говорится, ноленс, но пришлось заглянуть в стан врага - в логово pf. В результате неспешного поиска нарыл эссе камрада Rusty Russell'a, папку от iptables. С радостным повизгиванием и мыслями о том, что старый линуксоид врать не будет, принялся за вдумчивое изучение.

На lwn.net было опубликованно мое эссе, где я высказывал мысли о пакетном фильтре и объединенной системе управления потоками. И к этому эссе есть комментарий, где говорится "хорошо, если бы линукс как можно скорее перешел бы на использование pf из Open BSD". Комментарий заставил меня внести в TODO пункт "узнать больше о pf", который провисел там пару лет.

Теперь, по сравнению с мнением, которое я имел о pf раньше, я стал относится к нему значительно теплее. У него есть ряд минусов, но многие вещи сделаны просто красиво.Поиск в Google готовых результатов сравнения iptables и pf говорит, что есть много BSD-фанатов, которые просто ненавидят iptables, совсем нет пользователей iptables, ненавидящих pf , и, в целом, очень мало тех, кто действительно пользовался и знает и iptables, и pf.

Я всегда думал, что в iptables - он словно ассемблер среди пакетных фильтров (хотя не CISC RISC). Я всегда писал свои фильры так, как пишут shell-скрипты - с поддержкой переменных ( "макросов" в контексте pf ), расширений и т.д. Pf же идет по совсем другому пути, используя домен-специфичный язык высокого уровня, и это находит отражение в предлагаемых pf функциях и возможностях. Вот ряд примеров, которые демонстрируют принцип работы pf: "scrub" делает различные чистки/сбросы пакетов, подготавливая их к нормализации и дефрагментации - одной командой, а использованный в правиле "keep state" означает, что ответный и все следующие пакеты пройдут фильтрацию и будут приняты. В pf присутсвуют и возможности syn proxy, и выбор различных таймстампов, и ряд других возможностей, отсутствующих в iptables. Pf обрабатывает FTP через прокси, и это редкий случай, когда метод pf менее удобен, чем "modprobe ip_nat_ftp" в iptables.

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

Есть одно место, где pf заставляет пользователей iptables просто позеленеть от зависти - это управление загрузкой канала и квотирование. Нет, в pf тоже не все так просто, но он снабжен внятным единым синтаксисом правил. Я могу попытаться запомнить, как и что делать без особых усилий, вместо того, что б в очередной раз изучать Advanced Routing HOWTO, как это всегда происходит с iptables. (Кстати, я по-прежнему жду хороший инструмент с использованием графического интерфейса. Разработка такого инструмента была бы достойным делом, потому, что я представляю ограничение пропускной способности канала скорее визуально)

И, наконец, ряд советов для тех, кто переходит от одного решения к другому - это будет не простой переход. Я (к примеру) перевел ряд готовых решений использования, расположенных в конце FAQ'a по pf, а затем переписал их так, как Вы бы это сделали используя iptables. С NAT все довольно ясно (хотя известно, что iptables всегда осуществляет фильтрацию на "реальных" адресах, то есть. после DNAT /rdr, до SNAT/nat). Для фильтрации в iptables надо рассмотреть три отдельные цепочки: INPUT (пакеты, адресованные бранмауэру), FORWARD (проходящие через бранмауэр) и OUTPUT (пакеты, сгенерированные бранмауэром). Рассмотрим следующее правило pf :

pass in on $ext_if inet proto tcp from any to ($ext_if) \
port $tcp_services flags S/SA keep state
pass in on $ext_if inet proto tcp from any to $comp3 port 80 \
flags S/SA synproxy state

В iptables это принципиально разные правила, которые вряд ли могут быть перечислены последовательно. Первое - правило цепочки INPUT, второе - цепочки FORWARD:

iptables -A INPUT -i $ext_if -p tcp --dport $tcp_services --syn -j ACCEPT
iptables -A FORWARD -i $ext_if -p tcp -d $comp3 --dport 80 --syn -j ACCEPT

Это было одним изменением, которое я сделал в ipchains - который, я чувствую, существенное усовершенствование над подходом "по IP адресу назначения" - потому что это соответствует принципиальному различию в фильтрации.

Наконец, тут вы можете найти грубый эквивалент правил iptables вот этим примерам использования pf. (Примечание : нет "чистки" , но мы делаем сборку сегментов, потому, что используем "-m state" и NAT, каждый из которых требует отслеживания статусов соединений).

Оригинал тут.

Собственно, все сказано. Однако не удивлен. Ибо с фряхой контакта не имел давно, но общая логичность запомнилась.

Откладываем в сторону комплит референс по iptables, берем тот же самый комплит по pf.

Комментариев нет: