Вики IT-KB

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

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

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


web-server-nginx: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

Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Предыдущая версия справа и слеваПредыдущая версия
web-server-nginx: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 [05.09.2025 12:05] – удалено - внешнее изменение (Дата неизвестна) 127.0.0.1web-server-nginx: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 [05.09.2025 12:05] (текущий) – ↷ Страница перемещена из 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 в web-server-nginx:how-to-install-lem Алексей Максимов
Строка 1: Строка 1:
 +===== Настройка веб-сервера на базе стека LEMP в Ubuntu Server 14.04 LTS. Часть 3. Усиление безопасности системы. =====
  
 +==== Настройка параметров sysctl ====
 +
 +Добавляем в **/etc/sysctl.conf** некоторые параметры, которые помогут усилить стойкость системы перед всевозможными флуд-атаками:
 +
 +<file bash /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
 +</file> 
 +
 +Сохраним файл и применим его изменения в системе:
 +
 +<code>sudo sysctl -p</code>
 +
 +\\
 +\\
 +==== Настройка iptables ====
 +
 +\\
 +=== Защита от атак UDP flood ===
 +
 +Атаки UDP flood основаны на массированной посылке UDP-пакетов на порты различных UDP-сервисов.
 +Защиту можно реализовать путём изоляции UDP-сервисов от Интернет (если это возможно) или путём установки лимита количества соединений в единицу времени от каждого отдельно взятого внешнего IP.
 +Например, если наружу выставлен DNS-сервис (порт UDP 53), можно попробовать настроить такое ограничение с помощью iptables следующим правилом:
 +
 +<code>sudo iptables -I INPUT -p udp --dport 53 -j DROP -m iplimit --iplimit-above 1</code>
 +
 +\\
 +=== Ограничение TCP подключений ===
 +
 +Атаки HTTP flood основаны на массовой посылке HTTP-сообщений GET на TCP-порт веб-сервера с целью создания критической нагрузки на сервер.
 +При этом посылаться запросы могут как к корню веб-сервера, так и к всевозможным ресурсоёмким скриптам.
 +Помимо общей нагрузки на систему HTTP flood может привести к аномальному росту логов веб-сервера.
 +
 +Далее можно поставить ограничение по количеству одновременных соединений 
 +
 +<code># Лимит 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"
 +</code>
 +\\
 +=== Защита от атак SYN flood ===
 +
 +Ограничиваем максимальное число «полуоткрытых» соединений с одного IP к конкретному порту (не больше 50 соединений на каждый IP):
 +
 +<code>sudo iptables -A INPUT -p tcp --syn -m multiport --dports 80,443,758 \ 
 + -m connlimit --connlimit-above 50 -j REJECT \
 + -m comment --comment "Prevent SYN flood"</code>
 +
 +Отбрасываем неправильно сформированные пакеты:
 +
 +<code>sudo iptables -A INPUT -m conntrack --ctstate INVALID -j DROP \ 
 + -m comment --comment "Prevent invalid packets"</code>
 +
 +Не забываем сохранить правила iptables:
 +
 +<code>sudo sh -c "iptables-save > /etc/iptables.conf"</code>
 +
 +\\
 +=== Защита от атак SYN flood (скрипт с netstat и ipset) ===
 +
 +Предварительно проверить ситуацию на наличие присутствия SYN_RECV соединений можно посчитав их количество:
 +
 +<code>sudo netstat -n --tcp | grep SYN_RECV | wc -l</code>
 +
 +Другой пример. Просмотр количества полуоткрытых соединений в разрезе IP
 +
 +<code>netstat -nap | grep SYN_RECV | awk {'print $5'} | awk -F: {'print $1'} | sort -rn | uniq -c | sort -rn</code>
 +
 +Рассмотрим пример скрипта для зашиты от атак TCP SYN flood с использованием связки iptables + ipset + netstat. 
 +ipset - это расширение для iptables, которое позволяет работать с большими массивами данных, например IP-адресов,
 +обработка которых может быть вызвана из правил iptables
 +Чтобы установить расширение выполним:
 +
 +<code>sudo apt-get install ipset</code>
 +
 +После того как пакет установлен, создаём собственную цепочку **ipset**, например с названием "**DOS-SRC**"
 +
 +<code>sudo ipset -N DOS-SRC iphash</code>
 +Добавляем в iptables в цепочке **INPUT** правило блокирования всех пакетов для всех хостов, которые обнаруживаются в цепочке ipset "DOS-SRC": 
 + 
 +<code>sudo iptables -I INPUT 1 -m set --match-set DOS-SRC src -j DROP \ 
 + -m comment --comment "Prevent SYN_RECV DOS"</code>
 +
 +Сохраняем правила iptables:
 +
 +<code>sudo sh -c "iptables-save > /etc/iptables.conf"</code>
 +
 +Создадим каталоги для хранения вспомогательных файлов...
 +
 +Каталог для хранения скрипта обновления цепочек ipset (**ipset-DOS-SRC-refresh.sh**):  
 +<code>sudo mkdir /etc/ipset/
 +sudo chmod 755 /etc/ipset/</code>
 +
 +Каталог для сохранения файла цепочек ipset (**ipset.conf**):
 + 
 +<code>sudo mkdir /var/local/ipset/
 +sudo chmod 755 /var/local/ipset/</code>
 +
 +Создадим скрипт, с помощью которого будет обновляться созданная нами ранее цепочка ipset "**DOS-SRC**":
 +
 +<code>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</code>
 +
 +Наполним скрипт содержимым:
 +
 +<file bash /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
 +</file>
 +
 +Скрипт анализирует вывод команды **netstat**, выбирает соединения в состоянии **SYN_RECV** (признак SYN флуда) и добавляет эти IP в цепочку "**DOS-SRC**" утилиты ipset, а члены этой цепочки в свою очередь в режиме реального времени 
 +блокируется в **iptables** в цепочке **INPUT**.
 +
 +Запустим скрипт для проверки того, что при его запуске из cron не возникнет проблем:
 +
 +<code>sudo sh -c "/sbin/ipset -S > /var/local/ipset/ipset.conf"</code>
 +
 +В файл **/etc/rc.local** добавляем строчку восстановления сохранённого списка заблокированных адресов после перезагрузки системы:
 +
 +<code>sudo nano /etc/rc.local</code>
 +
 +Впишем команду загрузки ранее сохранённых правил ipset из файла ipset.conf (строку добавлять нужно до команды загрузки основных правил iptables):
 +
 +<file bash /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
 +</file>
 +
 +Теперь нам нужно настроить периодическое выполнение скрипта **ipset-DOS-SRC-refresh.sh**. 
 +Создадим для этого файл задачи cron: 
 +
 +<code>sudo touch /etc/cron.d/ipset-DOS-SRC-refresh
 +sudo nano /etc/cron.d/ipset-DOS-SRC-refresh</code>
 +
 +Наполним его содержимым таким образом, чтобы наш скрипт выполнялся раз в минуту: 
 +
 +<file bash /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</file>
 +
 +Через 10 минут проверим по логу, что наш скрипт успешно дёргается планировщиком cron
 +
 +<code>sudo grep CRON /var/log/syslog</code>
 +
 +В логе должны присутствовать записи о выполнении скрипта через заданные нами интервалы времени:  
 +
 +<code>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)</code>
 +\\
 +== Проверяем сохранение цепочек ipset при перезагрузке системы ==
 +
 +Для проверки можно вручную добавить какой-то IP в созданную нами цепочку ipset, а затем посмотреть состояние всех цепочек ipset:
 +
 +<code>sudo ipset -A DOS-SRC 111.111.111.111
 +sudo ipset -L</code>
 + 
 +После этого перезагружаем сервер, чтобы убедиться в том, что правила успешно создаются в iptables и ipset в процессе загрузки системы.
 +
 +Для удаления конкретного IP из цепочки ipset можно воспользоваться командой:
 +
 +<code>sudo ipset del DOS-SRC 111.111.111.111</code>
 +\\
 +== Проверяем работу механизма автоматической блокировки ==
 +
 +Воспользуемся утилитой hping3, чтобы пофлудить на наш сервер по известному порту (предполагается что порт открыт) пакетами TCP SYN. Разумеется, флуд нужно выполнять с другого внешнего IP, отличного от IP нашего сервера.
 +
 +Пример использования:
 +<code>sudo hping3 -i u1 -S -p 80 11.22.33.44</code>
 +где:
 +S - отсылка флага SYN 
 +p 80 - номер атакуемого порта
 +i u1 - интервал в 1 микросекунду между отправляемыми пакетами.
 +
 +Согласно нашим настройкам, не более чем через 5 минут после начала атаки на нашем сервере в цепочке ipset должен будет появиться IP адрес злоумышленника, и как следствие, любой трафик с него будет заблокирован. Напомню, что проверить текущее состояние цепочек ipset, выполним:
 +
 +<code>sudo ipset -L</code>
 +
 +\\
 +==== Учётная запись root ====
 +
 +Если ОС Ubuntu на вашем сервере развёрнута не вами самостоятельно, а вы взяли готовый шаблон преднастроенной виртуальной машины у хостера, то есть [[http://anosov.me/2011/07/five-simple-steps-for-ssh-protect-in-ubuntu/|рекомендация]] перед началом использования системы убедиться в том, что учётная запись **root** выключена. Некоторые хостинг провайдеры могут включать эту учётную запись в Ubuntu.
 +
 +Проверить состояние можно в файле **/etc/shadow**. Если учётная запись включена (не имеет признака "!"), выключить её можно командой:
 +
 +<code>sudo passwd -l root</code>
 +
 +
 +\\
 +==== Дополнительные источники информации ====
 +
 +  * [[https://www.opennet.ru/base/sys/sysctl_linux.txt.html|OpenNET - Описание некоторых sysctl переменных ядра Linux (sysctl proc linux kernel tune)]]
 +  * [[https://ru.wikibooks.org/wiki/Iptables]|Викиучебник - Iptables]]
 +  * [[http://serverfault.com/questions/245711/iptables-tips-tricks|serverfault.com - iptables Tips & Tricks]]
 +  * [[https://romantelychko.com/blog/1300/|Роман Теличко - Настройка Linux для высоконагруженных проектов и защиты от DDoS]]
 +  * [[http://www.ussr.kiev.ua/ru/ddos|Блокнот ITшника - Методы борьбы с DoS/DDoS атаками]]
 +  * [[https://debian.pro/510|Debian.pro - iptables+geoip. Баним по странам через iptables. Установка iptables-geoip/netfilter-geoip в Debian Squeeze]]
 +  * [[http://diff.org.ua/archives/2097|diff.org.ua - Ubuntu 14.04 — Iptables TARPIT]]
 +  * https://defcon.ru/network-security/2996/
 +
 +----
 +{{:user:blogroot.png?50&nolink |}} Автор первичной редакции:\\ [[user:blogroot|Алексей Максимов]] \\ Время публикации: 22.03.2016 16:14
 +
 +{{tag>Linux Ubuntu "Ubuntu 14.04" "14.04 LTS" "Ubuntu Server" Security iptables ipset netstat DDoS DoS sysctl Flood "UDP flood" "SYN flood" "TCP flood"}}
 +
 +~~DISCUSSION~~