DDoS атака на веб-сервер может нести за собой самые неприятные последствия для вашей инфраструктуры. Каждую атаку следует рассматривать как отдельный случай, и для этого мы рекомендуем в случае DDoS на ваш сервер, привлекать к решению этой проблемы квалифицированного системного администратора. В этой статье мы постараемся рассмотреть самые основные методы предотвращения распространенных атак на веб сервера.

Apache

Ddos атака в этом случае начинается с обнаружения большого количества процессов apache, ваш сервер может стать недоступен из-за превышения максимального числа процессов, или из-за нехватки оперативной памяти.

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

     1.Диагностика

Если есть возможность, нужно подключиться к серверу по ssh. С помощью команд ps и top можно обнаружить увеличение количества процессов httpd. В этом случае можно остановить apache или убить все процессы httpd.

Эти команды помогут определить, направление и состояние всех установленных на 80 порту или на всех портах соединений.

netstat -na | grep ':80 '

netstat -na

С помощью следующих команд можно просмотреть количество процессов httpd и количество подключений на 80 порт. При обнаружении количества соединение, которое превышает среднестатистическое, можно удостовериться что это DoS/DDoS-атака.

ps aux | grep -с httpd

netstat -na | grep -с ":80 "

В операционной системе Centos 7 нет команды netstat “из коробки”, но её можно поставить командой:

yum instal net-tools

Также можно воспользоваться альтернативным способом, командой ss, которая во время вывода отображает все соединения к web-серверу:

ss -o '( dport = :http or sport = :http )'

Следующей командой можно отобразить количество подключений с одного IP адреса к Web-серверу и отсортировать список по возрастанию:

ss -o '( dport = :http or sport = :http )' | awk '{print $6}' | cut -d : -f 1 | grep -v 'Address' | sort | uniq -c | sort -n 

С большой вероятностью http-флуд можно определить по побочным признакам. Следующей командой можно заставить через каждые 2 секунды выводить список логов apache, и если с размером верхнего access файла наблюдается большой рост, таким образом можно определить что атака идет именно на определенный сайт:

watch 'ls -laS /var/www/httpd-logs/'

Следующие команды смогут помочь обнаружить DoS/DDoS средствами tcpdump.

tcpdump будет записывать в файл ddos.log первые 200 пакетов, которые ожидают соединений на 80 порту:

tcpdump -n port 80 -c 200 -w check.log

С помощью этой команды можно разобрать log-файл и отсортировать его  по ip и количеству подключений:

tcpdump -nr check.log | awk '{print $3}' |grep -oE '[0-9]{1,}\.[0-9]{1,}\.[0-9]{1,}\.[0-9]{1,}' |sort |uniq -c |sort -rn

     2.Действия для прекращения атаки

В первую очередь вам нужно определить, на какой именно сайт идет атака. У apache есть модуль mod_status http://httpd.apache.org/docs/2.2/mod/mod_status.html

mod_status позволяет в реальном времени осуществлять мониторинг загрузки сервера.

  • Подключение mod_status в Apache 2.4

В apache2.4, вам нужно отредактировать файл /etc/apache2/mods-enabled/status.conf. Измените секцию:

<Location /server-status>

               SetHandler server-status

               Require local

               #Require ip ----

</Location>

на

<Location /server-status>

               SetHandler server-status

</Location>

Проверьте чтобы строка, была раскоментированна:

ExtendedStatus On

Перезапустите apache:

service httpd restart
  • Mod_status подключение в Apache 2.2

В apache2.2, измените /etc/httpd/conf/httpd.conf

Раскомментируйте строки, если их нет, то добавьте:

#LoadModule status_module libexec/apache22/mod_status.so

#Include etc/apache22/extra/httpd-info.conf

Измените секцию:

<Location /server-status>

               SetHandler server-status

               Order deny,allow

               Deny from all

               Allow from .examplesite.com

</Location>

на

<Location /server-status>

               SetHandler server-status

</Location>

Нужно раскомментировать строку:

ExtendedStatus On

Перезапустите apache:

service httpd restart
  • Использование server-status

Теперь по адресу

http: //server-ip-address/server-status доступна статистика запросов к сервису

Например, атака происходит с пустыми GET / запросами к веб-сайту examplesite.com, и вам необходимо ее отключить. Вы можете сделать это, создав файл .htaccess в корневом каталоге домена и записав в его содержимое:

Deny from All

Теперь при доступе к сайту будет генерироваться ошибка 403 Forbidden и нагрузка на другие сайты будет значительно снижена.

     3.Дополнительные настройки

  • iptables 

С помощью следующей команды можно фильтровать 80-й порт для конкретного IP:

iptables -A INPUT -p tcp --src xxx.xxx.xxx.xxx --dport 80 -j DROP

Следующей комбинацией можно создать цепочку, куда будут перенаправляться все подключения на 80-й порт сервера. Все нелегитимные IP будут добавляться в эту цепочку:

iptables -N chainname

iptables -A INPUT -p tcp --dport 80 -j chainname

while true; do tail -10000 /var/www/httpd-logs/site.com.access.log | sort | cut -f 1 -d " " | uniq -c | awk '($1>50){print $2}' | xargs -tn 1 iptables -A dos -p tcp -j DROP --dport 80 -s; sleep 30; done
iptables -F INPUT — очищение таблицы INPUT
iptables -F chainname— очищение таблицы chainname
iptables -X chainname— удаление таблицы chainname

Настройка с помощью iptables может привести к тому, что в цепочке будут дублироваться правила. Этого можно избежать, используя модуль ipset.

  • ipset 
ipset -N chainname iphash

iptables -A INPUT -p tcp -m tcp --dport 80 -m set --set chainname src -j DROP

while true; do tail -10000 /var/www/httpd-logs/site.com.access.log | sort | cut -f 1 -d " " | uniq -c | awk '($1>50){print $2}' | xargs -tl -I _ ipset -A chainname _;sleep 30; done
  • ICMP-flood 

В этом случае необходимо закрыть  icmp:

iptables -A INPUT -p icmp -j DROP --icmp-type 8

Также можно ограничить максимальное число полуоткрытых соединений с одного IP к конкретному порту, предварительно нужно установить нужный модуль:

iptables -I INPUT -p tcp --syn --dport 80 -m iplimit --iplimit-above 10 -j DROP

Следующей комбинацией можно ограничить максимальное число соединений с одного IP к конкретному порту:

/sbin/iptables  -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 3 -j REJECT
  • Apache оптимизация сервера

В первую очередь необходимо откорректировать дополнительные параметры в настройке сервера:

/etc/httpd/conf/httpd.conf

<IfModule mpm_itk_module>

   StartServers                    1

   MinSpareServers            1

   MaxSpareServers           1

   MaxClients                      150

   MaxRequestsPerChild  100

</IfModule>

Нужно изменить значение MaxClients , которое означает максимальное число процессов, учитывая количество процессов которые не приведут к падению сервера из-за нехватки ОП. Нужно учитывать, что каждый процесс apache занимает 4-8 МБ в памяти, поэтому следующей командой можно узнать, сколько  один процесс apache/httpd занимает памяти на вашем сервере и от этого значения определять MaxClients:

top -d 1 | grep -E 'http|apache' | awk '{a+=$7}END{print a/(1024*NR) " Mb"}'

Также следует откорректировать и  установить следующие параметры для того, чтобы устаревшие процессы apache могли прекратить свою работу быстрее:

Timeout                            60

MaxKeepAliveRequests 50
  • Настройка nginx как front-end для apache
server {

       listen       80;

       server_name  examplesite.com www.examplesite.com;

 deny all;

WWW домен необходимо отключать, корректируя конфигурацию nginx в соответствующем virtualhost. Это заставит nginx отдавать 403 Forbidden, а не перенаправлять запросы к apache web-server.

Nginx

     1. В первую очередь необходимо ограничить скорость запросов, чтобы Nginx принимал входящие запросы с нужной для реальных пользователей скоростью:

limit_req_zone $binary_remote_addr zone=one:10m rate=30r/m;

server {

# ... 

     location /index.html {

         limit_req zone=one;

     }

}

limit_req_zone $binary_remote_addr zone=one:10m rate=30r/m;

server {

# ... 

     location /example.html {

         limit_req zone=one;

     }

}

В этом примере конфигурации используются следующие параметры:

  • limit_req_zone — директива настраивает вызываемую зону общей памяти для хранения состояния запросов для указанного ключа, в данном случае IP-адреса клиента ( $binary_remote_addr).
  • limit_req — директива в location блоке для /index.html ссылается на зону общей памяти.

     2.Ограничение числа соединений, которые могут быть открыты одним клиентским IP

limit_conn_zone $binary_remote_addr zone=addr:10m;

server {     

# ...     

    location /products/ {         

        limit_conn addr 10;        

    } 

}

В этом примере конфигурации используются следующие параметры:

  • limit_conn_zone— директива настраивает зону общей памяти с именем addr для хранения запросов на указанный ключ, в этом случае (как и в предыдущем примере) IP-адрес клиента,$binary_remote_addr. 
  • limit_conn— директива в блоке location для / products относится к зоне совместно используемой памяти и устанавливает максимум 10 соединений с каждого IP-адреса клиента..

     3.Закрыть медленные соединения

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

client_header_timeout           30s;

client_body_timeout             30s;

По умолчанию этот параметр составляет 60 секунд.

 

В настоящее время это все общие меры для предотвращения атак на веб-серверы. Если вы столкнулись с атакой на ваш веб-сервер, сохраните журналы логов для дальнейшего изучения уязвимостей в вашем сервисе.