В марте, помнится, я написал в 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 мощен, но если большинству пользователей предложить на нем что-то сделать, они скажут "
Отрицательный пример: внутренняя организация 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/321
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=bwc
===
Этот недописанный пост изначально неспешно готовился как памятка на будущее для узкого круга лиц о том, какие изменения в ipfw хотелось бы видеть и хотелось бы сделать. Однако идеей заинтересовались во FreeBSD Foundation и согласились спонсировать разработку этих идей - правда, всё никак не сделают официальный анонс (ну и я сильно подробно не публиковал пока поэтому). Организаторам RootConf 2009 предлагаемые идеи понравились тоже, посему официально сообщаю - я буду рассказывать об этом на оной конференции, проходящей в Москве 13-14 апреля сего года. На странице http://www.rootconf.ru/papers2009/1
У меня, правда, есть еще одна проблема - негде остановиться в Москве в ночь с 12 на 15 апреля :) Никто не хочет впустить? :)
April 6 2009, 07:49:49 UTC 3 years ago
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
April 6 2009, 11:14:58 UTC 3 years ago
April 6 2009, 12:37:34 UTC 3 years ago
April 6 2009, 12:46:51 UTC 3 years ago
Для 17 адресов уже однозначно таблицу
А алгоритм назначения номеров этим вновь создаваемым таблицам предложите? Чтоб учитывалось, если какие-то табдицы явно у вас уже используются.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.
удаление таблиц достаточно очевидно.
таким образом, внутренние таблицы с юзерскими пересекаться не должны никак.
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 и регистров, не хочется вводить лишнюю сущность, не адресуемую машиной (уже упоминал, что возможность машинного управления неплохо б сохранить).
В общем, мысль интересная, но замеры бы не помешали.
January 4 2010, 18:22:50 UTC 2 years ago
Re: Для 17 адресов уже однозначно таблицу
Надо ещё не забывать счётчики++.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
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 "отложить" пакет, а потом по шедулеру его "подхватить".
April 11 2009, 07:53:44 UTC 3 years ago
April 20 2009, 07:12:52 UTC 3 years ago
April 14 2009, 14:03:24 UTC 3 years ago
Пожелание - пиши больше статей.
April 20 2009, 23:20:09 UTC 3 years ago
Кстати, а вам как участнику случайно, не известно что все таки с видеозаписями, а то что то похоже нихотят выкладывать :(
May 30 2009, 11:55:05 UTC 2 years ago
http://smotri.com/video/view/?id=v98648
Вадим судя по постам вы в ЖЖ, не очень активно пишете, а где то по русски на тему FreeBSD общаетесь, или пишете, а то найти информацию такого плана как у вас в докладе весьма не просто, а иногда хочется.
June 23 2009, 17:30:21 UTC 2 years ago
Ты зацени вот что: http://gzt.ru/topnews/economics/245
http://gzt.ru/search/?author=21
January 15 2010, 15:31:24 UTC 2 years ago
January 15 2010, 15:55:12 UTC 2 years ago
November 8 2010, 12:57:40 UTC 1 year ago
November 8 2010, 13:10:31 UTC 1 year ago
January 5 2010, 16:57:47 UTC 2 years ago
January 7 2010, 13:10:00 UTC 2 years ago
January 26 2010, 12:38:04 UTC 2 years ago
Нас интересует в первую очередь, пожалуй, ipfwsync.
Кстати, если бы вы взялись за ipfwsync за денежный грант, сколько бы вы хотели по деньгам и по срокам?
February 3 2010, 22:49:45 UTC 2 years ago