Fix: rate-limiter (tower_governor) считал весь трафик одним клиентом
Дефолтный PeerIpKeyExtractor брал IP из TCP-peer'а, а не заголовков — а nginx проксирует локально, так что peer всегда 127.0.0.1. В итоге лимит "3 запроса/5с" на /auth и "10/100мс" на остальной API/v1 был не per-visitor, а глобальным на весь прод: несколько попыток логина от кого угодно — и все остальные посетители ловили 429 на /auth (это и мешало зайти в свежесозданную админку — 401 на пробное неверное дело быстро съедал бюджет, дальше только 429). Добавлен SmartIpKeyExtractor (x-forwarded-for/x-real-ip/forwarded, именно то, что реально шлёт nginx) в оба GovernorConfigBuilder.
This commit is contained in:
+11
-1
@@ -17,7 +17,9 @@ use axum::{
|
||||
use metrics_exporter_prometheus::{Matcher, PrometheusBuilder};
|
||||
use serde_json::json;
|
||||
use std::{sync::Arc, time::Instant};
|
||||
use tower_governor::{governor::GovernorConfigBuilder, GovernorLayer};
|
||||
use tower_governor::{
|
||||
governor::GovernorConfigBuilder, key_extractor::SmartIpKeyExtractor, GovernorLayer,
|
||||
};
|
||||
use tower_http::{
|
||||
cors::CorsLayer,
|
||||
services::{ServeDir, ServeFile},
|
||||
@@ -111,8 +113,15 @@ pub fn create_router(state: ApiState, frontend_dir: &str) -> Router {
|
||||
let static_path = std::path::PathBuf::from(frontend_dir);
|
||||
let index_path = static_path.join("index.html");
|
||||
|
||||
// SmartIpKeyExtractor читает x-forwarded-for/x-real-ip/forwarded (в этом
|
||||
// порядке), падая на peer IP только если их нет. Без этого — дефолтный
|
||||
// PeerIpKeyExtractor видел бы просто 127.0.0.1 (nginx проксирует локально)
|
||||
// ОДИН И ТОТ ЖЕ для абсолютно всех посетителей сразу, и лимит превращался
|
||||
// бы в глобальный на весь сервис, а не per-visitor (см. incident: 3 попытки
|
||||
// логина от кого угодно — и /auth 429 для всех остальных до истечения окна).
|
||||
let gov_conf = Arc::new(
|
||||
GovernorConfigBuilder::default()
|
||||
.key_extractor(SmartIpKeyExtractor)
|
||||
.per_millisecond(100)
|
||||
.burst_size(10)
|
||||
.finish()
|
||||
@@ -121,6 +130,7 @@ pub fn create_router(state: ApiState, frontend_dir: &str) -> Router {
|
||||
|
||||
let seed_limit_conf = Arc::new(
|
||||
GovernorConfigBuilder::default()
|
||||
.key_extractor(SmartIpKeyExtractor)
|
||||
.per_millisecond(5000)
|
||||
.burst_size(3)
|
||||
.finish()
|
||||
|
||||
Reference in New Issue
Block a user