UNИX, весна 2009, 09 лекция (от 22 апреля)
Материал из eSyr's wiki.
- Диктофонная запись: http://esyr.org/lections/audio/uneex_2009_summer/uneex_09_04_22.ogg
Фактически, третью лекцию лектор пересказывает pf howto. В книге всё понятно, и её рекомендуется читать всем, даже если не собираетесь пользоваться pf.
Поверхностность обманчива: pf устроен так, чтобы облегчить работу пользователю, и если заглянуть внутрь простого правила в pf, то на самом деле оно раскрывается в довольно сложный набор, и тенденция в том. Недавно на опеннете была информационка, что отменили scrub (пересборка пакетов). Основная задача scrub — заменить кривые пакеты на опенбсдишные. Отменили потому, что он теперь включен по умолчанию.
Это всё дует в одну и то же дудку: инструмент должен ориентироваться на пользовательские задачи, а не плясать вокруг структуры ip-трафика.
Якоря.
Что такое якорь: как было сказано в прошлый раз, это похоже на пользовательскую цепочку в iptables: это свод правил, существующих в дополнение к основному своду правил pf, и может быть оттуда вызван. Смысл состоит не только в том, чтобы уменьшить количество видимых правил в одном фрагменте кода настр. pf, хотя и это тоже: можно представить некий набор правил, предназначенных для одной цели, и логично их оформить в виде якоря. Но главное достоинство якоря в том, что правила, которые лежат в якоре, не находятся в основном своде правил фаерволла, и есть гибкий механизм эти правила менять. Якорь нужен для того, чтобы там помещать правила, которые часто меняются. Меняются в связи с состоянием системы, в связи с тем, что залогинился пользователь, в связи со злобными действиями отдельных ip. Также, как это работает с таблицами, поскольку, этот свод правил в отдельной памяти и обрабатывается отдельно, то есть надежда, что блокировки у него не будет вообще, кроме как в случае, когда его содержимое потребовалось в момент его изменения.
Относительно того, что это такое, зачем это нужно. Какие они бывают: в прошлый раз лектор говорил, что в якорь можно складывать фильтр. правила и nat/binat/redirect, что в основном чаще всего используются правила типа filter. Тут мы приходим к ещё одному забавному свойству: поскольку якорь — штука, которую можно менять по ходу, то если где-то в тексте написано anchor goodguys, то в этом месте происходит нечто среднее между подстановкой и переходом. Это не макросы, подстанавливается оно в момент выполнения. Соответственно, как только модифицируется якорь, поведение pf меняется. Как это менять из us:
pfctl -a goodguys -f <filename>
Можно в тексте конфига написать что-то типа
block on $ext_if all anchor goodguys { pass in proto tcp from 10.20.30.40 port 80 }
Якоря могут быть вложенные. Зачем это делать: чтобы не модифицировать содержимое одного подъякоря для модификации другого. Можно например взять и включить все подъякори якоря без рек. обхода:
anchor "spam/*"
Когда пишется переход на анкор, то к нему можно приделать фильтр, например:
anchor "spam/*" on $ext_if proto tcp from any to any port 25
И если в этот момент не идёт трафик, соответствующий данному фильтру, то не будет никакой потери произв.
Далее в документации следуют утверждения, когда могут быть макросы, когда нет. Поскольку макросы раскрываются compiletime, то их надо описывать там же, где и сам якорь.
Очереди.
Возвращаемся к трафик шейпингу. В след раз можно поговорить, как это делается в линуксе, но то, как это сделано pf, настолько просто, что непонятно, почему все этого боятся.
Все пакеты, которые ходят через tcp/ip стек, находятся в очереди. Просто очередь имеет самый простой алгоритм, фифо.
Делать планирование входящих пакетов глупо, поэтому в pf такой возм. нет.
Немного теории. Какие бывают планировщики:
- Самый нерекомендуемый. В pf их два, они просто соответствуют двум диссертациям, соответственно на эту темы, одна из них — priority queueing, вторая — class-based queueing. В pf class-based тоже имеет свои приоритеты, поэтому первым ползоваться необязательно. С другой стороны, первый быстрее и более правильно работающий. Приоритезация: о чём вообще речь. Есть пресловутый интерфейс, из которого вылазят пакеты. Вы организуете несколько очередей fifo, в зависимости от того, как устроен фильтр, пакет попадает в соответствующую очередь и по разным правилам отп. Приоритетная организация очередей построена очень просто: Вы указываете пропускную способность очереди целиком. ... Как это делается в настройках: Идея следу.: вы должны объявить о том
altq on fxp0 bv 2mb queue {std_out, dns_out} queue std_out priq(default) #все пакеты, будущие выходить и з интерф., будут попадать по умолч. в std_out queue dns_out priority 5 priq
Что означает более высокий приоритет? Если идёт dns-запрос, то он вылезет первым, и если другие пакет ждут своей очереди, то они ещё подождут.
Этого мало. Теперь нужно где-то написать:
... pass out on fvp0 inet prot { udp tcp } from fxp0 to any port domain keep-state queue dns_out
поск. скзаано pass, то это будет сделано на пакете, и любой днс-трафик будет попадать в очередь с более высоким приоритетом.
Почему лектор про это рассказал, но не рекомендовал пользоваться приоритетными очередями? Если вы впихнули в очередь с высоким приоритетом пост. трафик, то можете сделать всем хуже.
Как этого избежать? Достаточно просто, если не будете пользоваться приоритетными очередями, а таким способом орг. очередей, когда приоритет наводится не в рамках всего трафика, а в рамках конкурирующих потоков. То есть если бы была возможность делать дерево, то там вполне можно устроить приоритеты.
Шаманство с приор. это довльно тяжело, поэтому есть CBQ. Там изн. предпю, что траф. разд. на очереди, очереди на подочереди и так далее. Осн. способ манип: манип. проп. способностями, а не приоритетами. Пример:
altq on fxp0 cbq pw 2Mb queue {std, ssh, ftp} queue std bw 50% cbq(default) queue ssh bw 25% { ssh_loging, ssh_bulk } queue ssh_login bw 25% priority 4 cbq(ecn) queue ssh_bulk bw 75% cbq(ecn) queue ftp bf 500Kb priority 3 cbr(borrow qred) #red делается, если ecn не поддерживается
borrow — то самое, о чём говорили в начале: ftp дали гарантированную скорость передачи, и если никто больше не занимает канал, то использует свободную пропускную способность.
Таким образом, мы получаем достаточно неплохое описание очереди, осталось только написать что-нибудь типа
pass out on fxp0 from any to any port 22 queue ssh
Что лектору не нравится: непонятно, в какую из подочередей упадёт поток. У pf есть замечательное свойство: можно указать несколько очередей:
pass out on fxp0 from any to any port 22 queue (ssh_bulk, ssh_login)
Если так пишете, то будет приниматься во внимание ToS и содержимое спец. флагов TCP типа SYN, ACK. ACK и ToS "low delay" будет попадать во вторую очередь, все остальные — в первую.
Всё остальное примерно понятно. Лектор обращает внимание, что это действует для исходящего трафика.
Redirect — в зависимости от того, на какой порт пришли, перенаправить трафик.
Какие есть упражнения:
Пусть есть нат 1 в 1. Как сделать так, чтобы 10.20.30.50 была включена в 123.45.67.__, и блоы бы неплохо, смотря на трафик понимать, что за машина. В простейшем случае, хорошо бы, чтобы последние октеты совпадали. Первое решгкение — сгенерировать 254 правила. Второй сопособ — подменять адрес сети, не трогая адрес компьютера. Когда идёт распр. даресов, можно подст. волшебное слово binat on $ext_if ... from $int_nat to any bitmask
loadbalancing: чтобы это работало, нужно исп. клаузу random. Djj,ot? jyf yt jxtyь хороша, и обычно вместо неё исп. round_robin. Обр. внимание, что эта штука опис., каким обр. происх. подмена адресов.
Есть ещё один крайцне оплезный штук, пусть у вас есть внеш и внутр диапазон адресов, которые разные: 10.0.0.0/8 плохо забитый и два раза по .../24. Как сделать так, чтобы при подмене каждый раз генерился один и тот же ip, чтобы можно было понять какой, посмотрев в таблицу? Какой бонус: если внутри появлися зулиган, то по тому, какой внкш. ip, то область поиска сильно сужается. Что делал лектор: написал хэш-функцию на питоне — по маку генерировал внутр. адрес и однозн. соотв.. Обычно эта задачарешается именно так: не исп. дин. расп. адресов, а выдаёте один в один. В pf есть клауза source-hash, которая так устр., что внеш. адр. выч. из внутр. Если у вас такая ситуация, как на факе: подсеть большая, но компьютеров много, то вер. пересеч. низкая.
Немного про раск. пакетов.
Метка у пакета может быть только одна. Метки в pf текстовые, длина текста — 63 большие лат. буквы и подч. Политика разд. дост. простая — при входе можно пометить пакет, и при выходе можно это обнаружить. Ничего более мутного в pf нет. Метки нестираемые. Они исчезают после покидания кернелспейса.
С другой стороны, помея. пакетов — техн. инстр., и, возм. польз. заджача решается другим способом.
Журнализация.
Есть спец. инт. pflog, в который идёт всё, про что скзаали log, или, если сказали logall, будут идти все пакеты. На этом инт. висит logd, который форм. лог tcpdump, который можно ей посмотреть tcpdump -r.
FTP
Классич. двунапр. соед.. Через fw такие штуки не пролезают по-человечески, хотя в pf есть возм. это сделать.
Если ftp-сервер за fw, то к нему плохо попасть passive.
Есть ещё такая проблема, что внутри пиркл. протокола есть передача ip. Поэтому у ftp-клиентов обычно есть галочка, исп. или не исп. этот адрес. Для противоборства можно сделать split horizon.
Ещё один вариант — использовать специального демона.
Ешё две вещи. Абсолютно прекрасная программа authpf. Что это такое: это такой shell, тоесть польз. логинится, и ему запускается вмест шелла authpf. Он выясняет, с какого ip польз. залогинился, его uid, и в зависимости от этого подкл. анкоры и таблицы небоходимые. Делается это путём доб./уд. в таблице authpfusers, а анкор наз. authpf. Можно взять и вручную задачть анкор authpf.rules, тогда при логине этот анкор будет обн. и добавляться для данного ip в обработку. Что из этого можно сделать: много чего . Например: вы не хотите, чтбы всем и каждому давался доступ к https. Что делать: берёте authpf и пишете простую штуку в authpf-якорь: для всех ip из authpfuser разрешить 443 порт.
Как лектор этим польз.: у лектора в фф стоит такая штука, как antisocial bookmarks. Есть social bookmarks, которые позв. всасывать букмарки. Они всем хороши, кроме одного: лежат они на левом сервере, а хорошо, чтобы на своём. Такое расширение есть, как вариант, можно выкачивать по ftp, но там пароли ходят клиртекстом. Поэтому ....
Есть такая вещь, как CARP, это протокол, расш. она как common address redundancy protocol. Что это такое? Это некая технология, позв. держать неск. идентичных серверов, которые предост. одеу услугу с одинаковвыми адресами на соотв. интерфейсах. Если одна машина сдохла, то начинает работать другая, при этом сохр. все состояния. Орг. это след. обпразом: некотроые спец. штуки внутри ядра и pfsync, а появл. этого протокола возн. в связи с чем: товарищи из cisco вышли на рынок с vrrp (virtual routing redundancy protocol), предост. то же самое, только для роутеров. Проблема в том, что протокол был запатентован. После чего openbsd сказали, что ни всё время сделали, продвинули свой протокол в ietf.
Каждый выпуск openbsd сопровождается музыкой и комиксами. Обычно они довольно злобные. В этот раз у них была описана история bsd.
Содержание |
[править] Конспект Kda
Весна в разгаре, на улице еще холодно. Станет теплее, народу будет еще меньше.
[править] Тенденция
Поверхность обманчивая, об этом было раньше. Тенденция, как было в прошлый раз. Все правила во фре стали state по умолчанию. Еще одно подвтерждение. В pf отменили слово scrab (пересборка проходящих пакетов). Основная задача scrab — превратить пакеты в bsd-шные. Говорить о кривости стека bsd нельзя, потому что он используется в большинстве случаев. Теперь scrab включается автоматически, а раньше была строгая рекомендация включать.
[править] Якорь
Что такое якорь? Это похоже на пользовательскую цепочку iptables. Свод правил, существующий в дополнение к основному линейному, и может быть вызван. Можно оформить в виде якоря и ссылаться на него. Главное достоинство не в сокращении, а в том, что правила в якоре не лежат в основном своде правил, и есть достаточно гибкий механизм эти правила менять. Якорь нужен, чтобы помещать туда правила, которые часто меняются. Например, состояние системы, логин пользователя, которому нужно что-то разрешить.
[править] Нет блокировки
Есть ненулевая вероятность, что, когда мы меняем свод правил, блокировки на него не будет вообще. Только если содержимое якоря потребовалось проходящему пакету, будет блокировка.
[править] Типы
Какие они бывают? Правила фильтрующие, подмены адресов. Чаще используются фильтрующие. Еще одно забавное свойство якорей. Поскольку якорь можно менять по ходу,
anchor goodguys
Происходит что-то среднее между переключением на свод правил и вставлением его. Макросы подставляются в момент компиляции. Точно так же подставляется адрес интерфейса, если он не в скобках.
block on 8ext_if all
Как меняется userspace?
pfctl -a goodguys -f -
Можно в файле написать что-то вроде
pass in proto tcp from 10.20.30.40 port 80
[править] Вложенность
Якоря могут быть вложенными. Можем включить все подъякори из текущего якоря без рекурсивного обхода
anchor "spam/*"
Возвращаемся к сказанному Евгением.
anchor "spam/*" on $ext_if proto tcp from any to any port 25
Может случиться, что обновление не приведет к потере производительности ввиду ненужности в данный момент.
[править] pfctl
С помощью pfctl можно манипулировать якорями. Все оказалось гораздо проще, чем могло быть.
[править] Traffic shaping
Мы переходим к еще одной теме. pf — это штука для крутых перцев, если вы не высокий профессионал, он будет у вас работать, хоть это и странно. Мы возвращаемся к теме traffic shaping. Можно поговорить о том, как это делается в линуксе. В pf это поражает своей простотой. Одно непонятно, почему этого так боятся. По умолчанию алгоритм включен, просто используется fifo.
[править] Schedule (планировщик)
Какие еще есть планировщики? Можно подключить другой планировщик и он будет работать по другим правилам. Для входящих пакетов это бесполезно. Вдруг такая необходимость есть, нужно будет создать связку виртуальных интерфейсов. В pf есть только на выходе из интерфейса.
Какие бывают планировщики кроме fifo? В pf два нерекомендуемых. Они соответствуют двум диссертациям, защищенным на эту тему. DRIQ, CBQ. В pf DRIQ пользоваться необязательно. Вылезают пакеты. Организуем несколько очередей. Не одно fifo, как было раньше, а несколько вариантов. Пакет попадает в одну очередь, другую или третью и по разным правилам попадает на выход. Указываем пропускную способность (например, 2 Мбит/сек). Указываем приоритет очередь (например, 1, 2, 3 и 4). Пока есть неотосланные пакеты в очереди с более высоким приоритетом, очереди с низким приоритетом будут ждать. Очередь для тех, кто без очереди. Следующий уровень — для тех, кто без очереди в очереди тех, кто без очереди.
Команда
altq on fxp0 bw 2Mb queue {stdout, dns_out}
На интерфейсе альтернативная организация очереди. В случае приоритетной очереди не обязательно ограничивать пропускную способность. В интерфейсе вешается альтернативный планировщик.
queue std_out priq (default) queue dns_out priority 5 priq(red) pass out on fxp0 inet proto {udp tcp} from (fxp0) to any port domain keep-state queue dns_out
[править] Дерево
Поскольку приоритет — штука жесткая, могут быть проблемы. Если мы не будем пользоваться приоритетными очередями, а сделаем некое дерево, то если одна ветвь заполнится одним процессом, это не страшно, другие ветви будут работать.
alt on fxp0 cbq bw 2Mb queue {std, ssh, ftp}
У нас есть некий ftp-трафик, про который известно, что он то есть, то нету. Если есть, не нужно давать воли. Если никого больше нет, можно давать волю. Есть ssh, который нужно пускать приоритетно.
queue std bw 50% cbq(default) queue ssh bw 25% { ssh_login, ssh_bulk }
Это вторая очередь. В нее вложено две.
queue ssh_login bw 25% priority 4 cbq(ecn) queue ssh_bulk bw 75% cbq(ecn)
[править] FTP
Наконец, ftp
queue ftp bw 500Kb priority 3 cbq(borrow red)
Ситуация, когда пакеты выбрасываются из очереди до того, как канал переполнен. Если нет поддержки ecn, а есть обычное соединение. Для того, чтобы не жрало трафик, достаточно выкинуть один пакет. Принимающая сторона скажет о пропаже, скорость снизится. Если поддерживается прием сообщений о том, что канал издыхает, файрвол будет слать ecn еще до реального переполнения канала. Что касается borrow, это то, о чем говорили в начале. Если больше никто не занимает канал, дайте ему больше. Чем быстрее скачает, тем быстрее освободится.
[править] Дополнительно
Получили неплохое описание очереди. Осталось написать что-то вроде
pass out on fxp0 from any to any port 22 queue(ssh_bulk, ssh_login)
Есть замечательная фича. Есть queue, можно вписать не одну очередь, а две. Если у нас есть трафик, определяемый одним пакетом, и он делится на быстрый и медленный. Медленный — передача файлов по ssh.
Такое ощущение, что нас обманули, traffic shaping, а ничего особенного.
[править] Iptables, tc
iptables и tc сфокусированы вокруг трафика, а не пользовательских задач. Нужно иметь в голове представление о задаче и теорию и проецировать задачу.
[править] NAT
Когда есть распределение адресов, можно сделать подмену сети с оставлением адреса компьютера.
/24 bi nat on $ex_if iren from $int_net to any bitmask
Есть внешний и внутренний диапазоны адресов, они не равны. Как сделать так, чтобы при подмене последних двух октетов генерировался один адрес, чтобы по внутреннему адресу однозначно генерировался внутренний. Если внутри завелся хулиган, можно сильно сузить круг поиска. Лектор написал на питоне хэш-функцию по мак-адресу. Не используется динамическое выделение адресов.
--``-- / source-hash
pf обладает тем свойством, что легко решает пользовательские задачи при сохранении низкоуровневости. Люди много занимались файрволами. Метка у пакета может быть только одна. Метки в pf текстовые, длина текста 63 символа. Политика раздачи простая. При входе мы можем пометить пакет, а при выходе на основании метки поступить с ним правильно. Если пакет был помечен меткой, она остается.
Помечание пакетов — технический инструмент. Задача может решаться другим способом.
[править] Журнализация
Ситуация такая. У вас есть специальный интерфейс log all. Либо в правиле слово log, тогда пакет пойдет в интерфейс. logd. Он формирует лог tcpdump.
[править] FTP
Ftp — классическое двунаправленное соединение. Через файрвол не пролезают. В pf есть работа с ним. Basic Ftp — два соединения для легкого определения, что передавать мало и быстро, а что много и медленно. Пассивное соединение требует подключения к серверу по произвольному порту. Если и клиент, и сервер за файрволом, то в одном файрволе нужно выковыривать дырки. Как правило, в серверном. Внутрь протокола Ftp входит понятие адреса сервера. Ftp на прикладном уровне передает адрес, по которому нужно подсоединяться. Клиент лезет на внутренний адрес. Некоторые клиенты понимают, что бывают идиоты, например, файрфокс может подконтачиться на тот же адрес, что и основной. Другой вариант — использовать замороченные ftp-серверы. Третий вариант — ftp-proxy. На сервере запущена программа, которая подменяет все, что надо.
[править] Userspace
Две вещи.
[править] authpf
Раз уж перешли к userspace, программа authpf. Что это? Такой шелл. Пользователь логинится и запускается программа. Определение, откуда залогинился пользователь. Включается нужный анкор, после логофа отключается. Точнее, ip добавляется в таблицу и потом убирается. authpf. Когда пользователь заходит в систему, это обрабатывается.
Что можно сделать? Ну, например, не хотим чтобы всем давался доступ, и все могли попытаться захакать движок. Http доступен, а https не всем разрешить. Для всех пользоватей из таблицы разрешить доступ на 443 порт. Логинимся — есть 443 порт, разлогиниваемся — отключается. В браузере у лектора стоит расширение. Хотим, чтобы были на сервере. Anti-social bookmarks. Syncplaces. Лень заводить WebDav. По ftp закачивать и скачивать. Пароль передается открытым текстом. Пользователь bookmarks_george, пароль bookmarks_george.
Открывается ssh, логинится, синхронизируются закладки через развесистый порт, разлогиниваемся. Попыток взломать не было.
[править] Common address redundancy protocol
Технология, позволяющая держать несколько однотипных серверов, с одними адресами на интерфейсах. Есть три файрвола, абсолютно одинаковых. Работает один. Если сломается, второй тут же подхватит, даже соединения не порвутся.
Cisco Systems вышли со своим изделием, аналогичным, только для роутеров, а не файрволов. Протокол запатентован, для реализации нужно платить деньги. А BSDшники сказали, что они делали то же самое, только денег не хотят. Сайт OpenBSD, там интересный аудиофайл. В 3.5 длинный скетч про покупателя, который хочет купить лицензию.
[править] Следующий раз
В следующий раз разговор про traffic shaping отдельно.