Ограничение запросов, защита от DDoS, circuit breaker, proxy cache
Kong предоставляет мощные инструменты для защиты API от перегрузок, DDoS-атак и злоупотреблений.
Проблема: Нужно предотвратить перегрузку API слишком частыми запросами от одного клиента.
Решение: Плагин rate-limiting ограничивает количество запросов за определённый промежуток времени.
# Ограничение: 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 — скрывать заголовки с лимитамиПроблема: Нужна максимальная производительность для single-node.
Решение: Хранение счётчиков в памяти worker'а.
curl -X POST http://localhost:8001/plugins \
--data "name=rate-limiting" \
--data "config.minute=100" \
--data "config.policy=local"Преимущества:
Недостатки:
Проблема: Нужно синхронизировать лимиты между узлами Kong без Redis.
Решение: Использование базы данных Kong (PostgreSQL).
curl -X POST http://localhost:8001/plugins \
--data "name=rate-limiting" \
--data "config.minute=100" \
--data "config.policy=cluster"Преимущества:
Недостатки:
Проблема: Нужна высокая производительность и синхронизация между узлами.
Решение: Хранение счётчиков в 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"Преимущества:
Недостатки:
Проблема: Разные лимиты для разных тарифов (бесплатный 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"Приоритет:
Проблема: Клиент должен знать свои лимиты.
Решение: 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 — секунд до сбросаПроблема: Нужно вернуть понятную ошибку при превышении лимита.
Решение: 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"
}
Проблема: Фиксированное окно позволяет "взрыв" запросов на границе окон.
Решение: Kong использует скользящее окно по умолчанию.
Фиксированное окно (1 минута):
[00:00-01:00] 100 запросов
[01:00-02:00] 100 запросов
Клиент может отправить 200 запросов за 2 секунды на границе (в 01:00)
Скользящее окно:
Конг проверяет последние 60 секунд от текущего момента
Клиент не может отправить больше 100 запросов за любые 60 секунд
Проблема: Нужно ограничить размер загружаемых файлов/данных.
Решение: Плагин 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"
}
Проблема: Нужно ограничить доступ к API с определённых IP адресов.
Решение: Плагин ip-restriction.
# Доступ только из внутренней сети
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."# Блокировка известных злоумышленников
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."
}
Проблема: Нужно обнаруживать и блокировать автоматических ботов.
Решение: Плагин bot-detection.
curl -X POST http://localhost:8001/plugins \
--data "name=bot-detection"Обнаруживает:
Использование с 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"Проблема: Часто запрашиваемые данные нагружают бэкенд.
Решение: Плагин proxy-cache кэширует ответы upstream.
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 от upstreamcurl -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"Проблема: Нужно кэшировать только определённые path.
Решение: Применение плагина к Route.
# Кэширование только для /api/static/*
curl -X POST http://localhost:8001/routes/static-route/plugins \
--data "name=proxy-cache" \
--data "config.cache_ttl=86400"Kong добавляет заголовки к кэшированным ответам:
X-Cache-Status: HIT ← ответ из кэша
X-Cache-Status: MISS ← ответ от upstream
X-Cache-TTL: 300 ← остаток времени жизни кэша
Проблема: При сбоях бэкенда нужно временно прекратить отправку запросов.
Решение: Встроенный механизм circuit breaker в Kong (через плагины или конфигурацию 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 отслеживает ошибки в реальном трафике)1. Target здоров → запросы отправляются
↓
2. 3 неудачных запроса (таймаут/5xx) → Target помечается unhealthy
↓
3. Kong прекращает отправку на этот Target
↓
4. Через interval (5 сек) — повторная проверка
↓
5. 2 успешных проверки → Target снова здоров
Проблема: Нужна защита от распределённых атак.
Решение: Комбинация плагинов Kong.
# 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"Проблема: Нужна защита от OWASP Top 10 (SQL injection, XSS).
Решение: Kong + внешний WAF (ModSecurity, AWS WAF).
Клиент → [WAF] → [Kong] → [Upstream]
# Многоуровневые лимиты
# 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"# Проверка счётчиков в Redis
redis-cli KEYS "kong_rate_limiting:*"
# Просмотр plugin metrics через Prometheus
curl http://localhost:8001/metrics# При недоступности 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"Вопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.