38.8 零信任
一句话
零信任把“网络位置”这个隐含凭证换成“每次请求的身份 + 设备 + 上下文校验”:它不消灭攻击,而是把“攻陷一台 = 攻陷一片”改成“每跳都要重新攻陷”,代价是每次决策的延迟和一个必须高可用的策略中心。
边界模型的三个假设,今天全部失效
| 假设 | 现实 |
|---|---|
| 内网是可信的 | 钓鱼、供应链、远程办公、云上多租户——攻击者常常已经在“内网” |
| 边界是清晰的 | 云、SaaS、移动办公、合作伙伴接入,边界已经不存在 |
| 过了 VPN 就能访问 | 一台被控终端连上 VPN,等于拿到全网通行证 |
传统模型像城堡:护城河(防火墙)+ 吊桥(VPN),一旦进城,所有门都开着。零信任的前提是假设网络已经被攻破,所以每一次访问都要重新证明“你是谁、你的设备是否健康、你有权访问这个资源吗”。
数字:可达面降得不多,期望损失降得很多
设定 1000 台主机、20 个服务。从一台被控主机出发,3 跳内的网络可达主机数与“单跳真正攻陷”的概率:
| 架构 | 可达主机 | 单跳攻陷 | 3 跳期望攻陷 |
|---|---|---|---|
| 扁平内网 | 999 | 100% | 999 台 |
| 按环境分段(3 段) | 333 | 95% | 333 台 |
| 按服务微隔离(白名单调用) | 200 | 60% | 59 台 |
| 零信任(逐请求身份 + 最小权限) | 156 | 30% | 8.4 台 |
皇冠资产占 1% 时,3 跳内摸到核心的概率:
扁平内网 100.0%
按环境分段(3 段) 96.4%
按服务微隔离(白名单调用) 44.6%
零信任(逐请求身份 + 最小权限) 8.1%
这张表的关键不是“可达主机从 999 降到 156”(只降了 6 倍),而是每跳的攻陷概率从 100% 降到 30%——攻击是乘法的:
扁平内网: 1 × 1 × 1 = 必中
零信任: 0.3 × 0.3 × 0.3 ≈ 2.7%(每多一跳,衰减一个数量级)
🔑 零信任真正改变的是攻击的经济学:不是让攻击者到不了,而是让“每往前一步”都要重新付出漏洞利用/身份冒用的成本。
零信任不是产品,是三个“每次”
| 传统 | 零信任 |
|---|---|
| 信任依据:网络位置(IP/网段/VPN) | 信任依据:身份 + 设备健康 + 上下文(时间、地点、行为) |
| 授权粒度:一次登录,长期有效 | 授权粒度:每次请求、最小权限、短时效 |
| 默认姿态:内网默认放行 | 默认姿态:默认拒绝,显式允许 |
| 失败模式:边界破了就全通 | 失败模式:单点被控只影响它能证明有权访问的资源 |
三个“每次”:
- 每次连接都认证:工作负载用 mTLS + 短生命周期证书(SPIFFE/SPIRE),人用 SSO + MFA + 设备证书。
- 每次请求都授权:策略中心(PDP)按“主体 + 资源 + 动作 + 上下文”判定,而不是按“在不在内网”。
- 每个会话都可撤销:短 TTL、持续风险评估、异常即降权或断连(凭证有效期 60 分钟 → 5 分钟,暴露窗口从 60,000 缩到 5,000 凭证·分钟)。
NIST SP 800-207 的七条信条(意译)
- 所有数据源和计算服务都视为资源,不因位置而区别对待。
- 所有通信都要加密与认证,无论在内网还是外网。
- 访问按单次会话授权,会话结束即失效。
- 授权策略是动态的,依据身份、设备、行为、环境。
- 持续监控资产与设备的完整性。
- 所有认证与授权都严格执行,并在每次访问前重新评估。
- 尽可能收集状态信息(日志、流量、设备姿态),用于改进决策。
Google 的 BeyondCorp 是这套思想最早的大规模落地:员工不再“连 VPN 才能办公”,而是每个应用前面都有一个身份感知代理,按用户与设备状态放行。Forrester 的 Kindervag 更早提出了那句口号:“永不信任,始终验证”。
落地四阶段:每一阶段都有可量化的收益
| 阶段 | 动作 | 量化变化 | 常见阻力 |
|---|---|---|---|
| ① 清点 | 资产、身份、服务依赖、数据流 | 没有清单就没有策略;先画出“谁能访问谁” | 没人维护 CMDB,依赖靠猜 |
| ② 强身份 | SSO + MFA + 设备证书 | MFA 覆盖 90% → 撞库成功降到 1/10(见 38.7 账号安全) | 老旧系统不支持 SSO |
| ③ 微隔离 | 从“网段”到“服务 + 身份”,mTLS 白名单 | 可达 999 → 200,期望攻陷 999 → 59 | 服务间调用关系不清,先观察后阻断 |
| ④ 持续验证 | 短 TTL、风险评分、最小权限、自动降权 | 凭证暴露 60,000 → 5,000 凭证·分钟 | 频繁重认证影响体验,需要 refresh 与无感续期 |
顺序不能反:没有身份与清单就上微隔离,会把正常调用也阻断;没有微隔离就做持续验证,只是在“全通”的网络上加了一道门禁。
代价:延迟、可用性、遗留系统
| 代价 | 数字 | 应对 |
|---|---|---|
| 每次请求多一次策略决策 | 缓存命中 95% 时平均 +0.25ms;全集中检查 +5ms | 本地策略缓存 + 短 TTL 推送;把 PDP 调用放到连接建立阶段而非每请求 |
| 策略中心成为关键路径 | PDP 可用性 99.9% → 每天约 864,000 次请求受影响 | 多副本 + 本地缓存 + 明确的降级策略 |
| 策略中心挂了的取舍 | fail-closed:全拒(可用性归零);fail-open:全放(安全归零) | 按资源分级:核心系统 fail-closed,低风险只读 fail-open + 告警 |
| 遗留系统不支持 mTLS/SSO | 无法直接接入 | 身份感知代理(IAP)在网关终结 mTLS,后端仍用旧协议 |
| 运维复杂度 | 策略即代码、变更评审、灰度 | 策略要能“只观察不阻断”(dry-run)上线 |
⚠️ 零信任把可用性风险集中到了策略中心。做零信任之前,先回答:PDP 挂了,业务是“全拒”还是“全放”?这个答案必须写进架构决策记录,而不是等故障时现场决定。
零信任不解决什么
| 问题 | 为什么零信任管不了 | 该看哪 |
|---|---|---|
| 注入、XSS、越权 | 请求身份合法、路径合法,只是内容/对象有问题 | 38.6 常见攻击 |
| 合法账号的滥用(内鬼) | 它确实有权限 | 行为基线、最小权限、审计、双人复核 |
| 终端被完全控制 | 攻击者用“合法身份 + 合法设备”活动 | 设备健康证明、EDR、行为检测 |
| 供应链投毒 | 依赖包本身带后门 | 38.10 供应链安全 |
| 数据本身没分级 | 不知道哪些是敏感数据,就无法定策略 | 38.5 数据分级与脱敏 |
| 业务逻辑漏洞 | 权限模型设计错误 | 38.3 授权 (RBAC / ABAC / 权限模型) |
可运行的可达面与成本模型
package main
import (
"fmt"
"math"
)
// 每种架构下,从一台被控主机出发 3 跳内能“网络可达”的主机数,
// 以及每一跳真正攻陷(拿到身份/利用漏洞)的概率。
type model struct {
name string
reach int // 3 跳内可触达的主机数
perHop float64 // 单跳攻陷概率
}
// expected 返回 3 跳内的期望攻陷主机数(每跳分支数取 reach 的立方根)
func expected(m model) float64 {
b := math.Cbrt(float64(m.reach))
e := b*m.perHop + b*b*m.perHop*m.perHop + b*b*b*m.perHop*m.perHop*m.perHop
if e > float64(m.reach) {
e = float64(m.reach)
}
return e
}
func main() {
models := []model{
{"扁平内网", 999, 1.00}, // 网络通 = 直接拿下
{"按环境分段(3 段)", 333, 0.95}, // 同段内仍然通,跨段要绕
{"按服务微隔离(白名单调用)", 200, 0.60}, // 要利用服务间接口
{"零信任(逐请求身份 + 最小权限)", 156, 0.30}, // 每跳都要有合法身份
}
fmt.Printf("%-32s %8s %8s %10s\n", "架构", "可达主机", "单跳攻陷", "3 跳期望攻陷")
for _, m := range models {
fmt.Printf("%-32s %8d %8.0f%% %9.1f 台\n", m.name, m.reach, m.perHop*100, expected(m))
}
// 皇冠资产占 1%:3 跳内摸到至少一台的概率 = 1 − e^(−期望攻陷数 × 1%)
fmt.Println("\n皇冠资产占 1% 时,3 跳内摸到核心的概率:")
for _, m := range models {
p := 1 - math.Exp(-expected(m)*0.01)
fmt.Printf(" %-32s %.1f%%\n", m.name, p*100)
}
// 策略检查的成本:缓存命中率决定平均延迟
qps, pdpLatencyMs, cacheHit := 10000.0, 5.0, 0.95
avg := pdpLatencyMs * (1 - cacheHit)
fmt.Printf("\n策略检查:%.0f QPS,未命中 %.1fms,缓存命中率 %.0f%% → 平均 +%.2fms,PDP 负载 %.0f QPS\n",
qps, pdpLatencyMs, cacheHit*100, avg, qps*(1-cacheHit))
fmt.Printf("不做检查 +0ms;每次集中检查 +%.1fms(P99 还要再算排队);命中率降到 80%% → +%.1fms\n",
pdpLatencyMs, pdpLatencyMs*0.2)
// PDP 不可用时:fail-closed 全拒 vs fail-open 全放
pdpAvail := 0.999
fmt.Printf("PDP 可用性 %.1f%%:%.0f QPS × 86400s × 0.1%% → 每天约 %.0f 次请求受影响(fail-closed 全拒 / fail-open 全放)\n",
pdpAvail*100, qps, qps*86400*(1-pdpAvail))
// 凭证有效期 = 被偷后的暴露窗口
stolenPerDay := 1000.0
fmt.Println("\n凭证有效期决定暴露窗口:")
for _, ttlMin := range []float64{60, 15, 5} {
fmt.Printf(" TTL %2.0f 分钟:每天 %.0f 个凭证泄露 → 暴露 %.0f 凭证·分钟\n",
ttlMin, stolenPerDay, stolenPerDay*ttlMin)
}
}
输出:
架构 可达主机 单跳攻陷 3 跳期望攻陷
扁平内网 999 100% 999.0 台
按环境分段(3 段) 333 95% 333.0 台
按服务微隔离(白名单调用) 200 60% 59.0 台
零信任(逐请求身份 + 最小权限) 156 30% 8.4 台
皇冠资产占 1% 时,3 跳内摸到核心的概率:
扁平内网 100.0%
按环境分段(3 段) 96.4%
按服务微隔离(白名单调用) 44.6%
零信任(逐请求身份 + 最小权限) 8.1%
策略检查:10000 QPS,未命中 5.0ms,缓存命中率 95% → 平均 +0.25ms,PDP 负载 500 QPS
不做检查 +0ms;每次集中检查 +5.0ms(P99 还要再算排队);命中率降到 80% → +1.0ms
PDP 可用性 99.9%:10000 QPS × 86400s × 0.1% → 每天约 864000 次请求受影响(fail-closed 全拒 / fail-open 全放)
凭证有效期决定暴露窗口:
TTL 60 分钟:每天 1000 个凭证泄露 → 暴露 60000 凭证·分钟
TTL 15 分钟:每天 1000 个凭证泄露 → 暴露 15000 凭证·分钟
TTL 5 分钟:每天 1000 个凭证泄露 → 暴露 5000 凭证·分钟
参数怎么给
| 你的阶段 | 优先做什么 | 别做什么 |
|---|---|---|
| 还没做 SSO/MFA | 先把身份统一,MFA 覆盖到管理员与资金操作 | 直接上微隔离,会阻断正常调用 |
| 已有 SSO,内网扁平 | 画服务依赖图 → 观察模式微隔离 → 白名单放行 | 一次性全量阻断 |
| 已有微隔离 | 上 mTLS + 工作负载身份,缩短证书/令牌 TTL | 只做网络 ACL,不做身份 |
| 多云/混合 | 统一策略中心 + 身份联邦 | 每个云一套独立策略 |
| 遗留系统多 | 身份感知代理(网关终结 mTLS/SSO) | 要求每个老系统自己改造 |
| 已做零信任 | 持续验证 + 行为基线 + 自动降权 | 把策略写死,一年不更新 |
反模式
| 反模式 | 后果 |
|---|---|
| 买了 ZTNA/VPN 替代品就宣布“零信任” | 只换了入口,内网仍然全通 |
| 只保护南北向,不保护东西向 | 一台被控主机仍可横向扫全网 |
| 策略中心单点部署 | PDP 挂 = 全站不可用或全站放行 |
| 默认 fail-open 且无告警 | 策略失效时静默裸奔 |
| 微隔离一次性全量阻断 | 打断正常调用,被迫回滚,信任受损 |
| 策略写死、没有 dry-run | 无法验证误杀,变更风险高 |
| 强制每请求都查中心 | 延迟 +5ms,P99 抖,团队最终关掉它 |
| 短 TTL 但没有 refresh/无感续期 | 用户频繁重登录,体验崩溃 |
| 只做认证不做授权 | 身份合法但权限过大,等于没做 |
| 把零信任当合规项目交差 | 文档齐全,攻击面没变 |
自检
Q1 零信任把 3 跳可达主机从 999 降到 156(约 6 倍),为什么期望攻陷数却从 999 降到 8.4(约 120 倍)?
▸ 答案:因为可达面只是“能不能发包”,攻陷是“能不能拿到身份/利用漏洞”,两者相乘。扁平内网每跳攻陷概率 100%(网络通即拿下),3 跳是 1×1×1;零信任每跳只有 30%(要有合法工作负载身份、要过策略、要利用目标接口),3 跳后每多一层就乘一次 0.3,且可达分支也被限制。降低可达面是线性收益,降低单跳成功率是指数收益,两者叠加才有 120 倍。
Q2 零信任和“上 VPN + 内网防火墙 + 堡垒机”的本质区别是什么?
▸ 答案:信任依据不同。VPN/防火墙信任“网络位置”:连上 VPN 就在内网,内网默认放行;堡垒机只是把运维入口收窄,登录后仍是全通。零信任信任“身份 + 设备 + 上下文”,并且每次请求都重新授权、默认拒绝、权限最小化、会话短时效。差别体现在横向移动:VPN 模型下一台终端被控即可扫全网(999 台),零信任下它只能访问策略允许的少数依赖(期望 8.4 台)。
Q3 策略中心(PDP)挂了,应该 fail-open 还是 fail-closed?怎么选?
▸ 答案:按资源分级,不能一刀切。核心写操作(支付、转账、权限变更)fail-closed——宁可拒,不可错;低风险只读(行情、文档、公开内容)可以 fail-open + 强告警 + 短时窗口,因为可用性损失更贵。同时必须做:PDP 多副本、本地策略缓存(TTL 内可离线判定)、降级开关与演练。关键是提前写进架构决策,而不是故障现场拍脑袋。
Q4 零信任能防住“越权访问”吗?为什么?
▸ 答案:不能。越权是“身份合法、请求合法,但访问了不属于自己的对象”(见 38.6 常见攻击),零信任的策略粒度通常到“服务/接口/资源类型”,判断不了“这条订单是不是你的”。它只能保证“调用方有权调用这个接口”,业务级的对象授权仍要在应用层做(WHERE owner_id = ?)。零信任缩小的是网络层爆炸半径,不是业务逻辑漏洞。
Q5 为什么令牌 TTL 不能无限短?从 60 分钟降到 5 分钟,收益和代价各是什么?
▸ 答案:收益是暴露窗口线性缩小:每天 1000 个凭证泄露时,60 分钟 TTL 对应 60,000 凭证·分钟,5 分钟对应 5,000(12 倍)。代价是刷新频率 ×12:refresh 请求量、PDP 负载、时钟/续期逻辑复杂度、以及用户可感知的重新认证(若 refresh 失败)。所以工程上用“短 access token + 长 refresh token + 无感续期 + 异常即撤销”,而不是把 TTL 压到 30 秒——那会把令牌系统变成每请求一次认证,延迟和可用性都不可接受。
跨篇相关:认证协议与令牌生命周期见 38.2 认证 (Session / JWT / OAuth2 / OIDC);授权模型与最小权限见 38.3 授权 (RBAC / ABAC / 权限模型);账号接管与 MFA 的量化收益见 38.7 账号安全;应用层漏洞(越权/注入)见 38.6 常见攻击;供应链攻击面见 38.10 供应链安全;数据分级决定策略粒度,见 38.5 数据分级与脱敏。