Скрестить nginx с ipset

INF[SZ] nginx-forum на nginx.us
Вт Май 24 08:54:32 MSD 2011


Коллеги ни у кого не возникало желания
скрестить Nginx с возможностями
пакетного фильтра через тот же ipset ?

Провел небольшой эксперимент. 
Суть проста - завалить сервер валидными
http запросами, затем поставить
ограничение на location и снова нагрузить
сервер. 

Сравнить нагрузку.


Размер index.html 0 байт т. е. пустой.
Размер 50x.html ттоже 0 байт


ab -n 1000000 -c 100 -k http://10.0.0.2/

нагрузка на сервер 

Cpu0  : 22.3%us, 29.9%sy,  0.0%ni, 29.9%id,  0.0%wa,  0.0%hi, 17.9%si, 
0.0%st
Cpu1  : 19.1%us, 30.4%sy,  0.0%ni, 31.4%id,  0.0%wa,  0.0%hi, 19.1%si, 
0.0%st
Cpu2  : 24.2%us, 32.8%sy,  0.0%ni, 23.2%id,  0.0%wa,  0.0%hi, 19.9%si, 
0.0%st
Cpu3  : 17.4%us, 23.5%sy,  0.0%ni, 40.6%id,  0.0%wa,  0.0%hi, 18.4%si, 
0.0%st
Mem:   2055132k total,   946732k used,  1108400k free,    31004k
buffers
Swap:  2096472k total,        0k used,  2096472k free,   402132k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND    
       
11439 nginx     20   0  130m  40m  908 S 63.8  2.0   0:22.42 nginx      
       
11438 nginx     20   0  130m  40m  852 S 62.8  2.0   0:21.18 nginx      
       
11437 nginx     20   0  130m  40m  852 S 62.2  2.0   0:19.70 nginx      
       
11436 nginx     20   0  130m  40m  852 S 61.2  2.0   0:21.41 nginx      
       

статистика ab 
Server Software:        nginx/0.8.54
Server Hostname:        10.0.0.2
Server Port:            80
Document Path:          /
Document Length:        0 bytes
Concurrency Level:      100
Time taken for tests:   16.828 seconds
Complete requests:      1000000
Failed requests:        0
Write errors:           0
Keep-Alive requests:    990047
Total transferred:      213958790 bytes
HTML transferred:       0 bytes
Requests per second:    59423.52 [#/sec] (mean)
Time per request:       1.683 [ms] (mean)
Time per request:       0.017 [ms] (mean, across all concurrent
requests)
Transfer rate:          12416.20 [Kbytes/sec] received

Теперь ограничим / в 15r/s

limit_req_zone $binary_remote_addr zone=antiddos:10m rate=15r/s;
limit_req zone=antiddos burst=15;

и снова протестируем нагрузку на
сервер

Cpu0  : 25.8%us, 42.7%sy,  0.0%ni, 12.6%id,  0.0%wa,  0.0%hi, 18.9%si, 
0.0%st
Cpu1  : 23.3%us, 35.5%sy,  0.0%ni, 22.9%id,  0.0%wa,  0.0%hi, 18.3%si, 
0.0%st
Cpu2  : 23.9%us, 41.9%sy,  0.0%ni, 13.3%id,  0.0%wa,  0.0%hi, 20.9%si, 
0.0%st
Cpu3  : 21.0%us, 34.0%sy,  0.0%ni, 26.3%id,  0.0%wa,  0.0%hi, 18.7%si, 
0.0%st
Mem:   2055132k total,  1286200k used,   768932k free,    31504k
buffers
Swap:  2096472k total,        0k used,  2096472k free,   728048k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND    
       
13118 nginx     20   0  140m  40m  892 R 80.8  2.0   0:28.41 nginx      
       
13119 nginx     20   0  140m  40m  896 R 77.5  2.0   0:30.16 nginx      
       
13120 nginx     20   0  140m  40m  892 R 77.2  2.0   0:30.73 nginx      
       
13117 nginx     20   0  140m  40m  888 R 74.2  2.0   0:29.02 nginx      
       

нагрузка по каждому ядру возросла на 15%

Вот вывод ab во втором случае

Server Software:        nginx/0.8.54
Server Hostname:        10.0.0.2
Server Port:            80
Document Path:          /
Document Length:        0 bytes
Concurrency Level:      100
Time taken for tests:   17.093 seconds
Complete requests:      1000000
Failed requests:        0
Write errors:           0
Non-2xx responses:      999796
Keep-Alive requests:    990049
Total transferred:      174969528 bytes
HTML transferred:       0 bytes
Requests per second:    58503.31 [#/sec] (mean)
Time per request:       1.709 [ms] (mean)
Time per request:       0.017 [ms] (mean, across all concurrent
requests)
Transfer rate:          9996.38 [Kbytes/sec] received

Сразу же оговорюсь, что при различных
равных index.html и 50x.html мы будем получать
ту же самую картину. 

Выигрыш в нагрузке на сервер от
ограничений будет только в том случае,
когда размер запрашиваемой страницы
много больше чем размер страницы с
кодом ошибки.

Если же блокировать с помощью связкой
nginx->ipset->iptables, то HTTP запросы от атакующих
не будут доходить до nginx и нагрузка на
сервер будет равна нулю.

Можно например ввести такой синтаксис

location / {
limit_req zone=antiddos burst=15
ipset name=blocked rate=150r/s;
}

соответственно после 150 запросов в
секунду добавлять ip адрес в set blocked
создать тип сета iptree (набор с временем
жизни записи), и временем жизни записи
например 1 час

ipset --create blocked iptree --timeout 3600

создаем правило в iptables которое
блокирует данный сет

iptables -A INPUT -m set --set blocked src -j DROP

Эти же возможности можно будет
использовать для приоритезации
трафика от отпределенных location
(nginx->ipset->tc), для ограничения скорости
для отдельных location или ip адресов
превысивших порог запросов. 

Кто что думает по поводу этой идеи ?

Posted at Nginx Forum: http://forum.nginx.org/read.php?21,200292,200292#msg-200292




Подробная информация о списке рассылки nginx-ru