
Flask 如何用 nginx 反向代理 WSGI 服务器并配置 X-Forwarded 头与 ProxyFix【免费下载链接】flaskThe Python micro framework for building web applications.项目地址: https://gitcode.com/gh_mirrors/fl/flask当 Flask 应用部署到生产环境时官方文档明确建议不要使用内置开发服务器而是用 Gunicorn、Waitress 这类专用 WSGI 服务器来运行应用。此时通常还需要在 WSGI 服务器前面再放一层 HTTP 服务器——也就是 nginx 反向代理——由它来处理入站请求、TLS 以及安全和性能相关问题。这篇文章说明两件事如何配置 nginx 把请求转发给本地 WSGI 服务器并添加X-Forwarded-头以及如何在 Flask 应用中用 Werkzeug 的ProxyFix中间件信任并使用这些头。为什么需要反向代理和 X-Forwarded 头当使用反向代理时代理会拦截所有外部请求并转发给本地 WSGI 服务器。此时从 WSGI 服务器和 Flask 应用的角度看请求来自 HTTP 服务器所在的本地地址而不再是远程客户端。为了让应用拿到真实的客户端信息HTTP 服务器应当设置X-Forwarded-头把真实值传递给应用然后再通过ProxyFix中间件告诉应用去信任并使用这些值参见 部署总览 中对 reverse proxy 的定义。准备让 WSGI 服务器监听本地地址以 Gunicorn 为例Waitress 同理见 Gunicorn 文档、Waitress 文档$ cd hello-app $ python -m venv .venv $ . .venv/bin/activate $ pip install . # install your application $ pip install gunicorn # equivalent to from hello import app $ gunicorn -w 4 hello:app其中hello:app表示from hello import app格式为{module_import}:{app_variable}如果使用应用工厂模式也可以写成函数调用形式如gunicorn -w 4 hello:create_app()。-w指定 worker 进程数默认只有 1 个 worker文档给出的起始值是CPU * 2。关键点Gunicorn 不应以 root 运行因此无法绑定 80/443 端口这正是需要 nginx 这类反向代理放在前面的原因。文档同时警告不要使用-b 0.0.0.0把 Gunicorn 绑定到所有外部 IP否则可以绕过反向代理直接访问 WSGI 服务器。默认的http://127.0.0.1:8000监听即可nginx 配置正是假设 WSGI 服务器监听在这个地址上。启动后 Gunicorn 会输出文档示例Starting gunicorn 20.1.0 Listening at: http://127.0.0.1:8000 (x) Using worker: sync Booting worker with pid: x配置 nginx 反向代理nginx 可以用系统包管理器安装Linux 上配置文件位于/etc/nginx/nginx.conf不同操作系统路径可能不同自行查找nginx.conf。nginx 本身的安装和运行不在 Flask 文档范围内。配置步骤删除或注释掉现有的server段添加新的server段用proxy_pass指向 WSGI 服务器监听的地址用proxy_set_header添加X-Forwarded-头server { listen 80; server_name _; location / { proxy_pass http://127.0.0.1:8000/; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Prefix /; } }四个头分别传递真实客户端 IPX-Forwarded-For、协议X-Forwarded-Proto、主机名X-Forwarded-Host和路径前缀X-Forwarded-Prefix。如果 WSGI 服务器监听地址不是http://127.0.0.1:8000替换proxy_pass的目标即可。用 ProxyFix 让 Flask 信任这些头nginx 设置好头之后还需要在应用中启用 Werkzeug 提供的ProxyFix中间件。写法是包装应用的wsgi_app属性而不是包装app本身——这样app仍指向你的 Flask 应用而不是中间件你可以继续直接配置appfrom werkzeug.middleware.proxy_fix import ProxyFix app.wsgi_app ProxyFix( app.wsgi_app, x_for1, x_proto1, x_host1, x_prefix1 )参数含义是每一级代理负责设置哪些头x_for、x_proto、x_host、x_prefix表示各有多少个代理设置了X-Forwarded-For、X-Forwarded-Proto、X-Forwarded-Host、X-Forwarded-Prefix。上面的示例对应前面只有一级代理即本文的 nginx 场景。文档对此有明确的安全约束必须遵守只有应用确实位于代理后面时才应用这个中间件必须设置正确的代理层数——并非所有代理都会设置全部头而入站的X-Forwarded-头可以被伪造必须通过参数声明有几层代理在设置每个头中间件才知道该信任多少层如果这个配置弄错了可能成为安全问题。验证代理是否生效Flask 文档没有单独的nginx 部署成功检查清单验证方式是按文档给出的链路逐步确认WSGI 服务器已先于 nginx 启动并且proxy_pass指向的地址与 WSGI 服务器Listening at输出的地址一致本例为http://127.0.0.1:8000浏览器或curl通过 nginx 访问站点请求能返回应用页面说明proxy_pass链路通了。测试时可以按 nginx 文档 的建议模拟域名在 Linux 的/etc/hosts或现代 Linux 系统对.localhost域名的处理中加一行例如127.0.0.1 hello.localhost在应用内部读取请求上下文时确认拿到的是代理传入的真实值主机、协议、客户端 IP 等而不是本地回环地址——这一步对应 proxy_fix 文档 描述的代理把外部请求转发给本地 WSGI 服务器的场景如果读到的Host等值是 nginx 本地地址而不是客户端真实值说明ProxyFix未生效或参数与实际代理层数不符。限制与边界不要把 WSGI 服务器绑定到0.0.0.0文档明确说明在反向代理场景下这样做会绕过代理WSGI 服务器应只监听127.0.0.1由 nginx 的listen 80对外服务。nginx 配置示例是文档给出的基础形式server_name _匹配任意主机名生产环境中域名解析与配置不在 Flask 文档范围内需要按 nginx 自身文档补充。ProxyFix的参数必须与实际代理链匹配本文主路径是nginx 一层代理参数取 1如果实际链路上代理层数不同需要按 proxy_fix 文档重新确认每层设置了哪些头。下一步部署文档建议如果前面还有代理可能改写Host头可以设置TRUSTED_HOSTS来限制应用允许的Host取值配合ProxyFix明确告知应用该信任哪些代理值详见 web-security 文档。【免费下载链接】flaskThe Python micro framework for building web applications.项目地址: https://gitcode.com/gh_mirrors/fl/flask创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考