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.1 | 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] (текущий) – ↷ Страница перемещена из 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 ==== | ||
+ | |||
+ | Добавляем в **/ | ||
+ | |||
+ | <file bash / | ||
+ | # | ||
+ | # Включаем фильтрацию входящих пакетов, | ||
+ | # которые были отправлены одним интерфейсом, | ||
+ | # | ||
+ | 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 означает, | ||
+ | # | ||
+ | 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) соединений. | ||
+ | # При возникновении проблем, | ||
+ | # системный журнал будет записано сообщение, | ||
+ | # 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 на 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, | ||
+ | # т.е. максимальное число попыток установить пассивное 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 | ||
+ | </ | ||
+ | |||
+ | Сохраним файл и применим его изменения в системе: | ||
+ | |||
+ | < | ||
+ | |||
+ | \\ | ||
+ | \\ | ||
+ | ==== Настройка iptables ==== | ||
+ | |||
+ | \\ | ||
+ | === Защита от атак UDP flood === | ||
+ | |||
+ | Атаки UDP flood основаны на массированной посылке UDP-пакетов на порты различных UDP-сервисов. | ||
+ | Защиту можно реализовать путём изоляции UDP-сервисов от Интернет (если это возможно) или путём установки лимита количества соединений в единицу времени от каждого отдельно взятого внешнего IP. | ||
+ | Например, | ||
+ | |||
+ | < | ||
+ | |||
+ | \\ | ||
+ | === Ограничение TCP подключений === | ||
+ | |||
+ | Атаки HTTP flood основаны на массовой посылке HTTP-сообщений GET на TCP-порт веб-сервера с целью создания критической нагрузки на сервер. | ||
+ | При этом посылаться запросы могут как к корню веб-сервера, | ||
+ | Помимо общей нагрузки на систему HTTP flood может привести к аномальному росту логов веб-сервера. | ||
+ | |||
+ | Далее можно поставить ограничение по количеству одновременных соединений | ||
+ | |||
+ | < | ||
+ | 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): | ||
+ | |||
+ | < | ||
+ | -m connlimit --connlimit-above 50 -j REJECT \ | ||
+ | -m comment --comment " | ||
+ | |||
+ | Отбрасываем неправильно сформированные пакеты: | ||
+ | |||
+ | < | ||
+ | -m comment --comment " | ||
+ | |||
+ | Не забываем сохранить правила iptables: | ||
+ | |||
+ | < | ||
+ | |||
+ | \\ | ||
+ | === Защита от атак SYN flood (скрипт с netstat и ipset) === | ||
+ | |||
+ | Предварительно проверить ситуацию на наличие присутствия SYN_RECV соединений можно посчитав их количество: | ||
+ | |||
+ | < | ||
+ | |||
+ | Другой пример. Просмотр количества полуоткрытых соединений в разрезе IP | ||
+ | |||
+ | < | ||
+ | |||
+ | Рассмотрим пример скрипта для зашиты от атак TCP SYN flood с использованием связки iptables + ipset + netstat. | ||
+ | ipset - это расширение для iptables, которое позволяет работать с большими массивами данных, | ||
+ | обработка которых может быть вызвана из правил iptables | ||
+ | Чтобы установить расширение выполним: | ||
+ | |||
+ | < | ||
+ | |||
+ | После того как пакет установлен, | ||
+ | |||
+ | < | ||
+ | Добавляем в iptables в цепочке **INPUT** правило блокирования всех пакетов для всех хостов, | ||
+ | |||
+ | < | ||
+ | -m comment --comment " | ||
+ | |||
+ | Сохраняем правила iptables: | ||
+ | |||
+ | < | ||
+ | |||
+ | Создадим каталоги для хранения вспомогательных файлов... | ||
+ | |||
+ | Каталог для хранения скрипта обновления цепочек ipset (**ipset-DOS-SRC-refresh.sh**): | ||
+ | < | ||
+ | sudo chmod 755 / | ||
+ | |||
+ | Каталог для сохранения файла цепочек ipset (**ipset.conf**): | ||
+ | |||
+ | < | ||
+ | sudo chmod 755 / | ||
+ | |||
+ | Создадим скрипт, | ||
+ | |||
+ | < | ||
+ | sudo chmod +x / | ||
+ | sudo nano / | ||
+ | |||
+ | Наполним скрипт содержимым: | ||
+ | |||
+ | <file bash / | ||
+ | IFCONFIG=/ | ||
+ | GREP=/ | ||
+ | AWK=/ | ||
+ | CUT=/ | ||
+ | NETSTAT=/ | ||
+ | IPSET=/ | ||
+ | IPTABLES=/ | ||
+ | SORT=/ | ||
+ | UNIQ=/ | ||
+ | srvIP=`$IFCONFIG eth0 | $GREP 'inet addr' | $AWK ' | ||
+ | for i in `$NETSTAT -ntu | $GREP SYN_RECV | $AWK ' | ||
+ | do | ||
+ | $IPSET -A DOS-SRC $i | ||
+ | done | ||
+ | $IPSET -S > / | ||
+ | </ | ||
+ | |||
+ | Скрипт анализирует вывод команды **netstat**, | ||
+ | блокируется в **iptables** в цепочке **INPUT**. | ||
+ | |||
+ | Запустим скрипт для проверки того, что при его запуске из cron не возникнет проблем: | ||
+ | |||
+ | < | ||
+ | |||
+ | В файл **/ | ||
+ | |||
+ | < | ||
+ | |||
+ | Впишем команду загрузки ранее сохранённых правил ipset из файла ipset.conf (строку добавлять нужно до команды загрузки основных правил iptables): | ||
+ | |||
+ | <file bash / | ||
+ | # Load ipset chains and rules | ||
+ | cat / | ||
+ | # | ||
+ | # Load iptables rules from this file | ||
+ | iptables-restore < / | ||
+ | # | ||
+ | exit 0 | ||
+ | </ | ||
+ | |||
+ | Теперь нам нужно настроить периодическое выполнение скрипта **ipset-DOS-SRC-refresh.sh**. | ||
+ | Создадим для этого файл задачи cron: | ||
+ | |||
+ | < | ||
+ | sudo nano / | ||
+ | |||
+ | Наполним его содержимым таким образом, | ||
+ | |||
+ | <file bash / | ||
+ | # Regular cron job for ipset chain DOS-SRC update | ||
+ | # | ||
+ | */5 * * * * root / | ||
+ | |||
+ | Через 10 минут проверим по логу, что наш скрипт успешно дёргается планировщиком cron | ||
+ | |||
+ | < | ||
+ | |||
+ | В логе должны присутствовать записи о выполнении скрипта через заданные нами интервалы времени: | ||
+ | |||
+ | < | ||
+ | Mar 22 11:50:01 WEB-SERVER CRON[1623]: (root) CMD (/ | ||
+ | Mar 22 11:55:01 WEB-SERVER CRON[1677]: (root) CMD (/ | ||
+ | \\ | ||
+ | == Проверяем сохранение цепочек ipset при перезагрузке системы == | ||
+ | |||
+ | Для проверки можно вручную добавить какой-то IP в созданную нами цепочку ipset, а затем посмотреть состояние всех цепочек ipset: | ||
+ | |||
+ | < | ||
+ | sudo ipset -L</ | ||
+ | |||
+ | После этого перезагружаем сервер, | ||
+ | |||
+ | Для удаления конкретного IP из цепочки ipset можно воспользоваться командой: | ||
+ | |||
+ | < | ||
+ | \\ | ||
+ | == Проверяем работу механизма автоматической блокировки == | ||
+ | |||
+ | Воспользуемся утилитой hping3, чтобы пофлудить на наш сервер по известному порту (предполагается что порт открыт) пакетами TCP SYN. Разумеется, | ||
+ | |||
+ | Пример использования: | ||
+ | < | ||
+ | где: | ||
+ | S - отсылка флага SYN | ||
+ | p 80 - номер атакуемого порта | ||
+ | i u1 - интервал в 1 микросекунду между отправляемыми пакетами. | ||
+ | |||
+ | Согласно нашим настройкам, | ||
+ | |||
+ | < | ||
+ | |||
+ | \\ | ||
+ | ==== Учётная запись root ==== | ||
+ | |||
+ | Если ОС Ubuntu на вашем сервере развёрнута не вами самостоятельно, | ||
+ | |||
+ | Проверить состояние можно в файле **/ | ||
+ | |||
+ | < | ||
+ | |||
+ | |||
+ | \\ | ||
+ | ==== Дополнительные источники информации ==== | ||
+ | |||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[http:// | ||
+ | * [[https:// | ||
+ | * [[http:// | ||
+ | * [[https:// | ||
+ | * [[http:// | ||
+ | * https:// | ||
+ | |||
+ | ---- | ||
+ | {{: | ||
+ | |||
+ | {{tag> | ||
+ | |||
+ | ~~DISCUSSION~~ |