安全这件事,跟小区安保很像。老式小区把力气全花在大门:高围墙、防爬刺、刷卡闸机,门卫老王睁大眼睛盯着每个进门的快递员。可门里却是一马平川——任何楼栋、任何楼层随便进出。于是失窃案频发:冒充快递员的窃贼只要混进大门,就能挨家挨户踩点。云原生世界的服务网格也面临同样的尴尬:防火墙把“南北向”流量把守得严严实实,服务与服务之间的“东西向”流量却几乎裸奔。mTLS 与零信任,就是一场物业改革:给每个服务发一张数字“工牌”,进出每栋楼都要双向亮证;不再相信“进门那一刻的信任”,而是默认拒绝、处处验证。这篇文章就从这场门禁改革讲起,看看 mTLS 如何双向认证、证书如何管理、零信任策略如何落地,以及如何用审计监控让安全“看得见、说得清”。
对 AI 从业者来说,mTLS 与零信任是云原生 AI 平台从“能跑”走向“敢上生产”的安全地基:掌握了它,你才能让模型服务、训练集群与多方数据在不可信的网络上放心协作。
目录
可视化演示
展示mTLS双向认证握手过程、DISABLE/宽容/严格三种模式对比,以及零信任网格中基于SPIFFE身份的服务互信认证。
本节配有交互动效(进入视口后自动加载,约 3KB)。
mTLS双向认证握手 客户端与服务端双向交换证书 mTLS=both×cert 双方互相验证身份后建立加密通道。
传统安全模型:围墙里的错觉
丽景苑小区曾经是“门禁模范生”:一圈三米高的围墙,门口有保安亭、刷卡闸机,来访者必须登记身份证。物业经理老王对这套系统信心满满,直到连续发生三起入室盗窃。业主们质问:大门查得这么严,小偷是怎么进来的?监控回放揭开了真相——戴着快递员帽子的窃贼,在大门顺利过关后,推着小推车把小区每栋楼逛了个遍,挨个拉门把手试锁。大门很严,门内却毫无防备。
传统网络安全模型就是这个“丽景苑模型”。在数据中心时代,防护资源集中在边界:防火墙、WAF、入侵检测系统死死盯着南北向流量——即外部进出机房的流量。而服务之间的东西向流量,也就是机房内部服务器之间的横向通信,默认是“内部人,全信任”,一路绿灯。微服务架构把单体应用拆成几十上百个小服务后,东西向流量暴增,攻击面随之爆炸:攻击者只要通过钓鱼或漏洞攻破一台边缘机器,就能沿着内部网络横向渗透,如同进了大门后挨家挨户试锁。
零信任安全模型(Zero Trust)彻底抛弃了“内网即安全”的假设,核心思想只有八个字:永不信任,始终验证。NIST SP 800-207 标准进一步把它拆为三条原则:不再以网络位置决定信任,所有请求先认证再授权,并持续评估会话风险。对企业来说,迁移不是推倒重来:边界防火墙依然保留作为南北向第一道闸,只是在其后叠加身份层;先以 PERMISSIVE(宽松)模式观察审计,再逐步切换到 STRICT(严格)模式。
老王后来做的事,和零信任如出一辙——他没有拆掉大门,而是在每栋楼装上独立门禁。围墙仍在,但信任不再由“进了大门”一次性授予;每一栋楼,都是新的验证关卡。
mTLS基础概念:双向亮证
新门禁制度推行那天,老王给业主们示范新规矩:业主进楼道要先刷卡,证明“我是本楼业主”;同时,业主还要反过来检查保安的工牌——工牌上有物业盖章、钢印和有效期,证明“你真的是保安”。业主们一开始觉得麻烦,直到有人拦住一个想混进楼里“抄水表”的陌生人——他没工牌,当场露馅。这个“双方都要出示证明”的流程,就是双向认证,也就是 mTLS 的全部精髓。
计算机世界里,TLS 原本是“单向亮证”:浏览器访问网银时,网银出示证书证明自己是真网银,浏览器核验后建立加密通道;但银行并不知道“你是谁”——那是用户名密码的事。mTLS(Mutual TLS,双向传输层安全)把规则升级为:客户端也持有证书,也必须向服务端证明身份。在服务网格(如 Istio)中,每个服务旁边都蹲着一个叫 sidecar 的“门卫代理”(通常是 Envoy),它自动完成证书交换、身份验证和流量加解密,业务代码完全不用改。
完整的 mTLS 握手可以看作门禁系统的两次刷卡:客户端先发出问候(ClientHello),服务端回赠自己的证书;客户端验证服务端证书后,亮出自己的证书;服务端再验证客户端证书。身份都确认了,双方才开始协商本次会话的加密密钥。这个“协商”并非简单传输一个密码,而是通过 TLS 主密钥派生算法,从双方都知晓的临时秘密“搅拌”出真正的会话密钥:
回到小区:老王说得好,“双向亮证”不是多此一举。业主确认保安身份,是为了防止“假保安”套话;服务确认客户端身份,是为了防止“假服务”钓鱼。mTLS 让每对服务在对话前,先互相验明正身。
- PMS(预主密钥)客户端与服务端通过非对称算法(如 ECDHE)临时协商出的秘密值,只有通信双方知道,它是后续一切密钥的“原材料”。
- PRF(伪随机函数)一台密码学“搅拌机”,把秘密和种子材料倒进去,输出长度固定的随机字节。
- 固定标签与随机数种子
master secret是协议规定的固定标签;客户端随机数与服务端随机数拼接成种子,保证每次握手会话独一无二,防止重放攻击。 - 输出主密钥PRF 的输出就是主密钥 MS,它被继续“搅拌”切分为对称加密密钥、消息认证密钥和初始化向量。
证书管理:让工牌可信
双向亮证的前提,是工牌本身可信。老王在小区推行过一阵“手写工牌”,结果没两天就有人用彩印伪造了一张,混进 3 号楼。教训很直接:工牌必须由统一机构签发、有防伪设计、有有效期,并且所有门禁系统共享同一套验证标准。在安全领域,这套体系叫 PKI(公钥基础设施),而证书就是那张“数字工牌”。
一张 X.509 证书里装着什么?持有者的公钥、身份信息(服务名、命名空间等)、证书签发者、有效期,以及签发者用自己私钥打上的“防伪钢印”——数字签名。签发证书的机构叫 CA(证书颁发机构)。现实中签发链通常分三层:根 CA(相当于公安部)→ 中间 CA(相当于省厅)→ 叶子证书(相当于具体员工工牌)。在 Istio 服务网格中,控制平面组件 istiod 内置了一套 CA,它会根据 Kubernetes 里 service account 的令牌自动签发证书,身份标识采用 SPIFFE 标准,形如 spiffe://example.com/ns/prod/sa/payments——这就是服务在网格里的“身份证号”。
门禁系统验明一张工牌,不是只看钢印,而是从叶子证书逐级往上验证,直到根证书。这个链条可以写成一条逻辑式:
一句话总结证书管理:工牌要“统一签发、逐级可查、到期作废、丢失挂失”。老王后来把工牌有效期从三年缩短到一年,门禁系统也接入了统一的发证机关。信任不是一句口号,而是一条可验证的链。
- 叶子证书 C业务服务持有的“工牌”,包含服务公钥、SPIFFE 身份和有效期。
- 逐级上溯验证每一级证书的签名都用上一级 CA 的公钥验证,保证证书内容没被篡改。
- 根证书是信任锚最顶层的根证书由根 CA 自签名,被所有客户端预置信任,是整条信任链的终点。
- 逻辑与的威力$\bigwedge$ 表示每一环都必须通过,只要中间任何一环验证失败,整条链的信任立刻崩塌。
零信任策略:默认拒绝与最小权限
丽景苑的工牌制度落地后,又出了新问题:保洁阿姨拿着自己的工牌,居然能刷开财务室的门。老王气得直拍桌子——工牌是真的,但权限给得太大了。他连夜修改规则:保洁只在工作日 9 点到 18 点能进各楼一层,电梯卡限定 1 到 2 层;维修工只有报修工单生效期间能进对应楼层;任何人的工牌一旦报失,全小区所有门禁立刻同时拒绝这张卡。这套规则总结成两句话:默认拒绝一切,只授予最小必要权限。
这就是零信任策略的两根支柱:默认拒绝(deny by default)与最小权限(least privilege)。mTLS 解决的是“你是谁”,授权策略解决的是“你能做什么”;两者缺一不可。零信任还要求持续验证——不是进门刷一次卡就一劳永逸,而是每次访问都要重新评估。在服务网格中,PeerAuthentication 负责强制 mTLS(STRICT 模式下,非加密流量直接被拒),AuthorizationPolicy 负责声明式授权。更精细的实现还会引入“信任评分”机制,把身份、设备、行为三个维度的信息加权成一个动态分数:
老王的门禁改革,本质是把“一次进门、到处乱走”改成了“处处设卡、按需开门”。零信任亦如此:哪怕持有合法证书,也没有默认的全局访问权;每一笔访问,都要单独验证、单独授权。
- I(身份因子)请求方的数字身份强度,如证书是否由可信 CA 签发、SPIFFE 身份是否在允许名单。
- D(设备因子)发起方所在节点或设备的健康度,如补丁版本、是否被打上“已入侵”标记。
- B(行为因子)该请求的行为上下文,如访问时间、频率、数据敏感度;深夜批量拉取客户数据会显著拉低评分。
- 加权求和与阈值 θ三个因子加权求和后与阈值比较,达标才放行——这就是“动态信任”而非“一锤定音”。
策略配置实践:门禁规则表落地
规则想得再美,写不进系统就是空谈。老王把整套门禁规则整理成一本《门禁规则表》,一条条写清楚:谁、在什么时间、能进哪栋楼哪层。保安只需要查表执行,不用凭感觉放行。在服务网格里,这张“规则表”就是一系列声明式配置:目标规则(DestinationRule)、授权策略(AuthorizationPolicy)、命名空间隔离和流量管控。
目标规则定义“怎么连”:比如要求某个服务的所有流量必须启用 mTLS,或配置负载均衡策略。授权策略定义“谁能连”:它声明主体(来源身份)、操作(读/写)、资源(目标服务),规则分 ALLOW(放行)与 DENY(拒绝)两类。命名空间则是天然的租户边界,不同团队各占一个“楼栋”,默认互相不可见。此外,流量管控还能实现金丝雀发布:把 5% 的流量切到新版本服务——就像试运行一部新电梯,先让少数人用。一个典型的 STRICT 模式配置如下:
规则表怎么执行,直接决定安全边界是否牢固。门禁系统的判定逻辑可以抽象成一条优先级明确的决策式:
《门禁规则表》写得越清晰,保安执行越不迷茫。服务网格的策略也一样:先拒绝一切,再按业务需求一条条显式放行。规则不是越多越好,而是每一条都经得起审视。
- 规则命中检查对每个请求三元组(主体 s、动作 a、资源 r)逐一匹配策略规则。
- 拒绝优先当 DENY 与 ALLOW 同时命中时,拒绝规则优先生效,防止配置冲突造成越权。
- 显式放行只有命中了显式声明的 ALLOW 规则才放行,这就是“白名单思维”。
- 默认拒绝兜底任何规则都没命中时一律拒绝——这是零信任与“默认允许”的传统防火墙的本质区别。
apiVersion: security.istio.io/v1beta1kind: PeerAuthenticationmetadata: name: default namespace: prodspec: mtls: mode: STRICT
合规审计监控:天网与台账
门禁系统升级后,老王心里还是没底:规则定得再好,万一有人绕过怎么办?于是他干了三件事:第一,每个楼栋门口装高清摄像头;第二,把纸质的访客登记本换成电子台账,每次刷卡自动记录;第三,每年请第三方安保审计公司来查整套门禁流程。出了纠纷,调监控、翻台账,几分钟就能还原每个人的行动轨迹。老王说:“安全系统不只要能用,还要能自证清白。”
服务网格的安全运营同样靠这三板斧:审计日志、监控指标、可观测性。审计日志相当于电子台账——Envoy sidecar 可以记录每次请求的来源身份、目标服务、动作和结果,满足“全程留痕”;监控指标相当于摄像头——关注 mTLS 覆盖率、证书剩余有效期、非 mTLS 流量突增、大量 401/403 异常等关键信号;可观测性则把零散的日志和指标串成完整的服务拓扑,Kiali 可以可视化展示哪些服务间已启用 mTLS 加密。其中,mTLS 覆盖率是最直观的落地指标:
这些指标和日志,最终都服务于合规遵从:SOC 2、PCI-DSS、GDPR 等标准都要求“传输加密 + 访问控制 + 审计留痕”,而 mTLS 与零信任策略正好同时满足这三项。老王的体会很朴素:摄像头和台账不是为了好看,而是让每个安全决策都可追溯、可解释。云原生世界的审计监控,就是那盏永远亮着的“天网”。
- 分子mTLS 加密流量:由 sidecar 统计的、启用了双向 TLS 的服务间请求数。
- 分母服务间总流量:服务网格内全部服务间请求的总数。
- 乘以 100%把比例换算成百分比,便于设定安全基线,例如要求覆盖率不低于 99%。
AI 应用场景
金融核心系统的东西向流量加密
阶段:模型上线与生产安全
解决的问题:银行 AI 风控系统拆成若干微服务后,用户特征、交易行为等敏感数据在服务间高频流转。传统方案只做南北向防火墙,服务间明文传输一旦被横向渗透,数据直接裸奔;且监管要求敏感数据全链路加密。
具体案例:某股份制银行将风控推理链路(特征服务 → 模型服务 → 决策服务)接入服务网格,开启 STRICT 模式下的 mTLS,并为每个服务命名空间配置最小权限的 AuthorizationPolicy。改造后,审计系统可以按请求追踪“谁在什么时间调用了模型服务”,顺利通过等保测评。
云原生 AI 推理平台的多租户隔离
阶段:多租户模型服务部署与隔离
解决的问题:大模型推理平台同时服务多个业务方,租户 A 的模型和 Prompt 数据绝不能泄露给租户 B。单纯依靠 Kubernetes 网络策略难以做到逐请求身份认证,误配置会导致跨租户越权访问。
具体案例:某 AI 平台按租户划分命名空间,命名空间之间默认拒绝;租户内的服务通过 mTLS 双向认证建立加密通道,Gateway 网关在入口处校验 SPIFFE 身份再转发。上线后,租户间流量为零,安全团队还能通过 mTLS 覆盖率仪表盘对外展示隔离效果。
GPU 训练集群的模型权重防窃取
阶段:分布式训练安全加固
解决的问题:大模型分布式训练时,GPU 节点之间要高频传输梯度数据,这些梯度包含训练数据的敏感信息。传统集群内网无加密,一旦某个节点被攻破,攻击者即可嗅探或篡改梯度,甚至投毒模型。
具体案例:某 AI 公司为训练集群启用服务网格 mTLS,所有节点间梯度传输强制加密;同时用零信任策略限制只有训练命名空间内的 Worker 节点能访问参数服务器。配合证书自动轮换,即使单个节点被入侵,也无法横向扩散。
Python 演示
import hashlibimport time class Cert: """简化数字证书:以 CA 共享密钥模拟非对称签名。""" def __init__(self, subject, issuer, pubkey, valid_days=30): self.subject = subject self.issuer = issuer self.pubkey = pubkey self.expiry = time.time() + valid_days * 86400 self.signature = "" def sign_by_ca(self, ca_key): body = f"{self.subject}|{self.issuer}|{self.pubkey}|{self.expiry}" self.signature = hashlib.sha256((body + ca_key).encode()).hexdigest() def verify_by_ca(self, ca_key): body = f"{self.subject}|{self.issuer}|{self.pubkey}|{self.expiry}" expect = hashlib.sha256((body + ca_key).encode()).hexdigest() if not self.signature or self.signature != expect: raise PermissionError(f"{self.subject} 证书签名不合法") if self.expiry < time.time(): raise PermissionError(f"{self.subject} 证书已过期,有效期至 {self.expiry}") print(f"[验证通过] {self.subject} 由 {self.issuer} 签发,有效期至 " f"{time.strftime('%Y-%m-%d', time.localtime(self.expiry))}") def mutual_tls(ca_key, client_cert, server_cert): print("== 第 1 步:客户端校验服务端证书 ==") server_cert.verify_by_ca(ca_key) print("== 第 2 步:服务端校验客户端证书 ==") client_cert.verify_by_ca(ca_key) session_key = hashlib.sha256((client_cert.pubkey + server_cert.pubkey).encode()).hexdigest()[:16] print(f"== 双向认证通过,会话密钥 {session_key} ==") return session_key class ZeroTrustPolicy: """默认拒绝,仅显式放行的零信任策略表。""" def __init__(self): self.rules = [ ("billing-service", "pay-api", "write"), ("billing-service", "report-api", "read"), ("auth-service", "report-api", "read"), ] def allow(self, identity, target, action): if (identity, target, action) in self.rules: print(f"[策略放行] {identity} 允许 {target} 的 {action} 操作") return True print(f"[默认拒绝] {identity} 禁止 {target} 的 {action} 操作") return False def main(): ca_key = "org-root-ca-2024" client_cert = Cert("billing-service", "org-ca", "pubkey-billing") server_cert = Cert("pay-api", "org-ca", "pubkey-pay") client_cert.sign_by_ca(ca_key) server_cert.sign_by_ca(ca_key) session_key = mutual_tls(ca_key, client_cert, server_cert) policy = ZeroTrustPolicy() policy.allow("billing-service", "pay-api", "write") policy.allow("billing-service", "report-api", "read") policy.allow("unknown-service", "pay-api", "write") print("加密报文摘要:", hashlib.sha256((session_key + "[转账-0001]").encode()).hexdigest()[:16]) if __name__ == "__main__": main()
self.signature = hashlib.sha256((body + ca_key).encode()).hexdigest()CA 用共享密钥为证书内容打“防伪钢印”,任何篡改都会导致验证失败。server_cert.verify_by_ca(ca_key)客户端先校验服务端证书,这正是“双向亮证”的第 1 步。session_key = hashlib.sha256((client_cert.pubkey + server_cert.pubkey).encode()).hexdigest()[:16]双方证书都合法后,用双方公钥材料派生会话密钥。if (identity, target, action) in self.rules:零信任的“显式放行”检查:策略表里有明确记录才允许访问。policy.allow("unknown-service", "pay-api", "write")没有身份凭据的服务发起写操作,触发默认拒绝。
常见误区
误区我把 PeerAuthentication 改成 STRICT,证书也装好了,从此安全无忧。证书到期前再续就行,反正服务网格会自动处理。
正解证书是有生命周期的,Istio 默认签发的证书有效期只有 24 小时,自动轮换依赖 istiod 的根证书、节点时钟同步等链路健康。即使 mTLS 全覆盖,吊销、私钥泄露、策略误配都会让防线失效。就像工牌会过期、会挂失,门禁系统也要持续维护,而不是装完就忘。
为何常见:在传统运维中,TLS 证书是“一次配置、长期不动”的静态资源,运维惯性让人低估了证书生命周期的管理成本。
误区零信任嘛,就是不再相信任何边界,所以内网干脆随便连,反正每个请求都会验证。
正解零信任不是取消边界,而是把信任决策的依据从“网络位置”换成“身份 + 上下文”。防火墙、WAF 依然保留,作为南北向第一道闸门;所谓“默认拒绝”意味着“没被显式允许就拒绝”,而不是“先随便连,再等着被验证”。比喻来说,小区大门没有拆,只是每栋楼又加了独立门禁。
为何常见:“不信任网络”的口号很容易被误读成“网络没用”,忽略了纵深防御中边界层仍然承担着大量基础防护职责。
误区所有服务都启用 mTLS 后,黑客就进不来了,加密等于安全。
正解mTLS 只解决传输层的身份认证与加密,应用层注入、业务逻辑漏洞、供应链攻击都不在它的保护范围内;私钥一旦泄露,加密通道同样形同虚设。mTLS 是零信任的“第一公里”,远不是终点。就像双向亮证挡得住冒充者,却挡不住业主在家被电信诈骗。
为何常见:“加密就安全”是直觉性的过度外推,忽略了安全是分层体系,每一层都有各自的职责和盲区。
误区我把证书有效期设成 10 年,省得天天轮换,运维轻松,业务也不用中断。
正解证书有效期越长,私钥泄露后的暴露窗口就越大。零信任实践恰恰相反:提倡短证书(数小时到数天)加自动轮换,把单次泄露的损失控制在极短时间内。主流 CA 已把 TLS 证书有效期上限压到 13 个月,正是同样的逻辑。类比门禁密码:三个月一换虽然麻烦,但远比十年不换被人抄走安全。
为何常见:人们习惯用“管理成本”思维替代“风险成本”思维,只看到轮换带来的运维负担,看不到长证书背后的安全负债。
面试题
Q1. mTLS 与普通 TLS 的核心区别是什么?
- A.mTLS 只加密不认证
- B.mTLS 要求双方证书互验← 正确答案
- C.mTLS 只需要服务端证书
- D.mTLS 不依赖证书机构
答案:B。普通 TLS 通常只验证服务器身份(单向亮证),而 mTLS 要求客户端也出示证书、服务端也验证客户端,即双向认证。选项 B 准确描述了这一本质区别。
Q2. 零信任安全模型的核心主张是什么?
- A.永不信任且始终验证← 正确答案
- B.内网默认全部信任
- C.只信任边界防火墙
- D.只在登录时验证一次
答案:A。零信任的核心是“永不信任,始终验证”:不因流量来自内网就给予信任,每次访问都要基于身份与上下文重新验证。其余选项描述的是传统边界防御模型。
Q3. 在 Istio 服务网格中,mTLS 证书通常由谁负责签发?
- A.外部商业 CA 手动签发
- B.控制平面自动签发证书← 正确答案
- C.业务应用自行生成证书
- D.浏览器厂商统一签发
答案:B。Istio 的控制平面组件 istiod 内置 CA,会基于 Kubernetes ServiceAccount 自动为每个服务签发并轮换证书,无需人工介入。这正是服务网格“让安全成为基础设施能力”的体现。
Q4. PeerAuthentication 的 STRICT 模式表示什么?
- A.允许明文与加密混跑
- B.拒绝所有外部请求
- C.强制流量全部走 mTLS← 正确答案
- D.仅对特定端口加密
答案:C。STRICT 模式强制服务间的所有流量都必须启用 mTLS,任何明文流量都会被拒绝。PERMISSIVE 模式才允许明文与加密混跑。
Q5. 零信任策略落地时,最稳妥的第一步是什么?
- A.直接关闭所有流水线
- B.从宽松策略开始迭代
- C.先默认拒绝再显式放行← 正确答案
- D.一次性删除全部策略
答案:C。零信任讲究“默认拒绝 + 显式放行”,应先在目标范围内设置默认拒绝策略,再依据业务需求逐条放行,避免一次性全量收紧造成大面积故障。
Q6. 缩短证书轮换周期的好处有哪些?
- A.降低私钥泄露的长期危害← 正确答案
- B.缩小潜在攻击利用窗口← 正确答案
- C.显著提升网络吞吐性能
- D.简化证书管理复杂度
答案:AB。短证书意味着即使私钥泄露,攻击者能利用的时间窗口也很短。吞吐性能和证书轮换周期无关,短证书反而增加管理频率,因此 C、D 均不正确。
Q7. 在网络安全语境中,“东西向流量”指的是什么?
- A.进出机房的数据流量
- B.服务之间的横向流量← 正确答案
- C.用户访问页面的流量
- D.负载均衡分发的流量
答案:B。南北向流量是进出数据中心的流量,东西向流量是数据中心内部服务之间的横向流量。微服务架构下东西向流量剧增,成为零信任关注的重点。
Q8. 零信任安全建设通常包含哪些配套能力?
- A.双向认证与策略授权← 正确答案
- B.身份与日志审计← 正确答案
- C.数据库读写分离
- D.监控与持续验证← 正确答案
答案:ABD。零信任需要 mTLS 双向认证、AuthorizationPolicy 授权、审计日志、监控告警和持续验证等能力配套。数据库读写分离是数据层优化手段,与零信任的访问控制体系无关。
Q9. 证书被吊销后,常见的失效手段有哪些?
- A.使用证书吊销列表 CRL← 正确答案
- B.使用在线状态协议 OCSP← 正确答案
- C.清除全部业务日志
- D.关闭所有服务端口
答案:AB。CRL 是 CA 定期发布的吊销名单,OCSP 是实时查询证书状态的在线协议,两者都是标准的吊销检查手段。清除日志和关闭端口与证书吊销无关。
Q10. 即使 mTLS 已全覆盖,以下哪种攻击仍然有效?
- A.攻击者伪造客户端证书
- B.服务端证书意外过期
- C.应用层 SQL 注入攻击← 正确答案
- D.中间证书突然被吊销
答案:C。mTLS 只保护传输层的身份认证与加密,应用层漏洞(如 SQL 注入、越权)它完全感知不到。伪造证书会被 CA 验签拦住,过期或吊销会导致握手失败,这些 mTLS 都能防御。