跳转到内容
Glossary 4 分钟阅读 1461 次浏览

上游代理

了解上游代理及其工作原理。逐步学习如何配置级联代理服务器,实现更精细的网络控制。

上游代理

上游代理(upstream proxy)是指另一台代理服务器将客户端请求转发到的那台代理服务器,由此形成一条链路,其中第一台代理相当于上游代理的客户端。

什么是上游代理?

当客户端向代理服务器发送请求时,该代理服务器通常直接从互联网上的源站获取所请求的资源。但在许多架构设计中,第一台代理服务器并不直接与源站通信,而是把请求转发给另一台代理服务器,即上游代理。这第二台代理再处理该请求:或从自身缓存中返回,或继续转发给再上一级的上游代理,或从源站获取。

使用上游代理的主要目的包括:

  • 分层安全: 增加一层额外的安全防护与访问控制。
  • 专用功能: 将内容过滤、病毒扫描或高级缓存等特定任务交由专门的代理处理。
  • 网络分段: 打通不同的网络分段,或提供对外部网络的受控访问。
  • 匿名与隐私: 通过多跳转发隐藏原始客户端的 IP 地址。
  • 绕过限制: 让流量经由不同的地理位置或网络转发,以绕过地域封锁或网络限制。
  • 负载均衡: 在多个上游代理或源站之间分配请求。

带上游代理的请求流程为:Client -> Proxy A -> Upstream Proxy B -> Origin Server。在该场景中,Proxy A 被配置为使用 Proxy B 作为其上游。

级联代理详解

级联代理(cascading proxies),也称代理链(proxy chaining),指的是把多台代理服务器按顺序排列的架构:每台代理把请求转发给链上的下一台,直到最后一台代理与源站通信。这为客户端请求构建了一条多跳路径。

级联代理的优点

  • 更强的安全性: 每台代理都可以执行自己的一套安全策略、身份验证和访问控制。
  • 模块化架构: 不同代理可以专注于不同功能(例如一台做缓存,一台做 WAF,一台做出口管控)。
  • 复杂路由: 支持精细的路由逻辑,把特定类型的流量导向不同的链路或地理位置。
  • 匿名性更高: 跳数越多,追溯原始客户端就越困难。
  • 冗余绕行: 当链中某台代理故障或被封时,可提供备用路径。

级联代理的缺点

  • 延迟增加: 每增加一跳代理,都会带来处理延迟和网络延迟。
  • 复杂度高: 配置与运维更加繁琐,尤其在调试和排障时。
  • 单点故障: 若未做冗余设计,链中任意一台代理故障都可能中断服务。
  • 调试困难: 跨多台服务器追踪请求路径并定位问题并不容易。
  • 首部管理: 正确处理 X-Forwarded-ForVia 等首部,对日志记录和源站识别至关重要。

配置上游代理

以下是常见代理服务器的配置示例,演示如何让一台代理把请求转发到上游。

Nginx(作为面向上游的 reverse proxy)

Nginx 通常作为 reverse proxy 运行。要让一个 Nginx 实例把请求转发到上游代理,需在 location 块内的 proxy_pass 指令中指定上游代理的地址。

# Nginx 配置(例如 proxy.example.com)
# 该 Nginx 实例作为 Proxy A,转发到 Upstream Proxy B。

http {
    upstream upstream_proxy_b {
        # 上游代理(Proxy B)的地址
        server 192.168.1.100:3128; # 示例:Proxy B 的 IP 与端口
        # 可选:若 Proxy B 有多个实例,可添加多台服务器以实现负载均衡/故障转移
        # server 192.168.1.101:3128;
    }

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

        location / {
            # 将请求转交给已定义的 upstream_proxy_b
            proxy_pass http://upstream_proxy_b;

            # 代理链推荐设置的首部
            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 Via "1.1 $hostname"; # 将当前代理加入 Via 首部
        }
    }
}

Squid(作为面向上游的 forward proxy)

Squid 常被用作 forward proxy。要让 Squid 使用上游代理,需使用 cache_peer 指令。

# Squid 配置(例如 proxy-a.conf)
# 该 Squid 实例作为 Proxy A,转发到 Upstream Proxy B。

# 定义上游代理(Proxy B)
# 语法:cache_peer hostname type http_port icp_port [options]
# type:parent 或 sibling(上游一般用 parent)
# http_port:上游代理的 HTTP 端口
# icp_port:ICP 端口(不使用或未知时通常为 0)
cache_peer 192.168.1.100 parent 3128 0 no-query default_parent

# 多个上游代理的示例(Proxy B 和 Proxy C)
# cache_peer 192.168.1.101 parent 3128 0 no-query round-robin
# cache_peer 192.168.1.102 parent 3128 0 no-query

# 允许客户端使用本代理的访问控制
acl localnet src 192.168.0.0/24 # 示例:您的客户端网络
http_access allow localnet
http_access deny all

# 指定 Squid 监听客户端请求的端口
http_port 3129 # Proxy A 监听 3129

# 可选:添加 Via 首部
via off # Squid 默认会添加 Via 首部;'off' 表示 Squid 不添加自己的 'Via' 首部,
        # 但仍会转发已有的首部。若要确保它*添加*自己的首部,请删除此行或设为 'on'。
        # 对于级联场景,通常更推荐 'via on' 或保持默认行为。

在这份 Squid 配置中,proxy-a 监听 3129 端口,并由于 default_parent 选项,把所有请求转发到 192.168.1.100:3128(Proxy B)。

配置级联代理

要搭建级联代理,需要把链中每台代理都配置为指向下一台。

场景:Client -> Proxy A -> Proxy B -> Internet

该场景包含链上的两台代理。

Proxy A 配置(前端代理)

Proxy A 是客户端的第一接入点,负责把请求转发给 Proxy B。

Nginx 作为 Proxy A:
(参见上文“配置上游代理”中的 Nginx 示例。upstream_proxy_b 块和 proxy_pass http://upstream_proxy_b; 指令使 Nginx 把请求发送到 Proxy B。)

Squid 作为 Proxy A:
(参见上文“配置上游代理”中的 Squid 示例。cache_peer 192.168.1.100 parent 3128 0 no-query default_parent 指令使 Squid 把请求发送到 Proxy B。)

Proxy B 配置(中间/上游代理)

Proxy B 接收来自 Proxy A 的请求,然后转发到互联网(若链路更长,则转发给另一台上游代理)。

Nginx 作为 Proxy B:
如果 Proxy B 同样是 Nginx 实例,通常会把它配置为向源站转发的标准 reverse proxy。如果它仅作为出口点或再下一级代理,其配置与 Proxy A 类似,只是 proxy_pass 的目标是下一台代理或真正的源站。

# Proxy B 的 Nginx 配置(192.168.1.100)
# 该 Nginx 实例接收来自 Proxy A 的请求并转发到互联网。

http {
    server {
        listen 3128; # Proxy B 监听 3128,接收来自 Proxy A 的请求
        server_name proxy-b.example.com; # 或直接监听 IP

        location / {
            # 此处 Proxy B 可以依据客户端的原始请求直接转发到源站
            # 或者,若链路继续,则转发给*另一台*上游。
            # 为简化起见,这里假设它依据原始请求转发到互联网。
            # Nginx 作为 forward proxy 更为复杂,通常涉及动态解析。
            # 更常见的场景是 Nginx 作为已知源站集合的 reverse proxy,
            # 或作为单一“下一跳”代理的前置。

            # 示例:若 Proxy B 转发到某个已知的特定源站
            # proxy_pass http://www.example.com;

            # 若 Proxy B 需要作为面向任意域名的通用 forward proxy(在 Nginx 中较少见)
            # 这需要动态解析,通常由 Squid 之类的专用 forward proxy 处理。
            # 要让 Nginx 充当通用 forward proxy,往往需要自定义 Lua 脚本或模块。
            # 更简单的 Nginx Proxy B 可能只是转交给*另一个*固定的上游。
            # 若要真正面向“互联网”转发,通常首选 Squid。

            # 若 Proxy B 只是出口点且不知道最终源站(如 Squid 那样)
            # 这正是 Nginx 作为*通用*forward proxy 能力受限之处。
            # 如果 Proxy B 是 Nginx,它更可能是针对特定服务的 reverse proxy,
            # 或者是既定链路中的下一跳,且该下一跳同样是固定的。
            # 就级联而言,如果 Nginx 是 Proxy B,通常会把它配置为
            # 转交给*已知*的下一跳或已知的源站。
            # 对于面向“通用互联网”的出口,Squid 更合适。

            # 这里假设 Proxy B 转发到一个已知的*最终*上游,例如匿名化代理
            # 或某个特定的出口网关。
            proxy_pass http://final_egress_proxy:8080; # 示例:转发到最终出口代理
            # 或者,若它是回源前的最后一跳且 Nginx 配置了动态上游解析:
            # proxy_pass $scheme://$host$request_uri; # 需要为动态 forward proxy 做自定义配置
            # 为简化起见,这里假设 Proxy B 是提供通用互联网访问的 Squid 代理。

            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 Via "1.1 $hostname";
        }
    }
}

Squid 作为 Proxy B:
Proxy B 接收来自 Proxy A 的请求,可配置为直接从互联网获取,或转发给再上一级的上游。如果它是通往互联网前的最后一台代理,就不需要指向其他代理的 cache_peer 指令(除非用于特定域名或故障转移)。

# Proxy B 的 Squid 配置(192.168.1.100)
# 该 Squid 实例接收来自 Proxy A 的请求并从互联网获取资源。

# Proxy B 监听 3128,接收来自 Proxy A 的请求
http_port 3128

# 可选:若 Proxy B 自身也有上游(例如 ISP 代理或其他特定代理)
# cache_peer upstream.isp.com parent 8080 0 no-query default_parent

# 允许 Proxy A(及其他授权客户端)连接的访问控制
acl proxy_a_network src 192.168.1.0/24 # 示例:Proxy A 所在的网络
http_access allow proxy_a_network
http_access deny all

# 按 Proxy B 的需要配置缓存、日志等

进阶级联:条件上游

若需要更复杂的路由,您可以把特定域名或路径的请求发送到不同的上游代理。

Nginx 条件上游:

http {
    # 通用流量的 upstream 组
    upstream general_upstream {
        server 192.168.1.100:3128; # Proxy B
    }

    # 特定敏感流量的 upstream 组
    upstream secure_upstream {
        server 192.168.2.200:4444; # 安全代理 Proxy C
    }

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

        location /secure/ {
            # 发往 /secure/ 的请求交给安全代理 Proxy C
            proxy_pass http://secure_upstream;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

        location / {
            # 其余所有请求发往 Proxy B
            proxy_pass http://general_upstream;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

Squid 条件上游:

# 定义多个 cache_peer
cache_peer 192.168.1.100 parent 3128 0 no-query name=general_proxy
cache_peer 192.168.2.200 parent 4444 0 no-query name=secure_proxy

# 用于识别特定流量的 ACL
acl secure_domains dstdomain .secure.example.com
acl secure_urls url_regex ^https://secure\.

# 依据 ACL 分流请求
cache_peer_access secure_proxy allow secure_domains
cache_peer_access secure_proxy allow secure_urls
cache_peer_access general_proxy allow all

# 确保未匹配任何显式 peer 访问规则的流量走直连或 default_parent
# 若未设置 default_parent,请求可能失败,或依据 'never_direct'/'always_direct' 走直连
# 通常更好的做法是设置 default_parent,或在最后加一条兜底的 'cache_peer_access'。

级联代理的关键考量

延迟与性能

链中每台代理都会增加处理时间和网络延迟。尽量减少跳数,并确保代理与网络链路具备高性能,这一点至关重要。请监控端到端延迟以发现瓶颈。

安全与身份验证

  • 代理间身份验证: 在各代理之间实施身份验证(例如 IP 白名单、共享密钥、客户端证书),防止中间代理被未授权访问。
  • SSL/TLS 终止: 确定在何处进行 SSL/TLS 终止。若代理会解密流量,须做好证书管理,并为后续跳数重新加密。
  • 访问控制: 在每台代理上配置严格的访问控制列表(ACL),只允许来自授权上游/下游代理或客户端的流量。

调试与排障

跨多台代理追踪请求可能十分复杂。
* X-Forwarded-For 首部: 该首部记录原始客户端 IP 地址以及链中后续代理的 IP。请确保它在每一跳都被正确追加(Nginx 中用 $proxy_add_x_forwarded_for)。
* Via 首部: Via 首部标明请求经过的中间代理。每台代理都应把自身标识加入该首部。
* 日志记录: 集中式日志与关联 ID 对于在整条代理链上追踪请求必不可少。

负载均衡与故障转移

为保证高可用并分散流量,请为上游代理配置负载均衡。
* Nginx:upstream 块中使用多条 server 指令,并配合 least_connround_robinbackupdown 等选项。
nginx upstream proxy_b_cluster { server 192.168.1.100:3128 weight=5; # 主 Proxy B server 192.168.1.101:3128 backup; # 备用 Proxy B server 192.168.1.102:3128; # 另一台主 Proxy B least_conn; # 使用最少连接算法 } # 然后 proxy_pass http://proxy_b_cluster;
* Squid: 使用多条 cache_peer 指令,并配合 round-robinweighted-round-robinfailoverno-query 等选项。
squid cache_peer 192.168.1.100 parent 3128 0 no-query weight=10 cache_peer 192.168.1.101 parent 3128 0 no-query weight=5 cache_peer 192.168.1.102 parent 3128 0 no-query round-robin

首部管理

谨慎管理 HTTP 首部至关重要。除 X-Forwarded-ForVia 之外,还应考虑用 Proxy-Authorization 向上游代理进行身份验证,并按策略确保其他相关首部被正确转发或剥离。

对比:单一上游与级联上游

特性 / 方面 单一上游代理 级联上游代理
复杂度 低;配置与运维更简单。 高;跨多台服务器的配置、运维与调试都很繁琐。
延迟 开销极小;仅多一跳网络。 开销更大;每台代理都带来一跳网络和处理延迟。
灵活性 受限于单台代理的能力。 高;可在每一环节实现专用功能并做复杂路由。
安全层级 单层安全与访问控制。 多层安全;每台代理可执行不同策略。
匿名性 相对源站提供基本匿名性。 匿名性更强;多跳转发使追溯原始客户端更困难。
调试 相对直接。 有难度;需要谨慎管理首部(X-Forwarded-ForVia)和日志。
故障影响 唯一上游故障会中断全部流量。 若未配置故障转移,链中任意代理故障都可能中断服务。
使用场景 基础内容过滤、缓存、简单访问控制。 高级安全、合规、地域路由、专用服务、高匿名需求。
已更新: 03.03.2026
返回分类

试用我们的代理

遍布 100+ 国家的 20,000+ 代理

support_agent
GProxy Support
Usually replies within minutes
Hi there!
Send us a message and we'll reply as soon as possible.