Flask中request.remote_addr总为127.0.0.1或内网IP,是因为Nginx反向代理导致;真实IP需通过Nginx透传的X-Forwarded-For头获取,且必须经ProxyFix中间件配置trusted_proxies校验后才可信。

因为 Nginx(或其他反向代理)挡在了 Flask 前面,request.remote_addr 拿到的只是代理的 IP,不是用户真实 IP —— 这不是 Flask 的 bug,而是网络拓扑决定的。
request.remote_addr 总是 127.0.0.1 或内网地址
Flask 看到的 TCP 连接来源是 Nginx 本机,不是浏览器。它根本不知道原始客户端在哪,request.remote_addr 只反映 WSGI server 收到连接的对端地址。
- 如果你用
app.run()直连调试,request.remote_addr是对的;一旦加了 Nginx,就失效 - 哪怕 Nginx 和 Flask 在同一台机器,只要走
localhost:80 → 127.0.0.1:5000,request.remote_addr就是127.0.0.1 - 跨机器部署时常见值:`10.x.x.x`、`172.16.x.x`、`192.168.x.x` —— 全是 Nginx 所在服务器的内网出口 IP
Nginx 必须透传 X-Forwarded-For 头
不配置 Nginx,Flask 根本收不到真实 IP 的线索。光靠 Flask 代码无法“变”出这个头。
- 在
location块里加这行:proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - 别用
$remote_addr替代 —— 它只写最上一级代理 IP,丢掉原始客户端信息 - 如果链路中有 CDN 或二级负载均衡,
X-Forwarded-For会变成逗号分隔字符串(如"203.0.113.195, 198.51.100.1"),最左边才是用户真实 IP - 检查是否生效:在 Flask 里打印
request.headers.get("X-Forwarded-For"),为空说明 Nginx 没配或配错了
ProxyFix 中间件必须显式配置 trusted_proxies
Werkzeug 的 ProxyFix 不会自动信任任何代理 —— 缺少 trusted_proxies 参数等于没配。
FastAPI + Flask 混合部署最佳实践,解决路由定义、API 代理等常见问题,适用于同时运行 FastAPI API 与 Flask 前端的场景。
立即学习“Python免费学习笔记(深入)”;
- 错误写法:
app.wsgi_app = ProxyFix(app.wsgi_app)(默认trusted_proxies是空集,不生效) - 正确写法(单台 Nginx 在本地):
app.wsgi_app = ProxyFix(app.wsgi_app, trusted_proxies=["127.0.0.1"]) - 跨机器部署:
trusted_proxies=["10.0.1.5"](填 Nginx 服务器实际出口 IP) - 支持 CIDR 写法:
trusted_proxies=["192.168.0.0/16", "172.16.0.0/12"],但别写成"192.168.0.*"这种无效格式 - 启用后,
request.remote_addr才会自动替换为解析后的用户真实 IP
手动取 X-Forwarded-For 时最容易踩的坑
绕过 ProxyFix 自己解析 X-Forwarded-For 是高危操作,极易被伪造。
- 绝对不要这样写:
request.headers.get("X-Forwarded-For", "").split(",")[0].strip() - 必须先校验:
request.remote_addr是否落在你声明的可信代理列表里,否则直接忽略该头 - 注意空格和端口:
" 1.2.3.4:5000 "要先.strip().split(":")[0] - IPv6 地址带方括号(如
[::1]),ipaddress.ip_address()解析前需清理 -
request.environ.get("HTTP_X_FORWARDED_FOR")比request.headers.get()更稳定,尤其在 Gunicorn 等 WSGI 服务器下
真实 IP 获取不是“读一个字段”就能搞定的事,它依赖 Nginx 配置、WSGI 中间件、可信代理定义三者严格对齐。少一个环节,拿到的就可能是伪造的、过期的或中间代理的 IP。

















