Vadim Goncharov ([info]nuclight) wrote,

[RootConf] IPFW: несколько наборов правил и другие предполагаемые изменения

===
В марте, помнится, я написал в ipfw@ предложения по архитектурным улучшениям ipfw, как кандидат на GSoC 2008. Никто не отреагировал (многабукаф, фигли). Дальше, в конце мая в RU.UNIX.BSD разгорелся спор - народ хотел изменения "как Cisco ACLs, но лучше", однако конкретики не было, хотя со временем что-то уже вырисовалось, я поглядел на идеи для будущего из перевода рассказа о Netgraph и набросал примерный вариант, как это могло бы выглядеть. И что же? Тут же дискуссия заглохла. Стало понятно, что выносить такие вещи на публику не имеет смысла - как только доходит до дела, любители почесать языком тут же исчезают. С другой стороны, каждый раз пересказывать сначала идеи тем индивидам, которые заинтересованы и могут сделать, долго, поэтому я решил расписать это и сделать доступным на вебе, чтоб не потерялось. А может, со временем и поможет найти тех, кто заинтересован и либо сможет сделать, либо обсудить изменения планов, исходя из практических потребностей.

Пара слов во введение.

Текст не для новичков, предполагается, что есть знакомство с нетграфом на базовом уровне как пользователя, с ipfw на продвинутом уровне, а также некоторое представление о программировании и устройстве Unix внутри.

Итак, прежде всего: ipfw далеко не совершенен, его надо достаточно сильно изменить. Будем сравнивать с pf и iptables, когда потребуется.

Что вообще нужно от хорошей системы? Три вещи: расширяемость, мощность фич и удобство использования. Пользователей прежде всего привлекает третье - тот же pf, несмотря на кучу недостатков, имеет удобный синтаксис, с низким порогом вхождения. С другой стороны, ipfw и netgraph, неся в себе принципы unix way (комбинирование сложной системы из простых строительных блоков, каждая из которых хорошо выполняет свою узкую задачу), в принципе позволяют сделать очень много. Только для этого придется затратить много времени на изучение и конфигурирование. Почему так происходит? Потому что pf ориентирован на человека, простого пользователя, а ipfw/netgraph - в большей степени на машину, на как просто мышление программиста, так и возможность управления автоматически из другой программы. Отсюда, например, проистекает использование в ipfw номеров, а в pf - имен, везде где только можно.

Что лучше, первое или второе? А ни то, ни другое. Лучше и то, и другое сразу. Хорошая система должна предоставлять как удобство для новичка (простые вещи - понятны и просты же), так и оставлять возможность для профессионала залезть в потроха и сделать руками то, что он хочет, а обычный интерфейс не позволяет, и при этом не мешать ему в этом - если система навязывает единый стиль действий "как для новичка", она будет мешать.

Положительный пример: netgraph мощен, но если большинству пользователей предложить на нем что-то сделать, они скажут "ой, он же сложный, ужос-ужос, не хочу и не буду лезть у меня нет времени учить еще одну технологию" (стандартная отмазка, на самом деле они просто не хотят напрягать мозг ;)). Однако был написан mpd, который работает на нетграфе, сам его конфигурирует, а пользователю предоставляет достаточно простой и удобный интерфейс. И mpd пользуется популярностью.

Отрицательный пример: внутренняя организация pf. Это "вещь в себе", замкнутая система, совершенно не рассчитанная на внешнее вмешательство. Один из примеров. Там можно навешивать на пакет теги по именам. Удобно? Удобно. Вот только внутри эти имена компилируются в номера, которые, естественно, непредсказуемы заранее (поправили конфиг и все сдвинулось). Пользователю об этом знать незачем, правда? А вот попытка "скрестить" pf с чем-нибудь снаружи окончится неудачей, потому что внешняя сущность не имеет доступа к этим самым номерам. Поэтому, когда мы делали теги в ipfw, мы сделали их несовместимыми с pf, номерами. Номер навешивается пользователем и неизменен (понижение удобства незначительно, всегда можно назначить номер в переменной shell-скрипта), это позволяет повесить его и в нетграфе и использовать все возможности последнего, что и было применено для фильтрации по содержимому пакета с помощью ng_tag(4).

Вывод: pf лечить нет смысла, он портируется из OpenBSD, и это лишняя головная боль портерам, которой у них и так хватает. А вот к родному ipfw можно и нужно приделать удобные пользователю shortcuts для типичных операций, при этом не отменяя внутренней расширяемости, позволяющей знающему залезть в потроха и сделать что-то непредусмотренное стандартными шаблонами.

Чего нам не хватает.

Как очевидно из вышесказанного, удобства для простого пользователя нам прежде всего не хватает. Но, как это ни парадоксально, фич и расширяемости - тоже. Несмотря на то, что можно написать моудль нетграфа для нужной задачи, с ipfw он будет интегрирован довольно слабо. Например, с той же фильтрацией по содержимому пакета - вот поймали мы байты, а дальше что? Этот пакет никак не связан со всеми остальными в том же соединении. А нам, допустим, надо его засунуть в трубу (зашейпить). И как? И всё, труба (пардон за каламбур). Да, можно на этот пакет создать динамическое правило, тогда все последующие начнут лететь в трубу. Но вот механизм динамических правил в ipfw таков, что соединение-то перехватывается в середине, не с первоначального SYN - а значит, думают динамические правила, это какой-то неправильный пакет, нет такого соединения. Его щас с той стороны по RST отфутболят. Поэтому мы правило-то создадим, для этого самого RST, но на 1 секунду (настраивается в sysctl). В результате, если соединение быстрое, пакеты летают чаще раза в секунду, правило будет сохраняться. Как только задержка - всё, нету шейпинга уже...

И это еще ладно, хоть как-то работать будет. Мы, может, хотим в нетграф на детектирование отправлять только первые N пакетов/килобайт соединения (чтоб процессор зря не грузить). А никак.

=== todo
http://vitus-wagner.livejournal.com/321586.html
pf: block in on $my_ext proto tcp from any !$allowed to any port 80 - ошибка в синтаксисе, неправильно !$allowed
надо понимать что перечисления в pf это всего лишь упрощения для записи правил в конфигах, но при загрузке они разворачиваются в несколько правил. Поэтому практически всегда перечисление с отрицанием даст тебе совершенно не то, что ты хотел. А вот таблица она всегда целостна, как один элемент

ngmatch-in ngmatch-out
osfp - больше одного хука
dlopen() для конфигурирующих модулей ipfw в юзерлэнде
хуки на динамических правилах (2 очереди, на смену стейта и каждый пакет) - можно сделать принудительный TTL, AUDIT, м.б. ipfwsync
сделать подробный экран для показа одного динамического правила по addr/id со всеми полями
обновление регистрами записи в таблице - время срабатывания
ipfw add 1000 fwd $natgw ip from 10.0.0.0/8 to not directly-connected
http://www.etinc.com/index.php?page=bwcompare.htm суппорт в dynrules для шейпинга через tcp window
===

Этот недописанный пост изначально неспешно готовился как памятка на будущее для узкого круга лиц о том, какие изменения в ipfw хотелось бы видеть и хотелось бы сделать. Однако идеей заинтересовались во FreeBSD Foundation и согласились спонсировать разработку этих идей - правда, всё никак не сделают официальный анонс (ну и я сильно подробно не публиковал пока поэтому). Организаторам RootConf 2009 предлагаемые идеи понравились тоже, посему официально сообщаю - я буду рассказывать об этом на оной конференции, проходящей в Москве 13-14 апреля сего года. На странице http://www.rootconf.ru/papers2009/12352.html доступны тезисы, там же, как обещают, будут позже выложены и презентация с видеозаписью доклада. Данный же пост, возможно, будет позднее дописан (или написан новый) с более подробной информацией о работе - ваши комментарии и пожелания по улучшению ipfw, впрочем, можете писать уже сейчас ;)

У меня, правда, есть еще одна проблема - негде остановиться в Москве в ночь с 12 на 15 апреля :) Никто не хочет впустить? :)
Tags: freebsd, ipfw, netgraph, админское, лытдыбр, сети

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    Your IP address will be recorded 

  • 23 comments

[info]zed_0xff

April 6 2009, 07:49:49 UTC 3 years ago

еще бы неплохо научить ipfw формировать из правил вида
allow tcp from any to 10.1.1.1, 10.1.1.2, 10.10.2.3, 10.11.12.3, ... etc
автоматом внутри себя таблички(table), ибо руками бывает лень из-за 8-10 айпишников табличку городить, а иначе получаем замедление скорости пропорционально количеству адресов. если я правильно понимаю внутренности ipfw

[info]nuclight

April 6 2009, 11:14:58 UTC 3 years ago

Тут вопрос не такой однозначный. Сложные алгоритмы, оптимизированные для больших значений, плохо работают на очень небольших, когда буквально несколько. Два-три адреса практически наверняка будут сравниваться быстрее, чем они же, но в таблице. Так что вам не зря лень. Правда, где проходит граница, как будут именно 8-10 айпишников, не знаю. Замерять надо.

[info]zed_0xff

April 6 2009, 12:37:34 UTC 3 years ago

ну для 2-3 адресов естественно неактуально, у меня вот сейчас есть и по 11 и по 17 адресов в строке

[info]nuclight

April 6 2009, 12:46:51 UTC 3 years ago

Для 17 адресов уже однозначно таблицу

А алгоритм назначения номеров этим вновь создаваемым таблицам предложите? Чтоб учитывалось, если какие-то табдицы явно у вас уже используются.

[info]zed_0xff

April 6 2009, 14:14:27 UTC 3 years ago

Re: Для 17 адресов уже однозначно таблицу

эти таблицы должны быть "внутренними", и соответственно не иметь визуально для юзера никакого интерфейса.
при добавлении нового правила(или изменении существующего) с несколькими адресами:
( Nip - это количество адресов в src или dst поле правила, Nt - это некоторый threshold, количество адресов в праивиле, ДО которого правило будет добавляться старым способом, а если больше - то с автосозданием внутренней таблицы. можно грабить корованы задавать это значение этого через sysctl )
1) если Nip < Nt - то создаем правило старым проверенным способом; return
2) берем все айпишники из нового (еще не добавленного) правила в некоторый массив a_ips
3) проходим по всем внутренним таблицам, ищем есть ли уже таблица содержимое которой == a_ips
4) если есть - создаем новое правило со ссылкой на нужную таблицу, увеличиваем refcount таблицы на +1
5) если нет - создаем таблицу с refcount=1, создаем правило с ссылкой на нее.

создание новых правил будет немного медленнее конечно, но я не думаю что это будет сильно заметно. к тому же можно сделать сей алгоритм отключаемым, если например тот же параметр в sysctl = 0.

удаление таблиц достаточно очевидно.

таким образом, внутренние таблицы с юзерскими пересекаться не должны никак.

[info]nuclight

April 6 2009, 15:28:46 UTC 3 years ago

Re: Для 17 адресов уже однозначно таблицу

Хм, выглядит неплохо, на первый взгляд технических возражений нет, хотя надо еще подумать. Есть, впрочем, несколько туманных соображений, исходя из планов дальнейшего развития:
1) текущая максимальная длина такого списка без таблицы - 30 (из длины опкода), то есть предлагаемые изменения касаются диапазона 11-30 адресов, и вопрос, скольким людям это реально надо. Хотя, конечно, чуть менее ленивый юзер может извратиться и сделать блок { src-ip 1.2.3.4,... or src-ip 5.6.7.8,... or ... }, но тогда:
2) необходимо добавлять оптимизатор в парсер, чтобы он это мог ловить (а пока что, исходя из нагрузок, юзер может расположить их нужным в перечислении, чтобы линейный поиск самых частых срабатывал сразу же, это эффективнее и таблиц) - но оптимизатор туда и так неплохо бы добавить. Правда, другим путем - ввести вместо правил отдельный язык, и плоский набор опкодов (не поделенный на правила), пускай сразу весь оптимизирует. Здесь эта идея, кстати, пригодится для счетчиков count/log, потому что рулесет с точки зрения локов на SMP следует держать в read-only.
3) также, из (1) и планируемых изменений адресации таблиц/portset и регистров, не хочется вводить лишнюю сущность, не адресуемую машиной (уже упоминал, что возможность машинного управления неплохо б сохранить).

В общем, мысль интересная, но замеры бы не помешали.

[info]poige

January 4 2010, 18:22:50 UTC 2 years ago

Re: Для 17 адресов уже однозначно таблицу

Надо ещё не забывать счётчики++.

[info]q_zmich

April 7 2009, 07:25:12 UTC 3 years ago

next_hop

Не секрет, что иногда производительности одного FreeBSD сервер в качестве маршрутизатора не хватает. Очень любят кушать NAT, DUMMYNET и т.д., поэтому иногда хочется разделить работу на несколько серверов, а не покупать "Циска двамильёнатристатыщ".
Например: два шейпера <-> два ната <-> три bgp-роутера, и всё это обложено динамической маршрутизацией.

Если соединять такие каскады "интерфейс в интерфейс" - то проблем с описанием не возникает. Однако, если на одном интерфейсе сидят несколько BGP-руотеров, то тут уже условиями via interface не обойдешься.

Понимаю, что задача несколько "частная", однако хотелось бы иметь условия вроде next-hop ip/prefix для исходящих пакетов: ipfw add 500 allow ip from any to any out next-hop 1.2.3.4. Реализация - наверное, принудительное привешивание тега, используемого в инструкции fwd на любой пакет, проходящий через роутинг в ip_output. Влияет на производительность, поэтому стоит сделать как опцию при компиляции.

Может быть имет смысл позволять делать лукапы в таблицы роутинга из правил ipfw. Например,
ipfw add 500 allow ip from any to any route dst next-hop 1.2.3.4
ipfw add 700 deny ip from any to any route src iface em0


[info]q_zmich

April 7 2009, 17:46:41 UTC 3 years ago

QoS dummynet

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

Хотелось бы совместить одно с другим, реализовав CIR/PIR (а возможно и прочие IRы)
Например:

Есть канал/пайпа 100 мегабит.
А его нарезаю на пайпы (mask dst-ip) по 1 мегабиту CIR и 2 мегабита PIR.
При этом на dummynet работает не один шедулер, а два последовательно: первый шедулер обрабатывает как обычно, выдирая из "личных" пайпов необходимое количество пакетов для реализации нижнего предела - 1 мегабит. Как только доработал первый шедулер - в дело включается второй, и если суммарная толщина канала (100 мегабит) еще не израсходована первым шедулером - по алгоритму wf2q выдирает из "личных" пайпов следующие пакеты.

Как вариант - реализовать это в виде модуля netgraph... я бы сделал, да что-то не пойму, как внутри вызова netgraph "отложить" пакет, а потом по шедулеру его "подхватить".

[info]terrakots

April 11 2009, 07:53:44 UTC 3 years ago

Там пару писем в личке, относительно Москвы. Ответь, плиз, надо, не надо, я подкорректирую планы.

[info]nuclight

April 20 2009, 07:12:52 UTC 3 years ago

C 8 числа я ехал поездами пересадками, так что ни на какие сообщения ответить не мог :) Сейчас вот вернулся обратно, буду потихоньку разгребаться...

[info]jabrusli

April 14 2009, 14:03:24 UTC 3 years ago

Слушаю твой доклад. Очень интересно.

Пожелание - пиши больше статей.

[info]f_andrey

April 20 2009, 23:20:09 UTC 3 years ago

Очень интересная презентация, и идеи, буду следить за развитием проекта.
Кстати, а вам как участнику случайно, не известно что все таки с видеозаписями, а то что то похоже нихотят выкладывать :(

[info]f_andrey

May 30 2009, 11:55:05 UTC 2 years ago

Кстати наконец то выложили :)
http://smotri.com/video/view/?id=v9864889761
Вадим судя по постам вы в ЖЖ, не очень активно пишете, а где то по русски на тему FreeBSD общаетесь, или пишете, а то найти информацию такого плана как у вас в докладе весьма не просто, а иногда хочется.

[info]freeresearcher

June 23 2009, 17:30:21 UTC 2 years ago

Блин, вот что называется - давно не читать ЖЖ. Отписал бы мне почтой - вписал бы.
Ты зацени вот что: http://gzt.ru/topnews/economics/245118.html - подзаголовочек номер раз в тексте. Я на сем славном ресурсе теперь редактор и в массы уже двинута тяжелая кавалерия.

http://gzt.ru/search/?author=21

[info]nuclight

January 15 2010, 15:31:24 UTC 2 years ago

Ты лучше скажи, что у тебя с аськой, один спам летит периодически?..

[info]freeresearcher

January 15 2010, 15:55:12 UTC 2 years ago

Выруби нахуй ее, у меня этот аккаунт потерян. Остался рабочий, а так связь только через гмейл.

[info]nuclight

November 8 2010, 12:57:40 UTC 1 year ago

А как у тебя сейчас с этим, в ночь с 20 на 21?

[info]freeresearcher

November 8 2010, 13:10:31 UTC 1 year ago

отпиши почтой (freeresearcher@gmail.com), я отвечу тогда личкой сегодня вечером - у жены спрошу. Думаю что нормально.

[info]blacklion

January 5 2010, 16:57:47 UTC 2 years ago

Вдруг наткнулся. А чем дело кончилось? 8-ка вышла :)

[info]nuclight

January 7 2010, 13:10:00 UTC 2 years ago

Дело, к сожалению, ничем не кончилось. У меня с весны посыпались проблемы в личной жизни (по иронии судьбы, начиная как раз с рутконфа), так что и Foundation прекратил контракт, и я из сообщества почти выпал, фрёй всё это время не занимался. Сейчас только вот потихоньку пытаюсь вернуться к жизни... Гляжу, как luigi@ вливает в ipfw пачку своих накопившихся наработок - когда закончит, из того, что изменилось, надеюсь что-то таки сделать из запланированного...

[info]_dyr

January 26 2010, 12:38:04 UTC 2 years ago

Было бы очень, очень здорово.

Нас интересует в первую очередь, пожалуй, ipfwsync.
Кстати, если бы вы взялись за ipfwsync за денежный грант, сколько бы вы хотели по деньгам и по срокам?

[info]nuclight

February 3 2010, 22:49:45 UTC 2 years ago

Со сроками не знаю, потому что это будет делаться в свободное от основной работы время (но думаю, где-нибудь к лету). Делать я в любом случае хочу в конечном итоге такое, что войдёт в базу. Больше интересует, однако, что именно вы хотите от ipfwsync? Каковы ваши потребности? К примеру, требуется ли синхронизация libalias? Если да, то в каком виде при multiple instances?
Create an Account
Forgot your login or password?
Facebook Twitter More login options
English • Español • Deutsch • Русский…