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:抓包与命令速查

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

学习目标

  • 用真实配置把 web-vscode、WebSocket、SSE、SSH、原始 TCP、长连接经"边缘 nginx → ingress-nginx → 容器"全部代理通
  • 掌握每种流量在每一跳的关键配置项
  • 拿到一张"每跳 checklist"和"按协议排错矩阵"

前置知识

  • 第39章 多跳链与协议矩阵(本章是它的配置落地)
  • 第13章 Nginx、第27章 Ingress

实战拓扑

  Client ──443──▶ [边缘 nginx] ──443──▶ [ingress-nginx] ──▶ Service ──▶ Pod
                   TLS 终止          按 Host 路由           code-server/sshd/app
  Client ──2222─▶ [边缘 L4 / 节点] ─────▶ [ingress tcp-services] ──▶ sshd:22

下面按流量类型给配置,每段都标出"为什么这么配"。


️ 一、边缘 nginx:HTTP + WebSocket + SSE 通吃

边缘是 L7 第一跳,TLS 终止后转给 Ingress。关键是 WebSocket 的 Upgrade 传递 + 长连接超时 + 关缓冲(第39章 三铁律):

# WebSocket 升级映射:有 Upgrade 头就 "upgrade",否则 "close"
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

upstream k8s_ingress {
    server 10.0.0.10:443;
    keepalive 64;                      # 到 Ingress 的连接池(第31章)
}

server {
    listen 443 ssl http2;
    server_name *.example.com;
    ssl_certificate     /etc/nginx/certs/wildcard.crt;
    ssl_certificate_key /etc/nginx/certs/wildcard.key;

    location / {
        proxy_pass https://k8s_ingress;
        proxy_http_version 1.1;                          # WS/keepalive 必须 1.1

        # —— 铁律三:逐跳头每跳重建(WebSocket 命门)——
        proxy_set_header Upgrade    $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        # —— 头传递(第04章)——
        proxy_set_header Host              $host;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP         $remote_addr;

        # —— 铁律一:长连接超时拉长(WS/SSE/长连接)——
        proxy_read_timeout  3600s;
        proxy_send_timeout  3600s;

        # —— 铁律二:关缓冲(SSE 必须;WS 不受影响但无害)——
        proxy_buffering off;
        proxy_cache off;
    }
}

这一份配置同时正确处理了普通 HTTP、WebSocket、SSE三种——因为它把三铁律都落实了。map $http_upgrade 是 nginx 代理 WebSocket 的标准写法。


️ 二、ingress-nginx:第二跳的对应配置

ingress-nginx 自动识别 WebSocket(检测到 Upgrade 头会自动处理升级),所以主要工作是把超时和缓冲也在这一跳配对(否则铁律一/二在这跳破功):

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ide
  annotations:
    # 铁律一:这一跳也要长超时(默认 60s 会掐断 WS/SSE)
    nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
    # 铁律二:这一跳也关缓冲(SSE)
    nginx.ingress.kubernetes.io/proxy-buffering: "off"
spec:
  ingressClassName: nginx
  tls:
  - hosts: [ide.example.com]
    secretName: ide-tls
  rules:
  - host: ide.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend: { service: { name: code-server, port: { number: 8080 } } }

铁律一的木桶效应:边缘配了 3600s,但若这里漏配,连接照样在 Ingress 的 60s 默认值上被掐——必须每跳都配。


️ 三、web-vscode(code-server):WebSocket 长连接重负载

code-server(浏览器版 VS Code)的终端、文件监听、协作全靠 WebSocket,是上面 WS 配置的典型消费者。额外注意:

# code-server Deployment 要点
spec:
  replicas: 1                 # ← 注意:多副本需会话保持,否则 WS 重连到别的 Pod 会丢状态
  template:
    spec:
      containers:
      - name: code-server
        image: codercom/code-server:latest
        ports: [{ containerPort: 8080 }]
  • 单副本最省心(编辑器状态在内存);要多副本必须 sticky session(第10章 cookie 亲和),把同一用户的 WS 钉到同一 Pod
  • L4 跳要小心连接级负载不均(第39章/第09章):长连接焊死后端

验证 WebSocket 通了:

# 用 websocat 测 WS 握手(应看到 101 Switching Protocols)
websocat -v wss://ide.example.com/  2>&1 | grep -i "101\|switching"
# 或 curl 看升级握手
curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" \
     -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" -H "Sec-WebSocket-Version: 13" \
     https://ide.example.com/ | head -5
#   HTTP/1.1 101 Switching Protocols   ← 通了

️ 四、SSH 进内部容器:两种方案

方案 A:L4 路径(ingress-nginx tcp-services)

SSH 不是 HTTP,走 L4。ingress-nginx 支持 TCP 透传:

# 1) ingress-nginx 的 tcp-services ConfigMap:节点 2222 → 内部 sshd
apiVersion: v1
kind: ConfigMap
metadata: { name: tcp-services, namespace: ingress-nginx }
data:
  "2222": "devns/ssh-svc:22"        # <外部端口>: <namespace>/<service>:<端口>
---
# 2) ingress-nginx 的 Service 要暴露 2222 端口(patch 它的 Service / 用 hostPort)
# 外部直接 ssh(L4 透传,按端口路由,无 SNI)
ssh -p 2222 dev@ingress.example.com
# 长连接防掐:客户端开 keepalive
ssh -o ServerAliveInterval=30 -p 2222 dev@ingress.example.com

方案 B:SSH over WebSocket(共享 443,穿企业防火墙)

只放行 443 的环境里,把 SSH 隧道进 WebSocket,复用 L7/Ingress 入口(第39章 的隧道思路、第19章):

# 容器侧/sidecar 跑 wstunnel server,Ingress 用普通 WS 路由把 wss://.../ssh 指给它
# 客户端:把 SSH 经 WebSocket 隧道出去
ssh -o ProxyCommand="wstunnel client -L stdio://%h:%p wss://gw.example.com/ssh" \
    dev@target-container
# 好处:走 443,和网页同一入口、过防火墙;代价:多一层隧道

选择:内网/能开专用端口 → 方案 A 简单;只放行 443/要穿防火墙 → 方案 B。


️ 五、SSE 服务:确保全链路流式

后端 SSE 服务除了发 text/event-stream,最好显式声明别缓冲:

HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache
X-Accel-Buffering: no          ← 显式告诉 nginx/ingress 这个响应别缓冲(铁律二保险)

data: {"msg":"hello"}\n\n
data: {"msg":"tick"}\n\n
# 验证流式:应每秒陆续收到,而不是憋一批一起来
curl -N https://app.example.com/events
# data: ... (实时一行行出来 = 全链路流式 OK;憋住才出 = 某跳缓冲了)

️ 六、原始 TCP(数据库/gRPC-over-TCP/自定义)

和 SSH 方案 A 一样,走 L4 tcp-services:

data:
  "5432": "dbns/postgres:5432"      # 暴露内部 PostgreSQL(L4 透传)
  "6379": "cachens/redis:6379"

需要后端拿真实客户端 IP 时,L4 加 PROXY protocol(第09章),两端都要支持。


每跳 Checklist(贴墙用)

跳HTTPWebSocketSSESSH/TCP长连接
边缘 nginxXFF/HostUpgrade+Connection+http1.1proxy_buffering off走 stream{} L4超时拉长
ingress-nginx默认自动识别+超时 annotationproxy-buffering: offtcp-services超时 annotation
Service默认默认默认ClusterIP/直连maxConnAge
Mesh sidecar默认透传透传TCP 模式idle 超时
后端 Pod—处理帧发 X-Accel-Buffering:no监听端口应用心跳

核心口诀:长连接/流式,超时每跳调长、缓冲每跳关闭、Upgrade 每跳重建——三铁律逐跳落实,缺一跳就断。


按协议排错矩阵

现象根因修在哪
WebSocket 握手失败(不是 101)某跳没传 Upgrade/Connection(逐跳头被删)每个 L7 跳重建 Upgrade(第39章)
WebSocket 连上但约 60s 断某跳 read/idle 超时太短(木桶短板)每跳调长超时
SSE 收不到 / 憋一批才来某跳缓冲了流(或门)每跳 proxy_buffering off + X-Accel-Buffering:no
SSH 经 Ingress 不通走了 L7 HTTP 路径(SSH 非 HTTP)用 L4 tcp-services 或 over-WS 隧道
SSH 长时间无操作就断L4/NAT idle 超时ServerAliveInterval + 调 L4 超时
code-server 多副本状态错乱WS 重连到了别的 Pod单副本,或 sticky session(第10章)
后端日志客户端 IP 全是上一跳XFF 多跳没正确回溯 / L4 没 PROXY protocolset_real_ip_from 信任链(第04章/第33章)
扩容后新 Pod 没流量L4 连接级长连接焊死(第09章)drain / maxConnectionAge / 客户端重连
大上传/下载打爆代理内存长连接无背压 + 缓冲流式 + 背压(第34章)

本章小结

  • 一份正确的边缘 nginx 配置(map $http_upgrade + 长超时 + 关缓冲 + 头传递)就能同时通 HTTP/WebSocket/SSE;关键是每一跳都配对。
  • SSH/原始 TCP 走 L4:ingress-nginx tcp-services(按端口)或 SSH over WebSocket 隧道(共享 443 穿防火墙)。
  • code-server 是 WS 重负载:单副本省心,多副本要 sticky。
  • 全链路口诀:超时每跳调长、缓冲每跳关、Upgrade 每跳重建;真实 IP 靠 XFF 信任链/PROXY protocol,长连接防 L4 负载不均。

综合实战篇 · 结语

这两章把全书拉到一个真实企业拓扑里跑了一遍——你会发现,多跳转发链的难点从来不是单个代理多强,而是让一条链上的每一跳在 TLS、超时、缓冲、逐跳头、L4/L7、真实 IP、背压上协调一致。任何一跳的默认值,都可能成为整条链的短板。

至此全书 40 章 + 3 附录 完结。从 第01章 的统一模型,到 底层机制篇 的背压与状态机,再到这一篇的多跳实战——希望你不仅能"配通",更能在任何一跳出问题时,沿着这条链精准定位到是哪一跳、哪条铁律被违反了。回到 手册首页。

Prev
第39章 企业多跳转发链:拓扑、协议矩阵与贯穿性难题
Next
第41章 更刁钻的流量:gRPC、长轮询、WebRTC、大文件、双向流