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