
前几天晚上,我帮一个朋友看 Nginx 配置。他问了个挺典型的问题:
“我这到底算正向代理,还是反向代理?”
这个问题看着像基础题,但真到项目里,很容易混。尤其是做网站部署、API 转发、采集任务、内网访问时,只要方向判断错了,后面的配置、日志和排障都会跟着乱。
我一般用一句话先拆开:
正向代理,是客户端找代理出去;反向代理,是服务端放代理在前面接请求。
这句话记住,后面基本就顺了。
正向代理的重点,是它替客户端访问外部目标。
请求大概是这样:
客户端 → 正向代理 → 目标服务器比如一台内网机器不能直接访问外部网站,它先把请求交给代理服务器,再由代理服务器去访问目标站点,最后把结果带回来。
这时,目标服务器看到的通常是代理服务器,而不是原始客户端。
所以正向代理常见于这些场景:
我们工作室做采集任务时也会遇到类似问题,比如一些任务会接青果的隧道代理,关注点不是后端服务怎么部署,而是“请求从哪个出口出去、失败后怎么切换、日志里能不能追到这次请求”。这就是典型的正向代理思路。
不过要注意:正向代理不等于一定要用 Nginx。
Nginx 可以做一些简单 HTTP 正向代理,但如果涉及浏览器访问 HTTPS 网站,通常会用到 CONNECT 隧道。原生 Nginx 的 HTTP 模块并不直接完整支持这类正向代理能力,往往需要第三方模块,或者直接选 Squid、TinyProxy、HAProxy、专门代理服务来做。
别把“能凑出来”和“适合生产长期用”混成一件事。
反向代理正好反过来。
用户访问的不是后面的真实业务服务,而是先访问 Nginx。Nginx 接住请求后,再把请求转发到后端应用。
请求大概是这样:
用户 → Nginx 反向代理 → 后端服务比如用户访问:
https://www.example.com/api/userNginx 实际可能把它转给:
http://127.0.0.1:8080/user用户不知道后面跑的是 Java、Go、Node.js,还是多个服务实例。它只知道访问一个域名。
这就是反向代理的关键:Nginx 代表后端服务对外接收请求。
反向代理常见用途包括:
大多数人日常说“Nginx 代理一下”,其实说的都是反向代理。
对比项 | 正向代理 | 反向代理 |
|---|---|---|
代理站在哪边 | 客户端一侧 | 服务端一侧 |
替谁工作 | 替客户端访问外部资源 | 替后端服务接收请求 |
隐藏谁 | 隐藏客户端 | 隐藏真实后端服务器 |
谁配置代理 | 客户端或客户端所在网络 | 服务端部署方 |
用户是否感知 | 通常需要客户端配置 | 用户一般无感知 |
常见用途 | 统一出口、采集代理、访问外部资源 | 网站入口、API 转发、负载均衡 |
Nginx 是否擅长 | 可做简单场景,不是最强项 | 非常常用,也很成熟 |
我自己的判断方法很简单:
代理替客户端出去,就是正向代理。 代理替服务端接客,就是反向代理。
最常见的 Nginx 反向代理配置是这样:
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
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;
}
}这段配置的意思是:
用户访问 example.com,Nginx 接住请求,然后把请求转给本机 8080 端口的后端服务。
这里有几个头字段很关键。
proxy_set_header Host $host;把原始域名传给后端。很多后端服务会根据 Host 判断站点、租户或回调地址。
proxy_set_header X-Real-IP $remote_addr;把用户真实 IP 传给后端。
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;记录请求经过的代理 IP 列表。多层代理环境里,这个字段很常见。
proxy_set_header X-Forwarded-Proto $scheme;告诉后端原始请求是 HTTP 还是 HTTPS,避免后端生成错误跳转。
很多线上问题,不是 proxy_pass 写错,而是这些头没传好。比如后端日志里全是 127.0.0.1,或者 HTTPS 站点跳回 HTTP,通常都和这里有关。
反向代理再往前一步,就是负载均衡。
upstream app_servers {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
}
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://app_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}这时 Nginx 不再只转发到一个后端,而是转发到一组后端服务。
默认情况下,Nginx 会轮询分发请求。也可以配置权重:
upstream app_servers {
server 192.168.1.10:8080 weight=3;
server 192.168.1.11:8080 weight=1;
}这表示第一台机器承担更多请求。
这种结构在 Web 项目里很常见:
用户请求 → Nginx → 多个应用实例 → 数据库或缓存这里的 Nginx 不是帮客户端访问外部资源,而是帮后端服务接住外部流量,所以它是反向代理。
Nginx 也可以写一个简单的 HTTP 正向代理配置:
server {
listen 8888;
resolver 8.8.8.8;
location / {
proxy_pass http://$http_host$request_uri;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
}
}客户端需要把代理地址配置成:
http://代理服务器IP:8888然后客户端访问外部 HTTP 网站时,请求会先到这台 Nginx,再由 Nginx 去访问目标站点。
但这段配置只适合说明概念,不建议直接当完整生产方案。
原因有两个:
第一,它主要适合普通 HTTP 请求。
第二,HTTPS 正向代理通常需要 CONNECT 方法建立隧道,原生 Nginx 并不完整支持这类场景。真要长期跑,建议评估更合适的代理服务,或者确认 Nginx 是否已加载对应第三方模块。
正向代理主要解决的是:
客户端怎么访问外部资源典型用途包括:
做采集或接口调试时,正向代理更关注“出去”的质量:出口 IP 是否稳定、失败能不能定位、目标站返回异常时能不能判断是代理问题还是目标站问题。
反向代理主要解决的是:
外部请求怎么进入后端服务典型用途包括:
比如一个网站有前台、后台、API 三部分,就可以用 Nginx 按路径分发:
server {
listen 80;
server_name example.com;
location /api/ {
proxy_pass http://127.0.0.1:8080/;
}
location /admin/ {
proxy_pass http://127.0.0.1:9000/;
}
location /static/ {
root /data/www;
}
}用户只访问一个域名,Nginx 在后面把不同请求分给不同服务。这个场景就是反向代理。
误区一:看到 proxy_pass 就认为一定是反向代理。
不一定。proxy_pass 只是转发指令,关键还要看代理站在哪边。
误区二:正向代理和反向代理只是方向不同。
方向只是表象。真正差异是控制权和隐藏对象不同:正向代理通常由客户端侧控制,隐藏客户端;反向代理由服务端侧控制,隐藏后端服务。
误区三:Nginx 做正向代理和反向代理一样成熟。
不一样。Nginx 做反向代理非常成熟;做完整正向代理,尤其是 HTTPS 隧道场景,通常不是它最舒服的位置。
误区四:用了反向代理就拿不到真实用户 IP。
不是拿不到,而是要正确传递和读取头字段。Nginx 要设置 X-Real-IP、X-Forwarded-For,后端也要按可信代理规则读取,不能随便相信客户端伪造的头。
正向代理和反向代理的区别,不在 Nginx 这个软件本身,而在请求关系里。
正向代理解决“客户端怎么出去”。
反向代理解决“外部请求怎么进来”。
做网站入口、API 转发、负载均衡,按反向代理理解。
做统一出口、采集代理、外部资源访问,按正向代理理解。
配置 Nginx 前,先问一句:这个代理到底替谁办事?这个问题答清楚,后面的配置基本就不会跑偏。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。