部署在AWS Elastic Beanstalk的Flask API如何按真实IP限流?
解决Flask-Limiter在AWS Elastic Beanstalk上按真实IP限流的问题
问题根源
AWS Elastic Beanstalk环境中,所有请求会先经过反向代理(如Nginx)再转发到你的Flask应用。默认情况下Flask会将代理服务器的IP(127.0.0.1)识别为请求的远程地址,导致所有真实客户端的请求被归为同一IP,触发错误的限流规则。
解决方案
1. 配置Flask信任代理服务器
让Flask明确信任Elastic Beanstalk的代理,这样它会自动从代理传递的请求头中提取真实客户端IP。在Flask应用初始化代码中添加:
from flask import Flask app = Flask(__name__) # 信任代理服务器(生产环境建议指定EB代理的具体IP段,*为简化配置) app.config['TRUSTED_PROXIES'] = ['*'] # 指定代理传递真实IP的请求头,EB默认使用X-Forwarded-For app.config['REAL_IP_HEADER'] = 'X-Forwarded-For'
配置完成后,原有的get_remote_address函数会自动返回真实客户端IP,无需修改Limiter的初始化代码。
2. 自定义IP提取函数(备选方案)
如果上述配置未生效,可以自定义key_func直接处理请求头,兼容多层代理的场景:
from flask import request from flask_limiter import Limiter def get_real_ip(): # X-Forwarded-For格式为:客户端IP, 代理1IP, 代理2IP... x_forwarded_for = request.headers.get('X-Forwarded-For') if x_forwarded_for: # 取第一个非代理的真实IP return x_forwarded_for.split(',')[0].strip() # fallback到默认远程地址 return request.remote_addr # 初始化Limiter时使用自定义函数 limiter = Limiter( app, key_func=get_real_ip, storage_uri=db_host, strategy="fixed-window", ) limiter.init_app(app)
3. 确认EB代理配置(可选)
默认情况下EB的Python环境已配置Nginx传递真实IP头,若需自定义可在项目根目录创建.ebextensions/nginx/conf.d/elasticbeanstalk/00_custom_proxy.conf文件,内容如下:
proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Real-IP $remote_addr;
部署时EB会自动应用该配置。
验证
修改后重新部署到EB,用不同真实IP发起请求,确认限流规则仅针对单个真实IP生效,不会出现跨IP触发429的情况。
内容的提问来源于stack exchange,提问作者Faz
相关产品推荐
相关产品推荐

