Nginx功能篇20—代理服务

概述

本质,您将学习到 Nginx 的代理服务。

正向代理 VS 反向代理

正向代理

正向代理:代理的一种方式,客户端或浏览器需要主动配置相关参数。配置完成后,客户端向代理服务器(如 Nginx、Squid、TinyProxy‌ 等)发送请求,由代理服务器代表客户端向外部目标服务器发起请求,并将响应返回给客户端。

对个人来说,正向代理主要用于:

  • 绕开网络审查(需要遵守当地的法律法规)
  • 隐藏客户端的 IP 地址

对于企业来说,正向代理主要用于:

  • 帮助内网客户端访问公网资源(包含缓存加速)
  • 身份认证与访问日志审计,满足安全合规要求
  • 内容过滤或访问控制(如限制访问特定的网站)

说明
Nginx 可通过 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 或 5s
  • proxy_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 地址,防止被直接攻击
提示
需要说明的是,反向代理 ≠ 负载均衡。反向代理是七层(应用层)负载均衡的基础,两者不是同一个概念,反向代理关注 "请求与转发",负载均衡关注 "转发给谁(选择后端节点)"。反向代理可以不做负载均衡,比如后端服务器只有一台的情况,此时不存在选择节点的问题。实现负载均衡的效果也不一定非要使用反向代理,现代架构中,专用的工作在第四层(传输层,如 TCP/UDP)的硬件负载均衡设备(如 F5、A10),直接基于 IP + 端口做流量分发,不涉及 HTTP 请求转发,性能极强而且非常昂贵(随便一台中端硬件设备都是十几万起步,高端的都是百万级的价格)。

与反向代理相关的指令

涉及到的指令非常多,但是最重要是这些:

  • 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、网络连通性等。

Avatar photo

关于 陸風睿

GNU/Linux 从业者、开源爱好者、技术钻研者,撰写文档既是兴趣也是工作内容之一。Q - "281957576";WeChat - "jiulongxiaotianci",Github - https://github.com/jimcat8
用一杯咖啡支持我们,我们的每一篇[文档]都经过实际操作和精心打磨,而不是简单地从网上复制粘贴。期间投入了大量心血,只为能够真正帮助到您。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇