Сегодня немножко подробней про то, как работает ипфв.
Если времени не хватит, то читать эту документацию совершенно ненапряжно. FreeBSD handbook написан крайне аккуратно и понятно.
Мало того, сегодняшний рассказ -- компиляция хэндбука про ипфв и ман ипфв. Вы могли бы и сами это почитать, но вдруг человеческие слова значат больше, чем документация.
Сначала из вредности напишем полный внешний вид правила ipfw. Квадратные скобочки означают необзяательность. <#> -- номер.
[<#>][set <#>][prob <вероятность>] <действие> [log[<уровень>]] [][{tag|untag}]<#><правило>
Правило задаются подряд, нумеруются по умолчанию с шагом в сто. Как только фильтр правило выделяет, с ним делается действие. Бывают проходные и окончательные действия. На окончательном обработка останавливается, на проходном (например, счетчик) -- продолжается.
Это напоминает нам нормальные алгоритмы маркова.
Что касается множества правил -- правила располагаются в столбик, сквозная нумерация. Но, при добавлении правила можно сказать, что оно принадлежит тому или иному множеству. От 0 до 31. Последнее правило 65535 всегда принадлежит множеству 31, и чаще всего DENY ALL. Идея в том, чтобы атомарно менять фаерволл. Например, выключить множество номер два.
ipfw set enable ipfw set disable ipfw set flush ipfw set swap
Удобно, когда вы хотите в процессе работы с компьютером менять поведение фаерволла.
Очень многие свойства, которые есть сейчас, добавлены в 2004-2006 году, по примеру pf.
Еще можно правила можно перемещать из одного множества в другое командой move. Номера при этом не меняются. Фаерволл продолжает работать также, как работал (если, конечно, оба этих множеств включены/выключены).
Ещё одна волщебная штука -- вероятность срабатывание правила. Это дает очень большой простор для всякого сетевого моделирования. Например, вы хотите посмотреть, как работает ваша система, если нужные пакеты приходят по разным маршрутам. Вы можете с некоторой вероятностью перекладывать пакет в другой интерфейс для моделирования подобной ситуации.
Журнализация бывает двух видов. Может класть пакеты прямо в сислог. Сислогд слушает сокет, а туда наваливаются сообщения. Такую Журнализацию можно делать прямо по сети. Но плох он тем, что это довольно глубокое путешествие в юзерспейс, через сокеты и всякие такие штуки. Если надо журнализировать очень много, ваш сислогд либо задохнется, либо будет поедать очень много ресурсов.
Другой способ -- посылать в специальный виртуальный интерфейс, в который можно смотреть tcpdump.
ifconfig ipfwfw0 create
tag|untag -- раскрашивание пакетов. У нас есть 256 цветов, которые вы можете по одним вам ведомомым приницпам накрасить пакет и он у вас будет накрашенным. Даже не цвета, а клейкие метки. На пакет можно наклеить сколько угодно такиех меток. Потом в правилах будет встречаться фильтр tagged и вы будете проверять, помечен пакет этим цветом или нет.
Такая простота -- видимость. На самом деле все непросто. Достаточно задуматься, какого уровня это пакет. Подразумевается, что для пользователя эта вещь достаточно прозрачная.
Результат фильтрации непонятно на каком уровне происходит.
Теперь давайте поговорим о том, что может происходить с пакетом.
allow, deny, host <ответ>.
Командочка host выбрасывает пакет, а адресату отправляется сообщение ("host unreachable" или другое), и адресат на сетевом уровне получает это сообщение.
Следующее по важности действие check-state. Оно имеет отношение к опциям keep state и limit по айпишнику, порту и количество соединений.
Фильтр лимит это не фильтр, это правило действие, которое записывает в специальнуб таблицу временныз правил или состояний, правило о том, что данное действие с данным соединением одобрено, но этих соединений должно быть не более чем столько то. И правило срабатывает только до этого лимита. allow лимит такой то.
ipfw add allow tcp from any to any limit port 80 10
Более частый случай правила типа keep-state. У вас какой-то пакет проезжает через ваш фильтр, в котором написано много чего. Правило типа allow, из него генерируется временное правило, что с такого-то на такой-то вот с таким-то разрешено. И если есть правило check state, то просматривается таблица временных правил.
Эти состояния нужны для двух вещей. Первая -- когда вы хотите просто убыстрить работу файерволла. И как правило все стараются написать правила таким образом, чтобы наиболее разгрузочные правила стояли первыми, а наименее используемые -- в конце. Операция keep-state позволяет не каждый раз проверять сложную логику.
Если чек стейт отсутствует, то его роль возьмет на себя любой первое попавшееся правило, в котором есть keep-state.
В качестве примера -- как это делать.
ipfw add check-state . . . ipfw add allow tcp from <mynet> to any setup keep state . . . ipfw add deny tcp from any to any
Слово setup матчит только те пакеты, в которых есть syn, но нету ack.
Самые часто используемые фильтры from и to. Может быть айпи адрес, маска, порт.
Следующая группа правил scipto, call, return.
Это goto. Дополнительное правило -- прыгать можно только вперед.
Зачем это нужно?
Чтобы позволит разрабатывать более секционированный свод правил.
fwd <ip> [<port>]
Вы можете вообще ничего не трогая переложить это пакет в другой интерфейс таким образом, что он придет вот этому адресу и будет подменен на этот порт. При этом ип адрес адресата останется старым, подмены адресов не произойдет. Просто другой компьютер получить не предназанченный ему пакет в целости и сохранности. В документации написано, что такое нужно для тестирования.
Гораздо более популярна команда divert socket. Это еще одна соверешенно волшебная штука от создателей ипфв, которая позволяет перекладывать пакет в юзерспейс. Вы отфильтровали пакет, а дальше хотите Deep Package Inspection, которое длеается приложением в юзерспейсе.
В ранних версиях ipfw вообще не было ната.
Ещё есть действие под названием reass. Это ситуация, когда вы пересобираете прищедший ип-пакет, как будто он был порожден вашим ип-стеком.
В ядре фрибсд есть передача произвольных типизированных сообщений netgraph.
Обработчик типизированных данных в кернел спейсе, с другой стороны обработчик гибкий и программируемый вами на си.
pipe <#> -- засунуть трафик в трубу номер столько-то. Что такое труба, она же dummy net. Это виртуальный канал передачи данных, обладающий пропускной способностью, задержкой и вероятностью по их утере. Типичный пример трафик шейпинга для цели чтобы пользователю было плохо. Такая цель бывает, опять же когда надо смоделировать плохое сетевое поведение.
ipfw pipe # config bw{<#>|<устройство>} delay <#> plr <скорость утери пакетов>
размер очереди размер хэш таблицы для бакетс. Всякие маски, это все не так интересно. RED -- random early drop -- определять ситуацию, когда наш поток близок к тому, чтобы сожрать все ресурсы, и тогда начинаем случайно дропать пакеты. Кстати сказать есть более плавный механизм gentle RED.
Есть ещё burst -- объем данных, которые мы пропускаем без шейпинга если труба пуста.
Если вы хотите сформулировать хитрый профиль, то его можно описать в файле и сказать profile имя_файла.
Это, конечно, не ограничение трафика в смысле его пропускания, а создание агрессивной среды. Трубы -- очень хорошая штука, чтобы на них экспериментировать.
Тут мы плавно переходим к разделу optionsт.
Помимо фильтро from и to, есть еще in и out -- пакеты пойманные на входе и на выходе. Это очень важные поля фильтрации.
Всевозможные опции tcp.
Всевозможные поля ip.
Отдельно флаг под названием diverted -- если пакет получен из divert сокета.
Фрагментирован ли пакет.
Отдельно стоит сказать про фильтры вида layer 2/ bridged. Это означает, что пакет в фаерволл вошел на уровне езернета, а вы уже чего-нибудь с ним делаете.
netmap + ipfw на интерфейсном уровне дает чудеса (juniper).
uid, gid, номер jail.
look up filters.
Набор волшебных адресов, которые к вам приезжают в попытке ддосить вашу машину, и они к вам приезжают, и они все разные. В look-up tables можно забить эти адреса, и по ним будет искаться за логарифм, а не линейно, как если бы было много правил.
Разбор примеров будет домашним заданием.