Translate

Показаны сообщения с ярлыком DDoS. Показать все сообщения
Показаны сообщения с ярлыком DDoS. Показать все сообщения

Защита Apache от DDOS атак

Собственно, речь пойдет о защите от SYN flood атак:
Очень популярная DoS атака заключается в посылке большого числа SYN пакетов на ваш сервер. При этом установка TCP связи не доводится до конца. Очередь полуоткрытых запросов соединений быстро заполняется, что мешает установке нормальных соединений. Так как соединение не должно быть обязательно завершено, такая атака не требует больших ресурсов от атакующей машины, поэтому её легко реализовать и контролировать.
Определить SYN атаку просто – команда netstat выдает огромный список полуоткрытых подключений:
netstat -n --tcp | grep SYN_RECV
tcp 0 0 xxx.xxx.xxx.xxx:80 yyy.yyy.yyy.yyy:1084 SYN_RECV
tcp 0 0 xxx.xxx.xxx.xxx:80 yyy.yyy.yyy.yyy:1228 SYN_RECV
tcp 0 0 xxx.xxx.xxx.xxx:80 yyy.yyy.yyy.yyy:2652 SYN_RECV
tcp 0 0 xxx.xxx.xxx.xxx:80 yyy.yyy.yyy.yyy:3446 SYN_RECV
Можем просто подсчитать количество:
netstat -n --tcp | grep SYN_RECV | wc -l
238
Для начала – проверяем параметр tcp_syncookies – он должен быть равен 1:
cat /proc/sys/net/ipv4/tcp_syncookies
1
Так и оставляем. По умолчанию в новых дистрибутивах этот параметр всегда включен.
Если параметр tcp_syncookies установлен (доступен только когда ядро собрано с CONFIG_SYNCOOKIES), тогда ядро обрабатывает SYN пакеты TCP в обычном режиме до тех пор, пока очередь не заполнится. После заполнения очереди включается механизм SYN cookies.
SYN cookies вообще не использует очередь SYN. Вместо этого ядро отвечает на каждый SYN пакет, как обычно SYN|ACK, но туда будет включено специально сгенерированное число на основе IP адресов и портов источника и получателя, а также времени посылки пакета. Атакующий никогда не получит эти пакеты, а поэтому и не ответит на них. При нормальном соединении, будет послан третий пакет, содержащий число, а сервер проверит был ли это ответ на SYN cookie и, если да, то разрешит соединение даже в том случае, если в очереди SYN нет соответствующей записи.
Включение механизма SYN cookies является очень простым способом борьбы против атаки SYN флудом. При этом немного больше загружается процессор из-за необходимости создавать и сверять cookie. Так как альтернативным решением является отклонять все запросы на соединение, SYN cookies являются хорошим выбором.
Также нужно увеличить очередь полуоткрытых соединений –tcp_max_syn_backlog (в Debian Lenny по-умолчанию 1024 соединения):
cat /proc/sys/net/ipv4/tcp_max_syn_backlog
1024
Увеличиваем:
echo "20000" > /proc/sys/net/ipv4/tcp_max_syn_backlog
Кроме того, можем уменьшить время ожидания соединенияtcp_synack_retries:
Целочисленное значение (1 байт) tcp_synack_retries определяет число попыток повтора передачи пакетов SYNACK для пассивных соединений TCP. Число попыток не должно превышать 255. Используемое по умолчанию значение 5 соответствует приблизительно 180 секундам на выполнение попыток организации соединения.
cat /proc/sys/net/ipv4/tcp_synack_retries
5
Уменьшаем до 1 (это примерно 9 секунд):
echo "1" > /proc/sys/net/ipv4/tcp_synack_retries
tcp_fin_timeout
Целое число в файле tcp_fin_timeout определяет время сохранения сокета в состоянии FIN-WAIT-2 после его закрытия локальной стороной. Партнер может не закрыть это соединение никогда, поэтому следует закрыть его по своей инициативе по истечении тайм-аута. По умолчанию тайм-аут составляет 60 секунд. В ядрах серии 2.2 обычно использовалось значение 180 секунд и вы можете сохранить это значение, но не следует забывать, что на загруженных WEB-серверах вы рискуете израсходовать много памяти на сохранение полуразорванных мертвых соединений. Сокеты в состоянии FIN-WAIT-2 менее опасны, нежели FIN-WAIT-1, поскольку поглощают не более 1,5 Кбайт памяти, но они могут существовать дольше.
cat /proc/sys/net/ipv4/tcp_fin_timeout
60
Меняем на 30:
echo "30" > /proc/sys/net/ipv4/tcp_fin_timeout
tcp_keepalive_probes
Целочисленная переменная tcp_keepalive_probes задает число передач проб keepalive, после которого соединение считается разорванным. По умолчанию передается 9 проб.
cat /proc/sys/net/ipv4/tcp_keepalive_probes
9
Ставим 5:
echo "5" > /proc/sys/net/ipv4/tcp_keepalive_probes
tcp_keepalive_intvl
Целочисленная переменная tcp_keepalive_intvl определяет интервал передачи проб. Произведение tcp_keepalive_probes * tcp_keepalive_intvl определяет время, по истечении которого соединение будет разорвано при отсутствии откликов. По умолчанию установлен интервал 75 секунд, т.е., время разрыва соединения при отсутствии откликов составит приблизительно 11 минут.
cat /proc/sys/net/ipv4/tcp_keepalive_intvl
75
Ставим 15:
echo "15" > /proc/sys/net/ipv4/tcp_keepalive_intvl
netdev_max_backlog
Здесь указывается максимальное количество пакетов в очередь на обработку если интерфейс получает пакеты быстрее, чем ядро может их обработать.
cat /proc/sys/net/core/netdev_max_backlog
1000
Увеличиваем:
echo "20000" > /proc/sys/net/core/netdev_max_backlog
somaxconn
Максимальное число открытых сокетов, ждущих соединения.
cat /proc/sys/net/core/somaxconn
1024
Увеличиваем:
echo "20000" > /proc/sys/net/core/somaxconn
Так как подобные изменения параметров ядра не сохранятся после перезагрузки – добавляем в /etc/rc.local:
echo "20000" > /proc/sys/net/ipv4/tcp_max_syn_backlog
echo "1" > /proc/sys/net/ipv4/tcp_synack_retries
echo "30" > /proc/sys/net/ipv4/tcp_fin_timeout
echo "5" > /proc/sys/net/ipv4/tcp_keepalive_probes
echo "15" > /proc/sys/net/ipv4/tcp_keepalive_intvl
echo "20000" > /proc/sys/net/core/netdev_max_backlog
echo "20000" > /proc/sys/net/core/somaxconn
Кроме того, можно добавить ограничение числа SYN пакетов в единицу времени в iptables:
iptables -N syn_flood
iptables -A INPUT -p tcp --syn -j syn_flood
iptables -A syn_flood -m limit --limit 500/s --limit-burst 1500 -j RETURN
iptables -A syn_flood -j DROP
Число новых SYN пакетов – максимум 500 в секунду, при превышении порога в 1500 – новые пакеты блокируются:
Более наглядно этот критерий можно представить себе как некоторую емкость с выпускным отверстием, через которое проходит определенное число пакетов за единицу времени (т.е. скорость «вытекания»). Скорость «вытекания» как раз и определяет величина –limit. Величина –limit-burst задает общий «объем емкости». А теперь представим себе правило –limit 3/minute –limit-burst 5, тогда после поступления 5 пакетов (за очень короткий промежуток времени), емкость «наполнится» и каждый последующий пакет будет вызывать «переполнение» емкости, т.е. «срабатывание» критерия. Через 20 секунд «уровень» в емкости будет понижен (в соответствии с величиной –limit), таким образом она готова будет принять еще один пакет, не вызывая «переполнения» емкости, т.е. срабатывания критерия.

http://sergeitvorogov.ru/archives/1390

Защита от DDoS с iptables и ipset





Всех приветсвую. Давно хотел написать что-то подобное, но все не хотел =). Решил полазить интернет, нашол только 1 пример рабочих конфигов, но они были направлены на защиту какого-то самописного сервера. Я раскажу, как защитить сайт, с помощью iptables. Рекомендую ознакомится со следущим небольщим справочником: Iptables FAQ

Далее, немного расскажу, про основные виды защиты не только сайтов.
  • Защита на уровне PHP. Не понимаю логики. Нам необходимо не пустить ботов к этому уровню, так как изза него очень большая нагрузка. Очень нерабочии варианты.
  • Я знаю, а точнее использую 2 способа защиты сервера от атак.
    1. Использование ipset для хранения IP зомби машин, и занос этих IP с использованием коммандлайнера раз в 60 секунд.
    2. Динамически с использованием модуля recent ограничивать запросы.
    Также для начала необходимо немного настроить сам сервер, чтобы он не загибался при 5к запросов.
    # Enables source route verification
    net.ipv4.conf.all.rp_filter = 1
     
    # Enables the magic-sysrq key
    kernel.sysrq = 1
     
    # TCP Explict Congestion Notification
    #net.ipv4.tcp_ecn = 0
     
    # we do not want all our interfaces to send redirects
    net.ipv4.conf.default.send_redirects = 1
    net.ipv4.conf.all.send_redirects = 0
     
    net.ipv4.ip_forward = 1
    net.ipv4.ip_dynaddr = 1
     
    # Controls the maximum size of a message, in bytes
    kernel.msgmnb = 65536
     
    # Controls the default maxmimum size of a mesage queue
    kernel.msgmax = 65536
     
    # Controls the maximum shared segment size, in bytes
    kernel.shmmax = 4294967295
     
    # Controls the maximum number of shared memory segments, in pages
    kernel.shmall = 268435456
     
    net.ipv4.tcp_keepalive_time = 15
    net.ipv4.tcp_keepalive_intvl = 10
    net.ipv4.tcp_keepalive_probes = 5
     
    net.ipv4.tcp_fin_timeout = 30
    net.ipv4.tcp_window_scaling = 0
    net.ipv4.tcp_sack = 0
    net.ipv4.tcp_timestamps = 0
     
    net.ipv4.netfilter.ip_conntrack_max = 224000
    net.ipv4.netfilter.ip_conntrack_tcp_timeout_close = 30
    net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait = 30
    net.ipv4.netfilter.ip_conntrack_tcp_timeout_last_ack = 120
    net.ipv4.netfilter.ip_conntrack_tcp_timeout_close_wait = 30
    net.ipv4.netfilter.ip_conntrack_tcp_timeout_fin_wait = 60
    net.ipv4.netfilter.ip_conntrack_tcp_timeout_established = 190
    net.ipv4.netfilter.ip_conntrack_tcp_timeout_syn_recv = 30
    net.ipv4.netfilter.ip_conntrack_tcp_timeout_syn_sent = 30
    Эти значения подобраны потом и кровью и используются на сервере с 14 гигами памяти. Вам я рекомендую по уменьшать некоторые из них.
    iptables -I INPUT 1 -p tcp -m tcp --dport 80 --tcp-flags FIN,SYN,RST,ACK SYN -m connlimit --connlimit-above 15 --connlimit-mask 32 -j DROP
    Устанавливаем число одновременных запросов на IP с префиксом/32 — максимум 15, остальное в DROP.
    ipset -N blacklist iphash
    iptables -A INPUT -p tcp -m tcp --dport 80 -m set --set blacklist src -j DROP
    Создаем специальный сет для хранения IP. При больших потоках запросов, а также over 100 правил вида:
    iptables -A INPUT -s x.x.x.x -j DROP
    Вы будите иметь колосальную нагрузку на свой сервер, но это единственный вариант для OpenVZ виртуализации, все экзотические правила, требуют специальных модулей, просите свой саппорт чтобы они на вашу ВМ их подключили.
    Преимущества ipset
    1. В одном списке, не может быть одинаковых записей. В iptables это не запрещено, поэтому ухудшается отклик сетевой подсистемы.
    2. Один списко позволяет хранить до MAX_INT(65k) записей.
    3. Хранятся они в виде бинарного дерева(может быть и не так =) ), что позволяет снизить кол-во проверок до log(кол-во записей) в худшем случае.
    Все мои коммандлайнеры предназначены для глобального access.log’а nginx’а. Если у вас другой вид записей, то тут уже правьте сами (:
    Давайте рассмотрим ситуацию, когда ддосят на / сайта. В принципе особой разницы нет что и как ддосят ,просто правим немного grep запрос и все (:
    256.256.256.256 - - [07/Mar/2011:06:23:16 +0300] "GET / HTTP/1.1" 200 2437 "-" "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.224 Safari/534.10" "example.com" "2437"  "0.019"
    В момент атаки на сервер сыпятся кучи таких запросов. Что нам нужно определить?
    1. Нужно найти IP который лезет на атакующий URL.(в данном случае на / сайта, хотя могут быть и /index.php /captcha.php и др.)
    2. Нашли, проверить что за последнии N записей в логе, он обратился к любому из этих URL более K раз. Тогда это наш клиент и мы его благополучно шлем по дальше.
    Начинаем по маленьку парситть логи. Так как tail -f нам дает большую задержку с использованием grep, awk, cut пока не заполнятся их буферы на чтение, будем использовать tail -n N (кол-во строк которые смотрим)
    Не забудьте в конечном варианте испроваить K на сколько вам нужно. На средних атаках, до 1к ботов я использую 15 на 10к строк логов.
    while true; do tail -n 1000 /var/log/nginx/access.log | grep "example\.org" | grep " GET / HTTP" ; sleep 60; done
    Все. Можете запустить на своем сервере, ессно сменив example.org на ваш домен, и хотя вообще можете полностью выкинуть этот греп, на этапе создания коммандлайнера он не нужен. Далее выдергиваем IP адрес клиента.
    while true; do tail -n 1000 /var/log/nginx/access.log | grep "example\.org" | grep " GET / HTTP" | cut -d " " -f1 ; sleep 60; done
    На выходе получаем:
    256.256.256.256
    
    Это всего лиш гипотетический пример, поэтому смотрите в оба (:
    Далее, нам нужно проверить, что все ипы у нас встречаются не более К раз, если такое случилось сразу его в магадан =)
    while true; do tail -n 1000 /var/log/nginx/access.log | grep "example\.org" | grep " GET / HTTP" | cut -d " " -f1 | sort | uniq -c; sleep 60; done
    Выход такой:
    1 256.256.256.256
    
    Первое число, кол-во повторений, второе сам IP. Далее awk выдергиваем то что нам нужно (:
    while true; do tail -n 1000 /var/log/nginx/access.log | grep "example\.org" | grep " GET / HTTP" | cut -d " " -f1 | sort | uniq -c | awk '{if($1>K){print $2}}'; sleep 60; done
    Вот и все. Мы получили IP тех, кто встретился нам более К раз. Осталось только его забанить.
    while true; do tail -n 1000 /var/log/nginx/access.log | grep "example\.org" | grep " GET / HTTP" | cut -d " " -f1 | sort | uniq -c | awk '{if($1>K){print $2}}' | xargs -tl -I _ ipset -A blacklist _; sleep 60; done
    На выходе увидете всякое разное (: .
    Перед началом написания коммандлайнера, нужно проверить какие запросы шлются на сервер:
    tail -f /var/log/nginx/access.log
    Если по какойто причине у вас атакующих ссылок несколько, а может быть что в конце ссылки стоит рандомное число, то вот тут нужно по другому делать
    grep -e "GET / HTTP" -e "GET /index.php HTTP" -e "GET /captcha.php HTTP"
    Есть еще один вариант, когда /index.php?123456789 куча цыферок. Вот в данном случае есть только 1 способ это все выдернуть, никакие iptables не помогут. Там нет регепсов.
    pcregrep --color "GET \/index\.php\?([0-9]+) HTTP"
    Ну а если я не разобрал ваш пример, пишите в комментарии, давайте урлы, или полностью строчки с логов, я и для них напишу паттерн. Чтобы ддосеры не спали, и занимались тренировкой мозгов.
    Вроде бы первый способ я озвучил. Давайте займемся вплотную Iptables
    recent match doc
    Читаем брошурку и понимаем. Также можете посмотреть на nth match. Очень интерстный, но я пока не придумал как его в нашей ситуации можно использовать, если вы знаете, пишити в комментариях.
    Вот тут уже не получится фильтровать сразу за раз несолько урлов, и каждое правило применяется абсолютно ко всем доменам, так как действует на уровне всего сервера.
    iptables -A INPUT -p tcp -m tcp --dport 80 -m string --string "GET / HTTP" --algo kmp --to 1024 -m recent --set --name httpddos --rsource 
    iptables -A INPUT -p tcp -m tcp --dport 80 -m string --string "GET / HTTP" --algo kmp --to 1024 -m recent --update --seconds 10 --hitcount 2 --name httpddos --rsource -j DROP
    Данные 2 правила делют следущее:
    Приходит пакет, если в нем есть «GET / HTTP», то обрабатывается слудущим модулем — recent. Если этого нет, то идет на следущее правило. Записали в память. Если в течении 10 секунд с этого IP еще раз придет запрос который удовлетворит GET / HTTP, то тогда этот запрос идет в DROP. Вот и весь смысл. Все просто, просто нужно чуточку почитать документацию, и погуглить, уже есть куча решений, но не всегда то что вам нужно.
    Есть одна проблема с модулем recent. Это количество запоминающихся IP адресов по дефолту.
    parm:           ip_list_tot:number of IPs to remember per list (uint)
    parm:           ip_pkt_list_tot:number of packets per IP to remember (max. 255) (uint)
    parm:           ip_list_hash_size:size of hash table used to look up IPs (uint)
    parm:           ip_list_perms:permissions on /proc/net/ipt_recent/* files (uint)
    parm:           ip_list_uid:owner of /proc/net/ipt_recent/* files (uint)
    parm:           ip_list_gid:owning group of /proc/net/ipt_recent/* files (uint)
    ip_list_tot = 100. для этого нам нужно сделать
    modprobe ipt_recent ip_list_tot=4000
    При большом количестве pps при большом количестве этого параметра, ksoftirq процесс может начать жрать кучу CPU.
    ip_list_tot = 100
     
    Просмотреть количество записей в данный момент можно с помощью команды:
    wc -l /proc/net/ipt_recent/*
    Одно главное замечание, все это применимо к Debian Lenny. Как все это использовать в франкенштейне CentOS пинайте, пожалуйста не меня, а гугл.

    Все эти методы я использую во время ддоса. Жду комментариев (:
  • Защита на уровне Apache. mod_evasive когдато пользовал, толку с него не намного больше чем от PHP
  • Защита на уровне nginx. Вот этот этап в проходе запроса уже более менеее нормальный. Можно закешировать страницы и nginx их будет отдавать практически без загрузки проца. Только канал будет использоваться гораздо более. Также можно настроить limit_req. Что это — читаем сайт sysoev.ru
  • Защита на уровне iptables. Этот этап мы будем сегодня рассматривать, так как это один из самых эффективных способов защиты сервера.
  • Постоянные читатели