воскресенье, 29 марта 2015 г.

Стабильность работы netmap-ipfw на Linux

Тест выполнялся почти 3е суток, нагрузка со стороны генератора флуда была около 6MPPS, рандомного udp флуда.
ps aux|grep kipfwroot     19036 72.1  0.0 676328  2728 pts/2    R    Mar26 2731:56 ./kipfw netmap:eth4-0 netmap:eth6-0root     19037 68.9  0.0 676328  2728 pts/2    R    Mar26 2610:52 ./kipfw netmap:eth4-1 netmap:eth6-1root     19038 69.7  0.0 676328  2728 pts/2    S    Mar26 2640:07 ./kipfw netmap:eth4-2 netmap:eth6-2root     19039 68.9  0.0 676328  2992 pts/2    S    Mar26 2610:41 ./kipfw netmap:eth4-3 netmap:eth6-3root     21088  0.0  0.0   7768   852 pts/1    S+   11:17   0:00 grep kipfw
Нагрузка на машине была почти предельная:
  [||||||||||||||||||||||||||||||||||||||||||         72.7%]     Tasks: 35, 55 thr, 47 kthr; 2 running  [|||||||||||||||||||||||||||||||||||||||            69.1%]     Load average: 2.15 2.60 2.69   [|||||||||||||||||||||||||||||||||||||||||          71.4%]     Uptime: 12 days, 11:33:08  [||||||||||||||||||||||||||||||||||||||||           68.2%]  Mem[|||||||                                     1332/32207MB]  Swp[                                                0/8190MB]

Но ничего не упало и паразитный трафик не прошел! :)

среда, 18 марта 2015 г.

Контроль за состоянием php-fpm силами monit на Debian

Вот так:
check process php5-fpm with pidfile /var/run/php5-fpm.pid
  start program = "/etc/init.d/php5-fpm start"
  stop program  = "/etc/init.d/php5-fpm stop"
  if failed unixsocket /var/run/php5-fpm.sock  then restart
  if 3 restarts within 5 cycles then timeout

вторник, 17 марта 2015 г.

Фильтрация трафика силами сетевой карты

Очень редко при защите от DDoS кто-либо освещает эту тему и совершенно неоправданно.

Итак, как? Начнем с того, что у Вас должна быть приличная 10GE сетевая карточка (например, Intel XL710 или же Intel 82599 - я буду проводить тесты на нем). Сразу хочу оговориться, что драйверы для сетевой карты нужно брать НЕ из дистрибутива (они очень малофункциональны), а из проекта ixgbe на Sourceforge.

Во-вторых, нужен механизм управления этим всем делом. Обычно, это делается силами ethtool.

Приступим!

Для начала нам нужно сконфигурировать сетевую и ее драйвер:
vim /etc/modprobe.d/ixgbe.conf
И добиваем к существующим там такой параметр (он нужен чтобы выделить 32 тысячи ):
FdirPballoc=3,3,3,3
После этого драйвер нужно передернуть и поднять ифейсы заново:
rmmod ixgbe
modprobe ixgbe
ifconfig 11.22.33.44. eth4
Что же мы сделали? Мы включили функциональность фильтрации сетевой. Почему именно 3?

Есть три варианта значения поля FdirPballoc и мы выбрали наибольший размер, чтобы побольше правил набить:
1 = 8k hash filters or 2k perfect filters
2 = 16k hash filters or 4k perfect filters
3 = 32k hash filters or 8k perfect filters (array of int)
Убеждаемся по dmesg, что все зацепилось:
dmesg|grep 'Flow Director'
[45847.024851] ixgbe: Flow Director packet buffer allocation set to 3
[45847.024874] ixgbe: 0000:0a:00.0: ixgbe_check_options: Flow Director will be allocated 256kB of packet buffer
Включаем поддержку ntuple фильтров на уровне сетевой:
ethtool -K eth4 ntuple on
Итак, посмотрим список наших правил - он должен быть пуст:
ethtool --show-ntuple eth4
4 RX rings available
Total 0 rules
А вот далее идет сложный синтаксис и поэтому привожу выдачу ethtool --help:
        ethtool -N|-U|--config-nfc|--config-ntuple DEVNAME    Configure Rx network flow classification options or rules
        rx-flow-hash tcp4|udp4|ah4|esp4|sctp4|tcp6|udp6|ah6|esp6|sctp6 m|v|t|s|d|f|n|r... |
        flow-type ether|ip4|tcp4|udp4|sctp4|ah4|esp4
            [ src %x:%x:%x:%x:%x:%x [m %x:%x:%x:%x:%x:%x] ]
            [ dst %x:%x:%x:%x:%x:%x [m %x:%x:%x:%x:%x:%x] ]
            [ proto %d [m %x] ]
            [ src-ip %d.%d.%d.%d [m %d.%d.%d.%d] ]
            [ dst-ip %d.%d.%d.%d [m %d.%d.%d.%d] ]
            [ tos %d [m %x] ]
            [ l4proto %d [m %x] ]
            [ src-port %d [m %x] ]
            [ dst-port %d [m %x] ]
            [ spi %d [m %x] ]
            [ vlan-etype %x [m %x] ]
            [ vlan %x [m %x] ]
            [ user-def %x [m %x] ]
            [ action %d ]
            [ loc %d]] |
        delete %d
Итак, запустим на машину DDoS атаку вот таким паттерном:
12:45:19.050037 IP 10.10.10.100.41356 > 10.10.10.200.61598: UDP, length 18
12:45:19.050045 IP 10.10.10.100.9967 > 10.10.10.200.24210: UDP, length 18
12:45:19.050052 IP 10.10.10.100.17254 > 10.10.10.200.44345: UDP, length 18
12:45:19.050061 IP 10.10.10.100.17516 > 10.10.10.200.41543: UDP, length 18
12:45:19.050069 IP 10.10.10.100.29307 > 10.10.10.200.60769: UDP, length 18
12:45:19.050078 IP 10.10.10.100.56313 > 10.10.10.200.49897: UDP, length 18
12:45:19.050085 IP 10.10.10.100.17761 > 10.10.10.200.6767: UDP, length 18
12:45:19.050093 IP 10.10.10.100.24303 > 10.10.10.200.12295: UDP, length 18
12:45:19.050101 IP 10.10.10.100.27105 > 10.10.10.200.52313: UDP, length 18
12:45:19.050109 IP 10.10.10.100.32141 > 10.10.10.200.55003: UDP, length 18
12:45:19.050119 IP 10.10.10.100.10274 > 10.10.10.200.11494: UDP, length 18

Итог - плачевен, машина почти убита нагрузкой:
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni, 75.0 id,  0.0 wa,  0.0 hi, 75.0 si,  0.0 st

Попробуем собрать фильтр под эту атаку.
ethtool --config-ntuple eth4 flow-type udp4 src-ip 10.10.10.100 m 255.255.255.0 action -1
Как можно догадаться, -1 означает безусловный drop трафика.

Посмотрим, что у нас получилось:
ethtool --show-ntuple eth4
4 RX rings available
Total 1 rules

Filter: 8189
    Rule Type: UDP over IPv4
    Src IP addr: 0.0.0.100 mask: 255.255.255.0
    Dest IP addr: 0.0.0.0 mask: 255.255.255.255
    TOS: 0x0 mask: 0xff
    Src port: 0 mask: 0xffff
    Dest port: 0 mask: 0xffff
    VLAN EtherType: 0x0 mask: 0xffff
    VLAN: 0x0 mask: 0xffff
    User-defined: 0x0 mask: 0xffffffffffffffff
    Action: Drop
Как удалить правило? Проще простого:
ethtool --config-ntuple eth4 delete 8189
Вуаля, при той же атаке в 7mpps мы не наблюдаем нагрузки вообще:
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
При этом убедиться, что правило flow director работает можно очень просто:
ethtool -S eth4 |grep fdir
     fdir_match: 916143392
     fdir_miss: 139427055
     fdir_overflow: 0
Вот таким образом можно сильно облегчить жизнь Linux боксу под атакой :) Но не стоит забывать, что функциональность по фильтрации довольно слабая - только IP и порты для входящего и исходящего трафика.

Но, например, таким образом можно сделать крутую защиту от UDP амплификации. И выживать пока не кончится аплинк :)

Установка exabgp - швейцарский нож для готовки BGP и flow spec

В Debian:
apt-get install -y python-pip

И ставим через pip:
pip install exabgp
 Блин, и чего с ней дальше делать :) Документация гхм...

четверг, 12 марта 2015 г.

Установка и использование ipset на Debian 7 Wheezy

Просто бесконечно проста с учетом того, что ipset теперь идет в поставке ядра:
dpkg -S /lib/modules/3.2.0-4-amd64/kernel/net/netfilter/ipset/ip_set_list_set.ko
linux-image-3.2.0-4-amd64: /lib/modules/3.2.0-4-amd64/kernel/net/netfilter/ipset/ip_set_list_set.ko
Ставим зависимости:
apt-get install ipset 
Создаем хэш:
ipset --create blacklist iphash --hashsize 4096
Смотрим его содержимое:
ipset --list
Name: blacklist
Type: hash:ip
Header: family inet hashsize 4096 maxelem 65536
Size in memory: 65656
References: 0
Members:
Добавляем несколько IP в список блокировки:
ipset --add blacklist 41.231.136.121
ipset --add blacklist 37.236.253.170
ipset --add blacklist 37.236.239.42
Убеждаемся, что они добавлены:
ipset --list
Name: blacklist
Type: hash:ip
Header: family inet hashsize 4096 maxelem 65536
Size in memory: 65704
References: 0
Members:
41.231.136.121
37.236.253.170
37.236.239.42
Добавляем правило iptables для отсечения товарищей, кто в этом списке:
iptables -I INPUT -m set --match-set blacklist src -p TCP --destination-port 80 -j DROP
В итоге это будет выглядеть примерно так:
iptables -nvL
Chain INPUT (policy ACCEPT 2822 packets, 188K bytes)
 pkts bytes target     prot opt in     out     source               destination        
    0     0 DROP       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            match-set blacklist src tcp dpt:80

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination        

Chain OUTPUT (policy ACCEPT 1882 packets, 320K bytes)
 pkts bytes target     prot opt in     out     source               destination          

Огромное преимущество ipset в том, что он сам проверяет на наличие дубликатов (на самом деле это приятное следствие из его структуры данных - хэша) и не нужно заниматься этим самостоятельно:
ipset --add blacklist 41.176.136.101
ipset v4.2: 41.176.136.101 is already in set blacklist.

Удалять IP из бана нужно следующим образом:
ipset --del blacklist 41.176.136.101

Полностью очистить спсиок блокировки можно так:
ipset --flush blacklist

Использования модуля при ну очень большом числе IP показывает, что он весьма стабилен и отлично работает:
ipset  -L | wc -l
43815
Баги/фичи:  "ipset v4.2: IP/port/element is outside of the set or set is full", при достжении размера очереди 65 тысячам IP:
ipset -L |wc -l
65541
Фикс - нет фикса (http://flug.org.ua/lists/debian-russian/71086/) Как обходник можно создать кучу хэшей и пропускать трафик через них.

Еще будет полезной фича ipset save, с помощью которой можно сделать восстановление/сохранение содержимого списков при перезагрузке:
ipset save
create blacklist hash:ip family inet hashsize 4096 maxelem 65536
add blacklist 41.231.136.121
add blacklist 37.236.253.170
add blacklist 37.236.239.42

Источники: http://lmn.name/archives/331 http://daemonkeeper.net/781/mass-blocking-ip-addresses-with-ipset/


воскресенье, 8 марта 2015 г.

Сброс полного содержимого BGP таблица в демоне Quagga

Обращаю внимание, что извлекать мы будем не скомпонованный дамп с "лучшими путями", а именно сырую информацию, на основании которой Quagga BGP демон выбирает лучший путь.

Осуществляется вот так:
vtysh -d bgpd -c "conf term" -c "dump bgp routes-mrt /var/run/bgpdata/rib.%F.%H%M 10m"
Отключается вот так:
vtysh -d bgpd -c "conf term" -c "no dump bgp routes-mrt /var/run/bgpdata/rib.%F.%H%M 10m"
Стоит отметить, что папка /var/run/bgpdata должна существовать и принадлежать пользователю quagga:quagga.

Если хотите вбить в конфиг, то это будет выглядеть вот так:
dump bgp routes-mrt /var/run/bgpdata/rib.%F.%H%M 10m
Стоит отметить, что внутри этого дампа (его размер считается как 40 мегабайт умноженное на число аплинков от которых принимается Full Table BGP).

Он в бинарном формате и чтобы конвертировать в текст понадобится спец тулза, которой конвертируем в текстовый вид (и 114 мб для 3*Full BGP превратятся сразу же в 450 мб в текстовом формате):
/opt/libbgpdump/bgpdump rib.2015-03-08.2010 -O rib.2015-03-08.2010.parsed 

За исследование и реализацию огромное спасибо Andrey Ziltsov :)

среда, 4 марта 2015 г.

Использование решения на базе Linux и netmap-ipfw для суперскоростной фильтрации паразитного трафика

Последнее время стали довольно распространены высокоскоростные атаки, осуществляемые с использованием различных вариантов усиления (amplification) трафика.

Как же с ними бороться? Довольно сложно, это стоит понимать. Дешевые решения в виде ACL на 10GE свиче либо аппаратных правил на NIC (сетевой карте) - могут блокировать лишь часть паразитного трафика с очень ограниченным набором параметров - src/dst IP, src/dst port и протокол.

Более серьезные решения требуют привлечения либо высокопроизводительных роутеров (речь про роутеры класса Juniper MX 120+, и к слову, возможности фильтрации трафика у роутеров тоже весьма ограничены) либо аппаратных фаерволлов, например, от Arbor. Роутеры стоят огромных денег, но почти всегда есть в ДЦ - это плюс. А специализированное железо от Arbor стоит совершенно непомерные суммы.

Итак, наше решение софт бокс-фильтр, машина 10GE картами, кучей процессорных мощностей и Linux либо FreeBSD на борту.

Стоит понимать, что стандартными средствами того же Linux атаку в 10Mpps не отбить, в конце концов, он просто упадет, например, вот так. Во FreeBSD ситуация во многом похожая и еще более усложняющаяся (для меня) не особо хорошим пониманием этой ОС.

Поэтому в качестве решения я обратился к системам прямого доступа к сетевой карте класса netmap, PF_RING, DPDK, а именно - мы будем использовать netmap, потому что он очень быстр, не требует лицензии и под него есть портированный фаерволл ipwf.

Итак, приготовим машину на Debian 7, с сетевыми картами ixgbe с по меньшей мере двумя интефейсами. Так как машина должна подключаться в разрез между атакуемой машиной и аплинком.

Сборка довольно проста, сначала нужно собрать netmap со всеми драйверами и загрузить его.

После этого нужно установить в систему заголовочные файлы для netmap, чтобы собрать тулкит:
Стягиваем заголовки:
cd /usr/include/net
wget https://raw.githubusercontent.com/luigirizzo/netmap/master/sys/net/netmap_user.h
wget https://raw.githubusercontent.com/luigirizzo/netmap/master/sys/net/netmap.h
Собираем:
cd /usr/src
git clone https://github.com/luigirizzo/netmap-ipfw.git
cd netmap-ipfw
make
Запускаем:
./kipfw netmap:eth4 netmap:eth6
После этого можем загрузить тестовое правило в ipfw:

cd ipfw
./ipfw add 1 deny tcp from any to any 80 in
Для испытания насколько это решение хорошо в продакшене я запустил syn флуд в 7mpps с тестовой машины силами trafgen.

Метрики моей  тесты машины (а это слабый CPU E5-2407 0 @ 2.20GHz x 4) на картинке:
top - 13:33:05 up 3 min,  2 users,  load average: 0.44, 0.13, 0.05
Tasks:  78 total,   2 running,  76 sleeping,   0 stopped,   0 zombie
%Cpu(s): 10.0 us, 14.8 sy,  0.0 ni, 74.6 id,  0.0 wa,  0.0 hi,  0.7 si,  0.0 st
KiB Mem:  32980328 total,   546592 used, 32433736 free,    45320 buffers
KiB Swap:  8387580 total,        0 used,  8387580 free,    32204 cached

  PID USER      PR  NI  VIRT  RES  SHR S  %CPU %MEM    TIME+  COMMAND                                                                                 
 3105 root      20   0  660m 9060 8908 R  99.5  0.0   0:25.36 kipfw    


  1  [|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]     Tasks: 26, 3 thr, 52 kthr; 2 running
  2  [                                                             0.0%]     Load average: 0.60 0.19 0.07
  3  [                                                             0.0%]     Uptime: 00:03:48
  4  [|                                                            0.7%]
  Mem[|||                                                   458/32207MB]
  Swp[                                                         0/8190MB]
Как можно видеть, машина прогрузилась лишь на 1/5, но одно ядро выгружено полностью (об этом отдельно).

Вполне неплохой показатель для такого слабого железа!

Теперь попробуем ту же самую задачу простого бриджинга сделать на Linux.

Ставим бридж утилс:
apt-get install -y bridge-utils
Добавляем интерфейсы в него:
brctl addbr mybridge
brctl addif mybridge eth4
brctl addif mybridge eth6
ifconfig mybridge up
И после этого вливаем те же 7mpps:
 1  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||99.1%]     Tasks: 25, 3 thr, 48 kthr; 2 running
  2  [|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]     Load average: 0.47 0.23 0.15
  3  [|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]     Uptime: 1 day, 14:24:01
  4  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||99.1%]
  Mem[||||                                                  497/32207MB]
  Swp[                                                         0/8190MB]


Шапка top выглядит еще более ужасающе:
top - 13:21:10 up 1 day, 14:24,  2 users,  load average: 1.57, 0.53, 0.26
Tasks:  73 total,   5 running,  68 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,  0.4 id,  0.0 wa,  0.0 hi, 99.6 si,  0.0 st
KiB Mem:  32980328 total,   812976 used, 32167352 free,    40784 buffers
KiB Swap:  8387580 total,        0 used,  8387580 free,   263172 cached

  PID USER      PR  NI  VIRT  RES  SHR S  %CPU %MEM    TIME+  COMMAND                                                                                 
   15 root      20   0     0    0    0 R  93.5  0.0  57:08.71 ksoftirqd/2                                                                             
   10 root      20   0     0    0    0 R  90.9  0.0  39:51.09 ksoftirqd/1                                                                             
    3 root      20   0     0    0    0 R  65.8  0.0  71:59.15 ksoftirqd/0                                                                             
   19 root      20   0     0    0    0 R  64.8  0.0  59:43.95 ksoftirqd/3                                                                             
 2806 root      20   0 20520  824  548 S   1.3  0.0   0:12.81 irqbalance                                                                              
 4723 root      20   0     0    0    0 S   1.0  0.0   0:18.05 kworker/1:2                                                                             
  342 root      20   0     0    0    0 S   0.7  0.0   0:13.04 kworker/2:1                                                                             
 2866 ntp       20   0 39076 2404 1764 S   0.7  0.0   0:08.80 ntpd                                                                                    
 5163 root      20   0     0    0    0 S   0.7  0.0   0:32.55 kworker/0:1    
Как можете видеть - Linux с этой задачей не справился потому что в нем используется схема с многократным копированием пакета вместо одноразового. Кроме этого, сам по себе стек Linux довольно тяжел и плохо приспособлен к подобной нагрузке по умолчанию.

А теперь попробуем силами все того же netmap-ipfw отбить эту атаку по отпечатку. А именно используя ее снимок из tcpdump:
11:43:10.008418 IP 198.18.51.106.62978 > 10.10.10.248.http: Flags [S], seq 1137192741, win 16, length 0
11:43:10.008419 IP 198.18.51.93.34560 > 10.10.10.113.http: Flags [S], seq 4245548258, win 16, length 0
11:43:10.008419 IP 198.18.51.98.30252 > 10.10.10.89.http: Flags [S], seq 1765400726, win 16, length 0
11:43:10.008420 IP 198.18.51.144.19980 > 10.10.10.91.http: Flags [S], seq 1052340006, win 16, length 0
11:43:10.008420 IP 198.18.51.30.38034 > 10.10.10.38.http: Flags [S], seq 2198215300, win 16, length 0
11:43:10.008421 IP 198.18.51.140.60388 > 10.10.10.133.http: Flags [S], seq 2831049352, win 16, length 0

В Linux блокировка такого трафика была бы задачей нетривиальной, но тут мы можем попробовать использовать необычайно малый размер окна и отсутствие опций tcp пакета вообще (в реальной жизни это нонсенс):
./ipfw add 8 deny tcp from any to any tcpwin 16 tcpdatalen 0
Сразу убеждаемся, что в правило начал лететь трафик:
./ipfw -a list
connected to 127.0.0.1:5555
nalloc 2248 nbytes 124 ptr (nil)
00008 578904841 23156193640 deny tcp from any to any tcpwin 16 tcpdatalen 0
65535  18831554   753262160 allow ip from any to any
Нагрузка машины-фильтра при этом была в рамках разумного:
top - 13:46:15 up 16 min,  2 users,  load average: 0.87, 0.65, 0.40
Tasks:  74 total,   2 running,  72 sleeping,   0 stopped,   0 zombie
%Cpu(s): 21.8 us,  3.0 sy,  0.0 ni, 74.7 id,  0.0 wa,  0.0 hi,  0.4 si,  0.0 st
KiB Mem:  32980328 total,   547800 used, 32432528 free,    45708 buffers
KiB Swap:  8387580 total,        0 used,  8387580 free,    32824 cached

 Как я уже обращал внимание, процесс kipfw выедает одно ядро полностью и это будет (если уже не является) причиной провалов в трафике, потому что он не успевает отбрабатывать весь проходящий трафик корректно.

Что с этим делать? Нужно делать патчи для kipfw для параллельной обработки либо попробовать запустить число инстансов kipfw по числу аппаратных очередей на сетевой карте. Таким образом в самом худшем случае на каждый процессор выйдет нагрузка не более чем 14/4=3.5Mpps на ядро, что в принципе разумная цифра.

В принципе, тот же самый подход скорее всего решит проблемы с производительностью kipfw на FreeBSD, там он ровно также упирается в скорость одного ядра.

Если у кого есть желание присоединиться к проекту в качестве тестера или разработчика - мои контакты справа.

понедельник, 2 марта 2015 г.

Сборка netmap с поддержкой ixgbe драйвера из поставки дистрибутива


Как гайд для начала рекомендую следующую статью: http://www.stableit.ru/2014/10/netmap-debian-7-wheezy-intel-82599.html

Обращаю внимание, что репо netmap переехал и новый адрес его такой: https://github.com/luigirizzo/netmap.git

Build netmap on Debian 7 Wheezy with ixgbe 10GE NIC (82599):

Get kernel sources:
cd /usr/src
apt-get source  linux-image-3.2.0-4-amd64
Стягиваем код netmap:
cd /usr/src
git clone https://github.com/luigirizzo/netmap.git
cd netmap/LINUX/
Собираем netmap и драйвер:
./configure --kernel-sources=/usr/src/linux-3.2.65 --drivers=ixgbe
make
make install

Load modules:
insmod ./netmap.ko
modprobe mdio
modprobe ptp
modprobe dca
insmod ixgbe/ixgbe.ko
Стоит обратить внимание, что данный режим работы единственный, стабильно работы которого удалось достичь на Linux.

Чтобы добиться запуска при загрузке машины нужно сделать что-то вот такое:
rmmod ixgbe
insmod /usr/src/netmap/LINUX/netmap.ko
modprobe mdio
modprobe ptp
modprobe dca
insmod /usr/src/netmap/LINUX/ixgbe/ixgbe.ko