Тема
Режим
Язык
Тема
Режим
Язык
Консультация
FREE Бесплатный аудит сайта за 15 мин Заказать →
NEW Остановили 2 млн атак credential stuffing Кейс →
Разборы атак и инструменты Telegram →
70% трафика могут быть ботами Проверить →
SOS Сайт под атакой? Поможем за 30 мин SOS →

Мониторинг и алерты: как узнать об атаке первым

Настраиваем систему мониторинга для раннего обнаружения DDoS-атак. Prometheus, Grafana, алерты в Telegram. Узнаём о проблеме раньше пользователей.

Худшее, что может случиться во время DDoS-атаки — узнать о ней от клиентов. «Ваш сайт не работает уже час» — такое сообщение означает, что вы потеряли продажи, репутацию и нервы. Правильно настроенный мониторинг позволяет узнать о проблеме за секунды и начать реагировать до того, как пользователи заметят.

Зачем нужен мониторинг для защиты от DDoS

DDoS-атака редко начинается мгновенно с максимальной мощности. Обычно есть паттерн нарастания: сначала небольшой всплеск трафика, потом рост, потом пиковая нагрузка. Если вы отслеживаете метрики в реальном времени — заметите аномалию на первом этапе и успеете включить защиту.

Кроме того, мониторинг помогает:

  • Отличить атаку от легитимного всплеска — вышла реклама, попали в топ Hacker News, упомянули в СМИ. Это не атака, хотя метрики похожи.
  • Понять тип атакиL3/L4 (сетевая) или L7 (прикладная). Для каждого типа нужны разные меры.
  • Оценить эффективность защиты — включили Cloudflare Under Attack, но трафик не упал? Значит атака проходит защиту, нужны другие меры.
  • Собрать данные для анализа — после атаки нужно понять, что случилось, откуда шёл трафик, какие endpoint'ы атаковали.
  • Документировать инциденты — для отчётов руководству, страховых случаев, работы с правоохранительными органами.

Что мониторить

Для эффективного обнаружения атак нужно отслеживать метрики на нескольких уровнях: сетевом, серверном и прикладном. Рассмотрим каждый уровень подробно.

flowchart LR
    subgraph Metrics["Метрики"]
        App[App] --> Prom[Prometheus]
        Nginx[Nginx] --> Prom
        Sys[System] --> Prom
    end
    
    subgraph Alerting["Алерты"]
        Prom --> Alert[Alertmanager]
        Alert --> TG[Telegram]
        Alert --> Email[Email]
    end
    
    subgraph Viz["Дашборды"]
        Prom --> Grafana
    end
Стек мониторинга: Prometheus + Grafana
Slowloris

Анатомия Slowloris-атаки

Атакующий
Slow headers
Keep-alive соединения
Пул соединений
0/12
Таймауты
Header: 10s
Web-сервер
Онлайн

Атакующий открывает сотни HTTP-соединений и отправляет заголовки медленно, по байту.

Соединения никогда не завершаются. Сервер ждёт окончания заголовков для каждого.

Все слоты web-сервера заняты незавершёнными запросами. Новые клиенты не могут подключиться.

Агрессивные таймауты заголовков и лимит соединений с одного IP решают проблему.

01

Ключевые метрики для мониторинга

Что отслеживать и какие пороги ставить

Базовые пороги для алертов

Пороги сильно зависят от вашего обычного трафика, но вот ориентировочные значения для среднего сайта:

  • RPS — алерт если в 5 раз выше обычного
  • CPU — warning при >70%, critical при >90%
  • Response time — warning при >1s, critical при >5s
  • 5xx errors — warning при >1%, critical при >5%
  • Active connections — алерт если в 10 раз выше обычного

Важно: сначала соберите baseline (обычные значения) за 1-2 недели, потом настраивайте пороги. Без baseline будет много ложных срабатываний.

02

Prometheus + Grafana

Стандарт индустрии для мониторинга

Prometheus + Grafana — самая популярная связка для мониторинга. Prometheus собирает и хранит метрики, Grafana визуализирует их и отправляет алерты. Оба инструмента бесплатны и open-source.

Архитектура

Prometheus работает по pull-модели: он сам ходит к вашим сервисам и собирает метрики. На каждом сервере/сервисе нужно поднять exporter — маленький агент, который отдаёт метрики в формате Prometheus.

Основные exporters для мониторинга DDoS:

  • node_exporter — системные метрики Linux (CPU, RAM, disk, network)
  • nginx-prometheus-exporter — метрики nginx
  • blackbox_exporter — проверка доступности извне (HTTP checks, DNS, TCP)
  • cloudflare_exporter — метрики из Cloudflare (если используете)
docker-compose.yml — базовый стек мониторинга
version: '3.8'

services:
  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus_data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.retention.time=30d'
    ports:
      - "9090:9090"
    restart: unless-stopped

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    volumes:
      - grafana_data:/var/lib/grafana
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=your_secure_password
      - GF_USERS_ALLOW_SIGN_UP=false
    ports:
      - "3000:3000"
    restart: unless-stopped

  node-exporter:
    image: prom/node-exporter:latest
    container_name: node-exporter
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /:/rootfs:ro
    command:
      - '--path.procfs=/host/proc'
      - '--path.sysfs=/host/sys'
      - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
    ports:
      - "9100:9100"
    restart: unless-stopped

volumes:
  prometheus_data:
  grafana_data:
prometheus.yml — конфигурация Prometheus
global:
  scrape_interval: 15s
  evaluation_interval: 15s

alerting:
  alertmanagers:
    - static_configs:
        - targets:
          - alertmanager:9093

rule_files:
  - /etc/prometheus/rules/*.yml

scrape_configs:
  # Сам Prometheus
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  # Системные метрики серверов
  - job_name: 'node'
    static_configs:
      - targets: 
        - 'server1:9100'
        - 'server2:9100'

  # Nginx метрики
  - job_name: 'nginx'
    static_configs:
      - targets: ['nginx-exporter:9113']

  # Blackbox (внешние проверки)
  - job_name: 'blackbox-http'
    metrics_path: /probe
    params:
      module: [http_2xx]
    static_configs:
      - targets:
        - https://yoursite.com
        - https://yoursite.com/api/health
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: blackbox:9115
💡
Совет
Для быстрого старта используйте готовые дашборды из Grafana Labs. Node Exporter Full (ID: 1860) — отличный дашборд для системных метрик. Просто импортируйте его в Grafana по ID.
03

Настройка алертов

Уведомления в Telegram, Slack, email

Метрики без алертов — как пожарная сигнализация без звука. Вы узнаете о проблеме только когда сами посмотрите в дашборд, а это может быть слишком поздно.

Alertmanager

Prometheus использует отдельный компонент — Alertmanager — для управления алертами. Он умеет:

  • Группировать похожие алерты (чтобы не получать 100 сообщений об одной проблеме)
  • Подавлять алерты во время maintenance window
  • Маршрутизировать разные алерты разным командам
  • Отправлять уведомления в разные каналы: email, Slack, Telegram, PagerDuty, webhook

Правила алертов для DDoS

Создайте файл с правилами алертов. Вот примеры ключевых правил для обнаружения атак:

/etc/prometheus/rules/ddos-alerts.yml
groups:
  - name: ddos-detection
    interval: 10s  # Проверяем чаще для быстрого обнаружения
    rules:
      # Аномальный всплеск трафика
      - alert: TrafficSpike
        expr: rate(nginx_http_requests_total[1m]) > 10 * avg_over_time(rate(nginx_http_requests_total[1m])[1h:5m])
        for: 2m
        labels:
          severity: warning
        annotations:
          summary: "Всплеск трафика на {{ $labels.instance }}"
          description: "RPS в 10 раз выше среднего за последний час"

      # Много 5xx ошибок
      - alert: HighErrorRate
        expr: sum(rate(nginx_http_requests_total{status=~"5.."}[5m])) / sum(rate(nginx_http_requests_total[5m])) > 0.05
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "Высокий уровень 5xx ошибок"
          description: "Более 5% запросов возвращают 5xx. Текущее значение: {{ $value | humanizePercentage }}"

      # Высокая нагрузка на CPU
      - alert: HighCPUUsage
        expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 90
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "Высокая нагрузка CPU на {{ $labels.instance }}"
          description: "CPU usage > 90% в течение 5 минут"

      # Сервер недоступен извне
      - alert: SiteDown
        expr: probe_success{job="blackbox-http"} == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "Сайт недоступен: {{ $labels.instance }}"
          description: "HTTP проверка не прошла в течение 1 минуты"

      # Медленные ответы
      - alert: SlowResponseTime
        expr: histogram_quantile(0.95, rate(nginx_http_request_duration_seconds_bucket[5m])) > 5
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Медленные ответы сервера"
          description: "95-й перцентиль времени ответа > 5 секунд"
alertmanager.yml — отправка в Telegram
global:
  resolve_timeout: 5m

route:
  receiver: 'telegram-notifications'
  group_by: ['alertname', 'severity']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  routes:
    - receiver: 'telegram-critical'
      match:
        severity: critical
      group_wait: 10s
      repeat_interval: 1h

receivers:
  - name: 'telegram-notifications'
    telegram_configs:
      - bot_token: 'YOUR_BOT_TOKEN'
        chat_id: YOUR_CHAT_ID
        message: |
           {{ .Status | toUpper }}
          {{ range .Alerts }}
          Alert: {{ .Labels.alertname }}
          Severity: {{ .Labels.severity }}
          {{ .Annotations.summary }}
          {{ .Annotations.description }}
          {{ end }}
        
  - name: 'telegram-critical'
    telegram_configs:
      - bot_token: 'YOUR_BOT_TOKEN'
        chat_id: YOUR_CHAT_ID
        message: |
           CRITICAL ALERT
          {{ range .Alerts }}
          {{ .Annotations.summary }}
          {{ .Annotations.description }}
          Started: {{ .StartsAt.Format "15:04:05" }}
          {{ end }}

# Чтобы создать Telegram бота:
# 1. Напишите @BotFather в Telegram
# 2. Создайте бота командой /newbot
# 3. Получите token
# 4. Добавьте бота в группу или получите chat_id через @userinfobot
04

Внешний мониторинг (Uptime Monitoring)

Проверка доступности извне

Внутренний мониторинг (Prometheus на вашем сервере) не увидит проблему, если сервер полностью недоступен или проблема на уровне сети/DNS. Поэтому критически важно иметь внешний мониторинг — проверки из разных точек мира.

Варианты внешнего мониторинга

  • UptimeRobot — бесплатно до 50 мониторов с интервалом 5 минут. Отличный выбор для старта.
  • Pingdom — более функциональный, платный. Детальные отчёты, Real User Monitoring.
  • StatusCake — бесплатный план с хорошими возможностями.
  • Better Uptime — современный интерфейс, status pages, on-call расписания.
  • Self-hosted Blackbox Exporter — разместите на VPS в другом дата-центре для независимых проверок.

Что проверять

  • Главная страница — базовая проверка доступности
  • /api/health или /health — специальный endpoint, который проверяет состояние приложения (БД доступна, кэш работает)
  • Критичные endpoint'ы — страница логина, корзина, API
  • DNS resolution — проверка что DNS отвечает корректно
  • SSL certificate expiry — алерт за 30 дней до истечения

Health Check Endpoint

Создайте специальный endpoint для проверки здоровья приложения. Он должен проверять критические зависимости:

Пример health check endpoint (Node.js/Express)
app.get('/health', async (req, res) => {
  const health = {
    status: 'ok',
    timestamp: new Date().toISOString(),
    checks: {}
  };

  // Проверка базы данных
  try {
    await db.query('SELECT 1');
    health.checks.database = { status: 'ok' };
  } catch (err) {
    health.checks.database = { status: 'error', message: err.message };
    health.status = 'degraded';
  }

  // Проверка Redis
  try {
    await redis.ping();
    health.checks.redis = { status: 'ok' };
  } catch (err) {
    health.checks.redis = { status: 'error', message: err.message };
    health.status = 'degraded';
  }

  // Проверка внешнего API (если критичен)
  try {
    const response = await fetch('https://api.payment.com/health', { timeout: 5000 });
    health.checks.payment_api = { status: response.ok ? 'ok' : 'error' };
  } catch (err) {
    health.checks.payment_api = { status: 'error' };
    // Не меняем общий статус — внешний API не критичен
  }

  const statusCode = health.status === 'ok' ? 200 : 503;
  res.status(statusCode).json(health);
});
05

Логирование и анализ

Логи — ключ к пониманию атаки

Метрики показывают что происходит, логи показывают почему. Во время атаки логи — основной источник информации для анализа.

Что должно быть в логах nginx

Стандартный формат логов nginx недостаточен для анализа атак. Расширьте его:

nginx.conf — расширенный формат логов
log_format detailed '$remote_addr - $remote_user [$time_local] '
                        '"$request" $status $body_bytes_sent '
                        '"$http_referer" "$http_user_agent" '
                        '$request_time $upstream_response_time '
                        '$http_x_forwarded_for $http_cf_connecting_ip '
                        '$http_cf_ipcountry $connection $connection_requests';

access_log /var/log/nginx/access.log detailed;

# Отдельный лог для ошибок с большей детализацией
error_log /var/log/nginx/error.log warn;

Быстрый анализ логов

Во время атаки нужно быстро понять: откуда идёт трафик, на какие URL, с какими User-Agent. Вот полезные команды:

Анализ трафика в реальном времени
⚠️
Важно
Для серьёзного анализа логов используйте ELK Stack (Elasticsearch + Logstash + Kibana) или Loki + Grafana. Они позволяют искать по логам, строить графики, создавать алерты. Это отдельная большая тема, но инвестиция окупается.
06

Автоматизация реагирования

Автоматические действия при атаке

Когда атака случается ночью или в выходные, автоматизация может спасти ситуацию до того, как человек успеет отреагировать.

Примеры автоматических действий

  • Автоматическое включение Cloudflare Under Attack Mode — при обнаружении аномального трафика
  • Автоматическая блокировка IP — если IP превышает лимит запросов
  • Включение дополнительных серверов — auto-scaling при росте нагрузки
  • Переключение на статическую версию сайта — если динамика не справляется
  • Уведомление дежурного — эскалация по on-call расписанию

Пример: автоматическое включение Under Attack при аномалии

auto-under-attack.sh — скрипт автоматической защиты
#!/bin/bash

# Настройки
ZONE_ID="your_cloudflare_zone_id"
API_TOKEN="your_cloudflare_api_token"
THRESHOLD_RPS=1000  # Порог RPS для включения защиты
LOG_FILE="/var/log/nginx/access.log"
STATE_FILE="/tmp/under_attack_enabled"

# Получить текущий RPS
CURRENT_RPS=$(tail -1000 "$LOG_FILE" | awk -v now="$(date +%s)" -v window=60 '
  BEGIN { count=0 }
  {
    # Парсим время из лога nginx
    gsub(/\[|\]/, "", $4)
    cmd = "date -d "" $4 "" +%s"
    cmd | getline log_time
    close(cmd)
    if (now - log_time < window) count++
  }
  END { print count/window }
')

echo "Current RPS: $CURRENT_RPS"

# Если RPS выше порога и защита не включена
if (( $(echo "$CURRENT_RPS > $THRESHOLD_RPS" | bc -l) )) && [ ! -f "$STATE_FILE" ]; then
  echo "Enabling Under Attack Mode..."
  curl -s -X PATCH "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/security_level" \
    -H "Authorization: Bearer $API_TOKEN" \
    -H "Content-Type: application/json" \
    --data '{"value":"under_attack"}'
  touch "$STATE_FILE"
  
  # Отправить уведомление
  curl -s -X POST "https://api.telegram.org/bot$TG_BOT_TOKEN/sendMessage" \
    -d "chat_id=$TG_CHAT_ID" \
    -d "text= Auto-enabled Under Attack Mode. RPS: $CURRENT_RPS"
fi

# Если RPS нормализовался и защита была включена автоматически
if (( $(echo "$CURRENT_RPS < $THRESHOLD_RPS / 2" | bc -l) )) && [ -f "$STATE_FILE" ]; then
  echo "Disabling Under Attack Mode..."
  curl -s -X PATCH "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/security_level" \
    -H "Authorization: Bearer $API_TOKEN" \
    -H "Content-Type: application/json" \
    --data '{"value":"medium"}'
  rm -f "$STATE_FILE"
  
  curl -s -X POST "https://api.telegram.org/bot$TG_BOT_TOKEN/sendMessage" \
    -d "chat_id=$TG_CHAT_ID" \
    -d "text= Auto-disabled Under Attack Mode. RPS normalized: $CURRENT_RPS"
fi
Осторожно с автоматизацией
Автоматические действия могут навредить, если сработают неправильно. Начните с автоматических уведомлений, потом добавляйте действия с подтверждением (человек должен одобрить), и только после обкатки переходите к полной автоматизации.
07

Чек-лист мониторинга

Что должно быть настроено

Полный чек-лист мониторинга для защиты от DDoS

0 / 10
Используйте Let's Encrypt или Cloudflare для бесплатных сертификатов
Лимитируйте /login, /api, /search — основные точки атак
Cloudflare WAF, ModSecurity или аналоги
Снижает нагрузку на origin в 5-10 раз
Grafana + Prometheus или встроенный в CDN
Быстрое переключение при атаке на основной
Телефон техподдержки для экстренных случаев
Блокировка регионов откуда не ждёте трафик
hCaptcha или Cloudflare Turnstile
Telegram/Slack уведомления при аномалиях
Итого
Правильно настроенный мониторинг — это ваши глаза и уши. Он позволяет узнать об атаке за секунды, понять её тип и масштаб, принять меры до того как пострадают пользователи. Инвестируйте время в настройку мониторинга до того, как он понадобится — во время атаки будет не до этого.

Тест: Мониторинг и алерты: как узнать об атаке первым

Вопрос 1 из 4
Как обычно начинается DDoS-атака?
Обычно есть паттерн нарастания трафика.
При какой кратности RPS нужен алерт?
Алерт при RPS в 5 раз выше обычного.
Critical алерт по CPU устанавливается при?
Critical при CPU >90%, warning при >70%.
Зачем нужен мониторинг при защите от DDoS?
Мониторинг позволяет узнать об атаке первым и понять её тип.
0 / 4

Получите план защиты под ваш сайт

Оставьте контакт и адрес сайта — пришлём план защиты и список приоритетных шагов.

  • Приоритетные шаги на 7 дней
  • Быстрая обратная связь
  • План в удобном формате
Без спама. Можно указать Telegram (@username) или email.
Написать в Telegram