客户端说的是 HTTP,代理看得到路径吗

orders 要把 sku=paper 请求送到库存服务:应用协议、连接的传输加密、代理是否能看见请求路径,是三个独立问题。第 03 篇中的 route 要求 Envoy 能读 HTTP 的 host/path;若所见的只是透传 TLS 密文,代理可以依据连接层可见信息决定去向,但不能凭空读取加密后的 /quote。本篇先用同一个 inventory-v1 实测 TLS 主机名校验和 ALPN,再说明 HTTP/2、gRPC 与 TLS 终止/透传的边界;未声称已运行 sidecar 协议识别。

明文 HTTP 与 TLS 握手、SNI、ALPN 分层后代理可能终止或透传,再由上游处理请求

图中的 SNI 是 TLS 握手给服务器提示的名称,ALPN 是协商应用协议的扩展;它们不等于 HTTP Host、gRPC method 或最终用户 JWT。代理只有在终止相应 TLS 连接并解析上层协议时,才可能按 HTTP 路径或 gRPC 请求元数据作七层治理。TLS 透传和 HTTP 路由适用于不同可见范围。

两条连接不一定采用同一协议

调用方到代理是下游连接,代理到后端是上游连接。客户端至入口网关可以 TLS 终止后以另一条连接转发;sidecar 场景可能有应用到本地代理的明文、两个代理之间的 mTLS,以及远端代理到应用的连接。不能由某一段使用 TLS 就宣称其余连接段都加密,也不能把最终用户认证与代理间工作负载身份混为一谈。具体部署的 TLS mode 需要逐段核对第 19–21 篇的身份、认证和授权证据。

HTTP/1.1 可以在一个 TCP 连接上复用请求;HTTP/2 用流多路复用,gRPC 在常见模式下依赖 HTTP/2,并在其上定义调用消息和状态。Envoy 能识别的协议受端口声明、检测与连接协商影响:将 TLS 端口当作明文 HTTP 端口,或把不支持的 HTTP/2 链路误标成 gRPC,都可能让七层策略不生效。版本相关的自动检测、ALPN 行为和特性支持必须和冻结的 Istio/Envoy 配置核对,不能用端口号猜。

在 TLS 透传时,可见的 SNI 可以用于连接级路由,但 HTTP Host、路径及 gRPC 方法对这个未解密的代理不可见;在 TLS 终止后,代理可按相应协议解析请求,而证书信任、名称校验和请求是否已获授权仍是不同步骤。更改 SNI、HTTP Host 或目标端口应分别设计测试,不能把它们当同一字段。

对同一个库存进程做 TLS 直连对照

examples/service-mesh/apps/mesh-demo/main.go 现在支持可选的 -tls-cert/-tls-key,原有无网格 HTTP 路径保持不变。在 examples/service-mesh/ 运行:

1
GO_BIN=/tmp/service-mesh-tools/go/bin/go bash scripts/run-09.sh

脚本在 /tmp 临时生成仅用于合成实验的自签名证书和不提交的私钥,SAN 只包含 inventory.mesh.invalid;服务绑定 127.0.0.1,证书与私钥仅用于本次进程,退出时删除。curl 显式信任该实验公钥并把正确域名解析到 loopback:sm-09-valid 返回 HTTP 200、inventory_version=v1;把 URL 主机名改成 wrong.mesh.invalid,仍指向同一 IP/端口,则 curl 在证书名称校验处退出 60,没有业务响应。openssl s_client 使用正确 SNI、验证主机名并提供 h2,http/1.1,该次握手输出 ALPN protocol: h2。GET /ledger 仍为 []。

2026-10-03 的原始输出、命令、退出码、Go/OpenSSL 版本及源码 SHA-256 保存在 examples/service-mesh/evidence/09/20261003T093014Z-99/,四项断言 PASS。核对 ALPN 应读取完整协商输出,不能把未显示字段当成服务端不支持该协议。

上述 TLS 进程实验不包含 Envoy TLS listener、sidecar 或客户端证书,不能证明 mTLS 与 TLS 透传;真实 gRPC 调用由下面的独立实验覆盖。

把 TLS 握手与真实 RPC 分开验证

在 examples/service-mesh/ 先运行 bash scripts/run-09.sh。它用临时证书启动库存 HTTPS 服务,正确名称应返回库存响应,错误名称应使 curl 退出 60;脚本结束删除临时私钥。openssl s_client 的 ALPN 结果只能证明协商协议,不能证明 /inventory.Inventory/Quote 被执行。

真实 RPC 使用独立模块:

1
bash scripts/run-E03.sh evidence/E03/replay

E03 通过 gRPC ServiceDesc 注册 Quote unary 方法,客户端目标是 xds:///inventory,bootstrap 在进程启动前提供控制面地址和 node ID。客户端使用同一 channel,经 LDS/RDS/CDS/EDS 先到 v1,再到 v2;故障 EDS 指向接受 TCP 却不提供 gRPC 响应的端点,deadline 到期后恢复 v1。这里使用明文 loopback gRPC,不能将其与前面的 TLS 记录拼成“已经实测 gRPC mTLS”。

2026-10-03 的真实 gRPC 证据在 evidence/electives-20261003/E01-E03/E03-final/:stdout 依次记录 v1、v2、DeadlineExceeded、恢复 v1;stderr 包含控制面订阅/ACK 与服务端 handled ID。核对调用成功应看 RPC 状态、响应字段和方法处理记录,不能只看 HTTP/2 TCP 连接存在。

协议错误排查沿 地址 → TCP → TLS/ALPN → HTTP/2 → gRPC 方法与状态 进行。证书名称不匹配在 RPC 之前失败;方法名称错误发生在 RPC 分派层;deadline 则限制等待时间,不能回滚业务已经提交的副作用。

2026-10-03 Linux 实测记录在 examples/service-mesh/evidence/09/20261003T093014Z-99/,本轮运行通过;原始命令、退出码和日志限定结论适用范围。

[PATTERN] 协议适配必须保留分层错误;传输握手与应用调用分别验收。

原则 本章检验点
证据不能跨实验拼接 TLS 与明文 gRPC 分开记录
成功到业务方法为止 Quote handler ID 与响应对应
等待超时不等于未执行 结合第 01 篇账本解释未知结果

练习与参考解答

  1. 同一 IP 和端口上,inventory.mesh.invalid 成功而 wrong.mesh.invalid 失败,能否推断服务端业务拒绝了后者?参考解答:不能。失败发生在客户端验证证书的名称阶段,业务 HTTP handler 没收到后者的请求。核对 curl 退出 60、客户端 TLS 错误及没有对应应用请求 ID;换成代理路径时还要确认 TLS 在哪一段终止。
  2. 在透传 TLS 的入口上加一条仅匹配 HTTP /quote 的策略,预期如何设计反例?参考解答:入口若不终止 TLS,无法看到加密后的路径;分别测试两个相同 SNI、不同 HTTP 路径的合成请求,保存代理 TLS 配置、路由匹配/访问记录与应用日志。若想按路径治理,须在合适的可信边界终止 TLS,再检查新的上下游连接及身份约束。当前环境未运行此反例,不填具体状态码。

官方资料与系列导航

系列导航:00 基线 → 08 发现 → 09 HTTP、gRPC 与 TLS(本文)→ 10 按版本和请求属性选择后端。