UNИX, весна 2009, 08 лекция (от 15 апреля)
Материал из eSyr's wiki.
- Диктофонная запись: http://esyr.org/lections/audio/uneex_2009_summer/uneex_09_04_01.ogg
[править] Конспект Kda
Продолжаем разговор про межсетевые экраны. Все идет к тому, что разговор про pf будет разговором про pf из OpenBSD.
[править] stateful firewall
Ситуация с stateful файрвол. Идея в следующем. Межсетевой экран с состояниями выглядит следующим образом: есть кусок, связанный с фильтрацией трафика и этот кусок хотелось бы обойти следующим путем. Раз уж мы допустили само подключение сервера к клиенту, то все остальные пакеты под разрешающее правило обычно попадают. Можно устроить файрвол таким образом, что все те ситуации, когда пакет считается принадлежащим уже рассмотренному TCP-трафику. Когда применяем правило с запоминанием состояний, образуется временное специфическое правило, сохраняется в специальной таблице. Соответствие состояний.
[править] Пример
Мы пропускаем пакет.
pass out tcp from any to $www port 80 flags S/SA keep-state
Соединения данного типа можно пропускать через файрвол, не прогоняя через таблицу правил. Вместо прогонки пакета через таблицу правил, у которой линейная сложность распознавания, тем более что last wins, обращаемся к таблице с очень быстрым доступом по хешу.
[править] Интересное новшество в pf
Есть в ICMP, в UDP, про TCP речь идет почему: в BSD 4.1 было переписывание pf в интересную лектору сторону. Теперь в pf все правила по умолчанию keep-state. Каждое правило pass, имеющее отношение к трафику прописываются. Первый недостаток: сжирать больше памяти. Каждое соединение откладывается. С другой стороны, память сейчас большая. Другой недостаток: мы возможно захотим странного. Захотим пропускать трафик через машину, а потом взять и не пропускать. В частности, была речь о фильтре. Придется подключаться к pf.
Важен первый недостаток. Людей, которые занимаются набиванием памяти межсетевых экранов, хватает. В pf есть целая глава.
[править] Бонус новшества
Главный бонус в том, что это быстрее. Воспроизводится идея разработчиков pf — файрвол всегда работает примерно в одном штатном режиме. Стратегия last wins вроде бы должна давать проигрыш, а first wins при правильной организации ускорять. Но при first wins можно написать что-то, работающее если не вечно, то долго, а тут заданное время. Функционирование будет примерно одинаковым. Если идет соединение по TCP, то по умолчанию, когда вы пишете правило типа pass, у него указываются флаги. По умолчанию сразу речь идет о таблице состояний. Количество писанины уменьшается раза в полтора. Базовую задачу решаем ничуть не мене легко, чем в первом случае. Писанины меньше, оба правила делают одно и то же. Ленивый администратор будет применять первый метод. Лектор попался на это в линуксе.
[править] Подход
pf не был разработан как межсетевой экран с подходом от инструмента. Подход от задачи. Как сделать инструмент, который решит задачи. Подход от задачи делается все более и более глубоким. Мы упрощаем вид правила, чтобы оно стало более читаемым. Умолчания увеличивают эффективность и «правильность». Усложняем поведение межсетевого экрана по структуре. Одно правило приводит к двум вещам.
Типичный более простой пример — списки и возможность разворачивания. Правило одно, а в списке произведение всех списков правила.
[править] Modulate state
Интересно, что помимо keep-state есть еще довольно забавное modulate state. Sequential number в последовательности подменяется на действительно случайный.
[править] Типы состояний
Состояния в pf могут быть трех видов — привязанные к интерфейсу, к группе и плавающие. Можно подкрутить гайки, сказать, что правило привязано к интерфейсу. Получив пакет с другого интерфейса, на временном правиле получим отрицательный результат.
[править] Флуд
Относительно флуда. Когда мы говорим о том, что у нас каждое правило создает временное правило и сохраняет состояния, вдруг найдется человек, который пошлет волны пакетов, и таблицы переполнятся. У pf есть довольно богатый раздел настроек по лимитам, пределам, счетчикам, размерам и т.д. Никто не говорит, что для любого соединения можно создавать бесконечно много временных правил. Есть пределы для соединения, конкретного правила, любого правила.
(max 200)
Больше двухсот соединений по правилу не делается. Речь не о количестве срабатываний, а о количестве откладываемых состояний.
Как иначе мы определим, что произошло то же самое? Количество соединений в секунду.
overload <badguys> drop all from <badguys>
Как только с какого-то ip превышено ограничение, он попадает в таблицу и мы можем что-то сделать. Overload — таблица провинившихся ip.
[править] Возможности
Мы можем другие таблички делать. Письма посылать. Еще одна забавная штука. Один из способов пересобирать трафик — synproxy. Последовательность всех слов может быть достаточно произвольной. Лишь бы нормально читалось. Еще одно подтверждение BSD — простота для пользователя увеличивается, сложность подложки увеличивается.
[править] Synproxy
Принимается соединение, отсылается ack. Вся процедура подключения проделывается файрволом. И только после того, как процедура подключения прошла, он на другой стороне, куда идет проксирование, проигрывает процедуру после чего начинает гонять трафик. В чем смысл такой процедуры? Если происходит Synflood, чтобы не произошло, машина с другой стороны не увидит. Мы разбираемся на файрволе, что делать с человеком. А сервер ничего и не видит.
[править] Antispoof
Есть волшебное слово
antispoof [log] for dl0
Блокировка передачи всех пакетов на ip-адрес, связанный с пакетом на другие интерфейсы. Приходит пакет с валидным адресом, но оттуда, откуда не должен приходить. Это бывает довольно часто для обхода файрволов. Блокировка пропускания пакетов через все интерфейсы не равные данному. Запрещает принимать пакеты через любой интерфейс, если отправитель задан.
block in on!fxp0 inet from 10.0.0.0/24 to any block in inet from 10.0.0.0 to any
Эта штука блокирует попытку переслать пакет с адреса 10.0.0.1 на loopback, что бывает иногда нужно.
[править] Skip
Фича, про которую стоит рассказать.
set skip on lo0
Интерфейс не участвует в файрволе. При желании можем исключить и живой интерфейс.
[править] Добавление
antispoof — для упрощения конфига, делает то же, что и два block. Когда речь идет не о том, чтобы с подозрением относиться к пакету, пришедшего с другого адреса.
В pf можно по виду пакетов выяснять, какая система находится у отправителя.
[править] Forwarding
Когда мы пропускаем пакеты, NAT или не NAT, forwarding надо включить (в sysctl). Это может работать маршрутизатором без файрвола.
[править] Nat, dnat
nat on tl0 from 192.168.1.0/24 to any -> 24.5.0.5
Nat всегда делается на интерфейсе по выходу из него. Dnat в линуксе называется по-другому. Обратите внимание, что мы явно прописали ip-адреса, что может быть проблемой. Мы можем неожиданно сменить внутренний или внешний адрес.
fxp0:network
Адреса вытащатся сами. Можно сделать
(tl0)
что работает существенно медленнее. Без скобок формируется один раз, а со скобками смотрится каждый раз. Замена статического адреса функцией, вычисляющей его. Вместо слова nat пишем слово bind.
[править] Вкусность
Предположим, есть машины, которым запрещен доступ в интернет, возможно временно. Как их обслуживать? Можно поставить фильтрующее правило. Куда ставить, если сначала nat, потом filter?
no nat tl0 from $dummy to any
pfctl -s state
rdr on tl0 proto tcp 5000:5500 from any to any port 80 -> $www port 8080
[править] Документация
В документации есть много про проброс портов, nat и прочее.
[править] Проброс порта на внутренний сервер
Мы хотим пробрасывать порт на веб-сервер, который находится внутри ЛВС. Внешние лезут на файрвол. Внутренние лезут по тому же имени. Первый вариант: используйте то же. Второе вариант: прокси, netcat. Он работает быстрее и памяти ест меньше. OpenBSD'шники поразили лектора: очень любят userspace программы. Например, ftp proxy. А http прокси еще проще: netcat. Зачем извращения с файрволом?
127.0.0.1:5000 stream tcp new id nobody /usr/bin/nc nc -w 2 102.168.1.10 79 rdr on $int_ip proto tcp from $int_net to $ext_if port 80 -> 127.0.0.1 port 5000
[править] Дополнительно
Идея насчет создателей pf, думавших о приближенности к пользователю. Подтверждается наличием раздела в документации. Макросы, списки, pf-штуки, приводящие к размножению правил, можно написать
block all
Читайте документацию. Включение и выключение оптимизации. Несколько правил, например о вложенных сетях, сворачиваются в одно. Есть пример из шести правил, которые описывают работу и сворачиваются в один
block return
[править] Опции
Непонятно, что говорить про опции. Одну группу составляют счетчики и ограничения. Сколько времени длится tcp-timeout и т.д. Другая группа — где живет conf, где файлик с fingerprint'ами и т.д. Отдельная группа — сколько в системе таблиц, якорей и т.д. Такая штука, как log-интерфейс, на него будет складываться вообще все. Не используется аппаратный интерфейс и т.д. Всевозможные настройки оптимизации поведения файрвола. Какие виды: просто оптимизация, для high-latency сетей (например, спутник). Есть conservative — настраивает так, чтобы сеть работала во что бы то ни стало, но памяти будет есть много. Можно написать свой профайл оптимизации.
[править] Пересборка трафика
pf очень любит пересобирать трафик, проходящий через него. Мы уже с этим встречались. Файрвол, вместо передачи трафика, его модифицирует и ретранслирует. pf умеет делать много интересных вещей с трафиком, который через него проходит.
scrab in all
Что такое scrab? Это пересборка проходящего трафика. Пакеты фрагментированные собираются в целые. Random id. В ip пакете есть id, который должен быть случайным, некоторые ОС делают не совсем случайным. Делает случайным. TTL. Можно изменить TTL.
С фрагментацией можно делать много разного.
reassemble, crow
Что касается пересборки? В pf есть пересборка tcp-фреймов. Много ОС, у которых по-разному написан стек. Может быть несовместимость с Windows, например. Пакет пересобирается, хотя ничего существенного не меняется.
[править] Якорь
Последнее — якорь. Про это уже было в прошлый раз. Набор правил, в которым может быть nat, dnat, redirect. На набор можно ссылаться из основного кода. Идея якорей в том, чтобы обеспечить хранилища файрвольных правил, которые мы часто модифицируем из userspace. Останавливаем, перехакиваем, запускаем. Это нехорошо. При использовании якорей работа не останавливается, пока якорь не задействован и пакет не матчится. Ссылок на якорь может быть много. Что-то вроде пользовательской цепочки. Он — отдельная структура данных.
block on$ext_if all pass out on $ext_if all
[править] Конспект eSyr
Продолжается разговор про МЭ, точнее, конкретно про pf, который разрабатывается непрерывно в openbsd и вытягивается периодически в другие bsd. Всё идёт к тому, что рассказ про pf сведётся к рассказу про pgf в openbsd, поск. вся азработка и передний край именно там. Почему лектор делает это замечание: в процессе чтения документации выяснилась забавная вещь: то направление, а которое лектор хотел указать, расск. про pf, развивается в openbsd и только появляется других bsd. ОДно из напправлений ---- stateful firewall. С точки зрения pf, экран с сост. выгл. след образом: есть большой кусок, связанный с фильтрацией нашего трафика, и этот самый кусок хотелось бы вообще обойти след. путём: мы, когда применяем некое правило к tcp-соед., мы начинаем понимать, что в рамках этого соед., если мы его допустили, то и все ост. пакеты в его рамках под это правило отлично попадают, и тем самым мы можем устроить наш фаерволлл так, что в опред. месте, там, где говорим checkstatre? все ситуации, когда пакет считается принадл. к уже пропущ. tcp-трафику, запомненное правило к нему применяется. С точки зр. pf это выгл. след. образом: для потока запоминается специфич. временное правило, которое запоминается для потока и применяется впоследствии. Пример:
pass out tcp from any to $www port 80 flags S/SA keep-state
То есть, пропускать tcp от любого к $www по 80 порту, у которого есть влаги SYN или SYN,ACK, и соед. запоминается как состояние. После чего можно соверш. смело соед. данного типа пропускать через фаерволл, не прогоняя через таблицу правил. Это важно. Если мы не исп. таблицу сост., то время проверки линейно зависит от кол. правил, тем более, что это pf, вместо этого в самом начале делается поиск по таблице.
В bsd 4.1 было сделано сильное переписывание pf в интерсном лектору направлении, в частности, теперь все правила по-умолчани kepp-state. Какой у этого недостаток: будет отжирать больше памяти. С другой стороны, память ныняе большая. Второй недостаток: возможно, вы захотите странного, и может быть захотите пропускать такой трафик, а потом брать и не пропускать. Например, если вы исп. аналог l7filter. На самом еле, из этих двух недостатков важен первый, поскольку людей, страдающих dos-ом, много. Но, тем не менее, у pf емть ряд механизмов, позв. этому противодействовать.
Какой же с этого бонус: главный бонус в том, что оно работает существенно быстрее. Второе — воспр. та же идея разраб. pf, что фаервол, вне зависимости от того, как вы его накривили, более менее ровно. Потому что это last wins и тут, хотя, казалось бы, должен быть degradation, но скорость будет константной почти всегда.
Второе: если идёт соед. по tcp, то по умолчанию, когда пишете такое правило, то раз уж оно по умолчанию keep-state, то у него по умолч. пишутся флаги S,S/A. Обр. внимание, что таким обр. количество писанины уменьш. раза в полтора, и осн. задачу мы решаем ничуть не менее легко, чем в первом случае. Кроме того, правило, оба правило делают одно и то же, то ленивый адм. будет применять первый вид, даже не смотря на то, что в bsd старше 4.1 оно медлоеннее. И это очень важная тенденция, которая просм. в pf очень отчётливо и явно, а именно: pf изн. не был разраб. как МЭ с подходом исклю от инструмента, мы видели, что его дизайн был разр. с подходом от задачи. Этот подход от задачи делается всё более глубоким: мы упрощаем внеш. вид правил, причём таким обр., чтобы умолч., которые вклчаются, увел. эффективность и правильность, и упрощаем поведение нашего фаерволла по структуре: мы вспоминаем, что для данного правила есть флаги и кипстейт, и происх. две вещи. То есть, мы упрощ. польз. инт. и услож. подложку.
Другой пример: списки: мы пишем одно длинрное, но читаемое правило, и в подложке но разворачивается в их произведение.
Ещё есть такая штука, как modulate state, она подменяет плохой seqno на случайный.
Состояния в pf могут быть трёх видов: привязанный к инт., привязанный к группе инт. и плавающий. Можно немного укрутить гайки и сказать, что правило, которое работает, работает в привязке к соотв. интерфейсу, и получив соотв. пакет с другого интерфейса, вы, тем не менее, получите результат отрицательный. Иногда это слишком злобная политика, и нам нужно иметь группу интерфейсов, и если вы хотели плевать, то есть float, но не понятно, зачем это надо.
Антифлуд. Когда мы гвоорим о том, что у нас каждое правило в openbsd теперь созд. временное правило, то мы начинаем заботиться вот чем: как бороться с ситуацией, когда придёт человек с syn flood. Что касается таблиц tcp, то там понятно: там есть счётчик, к которому говорим: первую тысячу соед. в секунду принимаем, а потом подвесить. У pf есть богатый раздел, посвящённый илмитам и счётчикам. Посему, никто не говорит, что будет созд. беск. количество временных правил, их может созд. огр. количество на праввило. Можно сказать в скобочках некоторое количество опций. Вспомнил про это лектор потому, что среди опций можно вписать след. штуку: max-per-conn 10, overload <badguys>, и в таблице сказать drop all from <badguys>. Это правило на ip.
Таблички доступны из userspace, и можно с ними делять разные вещи: письма начальству их рассылать...
Ещё одна фишка — syn proxy. Вообще, pf очень любит пересобирать проходящий через него траффик, и это --- одна из них.
Последовательность слов в правиле может быть дост. произвольной, лишь бы это нормально читалось. Это ещё одно подтверждение openbsd.
Можно в port 80 написать synproxy. Весь 3-level handshake проделывается фаерволлом, если коннектятся не с ней. как олько подкл. произошло, он проигрывает вторую процедуру подкл., посчле чего начинает гонять трафик. В чём смысл: если у нас снаружи идёт syn flood, то машина по сторону не увидит никогда. Дальше мы с флудером сами разбираемся, а сервер и не видит ничего.
Антиспуф. Можно написать antispoof [log] for dl0. Фактически, это всего два правила: первое блокирует приём всех пакетов на ip-адрес, связанный с указанных интерфейом, через другие интерфейсы. Это правило запрещает прохождение чрез другие интерфейсы трафика с ip-адресом в данную сеть, и блокирует траффик, если у него src ip с данного интерфейса. Аналогич. правила:
block in on ~fxp0 inet from 10.0.0.0/24 to any block in inet from 10.0.0.1 to any
Но тогда блокируется и ситуация, когда приходит пакет с иным ip с лупбэка, и для предотвр. этого можно написать set skip on lo0 10.0.0.1/24, и тогда lo0 вообще не будет принимать участие в фаерволле.
Ещё одна фича --- URPF, про неё расск. в прошлый раз.
Пассивное опр. ОС: лежит файл в /etc с фингерпринтами.
Packet forwarding нужно включать вне pf в sysctl.
Что касается ната: поддерживается нат 1 в 1, много в 1, много в много. Пример:
nat on tl0 from 192.168.1.0/24 to any -> 24.5.0.5
Что может предст. проблему: 24.5.0.5 может предст. проблему, поск. мы можем его сменить, 192.168.1.0/24 может предст. проблему, потому что мы его можем сменить. Для испр. этого можно сделать следующее:
nat on tl0 from fxp0:network to any -> tl0
Наконец, если эти адреса переменные, если мы ожидаем, что адрес на tl0 может меняться, то можно сказать
nat on tl0 from fxp0:network to any -> (tl0)
Мы помним, что tl0 быстрее (tl0), так как резолвинг в первом случае делаетсчя один раз, а не каждый раз, как во втором.
Когда nat один в много или много в много
binat on tl0 from fxp0:network to any -> (tl0)
покольку тут некоторые вещи могут работать по-другому.
Очередная вкусность: предположим, есть машины, которым (временно) запрещён доступ в интернет. Как их обслуживать: очевдно, пост. временное правило. Где его поставить, если сначала идёт нат, потом фильтр? Можно написать
no nat tl0 from $dummy to any
Почему придумано такое правило, если вместо него можно написать фильтруещее? Чтобы решение о натинге и ненатинге лежали рядом.
pfctl -s state
dnat:
rdr on tl0 proto tcp from any to any port 80 -> $www port 80
Можно писать диапазон портов.
Как разруливать запросы изнутри:
* split horizon * proxy: netcat, пропис. в inetd: 127.0.0.1:5000 stream tcp row all nobody /usr/bin/nc nc -w 20 192.168.1.10 80. Что делает эта команда: как только приходит соед. на 127.0.0.1:5000, то запускается nc, который редиректит трафик на 192.168.1.10:80. После чего пишется правило: rdr on $int_ip proto tcp from $int_net to $ext_if port 80 -> 127.0.0.1 port 5000
То, что создатели pf думали оп приближенности к пользователю, подтв. один пункт в документации --- shortcuts:
* Макросы * Списки * Разннобр. штуки, привод. к размножению правил
Options. Их такое количество, что лектору как-то даже непонятно, что говорить про них, поэтому он про них скажет вцелом. Одну группу опций составл. счётчики, лимиты и таймауты. Вторая группа по поводу того, где что лежит. Опции относительно таблиц. Опции, тон. к лимитам на оличество таблиц, правил, ... . Опции для логи-интерфейса. Всевозм. настр. оптимизации, напр., оптимизации поведения фаерволла (просто оптимизации, оптимиз. для медл. сетей, есть настройки, чтобы сеть работала во что бы то ни стало; можно самост. написать профайл по оптимизации и использовать его)
Лектор уже упоминал, что pf луюит пересобирать трафик. Ни с того, ни с сего, фаерволл, вместо того, чтобы траффик передавать, его накапливал и ретранслировал. Это и рекомм. делать по умолчанию. pf умеет делать довольно много интересных вещей тем же способом: например, собрать ip-пакет, а потом послать в правильном порядке. Вклю эот след. способом: scrub in all. Там есть много разных доп. параметров, про которые мы погвоорим. что аткое scrub. ... . Что можно делать: reassemble, crop.
Что касается пересборки tcp: в pf есть пересборка tcp-фреймов. Есть разные стеки, у которых разные стеки и пакеты разного качества (openbsd их понимает, а винда приходит в глубокое изумление), и pf их может пересобирать, после чего отпр. дальше, но уже в openbsd-стандарте.
Последнее, про что лектор успевате расскзаать, это якорь. Это такой набор правил, где может быть filter,nat,redirect, binat. Может быть их 4 типа, на якорь можно ссылаться из основного набора правил pf. идея якорей в том, чтобы бесп. такие хранилища фв-правил, которые вы часто модиф. из юзерспейса. Если их не исп., то для изм. правил нужно ост. фаерволл. А при исп. останавливать не надо. Кроме того, якоря можно отключать. Ссылок на якорь можно делать много. Это что-то вроде польз. цепочки в iptables. Главная фишка якоря в том, что его обновление не сказывается на работе фаерволла.