UNИX, весна 2009, 02 лекция (от 04 марта)

Материал из eSyr's wiki.

Версия от 16:59, 4 марта 2009; 158.250.19.110 (Обсуждение)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Лектор пообещал, что разговор про сетевые экраны будет построен по тому же принципу, что и в прошлом семестре — подъем по стеку протоколов. Но это неправильно. Нужно иметь полный список всех инструментов, понимать, какой инструмент для какой задачи подходит. Лектор не претендует на столь актуальное знание.

В начале разговор будет идти об инструментах. Какие задачи можно решить с помощью того или иного файрволла. Когда тема иссякнет, поднимется тема шифрования. Идти снизу вверх не получится. Это довольно тяжело сделать.

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

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

Задача интерфейсного файрволла редко встречающая — неправда. Оказывается, в рамках известных систем, таких как iptables в линуксе\dots

Тема слишком большая. Файрволлы на уровне два бывают. ОС общего назначения — линукс, фрибсд. Из компьютера нужно сделать мост (bridge). Устройство объединяет несколько сетевых интерфейсов и перекладывает пакеты. Например, какая-то железяка работает с каким-нибудь adsl-трансивером. Провод, из него pppoe, Интернет. Нестандартным образом организованный \dots. Объединение интерфесов в единую СПД. Канал данных превращается в виртуальный сетевой интерфейс. Нужно объединить интерфейсы для того, чтобы ходили фреймы.

Если еще нужно выполнять функцию файрволла, то это делается на уровне 2, интерфейсном. Под задачи есть заточки. Это была преамбула.

Каким образом нам решать задачу, какие есть стратегии решения задачи управления трафиком? У нас некий общий случай. Есть входящий трафик, есть черный ящик, выполняющий какую-то операцию. Это может быть на уровне интерфейса, туннелирование, адресация, что угодно. Нужно обработать разнородные входящие потоки данных и превратить их в разнородные исходящие потоки данных.

Какие есть пути решения задачи? Самый традиционный путь состоит в следующем. Берем все трафики, превращаем в потоки пакетов, возможно, присоединяем дополнительную информацию. При этом оба понятия условны. Под данными имеются в виду не только картинки, а и все, имеющее отношение к пакетам, все, что пришло из потока данных. Идентификация — не только уникальный идентификатор, но и служебная информация. Может быть приписано, к какому TCP он приписан. Или стоит на входе машина, которая позволяет раскрашивать пакеты в разные цвета.

Складываем в единую очередь, очередь обрабатываем. На основании накопленного принимаем решения, куда как перенаправлять, выбрасывать и прочее.

Первая схема — общей цепочки. Мы знаем несколько файрволлов, которые устроены по такой схеме. Современный бсд-шный файрволл pf. Есть некий общий поток пакетов, каждый пакет помечен. Еще пример подобного рода файрволлов. Старый файрволл ipf. Будем упоминать бсд-шные файрволлы (всего три).

По тем же канонам функционировал старый линуксовый файрволл ipchains, что-то похожее было. Каковы очевидные достоинства и недостатки подобного рода организации? Начнем с достоинств. Очень мало сущностей. Набор правил, программа в стиле обработки потока. Набор правил применяется к очередному пришедшему пакету, в зависимости от правил, пакет удаляется, перенаправляется и т.д. Способ обработки потока данных абсолютно унифицируем. Самым линейным был ipfw. Идея обработки пакетов по очереди.

Второе достоинство. Среди унифицируемого набора достаточно большие возможности по модификации, преобразованию, кажется, можно сделать почти что угодно. Но это не так. Недостаточно принимать решение, что делать с трафиком. Оказывается, нужны дополнительные модули, которые будут делать разные интересные вещи, невпихиваемые в такую схему. Автомат для сохранения состояний не удастся организовать. Типичный пример — NAT. Там адреса на сетевом уровне подменяем по каким-то правилам. Когда приходит пакет, который является ответом, неважно, на каком уровне пришел ответ, по каким-то внешним данным мы определяем, что пакет является ответом и осуществляем обратную подстановку.

Где-то в стороне от линейной системы должна быть табличка, в которую модули по преобразованию закладывают информацию. Когда настанет время преобразовывать пакет, другой модуль просканирует таблицу и произведет обратную замену. Пример — лежащий на поверхности. Получается что-то вроде стекового автомата. Есть поток, отдельная память для состояний. Получается сложная структура. Это недостаток. Глядя на записанные в столбик команды, сложно понять, как они работают. Они зависят от табличек.

Может быть написанный специалистом скрипт на сотню строк, который после работы с низким уровнем создаст таблицу на тысячи записей. Может быть ситуация, когда нужно вернуться по потоку назад. Эта задача настолько трудная, что пару лет существовала ошибка, приводящая к вечному циклу, несмотря на то, что все команды формально были правильные. Был написан патч. Если пакет 6000 раз прошел через одно правило, он сбрасывался.

Мы можем сохранить линейность правил, но разбить правила на цепочки и привязать каждую цепочку к обработке той или иной жизненной ситуации. Идея iptables следующая. Рассматриваем три различных пути пакетов. Транзитный пакет. Через какой-то интерфейс зашел, через какой-то выйдет. Входящий собственный пакет. Тот пакет, который мы получили, направлен именно этому компьютеру и должен быть поднят для обработки. И исходящий пакет, который мы сгенерировали сами. Для каждого из путей нужно сделать отдельные цепочки правил.

Prerouting, Forward, Postroute. Input, Output.

В любой документации по iptables написано, что он из таблиц, а таблицы из цепочек. На самом деле все наоборот. Мы не отказались от идеи сделать цепочки правил для различных ситуаций. Внутри этого безобразия мы сохраняем идею того, что пакеты идут подряд.

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

Есть совершенно другая стратегия. Описанная ранее стратегия — линейная. Другая стратегия — обработчики на разные случаи жизни, топологическая. Например, задача сделать pppoe. Входит ethernet, а выходит раздетый пакет, пригодный для дальнейшего использования. Дальше ppp. Или есть хитрый модуль, который позволяет по любому асинхронному серийному каналу выковыривать трафик, пригодный для передачи по ppp. То, что мы получаем через модем, это не то, что мы должны отдать на выход. Четности, проверки, управляющие символы. Десяток-другой подобного рода узлов. Например, банальное разветвление. Черная дыра. После чего мы заводим нужное количество экземпляров каждого класса, задаем граф. Будут узлы, для которых входящий трафик из real life. В конце концов есть выход на тот же ethernet.

Мы получаем какой-то объект данных, неважно, какого типа, важно, откуда он пришел. Он проходит по графу, возможно, пропадает, попав в черную дыру. Обработка, преобразования, ограничения. Свободная реализация известна лектору только одна. netgraph (ng). Изначально фри-бсд. Создан проприетарно, но быстро закоммичен. Унифицированное API для узла, пользовательская утилита, позволяющая создавать узлы и соединять друг с другом.

ng устроен функционально. Передачи не происходит, путь превращается в суперпозицию функций. Чем этот подход хорош? В отличие от непонятно каких правил, есть картина следования пакетов. Чем это плохо? Эта структура довольно плохо справляется с задачей произвольной фильтраци пакетов. Нужно в качестве одного из узлов вставить описанную ранее штуку. Но свои задачи решает хорошо и эффективно.

Совмещенная стратегия. Возможно, даже разрешены циклы. Отсылки на сторону внутрь ipfw не включены. Есть возможность передачи пакета специальному модулю, который может взаимодействовать с программой из userspace. Так сделано в FreeBSD. Преобразования осуществляют сторонние приложения. Это может быть на уровне ядра, но система правил на него не распространяется.

Как с той же самой проблемой справляются линейные файрволы? Для каждого случая жизни пишется отдельный helper. Он решает одну задачу. Пример — мы хотим проковырять дырку внутрь ftp-сервера. Если идет ftp-трафик, то можно обрабатывать по-другому. Таких модулей в iptables десятка три-четыре. Мелких доклеек к iptables довольно много.

Если в том же ipfw преобладала практика оформления сторонних модулей по тем же правилам, разницы особо нет. Есть топология, граф, рассчитанный на обработку. ipf — ipfilter. Для развесистого преобразования по направлениям. Линейные модели хороши простотой.

Вопрос в том, как этими стратегиями можно воспользоваться. С одной стороны, есть подсистема стека. Видимо, для того, чтобы тот или иной файрволл заработал, все пакеты изначально должны обладать не только информацией о том, что за пакеты. Собрали бсд без поддержки файрволла. Будут бродить пакеты без фильтрации, производительность несколько возросла. Можно ли скомпилировать с поддержкой всех трех файрволов? Производительность упала. Мы можем с большей или меньшей степенью свободы подключать к жесткому процессу какие-то модули. В разные моменты между разными моментами обработки ядро может захватить управление и посмотреть, как дела.

Существует три сущности, которые должны быть реализованы в ОС, чтобы она стала межсетевым экраном. Разметка проходящих пакетов в соответствии с правилами файрвола. Отсылки в процессе обработки пакетов. Userspace-утилиты для управления. Нет такого инструмента, что была система без файрвола, нажали кнопочку, стала система с файрвола.

При изучении линукса мы быстро наткнемся на пакет ebtables.

pf. В pf три года назад не было поддержки уровня 2. Сейчас ядерные ручки есть.

В случае, когда граф две стратегии. First wins, last wins. Файрвол пропускает соединение только из одной подсети или на 80-й порт. Мы пишем пропускать из какой-то сети. Пропускать на 80-й порт отовсюду. Никого не пропускать. Правила обрабатываются по порядку. Цепочки, организованные по принципу first wins, имеют вид условие — действие. В случае, когда цепочек много, более хитрый алгоритм first wins. В iptables каждая цепочка по принципу first wins. Цепочка отрабатывает, потом идет следующая цепочка. Одно из правил (действий) — перепрыгнуть цепочку. Чем first wins хороша? В отличие от last wins, где нужно применить все правила, а их тысячи, чем быстрее встретится правило, тем быстрее отработает файрвол. Наиболее часто встречающийся трафик будет обрабатываться быстрее всего. В ситуации маршрутизации стомегабитной сетки не слишком нужно. При сложной задачи правильность расположения правил позволяет экономить ресурсы.

Можно добавить первое правило, если TCP установлено, всегда его пропускать. До этого уже пропустили пакеты установки соединения. Это сильно повышает работоспособность файрвола. По принципу first wins устроены ipf, ipfw, iptables. Исключение — pf, он строит last wins. Применяются все правила к каждому пакету. В дополнительную информацию вносятся изменения. Пакет вылез из файрвола, на нем что-то написано, это и делаем. Не строго условие — действие, может быть, оно во время пробегания пакета моргнет лампочкой.

Все наоборот. Первое правило — не пропускать. Пускать из сети, пускать на 80-й порт. Недостаток — каждый раз применяются все правила. Этот недостаток — палка о двух концах. Если мы организуем замороченый файрвол по принципу first wins, мы не будем знать, сколько он будет болтаться в файрволе. Если же мы сделали по принципу last wins, то мы позаботились, чтобы не было слишком медленно. Вместо множества правил вида если адрес, то убить, есть таблица. Поиск по линейным правилам имеет линейную сложность.

Смешанные стратегии. В first wins файрволах есть возможность вернуть пакет обратно. В файрволах last wins есть finally.

Что можно сказать еще? Где здесь учет? Свойство файрвола — предоставление данных для учета. Мы делаем модуль счетчика. В случае файрволов с цепочками возникает задача поставить специальное правило в то место, через которое пакет еще пробегает. Особенно это нелегко при цепочке, где все в столбик. В разделенной на пять частей проще. Что мы хотим? Считать входящий или исходящий трафик. Можно остановиться и сказать, что данные есть, что с ними делать — дело ваше. В last wins счетчики могут жить в конце. Вариант в бсд — сетевой интерфейс, из которого лезет только нужный трафик, а дальше с ним можно делать, что захотим.

Таблицы. Поделили трафик на разные виды. Действия должны происходить в разное время. Ограничения, изменения, учет. Группировка. Группа правил для NAT. Группа правил, выкидывающих пакеты. Не конвенциональная группировка, а строгая. Ограничение на тип. Иногда эта невозможность здесь и сейчас применить правило смущает. Поскольку люди обсуждают, необходимость обойти возникает.

Резюме. Говоря о задачах преобразования, ограничения, перенаправления трафика, мы касаемся большего, чем iptables. Сами файрволы могут быть организованы сильно по-разному. У каждого типа свои достоинства и недостатки. Файрвол как таковой включает три компонента — поддержка метаинформации о пакете, ответвеления внутри стека для работы файрвола, userspace возможности работы с файрволом.

В следующий раз будем говорить о линуксовом файрволе.


UNИX, весна 2009


Лекции

01 02 03 04 05 06 07 08 09 11


Календарь

Февраль
25
Март
04 11 18 25
Апрель
01 08 15 22
Май
06


Эта статья является конспектом лекции.

Эта статья ещё не вычитана. Пожалуйста, вычитайте её и исправьте ошибки, если они есть.
Личные инструменты
Разделы