Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Живое ревью с ИИ
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. Rate Limiting и защита API
rate_limiting

Rate Limiting и защита API

Ограничение запросов, защита от DDoS, circuit breaker, proxy cache

Rate Limiting и защита API в Kong

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

#1. Rate Limiting — ограничение запросов

Проблема: Нужно предотвратить перегрузку API слишком частыми запросами от одного клиента.

Решение: Плагин rate-limiting ограничивает количество запросов за определённый промежуток времени.

#1.1. Базовая настройка

# Ограничение: 100 запросов в минуту на Route curl -X POST http://localhost:8001/routes/api-route/plugins \ --data "name=rate-limiting" \ --data "config.minute=100" \ --data "config.policy=local"

Параметры:

  • second, minute, hour, day — лимиты на разные интервалы
  • policy — где хранить счётчики (local, cluster, redis)
  • fault_tolerant — пропускать запросы при ошибке хранилища
  • hide_client_headers — скрывать заголовки с лимитами

#1.2. Politicies хранения счётчиков

#Local policy

Проблема: Нужна максимальная производительность для single-node.

Решение: Хранение счётчиков в памяти worker'а.

curl -X POST http://localhost:8001/plugins \ --data "name=rate-limiting" \ --data "config.minute=100" \ --data "config.policy=local"

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

  • ✅ Быстрее (нет сетевого вызова)
  • ✅ Нет зависимости от внешних систем

Недостатки:

  • ❌ Лимиты не синхронизируются между узлами
  • ❌ При перезапуске Kong счётчики сбрасываются

#Cluster policy

Проблема: Нужно синхронизировать лимиты между узлами Kong без Redis.

Решение: Использование базы данных Kong (PostgreSQL).

curl -X POST http://localhost:8001/plugins \ --data "name=rate-limiting" \ --data "config.minute=100" \ --data "config.policy=cluster"

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

  • ✅ Синхронизация между узлами
  • ✅ Персистентность (сохраняется при перезапуске)

Недостатки:

  • ❌ Медленнее (запросы к БД)
  • ❌ Дополнительная нагрузка на БД

#Redis policy (рекомендуется для production)

Проблема: Нужна высокая производительность и синхронизация между узлами.

Решение: Хранение счётчиков в Redis.

curl -X POST http://localhost:8001/plugins \ --data "name=rate-limiting" \ --data "config.minute=100" \ --data "config.policy=redis" \ --data "config.redis_host=redis.example.com" \ --data "config.redis_port=6379" \ --data "config.redis_password=secret" \ --data "config.redis_database=0" \ --data "config.redis_timeout=2000" \ --data "config.redis_ssl=false" \ --data "config.fault_tolerant=true"

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

  • ✅ Высокая производительность (in-memory)
  • ✅ Синхронизация между узлами
  • ✅ Персистентность (с AOF/RDB)

Недостатки:

  • ❌ Зависимость от Redis
  • ❌ Дополнительная инфраструктура

#1.3. Лимиты на уровне Consumer

Проблема: Разные лимиты для разных тарифов (бесплатный vs премиум).

Решение: Применение rate-limiting к Consumer.

# Бесплатный тариф: 100 запросов/час curl -X POST http://localhost:8001/consumers/free-user/plugins \ --data "name=rate-limiting" \ --data "config.hour=100" \ --data "config.policy=redis" # Премиум тариф: 10000 запросов/час curl -X POST http://localhost:8001/consumers/premium-user/plugins \ --data "name=rate-limiting" \ --data "config.hour=10000" \ --data "config.policy=redis" # Enterprise: 100000 запросов/час curl -X POST http://localhost:8001/consumers/enterprise/plugins \ --data "name=rate-limiting" \ --data "config.hour=100000" \ --data "config.policy=redis"

Приоритет:

  • Лимит Consumer переопределяет лимит Route/Service
  • Если Consumer не имеет собственного лимита, применяется лимит Route

#1.4. Заголовки rate limiting

Проблема: Клиент должен знать свои лимиты.

Решение: Kong добавляет заголовки к ответам.

curl -i http://localhost:8000/api/users \ -H "apikey: secret-key-123"

Ответ:

HTTP/1.1 200 OK
X-RateLimit-Limit-Minute: 100
X-RateLimit-Remaining-Minute: 95
X-RateLimit-Limit-Hour: 1000
X-RateLimit-Remaining-Hour: 950

Заголовки:

  • X-RateLimit-Limit-{period} — установленный лимит
  • X-RateLimit-Remaining-{period} — осталось запросов
  • При превышении: Retry-After — секунд до сброса

#1.5. Блокировка при превышении

Проблема: Нужно вернуть понятную ошибку при превышении лимита.

Решение: Kong автоматически возвращает 429.

# После превышения лимита curl -i http://localhost:8000/api/users

Ответ:

HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 60

{
  "message": "API rate limit exceeded"
}

#1.6. Скользящее окно vs фиксированное окно

Проблема: Фиксированное окно позволяет "взрыв" запросов на границе окон.

Решение: Kong использует скользящее окно по умолчанию.

Фиксированное окно (1 минута):
[00:00-01:00] 100 запросов
[01:00-02:00] 100 запросов
Клиент может отправить 200 запросов за 2 секунды на границе (в 01:00)

Скользящее окно:
Конг проверяет последние 60 секунд от текущего момента
Клиент не может отправить больше 100 запросов за любые 60 секунд

#2. Request Size Limiting

Проблема: Нужно ограничить размер загружаемых файлов/данных.

Решение: Плагин request-size-limiting.

# Ограничение: 1 MB curl -X POST http://localhost:8001/plugins \ --data "name=request-size-limiting" \ --data "config.allowed_payload_size=1048576" \ --data "config.size_unit=bytes"

Параметры:

  • allowed_payload_size — максимальный размер
  • size_unit — bytes, kilobytes, megabytes, gigabytes

Ответ при превышении:

HTTP/1.1 413 Payload Too Large
Content-Type: application/json

{
  "message": "Request size is larger than the limit"
}

#3. IP Restriction

Проблема: Нужно ограничить доступ к API с определённых IP адресов.

Решение: Плагин ip-restriction.

#3.1. Whitelist (разрешить только указанные)

# Доступ только из внутренней сети curl -X POST http://localhost:8001/routes/admin-route/plugins \ --data "name=ip-restriction" \ --data "config.allow[]=10.0.0.0/8" \ --data "config.allow[]=192.168.1.0/24" \ --data "config.message=Access denied. IP not in whitelist."

#3.2. Blacklist (запретить указанные)

# Блокировка известных злоумышленников curl -X POST http://localhost:8001/plugins \ --data "name=ip-restriction" \ --data "config.deny[]=203.0.113.0/24" \ --data "config.deny[]=198.51.100.50" \ --data "config.message=Your IP has been blocked."

Ответ при блокировке:

HTTP/1.1 403 Forbidden
Content-Type: application/json

{
  "message": "Access denied. IP not in whitelist."
}

#4. Bot Detection

Проблема: Нужно обнаруживать и блокировать автоматических ботов.

Решение: Плагин bot-detection.

curl -X POST http://localhost:8001/plugins \ --data "name=bot-detection"

Обнаруживает:

  • Известные скраперы (Scrapy, wget, curl)
  • Спам-боты
  • Автоматизированные инструменты

Использование с ACL:

# Блокировка обнаруженных ботов curl -X POST http://localhost:8001/consumers/bot-user/acl \ --data "group=blocked" curl -X POST http://localhost:8001/routes/api-route/plugins \ --data "name=acl" \ --data "config.deny[]=blocked"

#5. Proxy Cache — кэширование ответов

Проблема: Часто запрашиваемые данные нагружают бэкенд.

Решение: Плагин proxy-cache кэширует ответы upstream.

#5.1. Базовая настройка

curl -X POST http://localhost:8001/plugins \ --data "name=proxy-cache" \ --data "config.content_type[]=application/json" \ --data "config.cache_ttl=300" \ --data "config.strategy=memory" \ --data "config.cache_control=true"

Параметры:

  • content_type — какие типы контента кэшировать
  • cache_ttl — время жизни кэша (секунды)
  • strategy — где хранить кэш (memory, redis)
  • cache_control — уважать заголовки Cache-Control от upstream

#5.2. Кэширование в Redis

curl -X POST http://localhost:8001/plugins \ --data "name=proxy-cache" \ --data "config.content_type[]=application/json" \ --data "config.cache_ttl=3600" \ --data "config.strategy=redis" \ --data "config.redis_host=redis" \ --data "config.redis_port=6379" \ --data "config.redis_database=1"

#5.3. Условное кэширование

Проблема: Нужно кэшировать только определённые path.

Решение: Применение плагина к Route.

# Кэширование только для /api/static/* curl -X POST http://localhost:8001/routes/static-route/plugins \ --data "name=proxy-cache" \ --data "config.cache_ttl=86400"

#5.4. Заголовки кэширования

Kong добавляет заголовки к кэшированным ответам:

X-Cache-Status: HIT    ← ответ из кэша
X-Cache-Status: MISS   ← ответ от upstream
X-Cache-TTL: 300       ← остаток времени жизни кэша

#6. Circuit Breaker

Проблема: При сбоях бэкенда нужно временно прекратить отправку запросов.

Решение: Встроенный механизм circuit breaker в Kong (через плагины или конфигурацию upstream).

#6.1. Настройка через Upstream

# Создание upstream с health checks curl -X POST http://localhost:8001/upstreams \ --data "name=api-upstream" \ --data "slots=10000" \ --data "algorithm=round-robin" \ --data "hash_on=none" \ --data "healthchecks.active.unhealthy.tcp_failures=3" \ --data "healthchecks.active.unhealthy.http_failures=3" \ --data "healthchecks.active.unhealthy.timeouts=3" \ --data "healthchecks.active.healthy.successes=2" \ --data "healthchecks.active.healthy.http_statuses[]=200" \ --data "healthchecks.active.healthy.http_statuses[]=204" \ --data "healthchecks.active.type=http" \ --data "healthchecks.active.http_path=/health" \ --data "healthchecks.active.timeout=1" \ --data "healthchecks.active.interval=5" \ --data "healthchecks.passive.unhealthy.tcp_failures=3" \ --data "healthchecks.passive.unhealthy.http_failures=3" \ --data "healthchecks.passive.unhealthy.timeouts=3" \ --data "healthchecks.passive.healthy.successes=2"

Параметры:

  • active — активные health checks (Kong периодически опрашивает /health)
  • passive — пассивные health checks (Kong отслеживает ошибки в реальном трафике)

#6.2. Circuit Breaker логика

1. Target здоров → запросы отправляются
       ↓
2. 3 неудачных запроса (таймаут/5xx) → Target помечается unhealthy
       ↓
3. Kong прекращает отправку на этот Target
       ↓
4. Через interval (5 сек) — повторная проверка
       ↓
5. 2 успешных проверки → Target снова здоров

#7. DDoS защита

Проблема: Нужна защита от распределённых атак.

Решение: Комбинация плагинов Kong.

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

# 1. Rate limiting глобально curl -X POST http://localhost:8001/plugins \ --data "name=rate-limiting" \ --data "config.second=10" \ --data "config.policy=redis" # 2. IP restriction для известных атакующих curl -X POST http://localhost:8001/plugins \ --data "name=ip-restriction" \ --data "config.deny[]=203.0.113.0/24" # 3. Bot detection curl -X POST http://localhost:8001/plugins \ --data "name=bot-detection" # 4. Request size limiting curl -X POST http://localhost:8001/plugins \ --data "name=request-size-limiting" \ --data "config.allowed_payload_size=1048576"

#7.2. Интеграция с WAF

Проблема: Нужна защита от OWASP Top 10 (SQL injection, XSS).

Решение: Kong + внешний WAF (ModSecurity, AWS WAF).

Клиент → [WAF] → [Kong] → [Upstream]

#8. Best Practices

#8.1. Rate limiting стратегии

# Многоуровневые лимиты # Global: защита от атак curl -X POST http://localhost:8001/plugins \ --data "name=rate-limiting" \ --data "config.second=10" \ --data "config.policy=redis" # Route: защита сервиса curl -X POST http://localhost:8001/routes/api-route/plugins \ --data "name=rate-limiting" \ --data "config.minute=100" \ --data "config.policy=redis" # Consumer: тарифы curl -X POST http://localhost:8001/consumers/premium/plugins \ --data "name=rate-limiting" \ --data "config.hour=10000"

#8.2. Мониторинг

# Проверка счётчиков в Redis redis-cli KEYS "kong_rate_limiting:*" # Просмотр plugin metrics через Prometheus curl http://localhost:8001/metrics

#8.3. Graceful degradation

# При недоступности Redis — пропускать запросы curl -X POST http://localhost:8001/plugins \ --data "name=rate-limiting" \ --data "config.policy=redis" \ --data "config.fault_tolerant=true" \ --data "config.redis_timeout=1000"

Далее: Наблюдаемость: логи, метрики, трассировка