DDoS-атаки: типы и выявление на Linux
| Уровень сложности | Средний |
| Права root | Требуются |
| Требования | Терминал Linux |
| Категория | Безопасность |
| Совместимость с ОС | Debian, Ubuntu, RHEL |
| Примерное время чтения | 1 час |
Введение
DDoS-атака (Distributed Denial of Service) - это попытка сделать сервис недоступным, перегружая сервер большим количеством соединений или сетевого трафика.
Атаки могут происходить на разных уровнях модели OSI. От сетевого уровня до уровня приложений. В этой статье рассмотрим распространённые типы атак, их признаки на Linux-сервере, способы диагностики и частичной защиты стандартными средствами системы.
Виды атак
SYN Flood (L4)
В чем смысл атаки
TCP соединение устанавливается через механизм трёхстороннего рукопожатия:
SYN - SYN-ACK - ACK
При SYN flood атакующий отправляет большое количество SYN-пакетов, но не завершает соединение. Сервер создаёт запись о соединении и ждёт ACK. Когда таких соединений становится слишком много, очередь соединений переполняется, и сервер перестаёт принимать новые подключения.
Как это выглядит на сервере
ss -ant | grep SYN-RECV
Пример:
Что мы видим:
- Цель: 192.168.88.10:22 (SSH-порт)
- Состояние: SYN-RECV - классические «висящие» соединения от SYN Flood
- Source IP: Подменённые случайные адреса (137.107.123.240, 137.204.96.214 и т.д.)
- Порт источника: Случайные порты (1866, 1816, 1777...)
Количество соединений:
ss -ant | grep SYN-RECV | wc -l
Как выглядит в tcpdump
tcpdump -n 'tcp[tcpflags] & tcp-syn != 0'
Пример:
Защита стандартными средствами
sysctl -w net.ipv4.tcp_syncookies=1
Увеличить очередь соединений
sysctl -w net.core.somaxconn=65535
Ограничить новые соединения
iptables -A INPUT -p tcp --syn --dport 80 -m limit --limit 20/s -j ACCEPT
iptables -A INPUT -p tcp --syn --dport 80 -j DROP
UDP Flood (L3/L4)
В чем смысл атаки
UDP не требует установки соединения. Атакующий может отправлять огромное количество UDP-пакетов на случайные порты, заставляя сервер обрабатывать их.
Как выглядит на сервере
netstat -su
Пример:
Что мы видим:
- Общее количество полученных UDP-пакетов: 108 434.
- Пакеты, пришедшие на закрытые порты: 1 927 093 - Это главный признак UDP Flood: атакующий отправляет мусор на случайные порты, где нет слушающих приложений.
1,9 миллиона пакетов на закрытые порты классическая UDP Flood атака. Система-жертва тратит ресурсы на бесполезную обработку, что приводит к отказу в обслуживании легитимных UDP-запросов.
tcpdump
tcpdump -n udp
Пример:
Защита стандартными средствами
Если UDP-сервис не используется:
iptables -A INPUT -p udp -j DROP
Если используется:
iptables -A INPUT -p udp -m limit --limit 50/s -j ACCEPT
iptables -A INPUT -p udp -j DROP
ICMP Flood (L3)
В чем смысл атаки
Атакующий отправляет огромное количество ICMP echo request (ping). Это может перегрузить сетевой канал и сетевой стек сервера.
Пример tcpdump
tcpdump icmp
Что мы видим:
- Атакующий отправляет ICMP Echo Request (пинг) с подменных IP-адресов (33.103.97.126, 26.16.11.96 и др.)
- Цель (eye) отвечает ICMP Echo Reply на каждый запрос
- Высокая интенсивность - пакеты идут один за другим с микросекундными интервалами
- Цель перегружена ответами тратит CPU и сетевые ресурсы на обработку и отправку reply
Защита стандартными средствами
Ограничение ICMP
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
HTTP Flood (L7)
В чем смысл атаки
HTTP flood имитирует обычных пользователей и отправляет огромное количество HTTP-запросов. Цель - перегрузить веб-сервер.
Пример для Apache
Что мы видим:
- PID Apache будет показывать большое значение, может и все 100% CPU
- Появится множество дочерних процессов Apache (или потоков)
Логи Apache (главное доказательство атаки)
Защита стандартными средствами
Поиск атакующих IP
awk '{print $1}' /var/log/apache2/access.log | sort | uniq -c | sort -nr | head -10
Ограничение соединений
iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 20 -j DROP
Slowloris (L7)
В чем смысл атаки
Атакующий открывает большое количество HTTP-соединений, но очень медленно отправляет заголовки. Веб-сервер держит соединения открытыми и не может обслуживать новых пользователей.
Признак
ss -ant | grep :80 | grep -c ESTAB
Что мы видим:
- Apache держит сотни открытых подключений, но они ничего не делают
- В access.log почти нет записей, потому что атака не отправляет завершённые HTTP-запросы
- Новые легитимные пользователи не могут подключиться (таймаут или ошибка), хотя CPU и память могут быть почти не загружены
Отличие Slowloris от HTTP Flood
| Характеристика | HTTP Flood | Slowloris |
|---|---|---|
| Количество соединений | Постоянно меняется | Растёт и держится |
| Запросы | Полные, быстрые | Частичные, медленные |
| Логи Apache | Тысячи запросов | Почти пустые |
| Механизм | Перегрузка CPU/памяти | Исчерпание сокетов/потоков |
Защита стандартными средствами
Использование модуля mod_reqtimeout
Этот модуль встроен в Apache 2.2.15+ и 2.4+, его достаточно включить и настроить.
Включение модуля (Debian/Ubuntu):
sudo a2enmod reqtimeout sudo systemctl restart apache2
Дбавьте в /etc/apache2/apache2.conf или в виртуальный хост:
<IfModule mod_reqtimeout.c>
RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500
</IfModule>
Что означают параметры:
-
header=20-40:20 секунд на заголовки, при получении данных таймаут продлевается до 40 секунд -
body=20:20 секунд на тело запроса -
MinRate=500:клиент должен отправлять минимум 500 байт/сек, иначе соединение разрывается
DNS Amplification (L3/L7)
В чем смысл атаки
Заставить чужие серверы самим атаковать жертву, при этом многократно усиливая трафик. Злоумышленник отправляет маленький запрос, а жертва получает огромный ответ.
Пример tcpdump
tcpdump -n udp port 53
Что мы видим в выводе tcpdump
- DNS-серверы-усилители работают: 8.8.8.8, 1.1.1.1, 4.2.2.4, 208.67.222.222 отправляют ответы жертве (192.168.88.10)
- Разный эффект усиления:
8.8.8.8, 1.1.1.1, 4.2.2.2 отправляют маленькие ответы (28 байт) - усиления нет
208.67.222.222 (OpenDNS) отправляет 449 байт с TXT-записями - усиление есть - Коэффициент усиления (запрос ~60 байт, а ответ уже 449 байт) почти в 7.5x
Защита стандартными средствами
Ограничить DNS-ответы:
iptables -A INPUT -p udp --sport 53 -m limit --limit 20/s -j ACCEPT
iptables -A INPUT -p udp --sport 53 -j DROP
Полезные советы при атаках
Страница для отлова ботов (ловушка)
Иногда администраторы создают специальную страницу-ловушку, которая позволяет выявлять ботов.
Идея простая:
- Создаётся скрытая ссылка.
- Обычные пользователи её не видят.
- Боты переходят по всем ссылкам.
Пример HTML
<a href="/trap-ddos-check" style="display:none">test</a>
Если кто-то открывает эту страницу, то это почти наверняка бот.
Лог nginx:
185.231.54.12 - - [12/Apr/2026:13:22:11 +0300] "GET /trap-ddos-check HTTP/1.1"
Для автоматической блокировки можно использовать скрипт:
#!/usr/bin/env python3
import re
import os
import subprocess
from collections import defaultdict
from datetime import datetime, timedelta
# Белый список User-Agent для поисковых ботов (не блокируем)
safe_bots = [
"Googlebot",
"YandexBot",
"Mail.RU",
"bingbot",
"DuckDuckBot",
"Baiduspider",
"facebookexternalhit",
"Twitterbot",
"Applebot",
"AhrefsBot",
"SemrushBot",
"MJ12bot"
]
def is_safe_bot(user_agent):
"""Проверяет, не является ли бот легитимным поисковым роботом"""
if not user_agent:
return False
for bot in safe_bots:
if bot.lower() in user_agent.lower():
return True
return False
def block_ip(ip, user_agent=""):
"""Блокирует IP через iptables"""
if is_safe_bot(user_agent):
print(f"Пропускаем {ip} - легитимный бот ({user_agent[:50]}...)")
return False
try:
subprocess.run(f"iptables -A INPUT -s {ip} -j DROP", shell=True, check=True)
print(f"🔨 ЗАБЛОКИРОВАН {ip} - обнаружен бот (UA: {user_agent[:50]})")
return True
except subprocess.CalledProcessError:
print(f"Ошибка блокировки {ip}")
return False
def monitor_log(log_path='/var/log/nginx/access.log'):
"""Мониторит лог в реальном времени"""
print("Начинаю мониторинг страницы-ловушки /trap-ddos-check")
print("Помните: метод не даёт 100% точности!\n")
with open(log_path, 'r') as f:
f.seek(0, 2)
while True:
line = f.readline()
if line:
if '/trap-ddos-check' in line:
parts = line.split()
ip = parts[0]
user_agent = ""
if '"' in line:
ua_match = re.search(r'"([^"]*)"\s*$', line)
if ua_match:
user_agent = ua_match.group(1)
print(f"Обнаружен переход: {ip} -> {user_agent[:50]}")
block_ip(ip, user_agent)
else:
time.sleep(0.1)
if __name__ == "__main__":
import time
import sys
if not os.geteuid() == 0:
print("Запусти с sudo (нужны права для iptables)")
sys.exit(1)
try:
monitor_log()
except KeyboardInterrupt:
print("\nОстановлено. Блокировки сохранены в iptables.")
Топ IP по соединениям
netstat -ant | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr | head
Трафик в реальном времени
iftop
или
nload
Заключение
Даже без специализированных систем защиты администратор может обнаружить признаки DDoS-атаки с помощью стандартных утилит Linux.
Основные признаки:
- резкий рост количества соединений
- большое число пакетов одного типа
- повторяющиеся запросы от одних IP
- высокая загрузка сети
Анализ сетевых соединений, логов веб-сервера и захват пакетов позволяет определить тип атаки и принять меры для защиты сервиса.












