Новая Школа - онлайн-школа подготовки к ЕГЭ
Задача Задача №3543364
А
Аноним
12 января 2026 19:04 · публичный вопрос
А
Аноним

напиши анти ддос на джава

Ответ нейросети
12 января 2026 19:04

Ниже приведено простое, понятное решение на Java для защиты веб-приложения от попыток DDoS за счет ограничения количества запросов от одного IP за фиксированный временной период (фиксированное окно). Это пример учебного уровня, который можно расширять и адаптировать под реальные проекты. Он подходит для общего среднего школьного уровня и не требует специальных знаний сервера.

Как работает идея:

  • Для каждого IP хранится окно времени и количество запросов в этом окне.
  • Если за текущее окно количество запросов меньше порога, запрос разрешается.
  • Если достигнут порог, дальнейшие запросы в этом окне отклоняются с кодом 429 (Too Many Requests).
  • Окно считается по минутам (или по любому заданному значению windowMs).

Важно: это базовый пример. Для продакшна стоит рассмотреть более продвинутые решения (распределенный кэш, интеграцию с прокси/балансировщиком, разные алгоритмы и т.д.).

Шаги реализации:

  • Создаем простой RateLimiter, который хранит для каждого IP окно и счётчик.
  • Добавляем Servlet Filter, который применяет rate limiter к входящим HTTP-запросам.
  • В конфигурации указываем параметры: maxRequests и windowMs.

Пример кода

  1. RateLimiter (помощник, потокобезопасный базовый вариант)
import java.util.concurrent.ConcurrentHashMap;

public class SimpleRateLimiter {
    // Максимальное число запросов за окно
    private final int maxRequests;
    // Длительность окна в миллисекундах
    private final long windowMs;
    // Карта IP -> запись лимита
    private final ConcurrentHashMap<String, RateLimitEntry> map = new ConcurrentHashMap<>();

    public SimpleRateLimiter(int maxRequests, long windowMs) {
        this.maxRequests = maxRequests;
        this.windowMs = windowMs;
    }

    // Возвращает true, если можно обработать запрос, false — если перегружено
    public boolean allow(String ip) {
        long currentWindow = System.currentTimeMillis() / windowMs; // номер текущего окна
        RateLimitEntry entry = map.get(ip);
        if (entry == null) {
            RateLimitEntry newEntry = new RateLimitEntry(currentWindow, 0);
            RateLimitEntry existing = map.putIfAbsent(ip, newEntry);
            if (existing != null) {
                entry = existing;
            } else {
                entry = newEntry;
            }
        }

        synchronized (entry) {
            // если окно сменилось, сбрасываем счётчик
            if (entry.windowStart != currentWindow) {
                entry.windowStart = currentWindow;
                entry.count = 0;
            }
            if (entry.count < maxRequests) {
                entry.count++;
                return true;
            } else {
                // достигнут лимит в текущем окне
                return false;
            }
        }
    }

    // Вспомогательный класс записи per-IP
    static class RateLimitEntry {
        volatile long windowStart;
        volatile int count;
        RateLimitEntry(long windowStart, int count) {
            this.windowStart = windowStart;
            this.count = count;
        }
    }
}
  1. Servlet Filter для применения лимита
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class RateLimitFilter implements Filter {

    private SimpleRateLimiter limiter;

    @Override
    public void init(FilterConfig config) throws ServletException {
        // Пример конфигурации по умолчанию. Можно вынести в web.xml или параметры окружения.
        int maxRequests = 100;       // пример: 100 запросов
        long windowMs = 60_000;      // за 60 секунд
        limiter = new SimpleRateLimiter(maxRequests, windowMs);
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        String ip = request.getRemoteAddr();

        if (limiter.allow(ip)) {
            chain.doFilter(req, res);
        } else {
            HttpServletResponse response = (HttpServletResponse) res;
            response.setStatus(HttpServletResponse.SC_TOO_MANY_REQUESTS);
            response.setContentType("text/plain");
            response.getWriter().write("Too many requests. Please slow down.");
        }
    }

    @Override
    public void destroy() {
        // ничего особого
    }
}
  1. Как подключить (вариант настройки)
  • В веб-приложении (web.xml):
<filter>
    <filter-name>RateLimitFilter</filter-name>
    <filter-class>RateLimitFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>RateLimitFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
  • Или в Spring Boot можно сделать как фильтр через регистрацию бина, например:
    • аннотировать класс @Component и добавить @WebFilter (для сервлетов) или регистрировать через FilterRegistrationBean.
    • можно инъектировать параметры maxRequests и windowMs из application.properties.
  1. Что можно улучшать (варианты для расширения)
  • Переключение на Sliding Window вместо Fixed Window для более плавной скорости ограничения.
  • Использование Token Bucket или Leaky Bucket алгоритмов.
  • Распределенный лимит по нескольким серверам через Redis или распределенную кеш‑систему.
  • Интеграция с прокси/балансировщиком: Nginx/HAProxy могут выполнять часть ограничения до попадания запросов в приложение.
  • Добавление списков белых/черных IP, временных исключений для администраторов, CAPTCHA/челленджей после достижения порога и т.д.
  • Логирование и мониторинг количества отклонённых запросов для анализа нагрузки.

Замечания и предостережения

  • Это базовый учебный пример, не рассчитанный на продакшн‑использование без доработок.
  • В реальной инфраструктуре рекомендуется использовать распределённый лимит по нескольким машинам (Redis, Memcached) и/или внешний прокси.
  • Всегда тестируйте под нагрузкой в безопасной среде, чтобы не блокировать легитимные пользователи.

Если хочешь, могу адаптировать этот пример под конкретный стек (Spring Boot, Jakarta EE, обычный сервлет‑контейнер) или разобрать более продвинутые алгоритмы/решения под твою задачу. Также могу привести примеры тестирования нагрузки и как проверить работоспособность лимита.