Привет! Меня зовут Максим Рыбалко, я директор по управлению проектами в Т1 Иннотех. В современном цифровом мире DDoS-атаки превратились из теоретической угрозы в ежедневный вызов для бизнеса. В этой статье я не только расскажу о базовых принципах защиты, но и поделюсь реальными случаями из практики, распространёнными ошибками и техническими решениями, которые мы применяем.

Что такое DDoS-атака?

DDoS-атака — это кибератака, целью которой является перегрузка сервера, сети или веб-сайта огромным количеством запросов, что делает их недоступными для легитимных пользователей. Атака осуществляется с помощью множества устройств, объединённых в сеть (ботнет), которые одновременно отправляют запросы к целевой системе.

Основные характеристики DDoS-атак:

  • Распределённость: атака исходит из множества источников, что затрудняет её блокирование .

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

  • Цель: вывести систему из строя, сделав её недоступной.

Почему это опасно:

  • Финансовые потери: каждая минута простоя может стоить компаниям до $5600 (по данным Gartner).

  • Репутационные риски: клиенты теряют доверие после повторных инцидентов.

  • Маскировка других атак: часто DDoS используют как «дымовую завесу» для хищения данных.

Типы атак и реальные примеры

1. Объёмные атаки

  • Пример из практики: атака на 350 Гбит/с. через UDP-флуд.

  • Решение: фильтрация трафика на уровне провайдера + Anycast DNS.

2. Атаки на протоколы

  • Пример из практики: SYN-флуд, который «положил» API-шлюз из-за неверных настроек таймаутов.

  • Решение: Настройка tcp_syncookies в Linux и ограничение полуоткрытых соединений.

3. Атаки на приложения

  • Пример из практики: Slowloris-атака, которая обошла WAF из-за слишком «мягких» лимитов на длину заголовков.

Практика защиты от DDoS

1. Многоуровневая защита

  • Edge-фильтрация: отсекает 95 % мусорного трафика.

  • Кастомные правила WAF: например, блокировка запросов с поддельными User-Agent.

2. Ошибки, которые мы совершили (и исправили)

  • Ошибка 1: Геоблокировка всего трафика из Азии → легитимные клиенты не смогли работать.

    • Решение: Градуальная проверка через CAPTCHA + анализ сессий.

  • Ошибка 2: Отсутствие плана эскалации при атаке → 47 минут простоя.

    • Фикс: Чёткий runbook с ролями SOC, DevOps и менеджмента.

3. Мониторинг и аналитика

  • Неочевидные метрики:

    • Рост запросов к /wp-login.php (может указывать на брутфорс перед DDoS).

    • Аномальное соотношение GET/POST (1:100 — признак флуда).

  • Инструменты:

    • ELK-стек для анализа логов.

    • Кастомные дашборды в Grafana с порогами срабатывания.

Пример кода для базовой защиты от DDoS-атак

Один из способов защиты на уровне приложения — это ограничение количества запросов от одного IP-адреса за определённый промежуток времени. Это помогает снизить риск HTTP-флуда. Вот примеры кода на Python и Java.

Пример на Python с использованием Flask и Redis:

from flask import Flask, request, jsonify
import redis
import time

app = Flask(__name__)
# Подключение к Redis для хранения счетчиков запросов
redis_client = redis.StrictRedis(host='localhost', port=6379, db=0)

# Лимит запросов и временное окно
RATE_LIMIT = 100  # Максимальное количество запросов
TIME_WINDOW = 60  # Временное окно в секундах (например, 60 секунд)

@app.before_request
def rate_limit():
    # Получаем IP-адрес клиента
    client_ip = request.remote_addr

    # Создаем ключ для хранения счетчика запросов
    key = f"rate_limit:{client_ip}"

    # Получаем текущее количество запросов
    current_requests = redis_client.get(key)

    if current_requests and int(current_requests) >= RATE_LIMIT:
        # Если лимит превышен, возвращаем ошибку
        return jsonify({"error": "Too many requests. Please try again later."}), 429

    if not current_requests:
        # Если ключа нет, создаем его и устанавливаем время жизни
        redis_client.set(key, 1, ex=TIME_WINDOW)
    else:
        # Увеличиваем счетчик запросов
        redis_client.incr(key)

@app.route('/')
def index():
    return "Welcome to the protected service!"

if __name__ == '__main__':
    app.run(debug=True)

Пример на Java с использованием Spring Boot и Redis:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;

@SpringBootApplication
@RestController
public class DDoSProtectionApplication {

    @Autowired
    private StringRedisTemplate redisTemplate;

    private static final int RATE_LIMIT = 100; // Максимальное количество запросов
    private static final int TIME_WINDOW = 60; // Временное окно в секундах

    public static void main(String[] args) {
        SpringApplication.run(DDoSProtectionApplication.class, args);
    }

    @GetMapping("/")
    public ResponseEntity<String> index(HttpServletRequest request) {
        String clientIp = request.getRemoteAddr();
        String key = "rate_limit:" + clientIp;

        ValueOperations<String, String> ops = redisTemplate.opsForValue();
        String currentRequests = ops.get(key);

        if (currentRequests != null && Integer.parseInt(currentRequests) >= RATE_LIMIT) {
            return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS).body("Too many requests. Please try again later.");
        }

        if (currentRequests == null) {
            ops.set(key, "1", TIME_WINDOW, TimeUnit.SECONDS);
        } else {
            ops.increment(key);
        }

        return ResponseEntity.ok("Welcome to the protected service!");
    }
}

Как это работает:

  • Redis используется для хранения счётчиков запросов от каждого IP-адреса.

  • RATE_LIMIT определяет максимальное количество запросов, которые можно сделать за TIME_WINDOW (временное окно).

  • Если количество запросов от одного IP-адреса превышает лимит, сервер возвращает ошибку 429 Too Many Requests.

 Преимущества:

  • Простота реализации.

  • Эффективность против простых атак, таких как HTTP-флуд.

  • Возможность масштабирования с использованием Redis.

Ограничения:

  • Этот метод не защитит от сложных DDoS-атак, таких как SYN-флуд или UDP-флуд.

  • Для полной защиты рекомендуется использовать специализированные решения, такие как Cloudflare или AWS Shield.

Пример на Go для высоконагруженных API:

1. Кастомный rate-limiter 

package main

import (
	"context"
	"net/http"
	"time"
	"github.com/redis/go-redis/v9"
)

var rdb = redis.NewClient(&redis.Options{Addr: "localhost:6379"})
var ctx = context.Background()

func rateLimit(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		ip := r.RemoteAddr
		key := "rate_limit:" + ip

		current, err := rdb.Incr(ctx, key).Result()
		if err != nil {
			http.Error(w, "Internal error", http.StatusInternalServerError)
			return
		}

		if current == 1 {
			rdb.Expire(ctx, key, 1*time.Minute) // TTL = 1 мин
		}

		if current > 100 { // Лимит: 100 RPM
			http.Error(w, "Too many requests", http.StatusTooManyRequests)
			return
		}

		next(w, r)
	}
}

Почему Go? Он обрабатывает в три раза больше запросов в секунду, чем Python.

2. Фильтрация ботов через Nginx + Lua

http {
    lua_shared_dict ip_blacklist 10m;
    server {
        location / {
            access_by_lua_block {
                local ip = ngx.var.remote_addr
                local blacklist = ngx.shared.ip_blacklist
                if blacklist:get(ip) then
                    ngx.exit(ngx.HTTP_FORBIDDEN)
                end
            }
        }
    }
}

Дополнительные меры:

  • Использование CAPTCHA для подозрительных запросов, чтобы отсечь ботов.

  • Геофильтрация: блокируйте трафик из регионов, где он не ожидается.

  • Анализ поведения: внедрите системы машинного обучения для анализа трафика и выявления аномалий.

Что почитать для углублённого изучения



DDoS-атаки — это не страшилка, а реальность. Защита от них требует:

  1. Многоуровневой фильтрации (от edge до приложения).

  2. Постоянного тестирования (например, через Red Team).

  3. Чётких процессов (кто и когда нажимает «красную кнопку»).

«Лучшая защита — это когда атака даже не заметна для бизнеса» (из нашего внутреннего мануала).