SlideShare uma empresa Scribd logo
1 de 47
Реорганизация IPFW и
NETGRAPH: новый подход к
контролю сетевого стека
Вадим Гончаров
Томский политехнический университет
Человеко-машинные системы
• Процедурные              • Проективные
Набор функций (процедур)   На языке инструментальной
  внутри прикладной          области составляется
  области, описываемых в     проект, описывающий ее
  терминах прикладной        предполагаемое поведение,
  области. Набор решений     затем машина его
  ограничен.                 выполняет.
Процедурные системы
•   Набор слабосвязанных предписаний
•   Ограниченная осведомленность
•   Гарантированные (простые) навыки
•   Быстрота решения предусмотренной ситуации

Примеры:
   – Пульт управления телевизором
   – Мастер настройки Internet в Windows
Проективные системы
• Сложность решения задачи
• Информационная открытость: документация
• Ответственность

» Unix way:
ls -dt1 `grep -il отчет *` | head -1
История файрволов
• Сначала требовалась лишь статическая фильтрация
• Затем потребовалась динамика: отслеживание
  соединений и поддержка NAT
• Затем потребовалась возможность легкого
  расширения функционала
• Наконец, теперь требуется управляемость всем
  этим разросшимся хозяйством
Статическая фильтрация
Основа любого нынешнего файрвола. Наиболее популярный
  подход:
• набор правил (ruleset)
• каждое правило — отдельная логическая единица,
  состоящая из одного или нескольких условий и одного (или
  нескольких вспомогательных) действий, выполняемых при
  совпадении (match) условий
• правила имеют разный приоритет
Статические правила: реализация
Классический подход (ipfilter, ipfw1, pf) — фиксированная
  структура, описывающая все возможные варианты
  проверок, поле флагов описывает, какие именно проверки
  применены в данном конкретном правиле.
Недостатки:
• сложность расширения
• большой размер одного правила в байтах в ядре: у pf это
  более 600 байт (см. pfrulepl в vmstat -z), тогда как
  типичный размер cache-line процессора — 64 байта.
А в это время...
80-е — Berkley Packet Filter (BPF), виртуальная машина в ядре ОС
# tcpdump -d -s 123 src host 1.2.3.4
(000) ldh      [12]
(001) jeq      #0x800           jt 2          jf 4
(002) ld       [26]
(003) jeq      #0x1020304       jt 8          jf 9
(004) jeq      #0x806           jt 6          jf 5
(005) jeq      #0x8035          jt 6          jf 9
(006) ld       [28]
(007) jeq      #0x1020304       jt 8          jf 9
(008) ret      #123
(009) ret      #0
Ассемблер BPF
• Аккумулятор A
• Индексный регистр X
  16 слов памяти M[]
•
• Опкоды (opcode, код операции, т. е. инструкция)
  одинаковой длины (8 байт)
• DLT: Data Link Type
    – #define DLT_EN10MB 1 /* Ethernet 10Mb */
    – #define DLT_RAW    12 /* raw IP */
BSD/OS ipfw, 90-е
Базируется на расширенном BPF, в который
  компилируется из своего языка:
implicit permit;
output interface(pif0) {
srcaddr(212.22.64.128/26) {
        established {
            permit;
        }
        switch ipprotocol {
        case tcp:
            switch dstport {
            case pop3/tcp:
                permit;
Точки входа в сетевом стеке
BSD/OS ipfw   FreeBSD ipfw/pfil   Linux iptables
 pre-input        PFIL_IN         PREROUTING
   input                             INPUT
  forward                          FORWARD
pre-output*                         OUTPUT
  output*        PFIL_OUT         POSTROUTING
output и
  pre-output в
 BSD/OS ipfw:
• Всё наоборот с
  локальными
  пакетами
• В других системах
  forward → output
Linux iptables (netfilter, 2001)
• struct ipt_* (entry, match, ip, target, …)
• Переменная длина структур, в постоянных полях
  ссылки на функции конкретного модуля
• Введены средства облегчения управляемости
  (цепочки) и отслеживания соединений (conntrack)
  как неотъемлемая часть самого файрвола
FreeBSD/NetBSD: pfil(9)
      К локальным сокетам этой машины


                                ip_output()
  ip_input()


ether_demux()                 ether_output()


        Драйвера сетевых интерфейсов
FreeBSD: pfil(9)
• ipfw:
   pfil_add_hook(ipfw_check_in, NULL, PFIL_IN, pfh_inet);
   pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT, pfh_inet);
• pf:
   pfil_add_hook(pf_check_in, NULL, PFIL_IN, pfh_inet);
   pfil_add_hook(pf_check_out, NULL, PFIL_OUT, pfh_inet);
• ip_input():
   pfil_run_hooks(&inet_pfil_hook, &m, m->m_pkthdr.rcvif,
     PFIL_IN, NULL);
• pfil_list_add():
   if (flags & PFIL_IN)
           TAILQ_INSERT_HEAD(list, pfh1, pfil_link);
   else
           TAILQ_INSERT_TAIL(list, pfh1, pfil_link);
NetGraph
• Коммуникационный объектно—ориентированный
  фреймворк внутри ядра
• Граф в математике: узлы (nodes) и рёбра (edges)
• Граф в ядре: каждый узел имеет крючки (hooks),
  соединение хуков двух узлов образует ребро, вдоль
  которого передаются пакеты
• ОО-стиль: узлы управляются сообщениями (msg)
Команды в ngctl
+ mkpeer echo localhook hook1
+ name .:localhook myecho
+ show myecho:
  Name: myecho         Type: echo            ID: 00001645    Num hooks: 1
  Local hook     Peer name       Peer type    Peer ID          Peer hook
  ----------     ---------       ---------    -------          ---------
  hook1          ngctl9010       socket       00001644         localhook


                     localhook          hook1
                                                             myecho
    ngctl9010
   [ng_socket]                                              [ng_echo]
Типы узлов
• Граничные (edge nodes) — взаимодействие с
  остальной частью ядра
  – ng_ether, ng_socket, ng_ipfw, ng_iface, ...
• Внутренние — взаимодействие только с
  соседними узлами
  – ng_echo, ng_tee, ng_bpf, ng_tag, ng_pppoe, ...
ng_ether(4)
                ether_demux()

upper

          В норме хуки ноды как бы
          замкнуты между собой

lower

            Драйвер интерфейса
Обычный сокет
           int fd = socket(AF_INET);
Userland

Ядро
             Generic socket layer



             Машинерия TCP/IP
ng_socket
           int fd = socket(AF_NETGRAPH);
Userland

Ядро
                Generic socket layer



                Узел типа ng_socket
ng_ksocket
Userland

Ядро


       Generic socket layer
                              Узел типа ng_ksocket


       Машинерия TCP/IP
Пример графа
Граф из ядра легко
  можно
  визуализировать в
  пакете graphviz,
  скормив ему
  текстовый вывод
  команды ngctl dot
А вот такое
 автоматически
  создает mpd
(фрагмент для одного
интерфейса ng3 в
соединенном состоянии)
Правила ipfw2
• Расширяемость была достигнута введением
  опкодов, смоделированных наподобие BPF.
• FreeBSD следует POLA (принцип наименьшего
  удивления пользователя), поэтому интерфейс,
  основанный на правилах, требовалось сохранить
 Гибридная схема: связный список правил, каждое

  есть набор инструкций-опкодов
Опкоды
• Опкод начинается с номера, длины в 4-байтных словах
  (возможные аргументы) и флагов
• На каждое элементарное действие: O_IP_SRC,
  O_IP_SRC_MASK, O_IP_SRC_ME, O_IP_DSTPORT,
  O_RECV, O_VERREVPATH, O_LOG, O_ACCEPT,
  O_DIVERT и др.
• Парсер располагает сначала опкоды проверки условий,
  затем в конце — опкоды действия (action) правила; каждый
  опкод выставляет match в 0 или 1, при 0 исполнение
  естественным образом прекращается, не доходя до действия
Конъюнктивная нормальная форма (КНФ)
• Каждый опкод имеет флаги F_OR и F_OR
• По умолчанию правило исполняется как
  конъюнкция (AND) опкодов — первый же false
  прекращает работу данного правила
• В случае выставленного F_OR действует OR-блок
  — false переходит к следующему опкоду, true же
  пропускает опкоды до конца OR-блока
  (оптимизация выполнения)
Пример правила в КНФ
ipfw add deny { src-ip 1.2.3.4 or src-ip
  1.2.3.5 or dst-ip 5.6.7.8} { not dst-port
  80 or not dst-port 443 }
• O_IP_SRC, F_OR, 1.2.3.4
• O_IP_SRC, F_OR, 1.2.3.5
• O_IP_DST, 5.6.7.8
• O_IP_DSTPORT, F_OR|F_NOT, 80
• O_IP_DSTPORT, F_NOT, 443
• O_DENY
Динамические правила
• Коммутативная относительно
  источника/назначения хэш-функция
• O_PROBE_STATE, O_CHECK_STATE, O_LIMIT,
  O_KEEP_STATE
• Указатель на родительское правило: исполнение
  начинается с action offset и продолжается дальше
  как и в статическом варианте
Трюки делать можно, но...
• pf: одно правило с кейвордом reply-to
• ipfw:
  add   100   skipto 300 tag 1 in recv $ext_if1 keep-state
  add   200   skipto 300 tag 2 in recv $ext_if2 keep-state
  add   300   allow { recv $ext_if1 or recv $ext_if2 }
  add   400   allow in recv $int_if
  add   500   fwd $gw1 tagged 1
  add   600   fwd $gw2 tagged 2
Но лучше, чем когда нельзя
Задача: отфильтровать внутри транзитного
  PPTP GRE src-адреса нашей клиентской
  подсети
• pf: невозможно в принципе
• ipfw + netgraph позволяют это сделать, хотя и
  дорогой ценой — сложные скрипты и
  выражения для tcpdump
Выкурим кучу мануалов и начнем...
#define GRESTART IPHDRLEN(0)
/* Check that is GREv1 with seq num and proto set per RFC 2637 */
#define VALID_PPTP_GRE ((ip[GRESTART:4] & 0xff7fffff) = 0x3001880b)
/* ACK is optional 4 bytes to previous 12 */
#define GRE_DATA_START (GRESTART + ((ip[GRESTART+1] & 0x80) >> 5) + 12)
/* Actual IP subnet/Mask to find in the src IP of inner IP datagram */
#define SUBNET 0x52754000       /* 82.117.64.0 */
#define MASK    0xffffff00      /* 255.255.255.0 */
#define INNER_SRC_EQ_SUBNET(ppp_hdr_len) (ip[(GRE_DATA_START+ppp_hdr_len+12):4] & MASK =
    SUBNET)
/* Finally, expression: sort by most frequent pattern first */
proto gre and VALID_PPTP_GRE and (
        (
                (ip[GRE_DATA_START]=0x21) and INNER_SRC_EQ_SUBNET(1)
        ) or (
                (ip[GRE_DATA_START:2]=0xff03) and (ip[GRE_DATA_START+2]=0x21) and
    INNER_SRC_EQ_SUBNET(3)
        ) or (
                (ip[GRE_DATA_START:4]=0xff030021) and INNER_SRC_EQ_SUBNET(4)
        ) or (
                (ip[GRE_DATA_START:2]=0x0021) and INNER_SRC_EQ_SUBNET(2)
        )
)
Совершенно нечитаемо, правда?
$ cpp -P tcpdump-gre-addr-cpp
proto gre and ((ip[((ip[0]&0xf)<<2):4] & 0xff7fffff) = 0x3001880b) and (
 (
   (ip[(((ip[0]&0xf)<<2) + ((ip[((ip[0]&0xf)<<2)+1] & 0x80) >> 5) + 12)]=0x21) and
     (ip[((((ip[0]&0xf)<<2) + ((ip[((ip[0]&0xf)<<2)+1] & 0x80) >> 5) + 12)+1 +12):4] &
     0xffffff00 = 0x52754000)
 ) or (
   (ip[(((ip[0]&0xf)<<2) + ((ip[((ip[0]&0xf)<<2)+1] & 0x80) >> 5) + 12):2]=0xff03) and
     (ip[(((ip[0]&0xf)<<2) + ((ip[((ip[0]&0xf)<<2)+1] & 0x80) >> 5) + 12)+2]=0x21) and
     (ip[((((ip[0]&0xf)<<2) + ((ip[((ip[0]&0xf)<<2)+1] & 0x80) >> 5) + 12)+3 +12):4] &
     0xffffff00 = 0x52754000)
 ) or (
   (ip[(((ip[0]&0xf)<<2) + ((ip[((ip[0]&0xf)<<2)+1] & 0x80) >> 5) + 12):4]=0xff030021) and
     (ip[((((ip[0]&0xf)<<2) + ((ip[((ip[0]&0xf)<<2)+1] & 0x80) >> 5) + 12)+4 +12):4] &
     0xffffff00 = 0x52754000)
 ) or (
   (ip[(((ip[0]&0xf)<<2) + ((ip[((ip[0]&0xf)<<2)+1] & 0x80) >> 5) + 12):2]=0x0021) and
     (ip[((((ip[0]&0xf)<<2) + ((ip[((ip[0]&0xf)<<2)+1] & 0x80) >> 5) + 12)+2 +12):4] &
     0xffffff00 = 0x52754000)
 )
)
А теперь — в netgraph!
#!/bin/sh
PATTERN=`cpp -P tcpdump-gre-addr-cpp`
BPFPROG=`tcpdump -s 8192 -r dltraw.pcap -ddd
  $PATTERN | awk -f /tmp/bpf.awk`
...
ngctl mkpeer ipfw: bpf 190 $INHOOK
ngctl name ipfw:190 $NODENAME
ngctl msg $NODEPATH setprogram
  { thisHook=quot;$INHOOKquot; ifMatch=quot;$MATCHHOOKquot;
  ifNotMatch=quot;$NOTMATCHHOOKquot; $BPFPROG }

ipfw add 4492 netgraph 190 gre from 82.117.64.0/24
  to any iplen 60-1500
Что будем улучшать?
• Единый набор правил для всего — неудобен при большом
  количестве правил (хотя можно сгенерировать правила
  машиной)
• Надо сохранить управляемость машиной, привычный
  интерфейс (кто хочет учить netgraph?) и возможность
  знающему сотворить что-то, не укладывающееся в шаблоны
 Делаем несколько наборов правил, каждый — как узел

  netgraph, и человеческий интерфейс (кто хочет — прицепит
  узлы нестандартным образом сам)
Интерфейс?
ipfw chain mychain create [default-policy
  {allow | deny}]
ipfw chain mychain add 200 ...
ipfw chain mychain delete 300
ipfw chain mychain destroy
ipfw bind mychain to interface em0 direction
  out
ipfw pfil-order move ipfilter last
Влечет за собой другие изменения
• Меняем API/ABI — setsockopt() требует правки других
  файлов ядра при значительных изменениях типа таблиц;
  сообщения netgraph же легко расширяемы и естественным
  образом адресуются конкретному набору правил (узлу)
• Переведем на это же dummynet и введем в юзерлэнде
  модульную структуру парсера
• Динамические правила: серьезная переработка
  (единственный номер родительского правила недостаточен),
  нет интерфейса управлением соединением
Пока мы здесь, надо это перетрясти
   хорошенько и в других местах
Модули: более удобный к ним и netgraph
 интерфейс, кейворды ngcall/ngmatch, вызов
 наборов правил из других наборов правил
• ipfw ng_bpf mygreaddr create
• ipfw ng_bpf mygreaddr config `cpp -P
  tcpdump-gre-addr-cpp`
• ipfw add deny ngmatch mygreaddr
Похоже на BPF?
Возьмем еще больше от BPF!
• Введем регистры как аналог M[]: хранение
  информации о пакете, о динамическом
  соединении, tablearg будет аналогом
  аккумулятора A
• Вычисления над регистрами и данными
  пакета
И пристыкуем
• Динамические правила — собственный небольшой
  массив опкодов, использование регистров,
  вычислений
   – Хотите каждые 10 секунд медленно уменьшать
     пакетам соединения TTL, а потом обратно? Без
     проблем!
• Дополнительные обработчики соединений
• Операции над таблицами
Что еще?
• Наборы портов: add deny src-ip table(1) src-
  port portset(1) dst-port portset(tablearg) …
• API/ABI для изменения состояния
  динамических правил из netgraph и не
  только
  – отслеживание соединений
  – возможность failover в carp(4)
Более мелкие изменения
• Расширим tablearg до uint64_t, таблицы для хранения
  MAC-адресов, Ipv6
• Действия call/return внутри одного набора правил
• Операции над счетчиками и их проверка
• Быстрое сохранение/загрузка правил в бинарном виде
• Разворачивание и сворачивание типичных конструкций
  алиасами в парсере (reply-to?)
• Ваши предложения? :-)
Планы на будущее
• Можно уйти от ориентации на правила и
  сделать плоскую структуру опкодов, с
  оптимизатором в парсере
  – Позволит сделать описание конфигов на другом
    языке, по типу BSD/OS или Juniper
  – Проблемы со счетчиками, логами
  – Позволит сделать компиляцию в машинный код
    аналогично BPF JIT в 7.x
Если пофантазировать...
• Сделать ipfw узлом netgraph когда-то было
  фантастической идеей, из перечня его
  авторов
• Можно пойти дальше, перевести на netgraph
  и другие части сетевого стека, создать
  расширяемый визуальный конфигуратор
  сетевой системы в едином стиле
Идеи носятся в воздухе
Совсем недавно команда разработчиков Netfilter обнародовала
  сообщение о выпуске первой альфы нового файрвола для
  Linux, грядущего на замену iptables.
include quot;ipv4-filterquot;
chain filter output {
           ct state established,related accept
           tcp dport 22 accept
           counter drop
}
Чем оно отличается?
• Таблицы реализованы как хэши и RB-деревья
  прямо в наборе правил
   – нет возможности адресовать таблицу как
     отдельную сущность
• Требование декомпиляции ограничивает
  возможности по оптимизации
• Отсутствие обратной совместимости
• Фиксированные точки входа — не netgraph
Спасибо за внимание!

Mais conteúdo relacionado

Mais procurados

интернет контроль сервер V4
интернет контроль сервер V4интернет контроль сервер V4
интернет контроль сервер V4arealconsulting
 
196 Ch
196 Ch196 Ch
196 Chanjaan
 
Software Park Thailand Newsletter (Thai) Vol.2/2557
Software Park Thailand Newsletter (Thai) Vol.2/2557Software Park Thailand Newsletter (Thai) Vol.2/2557
Software Park Thailand Newsletter (Thai) Vol.2/2557Chanpen Thawornsak
 
คอมพิวเตอร์เบื้องต้น
คอมพิวเตอร์เบื้องต้นคอมพิวเตอร์เบื้องต้น
คอมพิวเตอร์เบื้องต้นPomPam Comsci
 
Lesson 1com
Lesson 1comLesson 1com
Lesson 1comSen Kung
 

Mais procurados (9)

интернет контроль сервер V4
интернет контроль сервер V4интернет контроль сервер V4
интернет контроль сервер V4
 
Alsfir 8
Alsfir 8Alsfir 8
Alsfir 8
 
196 Ch
196 Ch196 Ch
196 Ch
 
Software Park Thailand Newsletter (Thai) Vol.2/2557
Software Park Thailand Newsletter (Thai) Vol.2/2557Software Park Thailand Newsletter (Thai) Vol.2/2557
Software Park Thailand Newsletter (Thai) Vol.2/2557
 
4
44
4
 
Gwt.org.ua (ukr)
Gwt.org.ua (ukr)Gwt.org.ua (ukr)
Gwt.org.ua (ukr)
 
คอมพิวเตอร์เบื้องต้น
คอมพิวเตอร์เบื้องต้นคอมพิวเตอร์เบื้องต้น
คอมพิวเตอร์เบื้องต้น
 
Lesson 1com
Lesson 1comLesson 1com
Lesson 1com
 
3
33
3
 

Mais de Liudmila Li

11 Ban Net Scaler Xa
11 Ban Net Scaler Xa11 Ban Net Scaler Xa
11 Ban Net Scaler XaLiudmila Li
 
09 Ban Branch Repeater1
09 Ban Branch Repeater109 Ban Branch Repeater1
09 Ban Branch Repeater1Liudmila Li
 
07 Ibm System X And Blade Center For Citrix Forum(Ekatirenburg)
07 Ibm System X And Blade Center For Citrix Forum(Ekatirenburg)07 Ibm System X And Blade Center For Citrix Forum(Ekatirenburg)
07 Ibm System X And Blade Center For Citrix Forum(Ekatirenburg)Liudmila Li
 
04 Cvc2009 Yekaterinburg Xa5 Fp1 Sergey Kh
04 Cvc2009 Yekaterinburg Xa5 Fp1 Sergey Kh04 Cvc2009 Yekaterinburg Xa5 Fp1 Sergey Kh
04 Cvc2009 Yekaterinburg Xa5 Fp1 Sergey KhLiudmila Li
 
05 чэс описание решения V3
05  чэс описание решения V305  чэс описание решения V3
05 чэс описание решения V3Liudmila Li
 
01 Ap еKaterinburg
01 Ap еKaterinburg01 Ap еKaterinburg
01 Ap еKaterinburgLiudmila Li
 
11 Net Scaler Xa1
11 Net Scaler Xa111 Net Scaler Xa1
11 Net Scaler Xa1Liudmila Li
 
09 Branch Repeater1
09 Branch Repeater109 Branch Repeater1
09 Branch Repeater1Liudmila Li
 
06 03 Gazprombank Success Story
06 03 Gazprombank Success Story06 03 Gazprombank Success Story
06 03 Gazprombank Success StoryLiudmila Li
 
06 02 C I S Citrix Final
06 02 C I S Citrix Final06 02 C I S Citrix Final
06 02 C I S Citrix FinalLiudmila Li
 
06 01 сертифицированные продукты
06 01 сертифицированные продукты06 01 сертифицированные продукты
06 01 сертифицированные продуктыLiudmila Li
 
05 Bykov Citrix Last
05 Bykov Citrix Last05 Bykov Citrix Last
05 Bykov Citrix LastLiudmila Li
 
04 Xa5 Fp1 Sergey Kh
04 Xa5 Fp1 Sergey Kh04 Xa5 Fp1 Sergey Kh
04 Xa5 Fp1 Sergey KhLiudmila Li
 

Mais de Liudmila Li (20)

11 Ban Net Scaler Xa
11 Ban Net Scaler Xa11 Ban Net Scaler Xa
11 Ban Net Scaler Xa
 
10 Dg Xd
10 Dg Xd10 Dg Xd
10 Dg Xd
 
09 Ban Branch Repeater1
09 Ban Branch Repeater109 Ban Branch Repeater1
09 Ban Branch Repeater1
 
08 Xenserver Dg
08 Xenserver Dg08 Xenserver Dg
08 Xenserver Dg
 
07 Ibm System X And Blade Center For Citrix Forum(Ekatirenburg)
07 Ibm System X And Blade Center For Citrix Forum(Ekatirenburg)07 Ibm System X And Blade Center For Citrix Forum(Ekatirenburg)
07 Ibm System X And Blade Center For Citrix Forum(Ekatirenburg)
 
04 Cvc2009 Yekaterinburg Xa5 Fp1 Sergey Kh
04 Cvc2009 Yekaterinburg Xa5 Fp1 Sergey Kh04 Cvc2009 Yekaterinburg Xa5 Fp1 Sergey Kh
04 Cvc2009 Yekaterinburg Xa5 Fp1 Sergey Kh
 
06 [хост]
06 [хост]06 [хост]
06 [хост]
 
05 чэс описание решения V3
05  чэс описание решения V305  чэс описание решения V3
05 чэс описание решения V3
 
03 Bcc суэк
03 Bcc суэк03 Bcc суэк
03 Bcc суэк
 
01 Ap еKaterinburg
01 Ap еKaterinburg01 Ap еKaterinburg
01 Ap еKaterinburg
 
11 Net Scaler Xa1
11 Net Scaler Xa111 Net Scaler Xa1
11 Net Scaler Xa1
 
09 Branch Repeater1
09 Branch Repeater109 Branch Repeater1
09 Branch Repeater1
 
10 Xs Dg
10 Xs Dg10 Xs Dg
10 Xs Dg
 
08 Dg Xd
08 Dg Xd08 Dg Xd
08 Dg Xd
 
07 Ws08 R2 Virt
07 Ws08 R2 Virt07 Ws08 R2 Virt
07 Ws08 R2 Virt
 
06 03 Gazprombank Success Story
06 03 Gazprombank Success Story06 03 Gazprombank Success Story
06 03 Gazprombank Success Story
 
06 02 C I S Citrix Final
06 02 C I S Citrix Final06 02 C I S Citrix Final
06 02 C I S Citrix Final
 
06 01 сертифицированные продукты
06 01 сертифицированные продукты06 01 сертифицированные продукты
06 01 сертифицированные продукты
 
05 Bykov Citrix Last
05 Bykov Citrix Last05 Bykov Citrix Last
05 Bykov Citrix Last
 
04 Xa5 Fp1 Sergey Kh
04 Xa5 Fp1 Sergey Kh04 Xa5 Fp1 Sergey Kh
04 Xa5 Fp1 Sergey Kh
 

Nuclight Ipfw Rootconf2009

  • 1. Реорганизация IPFW и NETGRAPH: новый подход к контролю сетевого стека Вадим Гончаров Томский политехнический университет
  • 2. Человеко-машинные системы • Процедурные • Проективные Набор функций (процедур) На языке инструментальной внутри прикладной области составляется области, описываемых в проект, описывающий ее терминах прикладной предполагаемое поведение, области. Набор решений затем машина его ограничен. выполняет.
  • 3. Процедурные системы • Набор слабосвязанных предписаний • Ограниченная осведомленность • Гарантированные (простые) навыки • Быстрота решения предусмотренной ситуации Примеры: – Пульт управления телевизором – Мастер настройки Internet в Windows
  • 4. Проективные системы • Сложность решения задачи • Информационная открытость: документация • Ответственность » Unix way: ls -dt1 `grep -il отчет *` | head -1
  • 5. История файрволов • Сначала требовалась лишь статическая фильтрация • Затем потребовалась динамика: отслеживание соединений и поддержка NAT • Затем потребовалась возможность легкого расширения функционала • Наконец, теперь требуется управляемость всем этим разросшимся хозяйством
  • 6. Статическая фильтрация Основа любого нынешнего файрвола. Наиболее популярный подход: • набор правил (ruleset) • каждое правило — отдельная логическая единица, состоящая из одного или нескольких условий и одного (или нескольких вспомогательных) действий, выполняемых при совпадении (match) условий • правила имеют разный приоритет
  • 7. Статические правила: реализация Классический подход (ipfilter, ipfw1, pf) — фиксированная структура, описывающая все возможные варианты проверок, поле флагов описывает, какие именно проверки применены в данном конкретном правиле. Недостатки: • сложность расширения • большой размер одного правила в байтах в ядре: у pf это более 600 байт (см. pfrulepl в vmstat -z), тогда как типичный размер cache-line процессора — 64 байта.
  • 8. А в это время... 80-е — Berkley Packet Filter (BPF), виртуальная машина в ядре ОС # tcpdump -d -s 123 src host 1.2.3.4 (000) ldh [12] (001) jeq #0x800 jt 2 jf 4 (002) ld [26] (003) jeq #0x1020304 jt 8 jf 9 (004) jeq #0x806 jt 6 jf 5 (005) jeq #0x8035 jt 6 jf 9 (006) ld [28] (007) jeq #0x1020304 jt 8 jf 9 (008) ret #123 (009) ret #0
  • 9. Ассемблер BPF • Аккумулятор A • Индексный регистр X 16 слов памяти M[] • • Опкоды (opcode, код операции, т. е. инструкция) одинаковой длины (8 байт) • DLT: Data Link Type – #define DLT_EN10MB 1 /* Ethernet 10Mb */ – #define DLT_RAW 12 /* raw IP */
  • 10. BSD/OS ipfw, 90-е Базируется на расширенном BPF, в который компилируется из своего языка: implicit permit; output interface(pif0) { srcaddr(212.22.64.128/26) { established { permit; } switch ipprotocol { case tcp: switch dstport { case pop3/tcp: permit;
  • 11. Точки входа в сетевом стеке BSD/OS ipfw FreeBSD ipfw/pfil Linux iptables pre-input PFIL_IN PREROUTING input INPUT forward FORWARD pre-output* OUTPUT output* PFIL_OUT POSTROUTING
  • 12. output и pre-output в BSD/OS ipfw: • Всё наоборот с локальными пакетами • В других системах forward → output
  • 13. Linux iptables (netfilter, 2001) • struct ipt_* (entry, match, ip, target, …) • Переменная длина структур, в постоянных полях ссылки на функции конкретного модуля • Введены средства облегчения управляемости (цепочки) и отслеживания соединений (conntrack) как неотъемлемая часть самого файрвола
  • 14. FreeBSD/NetBSD: pfil(9) К локальным сокетам этой машины ip_output() ip_input() ether_demux() ether_output() Драйвера сетевых интерфейсов
  • 15. FreeBSD: pfil(9) • ipfw: pfil_add_hook(ipfw_check_in, NULL, PFIL_IN, pfh_inet); pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT, pfh_inet); • pf: pfil_add_hook(pf_check_in, NULL, PFIL_IN, pfh_inet); pfil_add_hook(pf_check_out, NULL, PFIL_OUT, pfh_inet); • ip_input(): pfil_run_hooks(&inet_pfil_hook, &m, m->m_pkthdr.rcvif, PFIL_IN, NULL); • pfil_list_add(): if (flags & PFIL_IN) TAILQ_INSERT_HEAD(list, pfh1, pfil_link); else TAILQ_INSERT_TAIL(list, pfh1, pfil_link);
  • 16. NetGraph • Коммуникационный объектно—ориентированный фреймворк внутри ядра • Граф в математике: узлы (nodes) и рёбра (edges) • Граф в ядре: каждый узел имеет крючки (hooks), соединение хуков двух узлов образует ребро, вдоль которого передаются пакеты • ОО-стиль: узлы управляются сообщениями (msg)
  • 17. Команды в ngctl + mkpeer echo localhook hook1 + name .:localhook myecho + show myecho: Name: myecho Type: echo ID: 00001645 Num hooks: 1 Local hook Peer name Peer type Peer ID Peer hook ---------- --------- --------- ------- --------- hook1 ngctl9010 socket 00001644 localhook localhook hook1 myecho ngctl9010 [ng_socket] [ng_echo]
  • 18. Типы узлов • Граничные (edge nodes) — взаимодействие с остальной частью ядра – ng_ether, ng_socket, ng_ipfw, ng_iface, ... • Внутренние — взаимодействие только с соседними узлами – ng_echo, ng_tee, ng_bpf, ng_tag, ng_pppoe, ...
  • 19. ng_ether(4) ether_demux() upper В норме хуки ноды как бы замкнуты между собой lower Драйвер интерфейса
  • 20. Обычный сокет int fd = socket(AF_INET); Userland Ядро Generic socket layer Машинерия TCP/IP
  • 21. ng_socket int fd = socket(AF_NETGRAPH); Userland Ядро Generic socket layer Узел типа ng_socket
  • 22. ng_ksocket Userland Ядро Generic socket layer Узел типа ng_ksocket Машинерия TCP/IP
  • 23. Пример графа Граф из ядра легко можно визуализировать в пакете graphviz, скормив ему текстовый вывод команды ngctl dot
  • 24. А вот такое автоматически создает mpd (фрагмент для одного интерфейса ng3 в соединенном состоянии)
  • 25. Правила ipfw2 • Расширяемость была достигнута введением опкодов, смоделированных наподобие BPF. • FreeBSD следует POLA (принцип наименьшего удивления пользователя), поэтому интерфейс, основанный на правилах, требовалось сохранить  Гибридная схема: связный список правил, каждое есть набор инструкций-опкодов
  • 26. Опкоды • Опкод начинается с номера, длины в 4-байтных словах (возможные аргументы) и флагов • На каждое элементарное действие: O_IP_SRC, O_IP_SRC_MASK, O_IP_SRC_ME, O_IP_DSTPORT, O_RECV, O_VERREVPATH, O_LOG, O_ACCEPT, O_DIVERT и др. • Парсер располагает сначала опкоды проверки условий, затем в конце — опкоды действия (action) правила; каждый опкод выставляет match в 0 или 1, при 0 исполнение естественным образом прекращается, не доходя до действия
  • 27. Конъюнктивная нормальная форма (КНФ) • Каждый опкод имеет флаги F_OR и F_OR • По умолчанию правило исполняется как конъюнкция (AND) опкодов — первый же false прекращает работу данного правила • В случае выставленного F_OR действует OR-блок — false переходит к следующему опкоду, true же пропускает опкоды до конца OR-блока (оптимизация выполнения)
  • 28. Пример правила в КНФ ipfw add deny { src-ip 1.2.3.4 or src-ip 1.2.3.5 or dst-ip 5.6.7.8} { not dst-port 80 or not dst-port 443 } • O_IP_SRC, F_OR, 1.2.3.4 • O_IP_SRC, F_OR, 1.2.3.5 • O_IP_DST, 5.6.7.8 • O_IP_DSTPORT, F_OR|F_NOT, 80 • O_IP_DSTPORT, F_NOT, 443 • O_DENY
  • 29. Динамические правила • Коммутативная относительно источника/назначения хэш-функция • O_PROBE_STATE, O_CHECK_STATE, O_LIMIT, O_KEEP_STATE • Указатель на родительское правило: исполнение начинается с action offset и продолжается дальше как и в статическом варианте
  • 30. Трюки делать можно, но... • pf: одно правило с кейвордом reply-to • ipfw: add 100 skipto 300 tag 1 in recv $ext_if1 keep-state add 200 skipto 300 tag 2 in recv $ext_if2 keep-state add 300 allow { recv $ext_if1 or recv $ext_if2 } add 400 allow in recv $int_if add 500 fwd $gw1 tagged 1 add 600 fwd $gw2 tagged 2
  • 31. Но лучше, чем когда нельзя Задача: отфильтровать внутри транзитного PPTP GRE src-адреса нашей клиентской подсети • pf: невозможно в принципе • ipfw + netgraph позволяют это сделать, хотя и дорогой ценой — сложные скрипты и выражения для tcpdump
  • 32. Выкурим кучу мануалов и начнем... #define GRESTART IPHDRLEN(0) /* Check that is GREv1 with seq num and proto set per RFC 2637 */ #define VALID_PPTP_GRE ((ip[GRESTART:4] & 0xff7fffff) = 0x3001880b) /* ACK is optional 4 bytes to previous 12 */ #define GRE_DATA_START (GRESTART + ((ip[GRESTART+1] & 0x80) >> 5) + 12) /* Actual IP subnet/Mask to find in the src IP of inner IP datagram */ #define SUBNET 0x52754000 /* 82.117.64.0 */ #define MASK 0xffffff00 /* 255.255.255.0 */ #define INNER_SRC_EQ_SUBNET(ppp_hdr_len) (ip[(GRE_DATA_START+ppp_hdr_len+12):4] & MASK = SUBNET) /* Finally, expression: sort by most frequent pattern first */ proto gre and VALID_PPTP_GRE and ( ( (ip[GRE_DATA_START]=0x21) and INNER_SRC_EQ_SUBNET(1) ) or ( (ip[GRE_DATA_START:2]=0xff03) and (ip[GRE_DATA_START+2]=0x21) and INNER_SRC_EQ_SUBNET(3) ) or ( (ip[GRE_DATA_START:4]=0xff030021) and INNER_SRC_EQ_SUBNET(4) ) or ( (ip[GRE_DATA_START:2]=0x0021) and INNER_SRC_EQ_SUBNET(2) ) )
  • 33. Совершенно нечитаемо, правда? $ cpp -P tcpdump-gre-addr-cpp proto gre and ((ip[((ip[0]&0xf)<<2):4] & 0xff7fffff) = 0x3001880b) and ( ( (ip[(((ip[0]&0xf)<<2) + ((ip[((ip[0]&0xf)<<2)+1] & 0x80) >> 5) + 12)]=0x21) and (ip[((((ip[0]&0xf)<<2) + ((ip[((ip[0]&0xf)<<2)+1] & 0x80) >> 5) + 12)+1 +12):4] & 0xffffff00 = 0x52754000) ) or ( (ip[(((ip[0]&0xf)<<2) + ((ip[((ip[0]&0xf)<<2)+1] & 0x80) >> 5) + 12):2]=0xff03) and (ip[(((ip[0]&0xf)<<2) + ((ip[((ip[0]&0xf)<<2)+1] & 0x80) >> 5) + 12)+2]=0x21) and (ip[((((ip[0]&0xf)<<2) + ((ip[((ip[0]&0xf)<<2)+1] & 0x80) >> 5) + 12)+3 +12):4] & 0xffffff00 = 0x52754000) ) or ( (ip[(((ip[0]&0xf)<<2) + ((ip[((ip[0]&0xf)<<2)+1] & 0x80) >> 5) + 12):4]=0xff030021) and (ip[((((ip[0]&0xf)<<2) + ((ip[((ip[0]&0xf)<<2)+1] & 0x80) >> 5) + 12)+4 +12):4] & 0xffffff00 = 0x52754000) ) or ( (ip[(((ip[0]&0xf)<<2) + ((ip[((ip[0]&0xf)<<2)+1] & 0x80) >> 5) + 12):2]=0x0021) and (ip[((((ip[0]&0xf)<<2) + ((ip[((ip[0]&0xf)<<2)+1] & 0x80) >> 5) + 12)+2 +12):4] & 0xffffff00 = 0x52754000) ) )
  • 34. А теперь — в netgraph! #!/bin/sh PATTERN=`cpp -P tcpdump-gre-addr-cpp` BPFPROG=`tcpdump -s 8192 -r dltraw.pcap -ddd $PATTERN | awk -f /tmp/bpf.awk` ... ngctl mkpeer ipfw: bpf 190 $INHOOK ngctl name ipfw:190 $NODENAME ngctl msg $NODEPATH setprogram { thisHook=quot;$INHOOKquot; ifMatch=quot;$MATCHHOOKquot; ifNotMatch=quot;$NOTMATCHHOOKquot; $BPFPROG } ipfw add 4492 netgraph 190 gre from 82.117.64.0/24 to any iplen 60-1500
  • 35. Что будем улучшать? • Единый набор правил для всего — неудобен при большом количестве правил (хотя можно сгенерировать правила машиной) • Надо сохранить управляемость машиной, привычный интерфейс (кто хочет учить netgraph?) и возможность знающему сотворить что-то, не укладывающееся в шаблоны  Делаем несколько наборов правил, каждый — как узел netgraph, и человеческий интерфейс (кто хочет — прицепит узлы нестандартным образом сам)
  • 36. Интерфейс? ipfw chain mychain create [default-policy {allow | deny}] ipfw chain mychain add 200 ... ipfw chain mychain delete 300 ipfw chain mychain destroy ipfw bind mychain to interface em0 direction out ipfw pfil-order move ipfilter last
  • 37. Влечет за собой другие изменения • Меняем API/ABI — setsockopt() требует правки других файлов ядра при значительных изменениях типа таблиц; сообщения netgraph же легко расширяемы и естественным образом адресуются конкретному набору правил (узлу) • Переведем на это же dummynet и введем в юзерлэнде модульную структуру парсера • Динамические правила: серьезная переработка (единственный номер родительского правила недостаточен), нет интерфейса управлением соединением
  • 38. Пока мы здесь, надо это перетрясти хорошенько и в других местах Модули: более удобный к ним и netgraph интерфейс, кейворды ngcall/ngmatch, вызов наборов правил из других наборов правил • ipfw ng_bpf mygreaddr create • ipfw ng_bpf mygreaddr config `cpp -P tcpdump-gre-addr-cpp` • ipfw add deny ngmatch mygreaddr
  • 39. Похоже на BPF? Возьмем еще больше от BPF! • Введем регистры как аналог M[]: хранение информации о пакете, о динамическом соединении, tablearg будет аналогом аккумулятора A • Вычисления над регистрами и данными пакета
  • 40. И пристыкуем • Динамические правила — собственный небольшой массив опкодов, использование регистров, вычислений – Хотите каждые 10 секунд медленно уменьшать пакетам соединения TTL, а потом обратно? Без проблем! • Дополнительные обработчики соединений • Операции над таблицами
  • 41. Что еще? • Наборы портов: add deny src-ip table(1) src- port portset(1) dst-port portset(tablearg) … • API/ABI для изменения состояния динамических правил из netgraph и не только – отслеживание соединений – возможность failover в carp(4)
  • 42. Более мелкие изменения • Расширим tablearg до uint64_t, таблицы для хранения MAC-адресов, Ipv6 • Действия call/return внутри одного набора правил • Операции над счетчиками и их проверка • Быстрое сохранение/загрузка правил в бинарном виде • Разворачивание и сворачивание типичных конструкций алиасами в парсере (reply-to?) • Ваши предложения? :-)
  • 43. Планы на будущее • Можно уйти от ориентации на правила и сделать плоскую структуру опкодов, с оптимизатором в парсере – Позволит сделать описание конфигов на другом языке, по типу BSD/OS или Juniper – Проблемы со счетчиками, логами – Позволит сделать компиляцию в машинный код аналогично BPF JIT в 7.x
  • 44. Если пофантазировать... • Сделать ipfw узлом netgraph когда-то было фантастической идеей, из перечня его авторов • Можно пойти дальше, перевести на netgraph и другие части сетевого стека, создать расширяемый визуальный конфигуратор сетевой системы в едином стиле
  • 45. Идеи носятся в воздухе Совсем недавно команда разработчиков Netfilter обнародовала сообщение о выпуске первой альфы нового файрвола для Linux, грядущего на замену iptables. include quot;ipv4-filterquot; chain filter output { ct state established,related accept tcp dport 22 accept counter drop }
  • 46. Чем оно отличается? • Таблицы реализованы как хэши и RB-деревья прямо в наборе правил – нет возможности адресовать таблицу как отдельную сущность • Требование декомпиляции ограничивает возможности по оптимизации • Отсутствие обратной совместимости • Фиксированные точки входа — не netgraph