开放问答
服务间 mTLS 场景下内部服务信任网关透传的 uid 导致越权,怎么收口?
该问题的正文、回答与评论。
提问者 温若衡-859 · 状态 open
mTLS服务网格越权身份鉴权Istio
背景:我们是一套典型微服务架构,流量入口是 API 网关 → BFF → 各业务服务,服务间用服务网格做 mTLS 互信,网关层已完成 JWT 校验并把调用方身份(uid / tenantId)塞进 X-User-Id、X-Tenant-Id 这类 header 往下透传。
现象:最近一次越权复盘发现,某个内部服务(比如订单服务的 /internal/query 接口)直接读 X-User-Id 决定数据隔离,而它对"这个 header 是谁写的"完全没有校验——只要 mTLS 握手通过、来源是网关切面,就当成可信身份。问题是网关的某个旁路/降级分支(以及一次我们自己的压测脚本)能绕过网关鉴权直连内网网段,于是伪造 header 就能读到别人的订单。根因我判断是:mTLS 只证明了"对端是网关这个服务身份",却没证明"对端此刻代表的是哪个终端用户",身份从 mTLS 的"服务身份"偷换成了"用户身份"。
已尝试的排查与结果:
- 加白名单只允许网关 pod IP 访问 /internal 接口——能挡外部,但挡不住网关自身被绕过的旁路分支,治标不治本;
- 让网关在 header 上加一个 HMAC 签名(用共享密钥签 uid+ts)——能防伪造,但引入了第二套密钥分发与轮换,和 mTLS 的证书体系重复,运维面又变大;
- 改成网关签发短时效 JWT(SPIFFE ID 作 iss、uid 作 sub),内部服务用网格 CA 验签——方向对,但卡在"内部服务怎么拿到网关的公钥做验签"以及"网格 CA 和网关 JWT 签名密钥是不是同一把",没想清楚。
期望得到的答案形态:
- 一个清晰的职责切分:哪一层负责"服务身份"(mTLS / SPIFFE)、哪一层负责"用户身份与授权"(token),二者如何组合而不互相偷换;
- 内部服务"只信任 mTLS 对端 + 验签 token"的最小可信集,以及网关公钥/CA 的具体分发方案(SBOM 之外,运维上怎么落地);
- 有没有现成的实践(Istio + SPIFFE、OAuth2 token exchange RFC 8693 等)可以参考,最好带配置片段或时序图。
已采纳
回答者
回答正文
评论
暂无评论。