OpenSSL报permitted subtree violation:证书SAN与CA名称约束排查 HTTPS叶证书没过期SAN也包含访问域名OpenSSL却报permitted subtree violation。别急着重装根证书这可能是CA证书的名称约束拒绝了下级名称。下面区分“访问名能否匹配”和“这条链能否为这些名称背书”再用error 47、48和离线命令定位。一、SAN匹配不代表名称约束通过主机名验证检查访问名是否匹配叶证书nameConstraints限制CA下级证书的名称范围。前者通过后者仍可失败。好比姓名对得上签发机构的授权范围却不覆盖这张证件。中间CA只允许example.test叶证书却含api.example.test与api.other.test。只访问前者多余DNS SAN仍可让路径被拒绝。二、从error 47和48定位不把depth当约束来源本次OpenSSL 1.1.1k FIPS离线实验中47对应permitted subtree violation48对应excluded subtree violation。前者是名称未落在允许范围后者是命中排除范围。错误日志还会给出subject与depth需要完整保留。depth 0是待验证叶证书1是签发它的CA以此类推。但名称约束失败时depth可以指向被检查名称所在的证书并不保证指向写着nameConstraints的CA。本例约束放在中间CA两类失败都报depth 0别因此只修改叶证书配置。hostname mismatch走主机名分支unable to get local issuer certificate先处理构链。错误可不止一条不用最后一行代替诊断。三、逐张检查最终证书不只看CSRopenssl version # 每个文件只放一张证书先确认文件角色 for f in root.pem issuing.pem leaf.pem; do printf \nfile%s\n $f openssl x509 -in $f -noout -subject -issuer \ -serial -fingerprint -sha256 openssl x509 -in $f -noout \ -ext subjectAltName,nameConstraints,basicConstraints done重点读取每张CA的Name Constraints和叶证书全部SAN。x509只读首张证书fullchain.pem也不例外多级链先拆分并编号。RFC 5280规定名称约束扩展只用于CA证书并应标为critical。permittedSubtrees表示允许范围excludedSubtrees表示排除范围命中排除范围仍应拒绝。存在多个受约束CA时要满足路径上适用的各级限制不是让下级写一个更宽范围就覆盖上级。四、固定信任材料分开验证名称与路径openssl verify -no-CApath -CAfile root.pem \ -untrusted issuing.pem -purpose sslserver \ -verify_hostname api.example.test -show_chain leaf.pem rc$? printf verify_exit%s\n $rc命令只验本地文件不连接网站。CAfile固定根untrusted提供中间链leaf.pem是目标。名称、用途、路径一起检查OK且退出0才通过show_chain成功时显示路径。为定位可另做不带verify_hostname的对照但它只是不执行这项访问名匹配并不会解除CA名称约束。本次多SAN越界样本去掉该参数仍报47。不能把这种诊断对照写进生产验收脚本宣称域名也已验证。不要提升中间CA为信任锚或关闭验证来消除错误这改变了信任边界并非修复原路径。五、配置片段表达什么修复就改什么[issuing_ca] basicConstraints critical,CA:TRUE,pathlen:0 keyUsage critical,keyCertSign,cRLSign subjectKeyIdentifier hash nameConstraints critical,permitted;DNS:example.test,excluded;DNS:admin.example.test这是CA扩展片段不是完整生产CA配置允许example.test及其DNS子域排除admin.example.test及其子域。它不是DNS解析规则也不是网站访问控制。pathlen:0描述中间CA层级不能替代名称范围检查两种约束要分别满足。DNS、IP、URI、邮件地址是不同名称类型不能把permitted;DNS当作“只允许所有类型身份属于这个域”的总开关。本文只测试DNS SAN不把结果推广到IP范围、通配符或其他客户端实现涉及前导点、国际化域名等边界时应另建准确样本验证。如果多余SAN是申请错误由授权CA按正确名称集合重新签发叶证书。若业务确需范围外名称应选择政策允许的签发路径或由CA管理员审批后调整并重签适用CA证书。只改CSR、配置文件或服务端server_name不会改变已经签名的扩展。六、用正反例确认不只测一个能通的名字本次用临时根、中间CA和serverAuth叶证书离线验证未改系统信任、时钟或生产服务材料已清理。不冒充浏览器或线上握手实测。叶证书或条件退出码与错误结论仅api.example.test0OK允许范围内仅api.other.test247depth 0超出允许范围api.example.test加api.other.test247depth 0访问名匹配仍不足仅admin.example.test248depth 0允许范围内但被排除合规证书验证wrong.example.test262depth 0主机名不匹配# 在隔离夹具中比较四份证书的路径约束不检查访问名 for f in good.pem outside.pem mixed.pem excluded.pem; do openssl verify -no-CApath -CAfile root.pem \ -untrusted issuing.pem -purpose sslserver $f rc$? printf %s exit%s\n $f $rc done四份文件对应表中前四行并非内置样本。循环不验访问名需另用verify_hostname。总体退出码可能来自末尾printf自动化应逐项判断rc。七、上线前还差一次真实客户端验证离线通过不说明服务已加载新证书。部署后从实际客户端读取线上指纹、SAN与链以正确主机名完成握手和业务请求。不同TLS库支持可能不同本机OK不能替所有客户端背书。八、验收清单与官方依据记录错误原文、退出码、depth与证书指纹定位名称及约束来源。检查全部DNS SAN和路径上适用的名称限制而非只找一个匹配名。合规正例通过越界及排除负例仍失败主机名另作明确校验。签发修改经过授权最终证书重新读取线上版本另行验收。依据OpenSSL扩展配置、verify手册、RFC 5280名称约束。先分清“名称匹配”和“名称授权范围”再决定重签哪一层。