Solving IT problems and building solutions

  • Wednesday, November 7, 2012

    Борьба с DDoS атаками средствами iptables и sysctl


    Сегодня я попытаюсь привести пример конфигурации фаервола, а также оптимизации системных настроек для повышения устойчивости сервера к так называем атакам типа «отказ в обслуживании».
    Информации в поисковиках на эту тему море, но, как обычно, это или малограмотные или очень разрознененные и не сведённые в одну схему примеры.
    Ниже приводится листинг разрешительной (не такой жёсткой как запретительная) политики настройки iptables, а также пример оптимизации настроек sysctl. В результате будет ограничено количество одновременных подключений с одного ip адреса на порт веб-сервера, сервера DNS, а также ограничено количество подключений к службе ssh (3 подключения за 5 минут с одного ip-адреса). Будет реализована защита от спуфинга на уровне файрвола, а также на уровне ядра.

    Хорошее развёрнутое русское руководство по iptables с подробным разъяснением принципов его работы и примерами использования (некоторые из которых используются чуть ниже) можно найти в статье iptables на Википедии (sic!), а про sysctl тут http://debian.telenet.ru/doc/sysctl.conf
    
    
    
    
    # БОРЬБА С DDOS
     
    iptables -N ssh_brute_check # Создаем цепочку для проверки попыток соединений на защищаемый порт
    # Если за последние 5 минут (300 секунд) с одного адреса было 3 или более новых соединений — блокируем этот адрес
    iptables -A ssh_brute_check -m conntrack --ctstate NEW -m recent --update --seconds 300 --hitcount 3 -j DROP
    # В противном случае — разрешаем, и при этом заносим в список
    iptables -A ssh_brute_check -m recent --set -j ACCEPT
    iptables -F INPUT # Очищаем цепочку INPUT
    iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Разрешаем пакеты по установленным соединениям
    # Все попытки открыть новое соединение по SSH направляем на проверку
    iptables -A INPUT -m conntrack --ctstate NEW -p tcp --dport 22 -j ssh_brute_check
    # Здесь можно разрешать те порты, для которых такая проверка не нужна. Например, HTTP
    iptables -A INPUT -m conntrack --ctstate NEW -p tcp --dport 80 -j ACCEPT
    iptables -P INPUT ACCEPT
     
     
    # позволяет узнать сколько одновременных подключений на порт с 1 айпи
    # netstat -plan | grep :80 | awk '{print $5}' | awk -F: '{print $1}' | sort | uniq -c
    # netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n
     
    # устанавливаем максимальное количество подключений с одного айпи.
    # В браузерах эта количество подключений к серверу ограничено 16 соединениями,
    # но стоит учитывать тех, кто сидит за NAT, а также что пользователь
    # может открыть 2 сайта на разных айпишниках одного и того же сервера.
    # Данный параметр подбирается оптимально с помощью предыдущей команды.
    iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 32 -j DROP
    iptables -A INPUT -p tcp --dport 80 -j ACCEPT
    # то же для DNS
    iptables -A INPUT -p udp --dport 53 -m connlimit --connlimit-above 8 -j DROP
    iptables -A INPUT -p udp --dport 53 -j ACCEPT
     
    # будет препятствовать спуфингу от нашего имени.
    # Ведь если мы получаем пакет с установленными флагами SYN и ACK
    # (такой комбинацией флагов обладает только ответ на SYN-пакет) по еще не открытому соединению,
    # это означает, что кто-то послал другому хосту SYN-пакет от нашего имени, и ответ пришел к нам.
    # Конечно, злоумышленнику предстоит еще угадать номер последовательности.
    # Согласно приведенному правилу, наш хост ответит RST-пакетом, после получения которого
    # атакуемый хост закроет соединение.
    iptables -I INPUT -m conntrack --ctstate NEW,INVALID -p tcp --tcp-flags SYN,ACK SYN,ACK -j REJECT --reject-with tcp-reset
     
    # Для защиты от SYN атак включаем SYN-cookies
    sysctl -w net.ipv4.tcp_syncookies=1
    # Увеличиваем размер очереди полуоткрытых соединений (также полезно при SYN флуде) (default 512)
    sysctl -w net.ipv4.tcp_max_syn_backlog=4096
    # Проверять TCP-соединение каждую минуту. Если на другой стороне - легальная машина, 
    # она сразу ответит. Дефолтовое значение - 2 часа.
    sysctl -w net.ipv4.tcp_keepalive_time=60
    # Повторить пробу через десять секунд
    sysctl -w net.ipv4.tcp_keepalive_intvl=10
    # Количество проверок перед закрытием соединения
    sysctl -w net.ipv4.tcp_keepalive_probes=5
    # Фильтр обратного пути, защита от спуфинга (подмены адресов)
    sysctl -w net.ipv4.conf.default.rp_filter=1
    # Уменьшение времени удержания «полуоткрытых» соединений
    # Сделаем так, чтобы перепередача осуществлялась на 3 секунде
    # и  полное время хранения полуоткрытых соединений в очереди составило 9 секунд
    sysctl -w net.ipv4.tcp_synack_retries=1
    # Изменяем время ожидания приема FIN до полного закрытия сокета
    sysctl -w net.ipv4.tcp_fin_timeout=10

    No comments:

    Post a Comment