获取的全是 172 开头的假 IP?Nginx 反代后,Flask 怎么才能拿到真实访客 IP?

📖 背景 监控大屏跑起来了。我想在后台加个日志,记录访客的来源 IP 防刷。 结果一看日志傻眼了:所有记录的 IP 都是 172.18.0.x。 我用的是 Nginx 反代 Flask 容器,request.remote_addr 拿到的全是 Docker 内网 IP,根本不是访客的真实公网 IP。

🔍 原因 小学生版解释: 访客(真实 IP)把信交给了门卫(Nginx)。Nginx 把信转交给里面的收发室(Flask 容器)。 Flask 看到信,问:"谁给的?" Nginx 说:"是我给的(172.18.0.x)"。 真实访客的 IP 根本没写在信封上。Flask 被骗了。

🛠 解决 两步。Nginx 加头,Flask 解析。

  1. Nginx 传递真实 IP 修改 Nginx 配置:
css 复制代码
location / {
    proxy_pass http://dashboard:5000;
    # 告诉 Flask,真实客户端 IP 是什么
    proxy_set_header X-Real-IP $remote_addr;
    # 如果有多层代理,用这个追加
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
  1. Flask 信任 Nginx 的头 修改 Flask 代码(通常是 app.py 或 init.py):
python 复制代码
from flask import Flask, request
from werkzeug.middleware.proxy_fix import ProxyFix

app = Flask(__name__)
# 告诉 Flask:我前面有 1 层代理(Nginx),请从 X-Forwarded 头里取真实 IP
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1)

@app.route('/')
def index():
    # 现在拿到的就是真实公网 IP 了
    return f"Your Real IP: {request.remote_addr}"

✅ 验证效果 重启 Nginx 和 Flask 容器。 用手机(不用 WiFi,用 4G)访问大屏。 看 Flask 日志,或者页面输出: 预期输出:Your Real IP: 你的4G公网IP(不再是 172 开头)。

💣 三个坑 配了 Nginx 忘了配 ProxyFix:Flask 默认出于安全考虑,不信任代理头。少写一行 ProxyFix,拿到的还是内网 IP。

remoteaddrvsremote_addr vs remoteaddrvsproxy_add_x_forwarded_for:X-Real-IP 适合单层代理。如果前面有 Cloudflare 和 Nginx 两层,必须用 X-Forwarded-For 列表,并取第一个 IP。

恶意伪造:代理头是可以伪造的(客户端自己带个假 IP 过来)。如果有严格的安全需求,必须配合 Nginx 的 real_ip_module 模块处理。

相关推荐
学长毕设22 分钟前
基于SpringBoot的景点管理系统-附源码
java·spring boot·后端
生锈的键盘1 小时前
从实战搞懂 Docker:一个 Python 项目的开发环境容器化笔记
后端
九零HTTP2 小时前
RFC 7230 把请求行分了四种,网关只用得上两种
后端
SomeOtherTime3 小时前
Rust生命周期介绍(AI回答)
开发语言·后端·rust
无责任此方_修行中3 小时前
「不止技术」AIE 2026 会后感悟
人工智能·后端·ai编程
SimonKing4 小时前
Workbuddy太占C盘空间了,写个迁移工具迁走10G的数据
java·后端·程序员
喵了几个咪5 小时前
GoWind Flow 拆解:一个 Go 工作流引擎与它的双模式设计器
开发语言·人工智能·后端·golang
倔强的石头_5 小时前
AI数据库是什么?我把金仓KES的库内三件套拆开看了一遍
后端
杨凯凡6 小时前
Spring Boot 大文件下载如何实现断点续传?HTTP Range、206 与 416 实战
spring boot·后端·http