概述
本质,您将学习到 Nginx 的代理服务。
正向代理 VS 反向代理
正向代理
正向代理:代理的一种方式,客户端或浏览器需要主动配置相关参数。配置完成后,客户端向代理服务器(如 Nginx、Squid、TinyProxy 等)发送请求,由代理服务器代表客户端向外部目标服务器发起请求,并将响应返回给客户端。
对个人来说,正向代理主要用于:
- 绕开网络审查(需要遵守当地的法律法规)
- 隐藏客户端的 IP 地址
对于企业来说,正向代理主要用于:
- 帮助内网客户端访问公网资源(包含缓存加速)
- 身份认证与访问日志审计,满足安全合规要求
- 内容过滤或访问控制(如限制访问特定的网站)
proxy_pass 指令实现简单 HTTP 协议的正向代理,但原生不支持 CONNECT 方法,因此无法代理 HTTPS 流量。若需支持 HTTPS 协议的正向代理,必须引入第三方模块 ngx_http_proxy_connect_module 并重新编译 Nginx,在配置上较为复杂。总体而言,Nginx 在正向代理方面的功能相对简陋,实际生产环境中使用较少(大约不到 10%),大多数正向代理场景会选择 Squid、TinyProxy 等专用代理软件。Nginx 中简单的正向代理配置:
...
events {
...
}
http {
...
server {
listen 8080;
# 不需要 server_name 指令的配置
# server_name my-tests.com www.my-tests.com;
location / {
resolver 8.8.8.8 8.8.4.4 valid=300s; # 必须配置
resolver_timeout 5s; # 可选配置
proxy_pass http://$http_host$request_uri;
proxy_set_header Host $http_host;
}
}
}
说明:
resolver 8.8.8.8 8.8.4.4 valid=300s;- 指正向代理时所使用的 DNS ,valid=300s表示 DNS 解析结果的缓存时间为 300 秒resolver_timeout 5s;- 设置 Nginx 进行单次 DNS 查询的超时等待时间上限,通常设置为 3s 或 5sproxy_pass http://$http_host$request_uri;- 通用 HTTP 协议正向代理的关键,变量$http_host表示客户端请求头中的Host字段,变量$request_uri表示完整请求路径(含参数)proxy_set_header Host $http_host;- 保证把客户端请求头中的Host字段传递给外部目标服务器
当然还有其他指令可以进一步配置,但 HTTP 协议的正向代理不是本文的重点。
利用以下命令行测试正向代理:
Shell > curl -x http://192.168.100.20:8080 http://www.my-games.com
反向代理
反向代理:代理的一种方式,指的是代理服务器拦截客户端请求并转发给后端服务器。在 Nginx 中,反向代理是 Nginx 的核心杀手锏功能,这也是它能快速占领市场份额的关键原因之一。
Q:为什么反向代理如此重要?
有了反向代理,有效解决了传统直连后端模式在性能、扩展性、安全性和运维成本等方面的核心痛点。它让 Nginx 得以在客户端与后端之间统一承担负载均衡、SSL 终止、缓存加速和安全防护等职责,是现代 Web 架构的基石,也是高可用系统中不可或缺的核心组件。
- 负载均衡 - 将客户端的请求分发到后端服务器,避免单点故障
- SSL 终止 - 在 Nginx 上处理 SSL/TTL 加密,可减轻后端服务器的负担
- 缓存加速 - 通过配置代理缓存,可减少对后端服务器的请求次数,提升性能与用户体验
- 安全防护 - 隐藏后端服务器的真实 IP 地址,防止被直接攻击
与反向代理相关的指令
涉及到的指令非常多,但是最重要是这些:
proxy_pass指令 - 设置后端服务器的协议(http 协议或 https 协议)和地址(IP 地址或域名),语法为proxy_pass URL;proxy_set_header指令 - 在请求转发给后端服务器之前,对 HTTP 请求头进行添加、修改或删除,语法为proxy_set_header field value;proxy_connect_timeout指令 - 定义 Nginx 代理服务器与后端服务器建立连接的超时时间,默认为proxy_connect_timeout 60s;proxy_send_timeout指令 - 定义 Nginx 代理服务器向后端服务器发送请求的超时时间,默认为proxy_send_timeout 60s;proxy_read_timeout指令 - 定义 Nginx 代理服务器从后端服务器读取响应的超时时间,默认为proxy_read_timeout 60s;proxy_next_upstream指令 - 定义在哪些错误情况下将请求转发给下一台后端服务器,默认为proxy_next_upstream error timeout;proxy_next_upstream_tries指令 - Nginx 最多向后端服务器发起请求的总次数,默认为proxy_next_upstream_tries 0;表示不限制总次数proxy_hide_header指令 - 移除后端服务器返回的特定响应头字段,防止这些响应头信息传递给客户端,暴露安全风险
简单版的反向代理配置:
...
events {
...
}
http {
...
server {
listen 192.168.100.20:80;
server_name tests.com www.tests.com
...
location / {
...
# 添加自定义的调试响应头
add_header X-Cache-Status $upstream_cache_status always;
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;
proxy_set_header Accept-Encoding ""; # 禁止后端压缩
# 指向的是单台后端服务器,也可以指向一组服务器
proxy_pass http://192.168.100.30:80;
...
# 连接优化相关
proxy_connect_timeout 10s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
proxy_next_upstream error timeout http_502 http_504;
# 移除后端服务器返回的高风险响应头字段
proxy_hide_header X-Powered-By;
proxy_hide_header X-AspNet-Version;
proxy_hide_header Server;
proxy_hide_header X-Debug-Token;
}
}
}
应用场景
场景一:缓存加速
在上一篇文档中已经介绍了代理缓存,参阅 这里
场景二:负载均衡
负载均衡涉及到相关的负载规则(或称负载算法,负载策略),其主要目是根据业务场景的不同来分发流量,实现流量的均衡分布。在社区版 Nginx 中,可用的基础负载规则有:
- 轮询(Round Robin)- 若不指定任何规则,则默认使用该规则
- 加权轮询(Weighted Round Robin)
- 最小连接(Least Connections)
- IP 哈希(IP Hash)
- 随机(Random)
关于负载均衡的知识与内容后面还会进一步说明,这里先知道就可以了。
上游服务器(Upstream Server):指一组后端服务器。当代理服务器拦截到客户端请求后,就会根据负载规则将这些请求转发给这些后端服务器。需要注意的是,在标准的生产环境中,后端服务器的数量通常建议大于等于 3 台(当然这不是强制的,1 台 或 2 台都是被允许的),以保证足够的性能、冗余以及可用性。在主配置文件 nginx.conf 中可通过 upstream 上下文来定义一组后端服务器,需要注意,upstream 上下文只能配置在 http 上下文中。
反向代理实现负载均衡的配置示例:
...
events {
...
}
http {
...
# 定义了名为 backend1 的一组后端服务器(未指定任何负载策略,默认使用轮询)
upstream backend1 {
server 192.168.100.30;
server 192.168.100.35;
server 192.168.100.40;
}
...
server {
listen 192.168.100.20:80;
server_name my-tests.com www.my-tests.com;
# 重定向跳转
return 301 https://www.my-tests.com$request_uri;
}
server {
listen 192.168.100.20:443 ssl http2 backlog=8000 reuseport;
server_name www.my-tests.com;
# SSL/TLS 证书相关的配置
ssl_certificate /usr/local/nginx/ssl/fullchain.pem;
ssl_certificate_key /usr/local/nginx/ssl/my_privkey.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 15m;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# 在代理层统一设置压缩响应
gzip on;
gzip_vary on;
gzip_buffers 32 4K;
gzip_comp_level 5;
gzip_types text/plain text/css text/xml application/json application/javascript application/xml application/xhtml+xml image/svg+xml application/x-font-ttf application/x-font-opentype application/vnd.ms-fontobject font/woff;
gzip_min_length 256;
location / {
...
# 下面是前面文档代理缓存中的内容(以 pxory_cache 开头的指令),应该很熟悉了
proxy_cache my_cache;
proxy_cache_key "$scheme$host$request_uri";
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_valid 500 502 503 504 10s;
proxy_cache_lock on;
proxy_cache_lock_timeout 5s;
proxy_cache_background_update on;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
# 添加自定义的调试响应头
add_header X-Cache-Status $upstream_cache_status always;
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;
proxy_set_header Accept-Encoding ""; # 禁止后端压缩
# 指向一组服务器
proxy_pass http://backend1;
# 连接优化相关
proxy_connect_timeout 10s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
proxy_next_upstream error timeout http_502 http_504;
# 安全风险控制
proxy_hide_header X-Powered-By;
proxy_hide_header Server;
}
}
}
使用者可根据实际情况下在示例配置之上做进一步的优化配置,如增加或删除相关指令,调整指令的指令参数等。
场景三:SSL 终止
场景二的示例配置就使用了 SSL 终止,Nginx 代理服务器实际处理 HTTPS 握手,但是在后端使用 HTTP 明文协议(proxy_pass http://backend1;),换言之,Nginx 在解密客户端的 HTTPS 加密流量后,会将明文的 HTTP 请求转发给后端服务器,后端服务器不需要处理 SSL 加解密,只需处理普通的 HTTP 请求。
错误排查
查阅 Nginx 代理服务器的错误日志、访问日志,检查软件防火墙(Firewalld)、SeLinux、网络连通性等。










