Nginx 反向代理(Reverse Proxy)是让 Nginx 作为前端接受外部请求,再转发给后端应用的经典架构。无论是 Node.js、Python(Gunicorn/Uvicorn)、Java(Tomcat)还是其他语言写的服务,只要监听在本机某个端口,都可以让 Nginx 做前端代理,统一管理 SSL、日志、限流与请求头。本文讲清搬瓦工 VPS 上 Nginx 反向代理的核心配置。

本文要点

  • proxy_pass 指令的写法与路径注意事项
  • 转发必要的请求头(真实 IP、Host 等)
  • WebSocket 的额外配置
  • upstream 块实现多后端与健康检查
  • 常见代理错误的排查

反向代理的工作原理

客户端向 Nginx 发送请求 → Nginx 根据配置把请求转给后端(如 localhost:3000) → 后端处理后把响应返回给 Nginx → Nginx 再返回给客户端。整个过程中客户端只看到 Nginx 的 IP,后端应用不需要暴露在公网。

组件角色典型端口
Nginx前端代理,处理 SSL、日志、限流80 / 443
Node.js / Python / Java后端应用,处理业务逻辑3000 / 8000 / 8080
数据库数据层,仅监听本地3306 / 5432

最简单的反向代理配置

假设后端应用跑在本机 127.0.0.1:3000

server {
    listen 80;
    server_name app.example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
    }
}

转发必要的请求头

默认情况下,后端收到的 REMOTE_ADDR 是 127.0.0.1(Nginx 本身),丢失了真实客户端 IP。添加以下头部让后端能获取真实信息:

location / {
    proxy_pass http://127.0.0.1:3000;

    # 传递真实客户端 IP
    proxy_set_header X-Real-IP         $remote_addr;
    proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;

    # 保留原始 Host
    proxy_set_header Host $host;

    # 关闭重定向自动修改
    proxy_redirect off;
}

后端应用如何获取真实 IP

后端需要读取 X-Real-IPX-Forwarded-For 头部,而非直接读 REMOTE_ADDR。各框架做法不同,请查阅对应文档。

配置 WebSocket 支持

若后端应用使用 WebSocket,需要额外添加协议升级头:

location /ws/ {
    proxy_pass http://127.0.0.1:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade    $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host       $host;
    proxy_read_timeout 3600s;   # 长连接超时
}

用 upstream 定义上游

当后端有多个实例,或想给上游起一个易读的名字时,使用 upstream 块:

upstream backend_app {
    server 127.0.0.1:3000;
    server 127.0.0.1:3001;   # 多个后端实例,轮询负载
    keepalive 32;             # 保持连接池
}

server {
    listen 80;
    server_name app.example.com;

    location / {
        proxy_pass http://backend_app;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

超时参数调整

参数默认值说明
proxy_connect_timeout60s连接上游超时
proxy_send_timeout60s向上游发送超时
proxy_read_timeout60s等待上游响应超时

对于响应慢的后端(如长时间运行的 API),适当加大 proxy_read_timeout,避免 504 Gateway Timeout。

不要把数据库直接暴露给代理

反向代理应指向应用进程,而非数据库端口。数据库应仅监听本地回环地址,由应用程序内部连接。

常见错误排查

  • 502 Bad Gateway:后端服务未启动或监听地址/端口不对,检查 proxy_pass 地址
  • 504 Gateway Timeout:后端响应太慢,加大 proxy_read_timeout
  • 400 Bad Request:后端对 Host 头有要求,确认 proxy_set_header Host 写正确

小结

  • proxy_pass 指向后端地址,注意末尾斜杠影响路径拼接
  • 必须转发 X-Real-IP、X-Forwarded-For、Host 等头部
  • WebSocket 需额外加 Upgrade / Connection 头
  • upstream 块适合多后端或统一命名

常见问题

proxy_pass 末尾加不加斜杠有什么区别?

有区别。proxy_pass http://127.0.0.1:3000/(有斜杠)会把 location 匹配的前缀去掉再拼接;无斜杠则把完整 URI 转发。通常代理根路径时两者等效,代理子路径时需注意。

后端是 HTTPS 需要特别配置吗?

需要把 proxy_pass 改为 https:// 并根据情况配置 proxy_ssl_verify on/off。若后端用自签名证书,可设置 proxy_ssl_verify off(仅内网可信环境)。

如何限制只允许 Nginx 访问后端端口?

让后端绑定 127.0.0.1(而非 0.0.0.0),这样只有本机进程能连接。配合防火墙不对外开放后端端口,双重保护。