DRF限流被绕过问题求助:Nginx X-Forwarded-For配置无效
问题根源与修复方案
核心问题分析
- Nginx配置逻辑误区:你使用的
$proxy_add_x_forwarded_for会将客户端主动发送的X-Forwarded-For值与Nginx实际获取到的真实客户端IP($remote_addr)拼接。比如客户端伪造X-Forwarded-For: 1.1.1.1,Nginx转发给后端的头部会变成X-Forwarded-For: 1.1.1.1, 2.2.2.2(其中2.2.2.2是用户真实IP)。而DRF默认会取X-Forwarded-For中的第一个IP作为限流依据,导致客户端可通过不断伪造不同IP绕过限流。 - Postman观察误解:你在Postman中看到的是发送给Nginx的请求头,Nginx修改的是转发给Gunicorn的后端请求头,客户端无法直接看到修改后的头部,因此你的推测方向有误,真正问题是DRF拿到的是伪造IP而非真实IP。
修复步骤
1. 修正Nginx的X-Forwarded-For配置
直接丢弃客户端发送的X-Forwarded-For,强制设置为真实客户端IP:
修改proxy_params文件中的配置:
# 替换原有的proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $remote_addr;
这样无论客户端如何篡改请求头,后端收到的X-Forwarded-For都是Nginx直接获取到的真实客户端IP。
2. 配置Django/DRF信任代理并正确获取IP
在Django的settings.py中添加以下配置,确保DRF使用X-Forwarded-For中的IP进行限流:
# 信任Nginx作为反向代理 USE_X_FORWARDED_HOST = True # 若使用HTTPS,添加该行(根据实际情况调整) SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') # 配置DRF限流规则与IP获取方式 REST_FRAMEWORK = { 'DEFAULT_THROTTLE_CLASSES': [ 'rest_framework.throttling.AnonRateThrottle', 'rest_framework.throttling.UserRateThrottle' ], 'DEFAULT_THROTTLE_RATES': { 'anon': '100/day', 'user': '1000/day' }, # 指定优先从X-Forwarded-For获取客户端IP 'REMOTE_ADDR_HEADER': 'HTTP_X_FORWARDED_FOR' }
3. 验证修复效果
在Django视图中添加调试代码,打印客户端IP:
from rest_framework.views import APIView from rest_framework.response import Response class DebugIPView(APIView): def get(self, request): client_ip = request.META.get('HTTP_X_FORWARDED_FOR') or request.META.get('REMOTE_ADDR') return Response({'client_ip': client_ip})
访问该接口,无论客户端如何篡改X-Forwarded-For,返回的IP都应为你的真实客户端IP,此时DRF限流会基于真实IP生效,无法绕过。
内容的提问来源于stack exchange,提问作者Nicolas
相关产品推荐
相关产品推荐

