HiHuo
首页
博客
手册
工具
关于
首页
博客
手册
工具
关于
  • 代理技术全栈手册

    • 代理技术全栈手册 - HiHuo
    • 原理篇

      • 第01章 代理是什么:正向 / 反向 / 透明 / 隧道的统一模型
      • 第02章 代理与网络层级:L3 / L4 / L5 / L7 在哪里截断流量
      • 第03章 一个请求穿过代理的一生:连接生命周期全景
    • 协议篇

      • 第04章 HTTP 代理协议:绝对 URI、CONNECT 隧道、转发头与连接池
      • 第05章 HTTPS 与 TLS 代理:终止 / 透传 / MITM / SNI / mTLS
      • 第06章 SOCKS 协议:SOCKS4/4a/5 与 UDP ASSOCIATE 报文级解析
      • 第07章 HTTP/2、gRPC 与 HTTP/3(QUIC) 代理的挑战
      • 第08章 代理自动配置:PAC / WPAD / 系统代理 / NO_PROXY
    • 层级与转发篇

      • 第09章 L4 代理:TCP/UDP 转发与连接级负载均衡
      • 第10章 L7 代理:协议感知与基于内容的路由
      • 第11章 透明代理:iptables REDIRECT/DNAT、TPROXY 与 eBPF 劫持
      • 第12章 数据搬运的艺术:splice / sendfile / 零拷贝 / io_uring
    • 组件横评篇

      • 第13章 Nginx / OpenResty:反向代理、upstream 与 Lua 可编程
      • 第14章 HAProxy:L4/L7、ACL、健康检查与 stick table
      • 第15章 Envoy:xDS 动态配置与 filter chain,为何是云原生数据面
      • 第16章 Traefik / Caddy:自动服务发现与自动 HTTPS
      • 第17章 Squid 与正向/缓存代理:企业出网、缓存与审计
      • 第18章 mitmproxy:抓包、改包、脚本化调试
      • 第19章 内网穿透与隧道:frp / gost / SSH 隧道 / ngrok
      • 第20章 科学上网生态的技术原理(技术中立)
    • 多语言手写篇

      • 第21章 Go:100 行手写 HTTP/CONNECT + SOCKS5 代理
      • 第22章 Rust:基于 tokio 的高性能 TCP 代理
      • 第23章 Python:asyncio 实现,适合调试与脚本
      • 第24章 C:epoll 裸写与零拷贝,及语言选型对比
    • 容器与K8s篇

      • 第25章 Docker 里的代理:HTTP_PROXY、build/pull 与 daemon 配置
      • 第26章 Sidecar 与流量劫持:Istio init-container 的 iptables 原理
      • 第27章 Ingress 与南北流量:Ingress-nginx 与 Gateway API
      • 第28章 Egress 与出网治理:出口网关、registry mirror、审计
      • 第29章 Service Mesh 数据面:Envoy Sidecar 全链路
    • 进阶篇

      • 第30章 可编程代理:Lua / Wasm / eBPF / xDS,代理的"软件定义"
      • 第31章 性能调优:并发模型、连接池、超时与重试、压测
      • 第32章 排错决策树:502 / 504 / 握手失败 / 环路 / 泄漏
      • 第33章 代理安全:开放代理、SSRF、凭证泄漏与攻击面
    • 底层机制篇

      • 第34章 代理的背压与流控:一个代理最难的部分
      • 第35章 socket 与 TCP 状态机:半关闭、超时、连接生命周期
      • 第36章 HTTP/2 帧、流控与 HPACK:h2 代理的内部机制
      • 第37章 负载均衡算法推导与韧性状态机
      • 第38章 Capstone:把玩具代理改造成生产级骨架
    • 综合实战篇

      • 第39章 企业多跳转发链:拓扑、协议矩阵与贯穿性难题
      • 第40章 端到端实战:把 6 类流量全代理通
      • 第41章 更刁钻的流量:gRPC、长轮询、WebRTC、大文件、双向流
      • 第42章 可落地完整参考实现:一套能跑的多协议转发栈
    • 附录

      • 附录 A:代理协议报文速查(HTTP / SOCKS / PAC / PROXY protocol)
      • 附录 B:组件选型决策树
      • 附录 C:抓包与命令速查

第39章 企业多跳转发链:拓扑、协议矩阵与贯穿性难题

学习目标

  • 看清企业典型的"多跳反代链"拓扑,理解一个请求要被易手多少次
  • 掌握 6 类流量(HTTP/WebSocket/SSE/SSH/原始 TCP/长连接)各自怎么穿过这条链
  • 深挖 WebSocket 的 Upgrade/101 握手,及它为何是多跳代理里最难的
  • 记住三条贯穿性铁律:超时是木桶短板、缓冲是或门、逐跳头要每跳重建

前置知识

  • 第01章 多跳模型、第09章 L4/第10章 L7、第27章 Ingress
  • 第04章 转发头/逐跳头、第34章 背压

原理

典型企业拓扑:一个请求的多次易手

企业里一个外部请求到达容器,往往要经过好几跳反向代理,每一跳都是 第01章 说的"连接一拆为二":

  Internet
     │
  ① [边缘 nginx / 云 LB]      ← 南北第一跳:TLS 终止、WAF、限流、粗路由
     │                            (TLS 终止 or SNI 透传?L4 or L7?)
  ② [K8s Ingress]            ← 第二跳反代:按 Host/Path 路由到 Service
     │   (ingress-nginx / Envoy Gateway)
  ③ [Service / Endpoints]    ← kube-proxy 或 ingress 直连 Pod IP(第27章)
     │
  ④ [Mesh sidecar(可选)]    ← 东西向:mTLS、重试、遥测(第26/29章)
     │
  ⑤ [后端 Pod]               ← code-server / sshd / app / SSE server ...

每跳都可以:改写头、做 TLS 决策、设超时、缓冲或流式、加 XFF、决定 L4 还是 L7。问题在于:这些决策必须在每一跳上协调一致——任何一跳配错,整条链就断。这正是企业流量转发的核心难点。

协议矩阵:6 类流量怎么穿过这条链

不同流量对这条链的要求天差地别。一张矩阵看清:

流量工作层链路要求头号坑
普通 HTTPL7每跳反代、加 XFF基线,最简单
WebSocket(web-vscode)L7→长连接每跳传 Upgrade、超时拉长、背压Connection 是逐跳头,断在中途
SSE(事件流)L7→流式每跳关缓冲、超时拉长一跳缓冲就收不到数据
SSH(连内部容器)L4走 TCP 路径 or 隧道,无 SNI塞不进 L7 HTTP Ingress
原始 TCP(DB/自定义)L4L4 透传、PROXY protocol同上,L7 代理不了
长连接(通用)L4/L7每跳 keepalive/心跳、负载均衡超时截断、L4 负载不均

下面把最棘手的几个拆开。

WebSocket 深挖:为什么它是多跳里最难的

WebSocket(code-server / web-vscode 的命脉)以 HTTP 起手,再"升级"成长连接的双向帧通道:

① 客户端发起升级握手(看起来是普通 HTTP GET):
   GET /ws HTTP/1.1
   Host: ide.example.com
   Upgrade: websocket            ← 我要升级到 websocket
   Connection: Upgrade           ← 逐跳头!(第04章)
   Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
   Sec-WebSocket-Version: 13

② 服务端同意:
   HTTP/1.1 101 Switching Protocols   ← 注意是 101,不是 200
   Upgrade: websocket
   Connection: Upgrade
   Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=   ← = base64(SHA1(Key + 固定GUID))

③ 此后这条 TCP 连接不再是 HTTP,而是双向 WebSocket 帧,长期存活

代理 WebSocket 的三个难点,全部源自这个机制:

  1. Connection/Upgrade 是逐跳头(第04章)。代理本应删除逐跳头——但 WebSocket 偏偏靠它们升级!所以每个 L7 跳必须显式地把 Upgrade/Connection: upgrade 重新传下去,否则升级请求在中途被某跳"规规矩矩地删掉逐跳头",握手就废了。这是 WS 经多跳代理最常见的失败。
  2. 101 之后变长连接:不再有"请求-响应"边界,连接长期存活 → 超时、背压、连接计数(第34章/第35章)全来了。默认 60s 读超时会把空闲的 IDE 连接掐断。
  3. HTTP/2 下要扩展 CONNECT:h2 没有 Upgrade 语义,WebSocket over h2 需要 RFC 8441 的 extended CONNECT(:protocol = websocket)。多数链路因此对 WS 降级走 h1——这也是为什么有些 h2 链路 WS 不通。

SSE 深挖:流式的"或门"特性

SSE(Server-Sent Events)是单向、无限的 HTTP 响应流(Content-Type: text/event-stream),服务端持续推 data: 事件。它对代理只有一个但致命的要求:

每一跳都必须关闭缓冲(streaming)。 只要链上任何一跳做了响应缓冲(第03章 的 proxy_buffering on),它就会"攒着不发",客户端要么收不到、要么一大批延迟涌来。

所以 SSE 的坑是"或门":N 跳里有 1 跳缓冲,整个流式就废。后端常发 X-Accel-Buffering: no 头显式告诉 nginx 别缓冲这个响应。

SSH 与原始 TCP:塞不进 L7 的东西

SSH、数据库、自定义二进制协议不是 HTTP,L7 的 HTTP Ingress 代理不了它们(第02章)。两条出路:

  • 走 L4 路径:用一个 L4 代理/TCP Ingress(ingress-nginx 的 tcp-services、或独立 LB)按端口转发。SSH 没有 SNI(第02章),无法像 HTTPS 那样按域名分流 → 只能按端口或专用监听器路由。
  • 隧道复用 443:把 SSH 包进 WebSocket 或 HTTP CONNECT(第04章),让它走和网页一样的 L7/443 入口——好处是穿越只放行 443 的企业防火墙,代价是多一层隧道。

所以企业常有两套入口:L7(HTTP/WS/SSE 走 80/443)+ L4(TCP 服务走专用端口),或干脆全隧道到 443。

三条贯穿性铁律(这章的精华)

把上面收成三条必须刻进脑子的规则:

铁律一 · 超时是"木桶短板"
   长连接(WS/SSE/SSH/长轮询)只能活到【最激进那一跳的超时】。
   边缘 nginx 3600s 没用,只要 Ingress 还是默认 60s,连接就在 60s 被掐。
   → 必须在【每一跳】都把 read/idle 超时调长。这是企业长连接头号 bug。

铁律二 · 缓冲是"或门"
   流式(SSE/流式响应)只要链上【任意一跳】缓冲就废。
   → 必须在【每一跳】都关缓冲(proxy_buffering off / X-Accel-Buffering: no)。

铁律三 · 逐跳头要"每跳重建"
   WebSocket 的 Upgrade/Connection 是逐跳头,规范要求代理删它。
   → 每个 L7 跳必须【显式重新设置】Upgrade/Connection: upgrade,否则握手断在中途。

其它贯穿性难题

  • TLS 每跳决策(第05章):常见模式是"边缘终止(公网证书)→ 到 Ingress 重加密或明文 → Ingress 可再终止 → Mesh 内 mTLS"。每个终止点是加 XFF、做内容决策的地方;要按域名分流又不解密则用 SNI 透传(第02章)。
  • 真实客户端 IP 的多跳传递(第04章/第33章):X-Forwarded-For 每跳追加,后端要只信任自己的代理链回溯取真实 IP;L4 跳加不了 XFF → 用 PROXY protocol(第09章)。
  • L4 连接级长连接负载不均(第09章):WS/SSH 长连接在 L4 跳焊死到一个后端,扩容时新 Pod 没流量 → 需要连接 drain / maxConnectionAge / 客户端重连。

本章小结

  • 企业流量要穿过多跳反代链(边缘→Ingress→Service→Mesh→Pod),每跳都做 TLS/超时/缓冲/头/路由决策,必须协调一致。
  • 协议矩阵:HTTP(基线)、WebSocket(Upgrade+长连接)、SSE(流式)走 L7;SSH/原始 TCP 走 L4 或隧道;长连接是贯穿性挑战。
  • WebSocket 难在 Connection/Upgrade 是逐跳头(每跳要重建)+ 101 后变长连接;SSE 难在缓冲"或门";SSH 难在非 HTTP(L4 或隧道)。
  • 三条铁律:超时=木桶短板(每跳调长)、缓冲=或门(每跳关)、逐跳头=每跳重建。

下一章 第40章 端到端实战,把这套原理落成真配置:边缘 nginx → ingress-nginx → 容器,把 web-vscode、SSH、WebSocket、SSE、原始 TCP、长连接全部代理通,并给每跳 checklist 与排错矩阵。

Next
第40章 端到端实战:把 6 类流量全代理通