diff --git a/.env b/.env index 834f92a..01f03ef 100644 --- a/.env +++ b/.env @@ -138,8 +138,8 @@ CORS_ALLOWED_ORIGINS=http://localhost:8001 # 可信代理层数 - nginx直接透传CDN的X-Forwarded-For(只传真实客户端IP,不追加) TRUSTED_PROXY_COUNT=1 -# 可信代理IP白名单 - nginx同机部署,信任本机回环地址 -TRUSTED_PROXY_IPS=127.0.0.1 +# 可信代理IP白名单 - CDN节点IP不固定,使用0.0.0.0信任所有来源(安全由CDN+nginx保证) +TRUSTED_PROXY_IPS=0.0.0.0 # ============================================================ diff --git a/.env.example b/.env.example index 690a503..f6db726 100644 --- a/.env.example +++ b/.env.example @@ -131,7 +131,7 @@ CAPTCHA_NOISE_DOTS=30 CORS_ALLOWED_ORIGINS=http://localhost:8001 # 可信代理层数 - 0=不信任X-Forwarded-For;仅部署在Nginx等反代后才设>=1 TRUSTED_PROXY_COUNT=1 -# 可信代理IP白名单(逗号分隔)- nginx同机部署,信任本机回环地址 +# 可信代理IP白名单(逗号分隔)- nginx同机部署填127.0.0.1;有CDN且动态边缘IP填0.0.0.0 TRUSTED_PROXY_IPS=127.0.0.1 # ============================================================ diff --git a/deploy/nginx.conf b/deploy/nginx.conf index c97c75a..835401f 100644 --- a/deploy/nginx.conf +++ b/deploy/nginx.conf @@ -44,7 +44,8 @@ server { proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # 透传上游X-Forwarded-For(不追加本机IP);无上游头时回退到直连IP + proxy_set_header X-Forwarded-For $http_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Connection ""; proxy_connect_timeout 60s; diff --git a/src/utils/ip.py b/src/utils/ip.py index 70abc54..ec9b17e 100644 --- a/src/utils/ip.py +++ b/src/utils/ip.py @@ -76,6 +76,12 @@ def get_client_ip(request) -> str: Returns: 客户端IP地址 """ + # === 临时调试 === + peer = request.client.host if request.client else 'None' + xff = request.headers.get('X-Forwarded-For', 'EMPTY') + print(f"[DEBUG IP] peer={peer}, trusted={peer in TRUSTED_PROXY_IPS}, count={TRUSTED_PROXY_COUNT}, xff={xff}", + flush=True) + # === 临时调试 === if TRUSTED_PROXY_COUNT > 0 and _peer_is_trusted_proxy(request): forwarded = request.headers.get('X-Forwarded-For', '') if forwarded: @@ -102,8 +108,13 @@ def _peer_is_trusted_proxy(request) -> bool: 若 TRUSTED_PROXY_IPS 为空或对端不命中 → 不信任代理头。否则应用被直接暴露 (如 Docker bridge 映射端口、未走 Nginx)时,客户端可随意伪造 XFF 首部, 绕过基于 IP 的登录锁定/请求限流。 + + 特殊值: TRUSTED_PROXY_IPS 包含 '0.0.0.0' 时信任所有对端(适用于 CDN 等 + 动态边缘IP场景,安全由 CDN + nginx 保证)。 """ if not TRUSTED_PROXY_IPS: return False + if '0.0.0.0' in TRUSTED_PROXY_IPS: + return True client = request.client return client is not None and client.host in TRUSTED_PROXY_IPS