Вики IT-KB

Пошаговые руководства, шпаргалки, полезные ссылки...

Инструменты пользователя

Инструменты сайта


unix-linux:ubuntu:ubuntu-14-04-lts-trusty-tahr:how-to-install-lemp-web-server-on-ubuntu-14-04:enhancing-system-security-via-iptables-and-sysctl-for-anti-dos-and-against-syn-icmp-udp-http-flood

Настройка веб-сервера на базе стека LEMP в Ubuntu Server 14.04 LTS. Часть 3. Усиление безопасности системы.

Настройка параметров sysctl

Добавляем в /etc/sysctl.conf некоторые параметры, которые помогут усилить стойкость системы перед всевозможными флуд-атаками:

/etc/sysctl.conf
#
# Включаем фильтрацию входящих пакетов, 
# которые были отправлены одним интерфейсом, а приняты другим.
#
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.lo.rp_filter = 1
net.ipv4.conf.eth0.rp_filter = 1
 
# Запрещаем маршрутизацию от источника.
# Маршрутизация от источника (source routing) позволяет отправителю
# определить путь, по которому пакет должен пройти по сети Internet, чтобы
# достигнуть пункта назначения. Это очень удобно для изучения и отладки
# работы сети, но нарушитель получает возможность подмены адресов
# компьютеров локальной сети. 0 означает, что маршрутизация отключена, 1 - наоборот.
#
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.lo.accept_source_route = 0
net.ipv4.conf.eth0.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
 
# Выключаем приём и отправку ICMP-пакетов перенаправления.
# Включение параметров имеет смысл только на муршрутизирующем сервере, а у нас задачи другие.
#
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.all.send_redirects = 0
 
# Увеличиваем порог осиротевших (orphan) соединений.
# При возникновении проблем, связанных с этим ограничением  в
# системный журнал будет записано сообщение, подобное этому: TCP: too many
# of orphaned sockets Это может служить поводом к тому, чтобы пересмотреть
# значения переменных tcp_fin_timeout или tcp_orphans_retries.
# Значение по умолчанию 16384
#
net.ipv4.tcp_max_orphans = 65536
 
# Использовать более частую проверку TCP-соединений. 
# Если на другой стороне - реальная машина, она сразу ответит.
# Значение переменной имеет смысл только для тех сокетов, 
# которые были созданы с флагом SO_KEEPALIVE 
# Значение по умолчанию - 7200 секунд / 2 часа.
#
net.ipv4.tcp_keepalive_time = 1800
 
# Уменьшаем интервал проверки жизнеспособности TCP-соединения.
# Это значение учитывается при подсчете времени, 
# которое должно пройти перед тем как соединение будет разорвано.
# Значения по-умолчанию:
# net.ipv4.tcp_keepalive_intvl = 75 секунд. 
# net.ipv4.tcp_keepalive_probes = 9
# Значения этих переменных могут использоваться для определения времени, 
# через которое соединение будет разорвано. 
# Со значениями по-умолчанию (9 попыток с интервалом 75 секунд) это займет примерно 11 минут. 
# Попытки определения жизнеспособности, в свою очередь, начнутся через интервал времени 
# определённый в tcp_keepalive_time после того, 
# как через данное соединение проследовал последний пакет. 
#
net.ipv4.tcp_keepalive_intvl = 15
net.ipv4.tcp_keepalive_probes = 5
 
# Отключаем ответы на ICMP-запросы, чтобы защититься от ICMP-флуда
# Как альтернативный вариант закрыть ICMP на iptables: 
# iptables -A INPUT -p icmp -j DROP --icmp-type 8
#
net.ipv4.icmp_echo_ignore_all = 1
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
 
# Включаем передачу syncookies вызывающему хосту в случае переполнения 
# очереди SYN-пакетов для заданного TCP-соединения.
#
net.ipv4.tcp_syncookies=1
 
# Увеличиваем очередь «полуоткрытых» TCP-соединений 
# (максимальное число запоминаемых запросов на соединение, 
# для которых не было получено подтверждения от подключающегося клиента)
# Эта опция работает только тогда, когда включена переменная tcp_syncookies. 
# Если сервер испытывает серьезные нагрузки, то можно попробовать увеличить этот параметр. 
# Значение по-умолчанию равно 128. 
# Если сервер имеет больше 128MB ОЗУ, то значение можно установить в 1024 и более. 
#
net.ipv4.tcp_max_syn_backlog = 1024
 
# Уменьшаем количество попыток передачи SYN,ACK-пакета в ответ на SYN-запрос. 
# т.е. максимальное число попыток установить пассивное TCP-соединение, 
# инициированное другим хостом. 
# Значение по-умолчанию 5.
#
net.ipv4.tcp_synack_retries = 2
 
# Уменьшаем время пребывания сокета в состоянии FIN-WAIT-2 (целое число в секундах) 
# Используется в тех случаях, когда другая сторона 
# по тем или иным причинам не закрыла соединение со своей стороны. 
# Каждый сокет занимает в памяти порядка 1.5 Кб, 
# что может привести к значительным утечкам памяти в некоторых случаях. 
# Значение по умолчанию - 60 секунд.
#
net.ipv4.tcp_fin_timeout = 10
 
# Увеличиваем длинну очереди пакетов на обработку в случае, 
# если интерфейс получает пакеты быстрей, чем ядро сможет обработать их.
# Значение по умолчанию 1000.
#
net.core.netdev_max_backlog = 10000
 
# Увеличиваем максимальное число всех открытых сокетов которые ждут соединения.
# Значение по умолчанию 128.
#
net.core.somaxconn = 10240
 
# Отключаем сохранение результатов измерений TCP-соединения в кеше при его закрытии. 
# Может положительно повлиять на производительность
#
net.ipv4.tcp_no_metrics_save = 1
 
# Включаем реализацию защиты от TIME_WAIT атак.
#
net.ipv4.tcp_rfc1337 = 1
 
# Запрещаем переадресацию пакетов (имеет смысл на маршрутизаторе)
#
net.ipv4.ip_forward = 0

Сохраним файл и применим его изменения в системе:

sudo sysctl -p



Настройка iptables


Защита от атак UDP flood

Атаки UDP flood основаны на массированной посылке UDP-пакетов на порты различных UDP-сервисов. Защиту можно реализовать путём изоляции UDP-сервисов от Интернет (если это возможно) или путём установки лимита количества соединений в единицу времени от каждого отдельно взятого внешнего IP. Например, если наружу выставлен DNS-сервис (порт UDP 53), можно попробовать настроить такое ограничение с помощью iptables следующим правилом:

sudo iptables -I INPUT -p udp --dport 53 -j DROP -m iplimit --iplimit-above 1


Ограничение TCP подключений

Атаки HTTP flood основаны на массовой посылке HTTP-сообщений GET на TCP-порт веб-сервера с целью создания критической нагрузки на сервер. При этом посылаться запросы могут как к корню веб-сервера, так и к всевозможным ресурсоёмким скриптам. Помимо общей нагрузки на систему HTTP flood может привести к аномальному росту логов веб-сервера.

Далее можно поставить ограничение по количеству одновременных соединений

# Лимит 1000/сек пакетов всего
sudo iptables -N TCP-FLOOD
sudo iptables -I INPUT -p tcp -m multiport --dports 80,443,758 -i eth0 -j TCP-FLOOD \
 -m comment --comment "Limit TCP connections"
sudo iptables -A TCP-FLOOD -m limit --limit 1000/sec -j RETURN \ 
 -m comment --comment "Limit TCP connections"
sudo iptables -A TCP-FLOOD -j DROP -m comment --comment "Limit TCP connections"


Защита от атак SYN flood

Ограничиваем максимальное число «полуоткрытых» соединений с одного IP к конкретному порту (не больше 50 соединений на каждый IP):

sudo iptables -A INPUT -p tcp --syn -m multiport --dports 80,443,522 \ 
 -m connlimit --connlimit-above 50 -j REJECT \
 -m comment --comment "Prevent SYN flood"

Отбрасываем неправильно сформированные пакеты:

sudo iptables -A INPUT -m conntrack --ctstate INVALID -j DROP \ 
 -m comment --comment "Prevent invalid packets"

Не забываем сохранить правила iptables:

sudo sh -c "iptables-save > /etc/iptables.conf"


Защита от атак SYN flood (скрипт с netstat и ipset)

Предварительно проверить ситуацию на наличие присутствия SYN_RECV соединений можно посчитав их количество:

sudo netstat -n --tcp | grep SYN_RECV | wc -l

Другой пример. Просмотр количества полуоткрытых соединений в разрезе IP

netstat -nap | grep SYN_RECV | awk {'print $5'} | awk -F: {'print $1'} | sort -rn | uniq -c | sort -rn

Рассмотрим пример скрипта для зашиты от атак TCP SYN flood с использованием связки iptables + ipset + netstat. ipset - это расширение для iptables, которое позволяет работать с большими массивами данных, например IP-адресов, обработка которых может быть вызвана из правил iptables Чтобы установить расширение выполним:

sudo apt-get install ipset

После того как пакет установлен, создаём собственную цепочку ipset, например с названием «DOS-SRC»

sudo ipset -N DOS-SRC iphash

Добавляем в iptables в цепочке INPUT правило блокирования всех пакетов для всех хостов, которые обнаруживаются в цепочке ipset «DOS-SRC»:

sudo iptables -I INPUT 1 -m set --match-set DOS-SRC src -j DROP \ 
 -m comment --comment "Prevent SYN_RECV DOS"

Сохраняем правила iptables:

sudo sh -c "iptables-save > /etc/iptables.conf"

Создадим каталоги для хранения вспомогательных файлов…

Каталог для хранения скрипта обновления цепочек ipset (ipset-DOS-SRC-refresh.sh):

sudo mkdir /etc/ipset/
sudo chmod 755 /etc/ipset/

Каталог для сохранения файла цепочек ipset (ipset.conf):

sudo mkdir /var/local/ipset/
sudo chmod 755 /var/local/ipset/

Создадим скрипт, с помощью которого будет обновляться созданная нами ранее цепочка ipset «DOS-SRC»:

sudo touch /etc/ipset/ipset-DOS-SRC-refresh.sh
sudo chmod +x /etc/ipset/ipset-DOS-SRC-refresh.sh
sudo nano /etc/ipset/ipset-DOS-SRC-refresh.sh

Наполним скрипт содержимым:

/etc/ipset/ipset-DOS-SRC-refresh.sh
#!/bin/bash
IFCONFIG=/sbin/ifconfig
GREP=/bin/grep
AWK=/usr/bin/awk
CUT=/usr/bin/cut
NETSTAT=/bin/netstat
IPSET=/sbin/ipset
IPTABLES=/sbin/iptables
SORT=/usr/bin/sort
UNIQ=/usr/bin/uniq
srvIP=`$IFCONFIG eth0 | $GREP 'inet addr' | $AWK '{print $2}' | $CUT -f2 -d ":"`
for i in `$NETSTAT -ntu | $GREP SYN_RECV | $AWK '{print $5}' | $CUT -f1 -d ":" | $SORT | $UNIQ | $GREP -v ${srvIP}`
do
$IPSET -A DOS-SRC $i
done
$IPSET -S > /var/local/ipset/ipset.conf

Скрипт анализирует вывод команды netstat, выбирает соединения в состоянии SYN_RECV (признак SYN флуда) и добавляет эти IP в цепочку «DOS-SRC» утилиты ipset, а члены этой цепочки в свою очередь в режиме реального времени блокируется в iptables в цепочке INPUT.

Запустим скрипт для проверки того, что при его запуске из cron не возникнет проблем:

sudo sh -c "/sbin/ipset -S > /var/local/ipset/ipset.conf"

В файл /etc/rc.local добавляем строчку восстановления сохранённого списка заблокированных адресов после перезагрузки системы:

sudo nano /etc/rc.local

Впишем команду загрузки ранее сохранённых правил ipset из файла ipset.conf (строку добавлять нужно до команды загрузки основных правил iptables):

/etc/rc.local
#
# Load ipset chains and rules
cat /var/local/ipset/ipset.conf | /sbin/ipset -R
#
# Load iptables rules from this file
iptables-restore < /etc/iptables.conf
#
exit 0

Теперь нам нужно настроить периодическое выполнение скрипта ipset-DOS-SRC-refresh.sh. Создадим для этого файл задачи cron:

sudo touch /etc/cron.d/ipset-DOS-SRC-refresh
sudo nano /etc/cron.d/ipset-DOS-SRC-refresh

Наполним его содержимым таким образом, чтобы наш скрипт выполнялся раз в минуту:

/etc/cron.d/ipset-DOS-SRC-refresh
#
# Regular cron job for ipset chain DOS-SRC update
#
*/5 * * * *   root /etc/ipset/ipset-DOS-SRC-refresh.sh

Через 10 минут проверим по логу, что наш скрипт успешно дёргается планировщиком cron

sudo grep CRON /var/log/syslog

В логе должны присутствовать записи о выполнении скрипта через заданные нами интервалы времени:

Mar 22 11:45:01 WEB-SERVER CRON[1557]: (root) CMD (/etc/ipset/ipset-DOS-SRC-refresh.sh)
Mar 22 11:50:01 WEB-SERVER CRON[1623]: (root) CMD (/etc/ipset/ipset-DOS-SRC-refresh.sh)
Mar 22 11:55:01 WEB-SERVER CRON[1677]: (root) CMD (/etc/ipset/ipset-DOS-SRC-refresh.sh)


Проверяем сохранение цепочек ipset при перезагрузке системы

Для проверки можно вручную добавить какой-то IP в созданную нами цепочку ipset, а затем посмотреть состояние всех цепочек ipset:

sudo ipset -A DOS-SRC 111.111.111.111
sudo ipset -L

После этого перезагружаем сервер, чтобы убедиться в том, что правила успешно создаются в iptables и ipset в процессе загрузки системы.

Для удаления конкретного IP из цепочки ipset можно воспользоваться командой:

sudo ipset del DOS-SRC 111.111.111.111


Проверяем работу механизма автоматической блокировки

Воспользуемся утилитой hping3, чтобы пофлудить на наш сервер по известному порту (предполагается что порт открыт) пакетами TCP SYN. Разумеется, флуд нужно выполнять с другого внешнего IP, отличного от IP нашего сервера.

Пример использования:

sudo hping3 -i u1 -S -p 80 11.22.33.44

где: S - отсылка флага SYN p 80 - номер атакуемого порта i u1 - интервал в 1 микросекунду между отправляемыми пакетами.

Согласно нашим настройкам, не более чем через 5 минут после начала атаки на нашем сервере в цепочке ipset должен будет появиться IP адрес злоумышленника, и как следствие, любой трафик с него будет заблокирован. Напомню, что проверить текущее состояние цепочек ipset, выполним:

sudo ipset -L


Учётная запись root

Если ОС Ubuntu на вашем сервере развёрнута не вами самостоятельно, а вы взяли готовый шаблон преднастроенной виртуальной машины у хостера, то есть рекомендация перед началом использования системы убедиться в том, что учётная запись root выключена. Некоторые хостинг провайдеры могут включать эту учётную запись в Ubuntu.

Проверить состояние можно в файле /etc/shadow. Если учётная запись включена (не имеет признака «!»), выключить её можно командой:

sudo passwd -l root


Дополнительные источники информации

Обсуждение

Алексей МаксимовАлексей Максимов, 02.04.2016 19:24
Добавление в ipset адресов,которые имеют больше,например, 1000 подключений при анализе текущих подключений:

netstat -na | awk '{print $5}' | awk -F: '{print $1}' | sort -rn | uniq -c | sort -rn | grep -v "127.0.0.1\|0.0.0.0" | grep -v ^$ | awk '($1>1000){print $2}' | xargs -tl -I _ ipset -A ddos _

Источник: https://kamaok.org.ua/?p=577
GordanGordan, 05.02.2018 17:49
У меня при выполнении запроса grep CRON /var/log/syslog выдало

grep: /var/log/syslog: Нет такого файла или каталога
GordanGordan, 06.02.2018 15:49
При выполнении
ipset -A DOS-SRC 111.111.111.111
Выдаётся сообщение
ipset v6.29: The set with the given name does not exit
Ваш комментарий:
 
unix-linux/ubuntu/ubuntu-14-04-lts-trusty-tahr/how-to-install-lemp-web-server-on-ubuntu-14-04/enhancing-system-security-via-iptables-and-sysctl-for-anti-dos-and-against-syn-icmp-udp-http-flood.txt · Последнее изменение: 07.06.2016 13:33 — Алексей Максимов

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki