Skip to content

24 Декабрь 2012

167

Ubuntu Linux: Базовая защита от DDOS с помощью iptables

iptables

Чаще всего люди задумываются о защите, когда уже слишком поздно. Когда уже за спиной час, два, а то и день downtime’а. Конечно для полноценной защиты нужно что-то большее чем iptables. Но и серьезные атаки, требующие такую защиту случаются гораздо реже. В общем описанное под катом — must have для любого сервера. И да, речь пойдет об общей защите (не только сайтов), без использования модулей, nginx, apache. Только iptables и настройки Linux.

:!:  Системные настройки:

В первую очередь настраиваем sysctl. Для этого идем в /etc/sysctl.d, создаем новый файл с названием 60-custom.conf, открываем на редактирование. Мой вариант хорошего конфига, устойчивого к DDOS, собран из кучи разных полезных статей:

net.ipv4.tcp_max_syn_backlog = 4096
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_synack_retries = 1
net.ipv4.netfilter.ip_conntrack_tcp_timeout_syn_recv = 30
net.ipv4.netfilter.ip_conntrack_tcp_timeout_syn_sent = 30
net.netfilter.nf_conntrack_tcp_timeout_established = 86400
net.netfilter.ip_conntrack_tcp_timeout_established = 86400
net.ipv4.tcp_keepalive_time = 60
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_keepalive_intvl = 10
net.core.somaxconn = 4096
net.core.rmem_default = 262144
net.core.wmem_default = 262144
net.core.rmem_max = 8388608
net.core.wmem_max = 8388608
net.core.netdev_max_backlog = 8192

Для применения только что измененных настроек, необходимо перезапустить службу: service procps restart

:!:  Оптимизация сервисов:

Перед тем как приступать к какой-либо защите, нужно настроить ваши сервисы (демоны) на оптимальную производительность. Если вы защищаете сайт — уделите время настройкам nginx и apache. Если какой-то другой сервис — настройте его. Цель такого тюнинга — дабиться того, чтобы сервис сбрасывал мертвые соединения как можно скорее и тем самым не расходовал лишние ресурсы. Естественно это особенно важно при защите от DDOS атак.

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

Apache

Файл настроек: /etc/apache2/apache2.conf

Вот два параметра, на которые следует обратить внимание. Их можно уменьшить как минимум на половину.

#
# Timeout: The number of seconds before receives and sends time out.
#
Timeout 60

#
# KeepAliveTimeout: Number of seconds to wait for the next request from the
# same client on the same connection.
#
KeepAliveTimeout 10

MySQL

Конечно напрямую базу не достанут, она же доступна только по localhost’у. Если у вас это не так — срочно покиньте этот блог :slim:  Но если сайт работает с базой — то при каждом запросе (в том числе и ddos’e) будет работать база, забирая ресурсы машины. Поэтому тюнинг ее настроек тоже нужен.

Файл настроек /etc/mysql/my.cnf

Советую обратить внимание на этот параметр и по возможности его уменьшить:

[mysqld] 
wait_timeout=60

:!: Настраиваем iptables:

Итак, фаервол в Linux имеем массу интересных возможностей, которые помогут защитить сервер от детского ддоса, а может быть и от некоторых видов взрослого. Настраивается iptables скриптом,  который необходимо запускать при каждом старте системы, т.к. при перезагрузке правила стираются. Есть несколько вариантов как добавить его в автозапуск, но лучше этого не делать. Потому что если вы лишите себя ssh доступа — единственный вариант получить доступ без звонка в дата центр — это перегрузить сервер по питанию, обычно такая возможность предоставляется.

Мой шаблон настроек:

#!/bin/bash

IPT='iptables'

# Prepare and set up iptables modules
rmmod xt_recent
modprobe ipt_recent ip_list_tot=5000 ip_pkt_list_tot=255

# FLUSH
$IPT -F
$IPT -X

$IPT -t nat -F
$IPT -t mangle -F
$IPT -t raw -F
$IPT -t filter -F

$IPT -t nat -X
$IPT -t mangle -X
$IPT -t raw -X
$IPT -t filter -X

echo "FLUSH TABLES";

# Create custom chains
$IPT -N BAN
$IPT -N SUSPIC

### banned ###
#$IPT -A INPUT --source 77.40.0.0/24 -j REJECT

echo "ADDED BANS";

## 1)
## BAN: drop all for 30 minutes from this IP
## SUSPIC: 3 suspic messages in 60 secs = ban
##

$IPT -A INPUT -m recent --name ban --rcheck --seconds 1800 --hitcount 1 -j DROP
$IPT -A INPUT -m recent --name suspic --rcheck --seconds 60 --hitcount 3 -j BAN

$IPT -A SUSPIC -m recent --name suspic --set -j DROP
$IPT -A BAN -m recent --name ban --set -j DROP

## 2)
## Drop broken packets. NEW packet alway must be have --syn flag.
##

$IPT -A INPUT -p tcp ! --syn -m state --state NEW -m multiport --dports 80,443,... -j DROP

## 3)
## Max established connections from 1 IP
##

$IPT -A INPUT -p tcp --dport 22 -m connlimit --connlimit-above 10 -j DROP

## 4)
## Protect SSH agains port scan. ACCEPT only after 2 connection trys in 15 sec
##

$IPT -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --name ssh --set
$IPT -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --name ssh ! --rcheck --seconds 3600 --hitcount 3 -j REJECT

## 5)
## Drop burst connections. Use hashlimit instead of limit due to possibility to limit connections from one IP.
##

$IPT -A INPUT -p tcp --dport 22 -m state --state NEW -m hashlimit ! --hashlimit 2/s --hashlimit-burst 1 --hashlimit-mode srcip --hashlimit-name SSH -j DROP
$IPT -A INPUT -p tcp --dport 80 -m state --state NEW -m hashlimit ! --hashlimit 4/s --hashlimit-burst 40 --hashlimit-mode srcip --hashlimit-name SITE -j SUSPIC

echo "ADDED RULES";

Это базовые настройки и не очень жесткие. Если хотите ужесточить — можно сделать policy на дроп всего и открывать отдельно только те порты и соединения, которые нужны.

Шаблон естественно нужно адаптировать под вашу ситуацию и ваши сервисы.

Секции в шаблоне пронумерованы, так что пройдем по ним и поймем что же происходит:

  1. Создано 2 новых цепочки: SUSPIC и BAN. Вы можете отправлять туда неудоволетворяющие соединения вместо DROP’а. Если было 3 SUSPIC за 60 секунд с одного IP адреса — такой хост автоматически получает BAN. А бан DROP’ает все пакеты с этого IP в течении 30 минут.
  2. Спорное правило. Инициализация соединений всегда должна содержать в себе syn пакет, если его нет — считается что соединение некорректно и сразу уходит в DROP. Вообще конечно это правильно, но некоторые сервисы с таким правилом могут не работать или работать плохо.
  3. Тут все легко — максимум открытых соединений с одного IP
  4. Правило защищает порты от сканирования. В данном примере — SSH порт. Трюк прост — начинаем пускать соединения только с третьего раза. Сканер портов обычно сканирует 1-2 раза порт, редко больше.
  5. Основное правило от ддоса. Защищаемся от резких перепадов кол-ва соединений в промежуток времени. В шаблоне 2 правила. Первое блокирует на 2 секунды все соединения с IP, если превышен лимит подключений с этого IP. Лимит подключений для первого правила — 1 соединение в 2 секунды. Соответственно лимит второго правила — 40 подключений в 4 секунды и блокировка на 4 секунды.

Для проверки как все работает, какие правила есть и сколько пакетов какие правила отфильтровали, используем команду:  iptables -nvL

:!: DROP vs REJECT

Можно фильтровать нежелательные пакеты несколькими способами.

  • DROP — для клиента это означает «нет ответа», то есть как будто на этом порту вообще ничего нет.
  • REJECT — клиенту возвращается ответ «соединение отклонено».

На мой взгляд лучше использовать DROP всегда когда это возможно. Это заставит атакующие машины выжидать таймаут.

:!: Полезное

  • Мануал по iptables: http://ipset.netfilter.org/iptables.man.html
  • Хорошо освещены некоторые возможности: http://suvan.ru/page/rashirenia-pravil.html
  • Все IP адреса и кол-во соединений с них, отсортированные по возрастанию:
    netstat -anp | grep 'tcp\|udp' | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n
  • Тоже самое, но на определенный порт:
    netstat -plan|grep :80|awk {'print $5'}|cut -d: -f 1|sort|uniq -c|sort -nk 1
  • Вывод всех соединений на определенном порту:
     netstat -na | grep ":8090\ " | sort | uniq -c | sort -nr | less
  • Количество открытых соединений и их тип:
    netstat -nat | awk '{print $6}' | sort | uniq -c | sort -n | sed 's/d)/d/'
  • Тоже самое, но на определенный порт:
    netstat -nat |grep :80| awk '{print $6}' | sort | uniq -c | sort -n | sed 's/d)/d/'
  • Сброс всех TIME_WAIT соединений:
    SEC_TO_TIMEWAIT=1 
    echo ${SEC_TO_TIMEWAIT} > /proc/sys/net/ipv4/tcp_tw_recycle 
    echo ${SEC_TO_TIMEWAIT} > /proc/sys/net/ipv4/tcp_tw_reuse
167 коммент.
  1. Sharm
    10 Мар 2013

    upd.

    Обновлен шаблон iptables, добавлены цепочки SUSPIC, BAN

    Более детальное описание правил

    Добавлены новые полезные команды

  2. Sharm
    31 Мар 2013

    upd.
    Обновлен конфиг sysctl

  3. Jeka
    23 Янв 2014

    ERROR: Module xt_recent is in use
    FLUSH TABLES
    ADDED BANS
    iptables v1.4.7: invalid port/service `…’ specified
    Try `iptables -h’ or ‘iptables —help’ for more information.
    ADDED RULES

    О эффективности смогу отписаться позже ;)

Обсуждение закрыто.