Методы борьбы с dos/ddos-атаками
  1. Бортовой журнал PHP кодера
  2. / В помощь
  3. /

    Методы борьбы с dos/ddos-атаками


Cуществует два типа DoS/DDoS-атак, и наиболее распространенная из них основана на идее флуда, то есть заваливании жертвы огромным количеством пакетов. Флуд бывает разным: ICMP-флуд, SYN-флуд, UDP-флуд и НТТР-флуд. Современные DoS-боты могут использовать все эти виды атак одновременно, поэтому следует заранее позаботиться об адекватной защите от каждой из них.
 

1.ICMP флуд. 

 
Очень примитивный метод забивания полосы пропускания и создания нагрузок на сетевой стек через монотонную посылку запросов ICMP ECHO (пинг). Легко обнаруживается с помощью анализа по¬токов трафика в обе стороны: во время атаки типа ICMP-флуд они практически идентичны. Почти безболезненный способ абсолютной защиты основан на отключении ответов на запросы ICMP ECHO:
 
# sysctl net. ipv4 . icmp_echo_ignore_all=1
 
Или с помощью брандмауэра:
 
# iptables -A INPUT -р icmp -j DROP --icmp-type 8
 

2.SYN флуд.

 
Один из распространенных способов не только забить канал связи, но и ввести сетевой стек операционной системы в такое состояние, когда он уже не сможет принимать новые запросы на подключение. Основан на попытке инициализации большого числа одновременных TCP-соединений через посылку SYN-пакета с несуществующим обратным адресом. После нескольких попыток отослать ответный АСК-пакет на недоступный адрес большинство операционок ставят неустановленное соединение в очередь. И только после n-ой попытки закрывают соединение. Так как поток АСК-пакетов очень велик, вскоре очередь оказывается заполненной, и ядро дает отказ на попытки открыть новое соединение.
Наиболее умные DoS-боты еще и анализируют систему перед началом атаки, чтобы слать запросы только на открытые жизненно важные порты. Идентифицировать такую атаку просто: достаточно попробовать подключиться к одному из сервисов.

Оборонительные мероприятия обычно включают в себя:
 
- Увеличение очереди «полуоткрытых» ТСР-соединений:
# sysctl -w net.ipv4.tcp_max_syn_backlog=1024
 
- Уменьшаем время ожидания ответного пакета на запрос SYN-ACK (защита от SYN-флуда):
# sysctl net.inet.tcp.msl=7500
 
- Превращаем сервер в черную дыру. Так ядро не будет слать ответные пакеты при попытке подключиться к незанятым портам (снижает нагрузку на машину во время DDoS'a на случайные порты):
# sysctl net.inet.tcp,blackhole=2
# sysctl net - inet . udp .blackhole=1
 
- Ограничиваем число ответов на ICMP-сообщения 50-ю в секунду (защита от ICMP-флуда):
# sysctl net.inet.icmp.icmplim=50
 
- Увеличиваем максимальное количество подключений к серверу (защита от всех видов DDoS):
# sysctl kern.ipc.somaxconn=32768
 
-Включаем DEVICE_POLLING — самостоятельный опрос сетевого драйвера ядром на высоких нагрузках (существенно снижает нагрузку на систему во время DDoS'a):
1.Пересобираем ядро с опцией «options DEVICE_POLLING»;
2.Активируем механизм поллинга: «sysctl kern.polling.enable=1»;
3.Добавляем запись «kern.polling.enable= 1» в /etc/sysctl.conf.
Уменьшение времени удержания «полуоткрытых» соединений:
# sysctl -w net.ipv4.tcp_synack_retries=l
 
- Включение механизма TCP syncookies:
# sysctl -w net.ipv4.tcp_syncookies=l
 
- Ограничение максимального числа «полуоткрытых» соедине¬ний с одного IP к конкретному порту:
# iptables -I INPUT -р tcp --syn --dport 80 -m iplimit --iplimit-above 10 -j DROP
 

3.UDP флуд

 
Типичный метод захламления полосы пропускания. Основан на бесконечной посылке UDP-пакетов на порты различных UDP-сервисов. Легко устраняется за счет отрезания таких сервисов от внешнего мира и установки лимита на количество соединений в единицу времени к DNS-серверу на стороне шлюза:
 
# iptables -I INPUT -р udp --dport 53 -j DROP -m iplimit --iplimit-above 1
 

4.НТТР флуд.

 
Один из самых распространенных на сегодняшний день способов флуда. Основан на бесконечной посылке HTTP-сообщений GET на 80-й порт с целью загрузить web-сервер настолько, что¬бы он оказался не в состоянии обрабатывать остальные запросы.
 
Часто целью флуда становится не корень web-сервера, а один из скриптов, выполняющих ресурсоемкие задачи или работающий с базой данных. В любом случае, индикатором начавшейся атаки будет служить аномально быстрый рост логов web-сервера. Методы борьбы с НТТР-флудом включают в себя тюнинг web-сервера и базы данных с целью снизить эффект от атаки, а также отсеивание DoS-ботов с помощью различных приемов. Во-первых, следует увеличить максимальное число коннектов к базе данных одновременно. Во-вторых, установить перед web-сервером Apache легкий и производительный nginx — он будет кэшировать запросы и отдавать статику. Это решение из списка «must have», которое не только снизит эффект DoS-атак, но и позволит серверу выдержать огромные нагрузки. Небольшой пример:
 
user www-data;
worker_processes 4;
pid /var/run/nginx.pid;
# Увеличиваем максимальное количество используемых файлов
worker_rlimit_nofile 80000;
 
error_log  /var/log/www/nginx_error.log;
 
events {
    worker_connections  2024;
    # multi_accept on;
    # Использовать эффективный метод epoll для обработки соединений
    # use epoll;
}
 
http {
        #log options
        access_log off; ## Отключпаем лог со
        log_format  main  '$host $remote_addr [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"'; ## Формат лога

        ## Устанавливает лимит на количество соединений
        #limit_req_zone  $binary_remote_addr  zone=allthem:30m   rate=300r/m;
        #limit_zone allthem $binary_remote_addr 30m;

        ## Путь и настройки для хранения кеша
        proxy_cache_path /var/cache/nginx levels=2 keys_zone=pagecache:32m inactive=30m max_size=1024m;
 
        #nginx options
        # Директива задаёт таймаут при чтении заголовка запроса клиента
        client_header_timeout  60;
 
        # Директива задаёт таймаут при чтении тела запроса клиента
        client_body_timeout    60;
 
        # Директива задаёт таймаут при передаче ответа клиенту
        send_timeout           60;
 
        # Директива задаёт таймаут, в течение которого keep-alive соединение
        # с клиентом не будет закрыто со стороны сервера
        keepalive_timeout      30;
 
        # Директива разрешает или запрещает использовать sendfile()
        sendfile        on;
        # Директива разрешает или запрещает использовать опции TCP_NOPUSH во FreeBSD
        # Подробнее http://sysoev.ru/nginx/docs/http/ngx_http_core_module.html#keepalive_timeout
        tcp_nopush     on;
        tcp_nodelay        on;
        client_max_body_size 50m;
 
        # Директива задаёт размер буфера для чтения заголовка запроса клиента
        #client_header_buffer_size    1k;
 
        # Директива задаёт максимальное число и размер буферов
        #для чтения большого заголовка запроса клиента
        #large_client_header_buffers  4 4k;
        proxy_max_temp_file_size 0;

        ## Включаем сжатие
        gzip on;
        gzip_min_length 1100;
        gzip_buffers 64 8k;
        gzip_comp_level 6;
        gzip_http_version 1.1;
        gzip_proxied any;
        gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
        gzip_disable "MSIE [1-6].(?!.*SV1)";
 
        proxy_set_header Range "";## Запретить nginx проксировать опасный заголовок
 
        # Не отдавать версию nginx в заголовке ответа
        server_tokens off;
 
        types_hash_max_size 2048;
        # server_tokens off;
 
        # server_names_hash_bucket_size 64;
        # server_name_in_redirect off;
 
        default_type application/octet-stream;
 
        include mime.types;
        include conf.d/*.conf; ## ополнительные конфиги (банлист и тп)
 
        include sites-enabled/*; ## Конфиги виртуальных хостов
 
        # Модуль позволяет описывать группы серверов, которые могут использоваться
        # в директивах proxy_pass и fastcgi_pass.
        upstream backend {
                # Директива задаёт имя и параметры сервера. Обратите внимание, мы будем
                # использовать имя "backend" в директиве proxy_pass
                # Ставим апач на порт 8778(или любой другой не занятый)
                # и желательно закрыть фаерволом доступ из вне по этому порту
                server 127.0.0.1:8778; 
        }
}
 
 
В случае необходимости можно задействовать nginx-модуль ngx_http_limit_req_module, ограничивающий ко¬личество одновременных подключений с одного адреса
(http://sysoev.ru/nginx/docs/http/ngx http limit req module.html).
 
Ресурсоемкие скрипты можно защитить от ботов с помощью задержек, кнопок «Нажми меня», выставления кукисов и других приемов, направленных на проверку «человечности».
 

УНИВЕРСАЛЬНЫЕ СОВЕТЫ 

 
Чтобы не попасть в безвыходное положение во время обрушения DDoS-шторма на системы, необходимо тщательным образом подготовить их к такой ситуации:
1.Все сервера, имеющие прямой доступ во внешнюю сеть, должны быть подготовлены к простому и быстрому удаленному ребуту (sshd спасет отца русской демократии). Большим плюсом будет наличие второго, административного, сетевого интерфейса, через который можно получить доступ к серверу в случае забитости основного канала.
2.ПО, используемое на сервере, всегда должно находиться в актуальном состоянии. Все дырки — пропатчены, обновления установлены (простой, как сапог, совет, ко-торому многие не следуют). Это оградит тебя от DoS-атак, эксплуатирующих баги в сервисах.
3.Все слушающие сетевые сервисы, предназначенные для административного использования, должны быть спрятаны брандмауэром ото всех, кто не должен иметь к ним доступ. Тогда атакующий не сможет использовать их для проведения DoS-атаки или брутфорса.
 
4. На подходах к серверу (ближайшем маршрутизаторе) должна быть установлена система анализа трафика (NetFlow в помощь), которая позволит своевременно узнать о начинающейся атаке и вовремя принять меры по ее предотвращению.
Добавь в /etc/sysctl.conf следующие строки:
 
# vi /etc/sysctl.conf
# Защита от спуфинга
net.ipv4.conf.default.rp_filter = 1
# Проверять TCP-соединение каждую минуту. Если на другой стороне — легальная машина, она сразу ответит. Дефолто-вое значение — 2 часа.
 
net.ipv4.tcp_keepalive_time = 60
# Повторить пробу через десять секунд 
net.ipv4.tcp_keepalive_intvl = 10
# Количество проверок перед закрытием соединения 
net. ipv4 . tcp_keepalive_probes = 5
 
Следует отметить, что все приемы, приведенные в прошлом и этом разделах, направлены на снижение эффективности DDoS-атак, ставящих своей целью израсходовать ресурсы машины. От флуда, забивающего канал мусором, защититься практически невозможно, и единственно правильный, но не всегда осуществимый способ борьбы заключается в том, чтобы «лишить атаку смысла». Если ты заимеешь в свое распоряжение действительно широкий канал, который легко пропустит трафик небольшого ботнета, считай, что от 90% атак твой сервер защищен. Есть более изощренный способ защиты. Он основан на организации распределенной вычислительной сети, включающей в себя множество дублирующих серверов, которые подключены к разным магистральным каналам. Когда вычислительные мощности или пропускная способность канала заканчиваются, все новые клиенты перенаправляются на другой сервер (или же постепенно «размазываются» по серверам по принципу round-robin). Это невероятно дорогая, но очень стойкая структура, завалить которую практически нереально.
Другое более-менее эффективное решение заключается в покупке дорогостоящих хардварных систем Cisco Traffic Anomaly Detector и Cisco Guard. Работая в связке, они могут подавить начинающуюся атаку, но, как и большинство других решений, основанных на обучении и анализе состояний, дают сбои. Поэтому следует хорошенько подумать перед тем, как выбивать из начальства десятки тысячи долларов на такую защиту.
 

КАЖЕТСЯ, НАЧАЛОСЬ. ЧТО ДЕЛАТЬ? 

 
Перед непосредственным началом атаки боты «разогреваются», постепенно наращивая поток пакетов на атакуемую машину. Важно поймать момент и начать активные действия. Поможет в этом постоянное наблюдение за маршрутизатором, подключенным к внешней сети (анализ графиков NetFlow). На сервере-жертве определить начало атаки можно подручными средствами.
 
Наличие SYN-флуда устанавливается легко — через подсчет числа «полуоткрытых» ТСР-соединений:
 
# netstat -na I grep п:80 ¦ I grep SYN_RCVD
 
В обычной ситуации их не должно быть совсем (или очень небольшое количество: максимум 1-3). Если это не так — ты атакован, срочно переходи к дропанью атакующих.
С НТТР-флудом несколько сложнее. Для начала нужно подсчитать количество процессов Apache и количество коннектов на 80-й порт
(НТТР-флуд):
 
# ps aux I grep httpd I wc -1
# netstat -na I grep ":80 " I wc -1
 
Значения, в несколько раз превышающие среднестатистические, дают основания задуматься. Далее следует просмотреть список IP-адресов, с которых идут запросы на подключение:
 
# netstat -па I grep ":80 " I sort I uniq -с I sort -nr I less
 
Однозначно идентифицировать DoS-атаку нельзя, можно лишь под-твердить свои догадки о наличии таковой, если один адрес повторяется в списке слишком много раз (да и то, это может говорить о посетителях, сидящих за NAT'OM). Дополнительным подтверждением будет анализ пакетов с помощью tcpdump:
 
# tcpdump -n -i ethO -s 0 -w output.txt dst port 80 and host IP-сервера
 
Показателем служит большой поток однообразных (и не содержащих полезной информации) пакетов от разных IP, направленных на один порт/сервис (например, корень web-сервера или определенный cgi-скрипт).
Окончательно определившись, начинаем дропать неугодных по IP-адресам (будет гораздо больше эффекта, если ты сделаешь это на маршрутизаторе):
 
# iptables-AINPUT-sxxx.ххх.ххх.ххх-ptcp- -destination - port http -j DROP
Или сразу по подсетям:
# iptables -A INPUT - s ххх. ххх .0.0/16- -ptcp- -destination-
port http -j DROP
 
Это даст тебе некоторую фору (совсем маленькую; зачастую 1Р-адрес источника спуфится), которую ты должен использовать, чтобы обратиться к провайдеру/хостеру (с приложенными к сообщению логами web-сервера, ядра, брандмауэра и списком выявленных тобой IР -адресов). Большинство из них, конечно, проигнорируют это сообщение (а хостинги с оплатой трафика еще и порадуются — DoS-атака принесет им прибыль) или просто отключат твой сервер. Но в любом случае это следует сделать обязательно, — эффективная защита от DDoS возможна только на магистральных каналах. В одиночку ты справишься с мелкими нападками, направленными на истощение ресурсов сервера, но окажешься беззащитным перед более-менее серьезным DDoS'ом.
 
Источник: Хакер + немного от себя