服务账号的 VPN 访问:证书还是共用登录
对比无人值守 VPN 访问的机器证书与存储密码,并把真正的权限边界放进登录之后执行的政策里。
几乎所有无人值守的 VPN 部署都落在两种设计上:把人的登录凭据放进脚本共用,或把机器证书绑定到主机上。它们的失效点不同,这比部署速度更重要。存储的密码会在其所有者修改或离职时失效;证书会在过期或主机重建而没带走私钥时失效。三项条件决定你能承担哪种代价,而在授权政策动手之前,两种设计都没有限制任何东西。
从任务出发,而不是从账号出发
任务定义边界:访问哪些目的地、哪些服务、什么时段、一次会话可以持续多久。隧道路由只是这条边界的一半。网关决定会话是否被允许;它背后的资源决定会话能做什么。先把清单写下来,并指定负责人,因为两种身份设计都必须满足它。
写的时候要把认证和授权分开。认证回答谁在连接;授权回答会话之后能到达哪里。RADIUS 把后一部分作为属性携带,例如 Filter-Id、Framed-IP-Address、Session-Timeout 和 Class,登录成功后由网关附加。只换掉登录方式而不管授权,等于什么都没限制。
共用的真人登录:密码成了边界
复用一个真人账号是最快的路径,也是老化得最糟的一条。凭据就是密码,于是它出现在脚本、环境文件和调度器配置里,每份副本都要轮换。所有者周五改了密码,任务在下一次运行时就失败,而没人盯着。
MFA 通常是这种设计崩塌的地方。脚本无法响应推送确认,于是账号被排除在政策之外,而这恰好是攻击者会挑的账号。例外、可信位置绕过和按账号豁免会不断累积,等下一个人读租户设置时,一条都看不见。
可归因性是另一项代价。网关日志里的每个会话都带同一个用户名,于是夜间同步无法与写它的人的工作区分开,而撤销任务就等于撤销那个人。
机器证书:身份绑定在主机上
证书把问题从账号知道什么,变成主机是什么。使用 EAP-TLS 时,客户端出示证书并证明持有匹配的私钥;政策服务器把主体或计算机账号映射到某个组,并应用该组的政策。没有提示,也没有躺在文本文件里的共享密钥。
它造出的边界比人们以为的窄。证书认证的是主机,不是任务,任何拥有 root 或本地管理员权限的人都能在那台主机上使用那把私钥。把私钥放在平台保护它的地方:在 Windows 证书存储中不可导出,在配置文件允许时由 TPM 保护,或在 Linux 上使用 root 拥有的 0600 文件。主机被攻破就是凭据被攻破。
过期是反复出现的故障。周日过期的证书会让任务在周日停摆,而网关通常只报一个笼统的认证失败,而不点名日期。把日期检查写进运行手册,从任务主机上执行:
openssl x509 -in client.pem -noout -subject -issuer -dates
ipsec listcerts
撤销需要一条网关会检查的路径。OpenVPN 通过 crl-verify 选项读取 CRL,strongSwan 则取决于连接配置文件如何构建,依赖 CRL 或 OCSP。两者都没有接上时,移除一台主机就意味着等证书过期。
在两者之间做决定的三项条件
对照你手上的平台来比较,而不是对照某个参考设计。
第一项条件:网关能否授权机器身份?如果它只把 RADIUS 用户名映射到目录用户,证书认证完主机就会卡在授权上。第二项条件:任务是否需要只有用户账号才携带的资源访问,例如映射的共享目录或按席位的许可证?那样机器身份无法替代,诚实的答案是带范围政策的专用用户账号。第三项条件:谁能在没有人参与的情况下轮换凭据?自动注册让证书的维护成本很低;一个人知道的密码做不到。
| Constraint | Machine certificate | Dedicated user account with stored secret |
|---|---|---|
| Unattended login | Private key proof, no prompt | Only if the account is exempted from MFA |
| Resource expects a user identity | Works only when the resource accepts computer accounts | Matches the access a person would have |
| Rotation | Re-enrollment, often automated | Secret change plus redeploy of every copy |
| Revocation speed | Tied to CRL or OCSP refresh | Disable the account, immediate |
把表格读成一份代价清单,而不是排名。存储密钥一列在撤销速度和只认用户账号的资源兼容性上占优;证书一列在轮换以及不为了让脚本跑通而削弱 MFA 上占优。
把限制放进政策,放在认证之后
无论选哪种身份,权限限制都属于认证之后执行的政策。在 NPS 中,网络政策按顺序评估,第一条匹配所有条件的政策会应用其设置,所以放在窄政策之上的宽政策会决定结果,不管客户端出示什么。微软在其NPS 政策概述中记录了条件与设置模型。
给任务它自己的组或政策条件,依据机器身份携带的某个东西:证书模板、呼叫站标识,或专用地址池里的地址。然后用属性约束会话:为网关映射的角色设置 Filter-Id,设置较短的 Session-Timeout,让卡住的任务重新认证而不是把会话挂上好几天,并使用来自另一侧由防火墙隔离的地址池的 Framed-IP-Address。应用层授权仍然分开:通往数据库服务器的隧道并不等于有权读取其中的表。
验证拒绝,然后规划移除
能连通并不能证明最小权限。相反,要测试拒绝:用任务身份连接并尝试访问清单之外的目的地;如果网关只应允许一个会话,就再开第二个并发会话;撤销凭据后重复登录。
然后在两个地方确认同一个会话。网关日志显示通过认证的身份;政策服务器日志显示哪条政策匹配、返回了哪些属性。在 OpenVPN 上服务器记录证书的通用名,strongSwan 上的 ipsec statusall 会打印已建立的隧道及其使用的身份。如果两份日志对身份的说法不一致,说明政策匹配的不是你以为的东西。
移除属于设计的一部分,而不是一次清理冲刺。写下所有要删除的东西(证书或账号、组成员关系、网络政策、地址池条目、目标上的防火墙规则),并在任务还容易重建时跑一遍。
如果你今天就开始,按这个顺序做:写下资源清单,用三项条件选定身份,把限制放进政策,然后在任务上线前演练一次拒绝。