X.509 证书中的 Name Constraints(名称约束)扩展是 PKI 安全的核心机制之一。它允许 CA 证书限制其下级证书的适用范围,防止被滥用来签发任意域名的证书。本文详细介绍其工作原理和实际使用方法。
什么是 Name Constraints#
Name Constraints 是 X.509 证书标准(RFC 5280)定义的一个关键扩展,主要用于 CA 证书。它声明了该 CA 可以签发证书的域名和 IP 地址范围。
作用场景#
- 限制中间 CA 权限:企业私有 CA 可以限制下级 CA 只能签发特定域名的证书
- 分层授权:在大型组织中实现细粒度的证书管理权限划分
- 安全边界:防止某个被入侵的子 CA 被用来签发其他域名的证书
约束类型#
Name Constraints 包含两种类型的约束:
| 类型 |
说明 |
| permitted |
允许使用的名称范围 |
| excluded |
禁止使用的名称范围 |
这两个可以同时使用,excluded 优先级更高。
证书格式#
Name Constraints 扩展的 ASN.1 结构如下:
1
2
3
4
5
6
7
8
9
10
11
12
|
NameConstraints ::= SEQUENCE {
permittedSubtrees [0] GeneralSubtrees OPTIONAL,
excludedSubtrees [1] GeneralSubtrees OPTIONAL
}
GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
GeneralSubtree ::= SEQUENCE {
base GeneralName,
minimum [0] BaseDistance DEFAULT 0,
maximum [1] BaseDistance OPTIONAL
}
|
支持的名称类型包括:
- dNSName:域名(如
example.com)
- iPAddress:IP 地址(如
192.168.1.0/24)
- directoryName:目录名称(DN)
- rfc822Name:电子邮件(较少使用)
实际操作#
创建带 Name Constraints 的 CA 证书#
使用 OpenSSL 创建根 CA 时添加名称约束:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# 创建扩展配置文件
cat > ext_nc.cnf << 'EOF'
basicConstraints = critical, CA:TRUE
keyUsage = critical, keyCertSign, cRLSign
nameConstraints = permitted;DNS:.example.com, permitted;DNS:*.internal.example.com, excluded;DNS:evil.com
EOF
# 生成自签名 CA 证书
openssl req -x509 -new -nodes \
-keyout root-ca.key \
-out root-ca.crt \
-days 3650 \
-subj "/C=CN/O=Example CA/CN=Example Root CA" \
-extfile ext_nc.cnf \
-extensions v3_ca
|
查看证书中的 Name Constraints#
1
2
|
# 查看证书扩展详情
openssl x509 -in root-ca.crt -noout -text | grep -A5 "Name Constraints"
|
输出示例:
1
2
3
4
5
6
|
X509v3 Name Constraints:
Permitted:
DNS:.example.com
DNS:*.internal.example.com
Excluded:
DNS:evil.com
|
验证下级证书是否符合约束#
当使用这个受限 CA 签发证书时,只能签发符合约束的域名:
1
2
3
4
5
6
7
8
|
# 尝试为受限域名签发证书 - 成功
openssl req -new -keyout server.key -out server.csr \
-subj "/C=CN/O=Example/CN=www.example.com"
openssl x509 -req -in server.csr \
-CA root-ca.crt -CAkey root-ca.key \
-out server.crt -days 365 \
-CAcreateserial
|
如果尝试签发不符合约束的域名(如 www.evil.com),证书验证会失败:
1
2
3
4
5
|
# 尝试为被排除的域名签发证书 - 失败
openssl x509 -req -in <(openssl req -new -keyout test.key -out /dev/stdout \
-subj "/C=CN/O=Test/CN=www.evil.com") \
-CA root-ca.crt -CAkey root-ca.key \
-out test.crt -days 365 2>&1
|
通常会报错:
1
2
|
Error opening CA certificate: ./root-ca.crt
3089079640:error:0B080074:x509 certificate routines:X509_check_ca:explicitly signs untrusted certificate:./root_ca.crt:verify error:num=0
|
IP 地址约束#
Name Constraints 也支持 IP 地址范围:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# 创建带 IP 约束的扩展配置
cat > ext_nc_ip.cnf << 'EOF'
basicConstraints = critical, CA:TRUE
keyUsage = critical, keyCertSign, cRLSign
nameConstraints = permitted;IP:10.0.0.0/255.0.0.0, permitted;IP:172.16.0.0/255.240.0.0, excluded;IP:10.100.0.0/255.255.0.0
EOF
openssl req -x509 -new -nodes \
-keyout root-ca-ip.key \
-out root-ca-ip.crt \
-days 3650 \
-subj "/C=CN/O=Example CA/CN=IP Restricted CA" \
-extfile ext_nc_ip.cnf \
-extensions v3_ca
|
查看 IP 约束:
1
|
openssl x509 -in root-ca-ip.crt -noout -text | grep -A3 "Name Constraints"
|
1
2
3
4
5
6
|
X509v3 Name Constraints:
Permitted:
IP:10.0.0.0/255.0.0.0
IP:172.16.0.0/255.255.240.0.0
Excluded:
IP:10.100.0.0/255.255.0.0
|
浏览器和应用程序支持#
主流浏览器和应用程序都支持 Name Constraints:
| 应用 |
支持情况 |
| Chrome/Edge |
完全支持 |
| Firefox |
完全支持 |
| OpenSSL 1.1.1+ |
支持(通过 -name_constraints 验证) |
| Java (Java 11+) |
支持 |
| Go (crypto/x509) |
支持 |
使用 OpenSSL 验证名称约束#
1
2
3
|
# 创建一个测试场景:受限 CA + 不符合的下级证书
# 验证时会检查名称约束
openssl verify -CAfile root-ca.crt -name_constraints server.crt
|
安全最佳实践#
1. 生产环境推荐配置#
对于需要严格权限分离的 PKI 系统:
1
2
3
4
5
|
cat > production_nc.cnf << 'EOF'
basicConstraints = critical, CA:TRUE
keyUsage = critical, keyCertSign, cRLSign
nameConstraints = permitted;DNS:yourcompany.com, permitted;DNS:*.yourcompany.com
EOF
|
2. 避免过度宽松的约束#
❌ 不推荐:允许所有域名
1
|
nameConstraints = permitted;DNS:.
|
✅ 推荐:明确指定允许的域名
1
|
nameConstraints = permitted;DNS:example.com, permitted;DNS:*.example.com
|
3. 结合其他安全措施#
Name Constraints 应与其他 CA 安全措施配合使用:
- 限制 CA 证书有效期
- 配合路径长度约束(pathlen)
- 使用专用的子 CA 处理不同业务线
1
2
3
4
5
6
7
8
|
# 完整的安全 CA 配置示例
cat > secure_ca.cnf << 'EOF'
basicConstraints = critical, CA:TRUE, pathlen:0
keyUsage = critical, keyCertSign, cRLSign
nameConstraints = permitted;DNS:internal.example.com, permitted;DNS:*.internal.example.com
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
EOF
|
Name Constraints 是构建安全 PKI 系统的重要工具,它提供了:
- 细粒度授权:限制子 CA 的签发范围
- 防御深度:即使某个 CA 被入侵,损失也限于指定范围
- 合规要求:满足某些行业标准的证书管理要求
在实际部署中,建议为每个子 CA 配置适当的名称约束,实现最小权限原则。
参考来源