在企业内网、测试环境或私有服务中,使用公共 CA 签发的证书不仅成本高昂,还可能带来安全风险。搭建私有 CA(Certificate Authority)可以完全掌控证书生命周期,实现内部服务的 HTTPS 加密和双向认证(mTLS)。本文将详细介绍如何使用 OpenSSL 搭建私有 CA 并签发内部证书。
什么是私有 CA#
私有 CA 是组织内部自行搭建和维护的证书颁发机构,与 Let’s Encrypt、DigiCert 等公共 CA 类似,但不向外部公开。私有 CA 通常用于:
- 内网 HTTPS:内部系统之间的安全通信
- 开发测试:模拟生产环境的 HTTPS 流程
- mTLS 双向认证:验证客户端和服务端双方身份
- 物联网设备:无法访问公共 CA 的嵌入式设备
搭建私有 CA 架构#
典型的私有 CA 采用两级结构:
- 根 CA(Root CA):信任的起点,长期有效(10-20 年),离线存储
- 颁发 CA(Issuing CA):实际签发终端证书,有效期较短(1-3 年)
这种设计更安全:根 CA 离线保存,日常签发由颁发 CA 完成,泄露风险更低。
创建根 CA#
根 CA 是整个 PKI 体系的信任根基,需要妥善保管。
1. 生成根 CA 私钥#
1
|
openssl genrsa -out root-ca.key 4096
|
生成 4096 位 RSA 私钥。私钥必须严格保密,建议设置文件权限为 600。
2. 自签名生成根 CA 证书#
1
2
3
|
openssl req -x509 -new -nodes -key root-ca.key -sha256 -days 825 \
-out root-ca.crt \
-subj "/C=CN/ST=Beijing/L=Beijing/O=SecDoc Internal CA/CN=SecDoc Root CA"
|
-days 825:约 2.27 年,这是 iOS 要求的最长有效期
-sha256:使用 SHA-256 签名算法
-nodes:私钥不加密(生产环境建议加密)
查看证书信息:
1
|
openssl x509 -in root-ca.crt -noout -subject -issuer -dates
|
输出示例:
1
2
3
4
|
subject=C = CN, ST = Beijing, L = Beijing, O = SecDoc Internal CA, CN = SecDoc Root CA
issuer=C = CN, ST = Beijing, L = Beijing, O = SecDoc Internal CA, CN = SecDoc Root CA
notBefore=May 1 16:05:44 2026 GMT
notAfter=Aug 3 16:05:44 2028 GMT
|
创建颁发 CA#
颁发 CA 由根 CA 签发,负责日常的证书签发工作。
1. 生成颁发 CA 私钥#
1
|
openssl genrsa -out intermediate-ca.key 4096
|
2. 创建配置文件#
创建 intermediate-ca.cnf 文件,定义证书扩展:
1
2
3
4
5
6
7
|
[ca]
subject_key_identifier = hash
authority_key_identifier = keyid:always
[v3_ca]
keyUsage = critical, keyCertSign, cRLSign
basicConstraints = critical, CA:TRUE, pathlen:0
|
keyUsage:允许签发证书和 CRL
basicConstraints:CA:TRUE 表示这是 CA 证书,pathlen:0 禁止再向下级联
3. 生成 CSR 并签发#
1
2
3
4
5
6
7
8
9
|
# 生成 CSR
openssl req -new -key intermediate-ca.key \
-out intermediate-ca.csr \
-subj "/C=CN/ST=Beijing/L=Beijing/O=SecDoc Internal CA/CN=SecDoc Issuing CA"
# 用根 CA 签发
openssl x509 -req -in intermediate-ca.csr -CA root-ca.crt -CAkey root-ca.key \
-CAcreateserial -out intermediate-ca.crt -days 400 -sha256 \
-extfile intermediate-ca.cnf -extensions v3_ca
|
验证颁发 CA 证书:
1
|
openssl x509 -in intermediate-ca.crt -noout -subject -issuer
|
输出:
1
2
|
subject=C = CN, ST=Beijing, L=Beijing, O=SecDoc Internal CA, CN=SecDoc Issuing CA
issuer=C = CN, ST=Beijing, L=Beijing, O=SecDoc Internal CA, CN=SecDoc Root CA
|
签发终端证书#
以签发一个内部服务器证书为例。
1. 生成服务器私钥和 CSR#
1
2
3
4
5
6
7
|
# 生成私钥
openssl genrsa -out server.key 2048
# 生成 CSR
openssl req -new -key server.key \
-out server.csr \
-subj "/C=CN/ST=Beijing/L=Beijing/O=Example Inc/CN=example.internal"
|
2. 创建证书配置文件#
创建 server.cnf 文件:
1
2
3
4
5
6
7
8
9
10
|
[server]
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = example.internal
DNS.2 = www.example.internal
IP.1 = 10.0.0.1
|
关键字段说明:
CA:FALSE:表示这是终端证书,不能再签发其他证书
serverAuth:用于服务器认证(TLS 服务器证书)
subjectAltName:SAN 扩展,现代浏览器强制要求
3. 签发证书#
1
2
3
|
openssl x509 -req -in server.csr -CA intermediate-ca.crt -CAkey intermediate-ca.key \
-CAcreateserial -out server.crt -days 365 -sha256 \
-extfile server.cnf -extensions server
|
查看证书信息:
1
|
openssl x509 -in server.crt -noout -subject -issuer -dates -serial
|
4. 验证证书链#
1
2
3
4
5
|
# 构建证书链(服务器证书 + 颁发 CA)
cat server.crt intermediate-ca.crt > server-chain.crt
# 验证证书链
openssl verify -CAfile root-ca.crt -untrusted intermediate-ca.crt server.crt
|
输出 server.crt: OK 表示验证通过。
导出与部署#
导出 PEM 格式(推荐)#
1
2
3
4
5
6
7
8
|
# 服务器证书 + 私钥(用于 Nginx/Apache)
cat server.crt server.key > server.pem
# 完整证书链
cat server.crt intermediate-ca.crt root-ca.crt > server-full-chain.pem
# CA 证书 bundle
cat intermediate-ca.crt root-ca.crt > ca-bundle.crt
|
导出 PKCS#12 格式(用于 Java / Windows)#
1
2
3
|
openssl pkcs12 -export -out server.p12 \
-inkey server.key -in server.crt \
-certfile root-ca.crt
|
需要输入密码,后续在 Java 中使用:
1
2
|
keytool -importkeystore -srckeystore server.p12 -srcstoretype PKCS12 \
-destkeystore keystore.jks -deststoretype JKS
|
分发与信任#
客户端需要信任私有 CA 证书才能验证通过。
Linux#
1
2
3
|
# 复制到系统 CA 目录
sudo cp root-ca.crt /usr/local/share/ca-certificates/secdoc-root-ca.crt
sudo update-ca-certificates
|
macOS#
1
2
|
# 添加到系统钥匙串(需要 root 权限)
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain root-ca.crt
|
Windows#
1
2
|
# 导入到受信任的根证书颁发机构
Import-Certificate -FilePath root-ca.crt -CertStoreLocation Cert:\LocalMachine\Root
|
Firefox#
Firefox 使用自己的证书存储,需要在浏览器设置中手动导入。
证书吊销与 CRL#
当私钥泄露或证书不再需要时,需要吊销证书。
1. 吊销证书#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
# 创建吊销列表配置
cat > crl.cnf << 'EOF'
[ca]
default_ca = CA_default
[CA_default]
database = index.txt
new_certs_dir = .
serial = serial
crl_dir = .
crlnumber = crlnumber
crl = crl.pem
default_md = sha256
default_crl_days = 30
EOF
touch index.txt
echo "01" > serial
echo "01" > crlnumber
# 吊销证书
openssl ca -revoke server.crt -config crl.cnf -keyfile root-ca.key -cert root-ca.crt
|
2. 生成 CRL#
1
|
openssl ca -gencrl -config crl.cnf -keyfile root-ca.key -cert root-ca.crt -out crl.pem
|
3. 验证吊销状态#
1
|
openssl verify -CAfile root-ca.crt -crl_check -crlfile crl.pem server.crt
|
最佳实践#
- 根 CA 离线存储:签发完成后断开网络,长期存档
- 最小权限原则:不同服务使用不同的证书
- 证书有效期:终端证书不超过 1 年,颁发 CA 不超过 3 年
- 安全存储:私钥使用硬件安全模块(HSM)或加密存储
- 定期轮换:建立证书到期提醒机制
- 备份策略:CA 密钥和证书定期备份,异地存储
私有 CA 是企业内网安全的基石。通过本文的操作流程,你可以快速搭建完整的 PKI 体系,为内网服务提供 HTTPS 加密和 mTLS 双向认证能力。关键在于严格管理根 CA 的密钥,仅在必要时使用颁发 CA 签发证书,并建立完善的证书吊销和更新机制。
参考来源#
- OpenSSL 官方文档:https://www.openssl.org/docs/
- Mozilla SSL Configuration Generator:https://ssl-config.mozilla.org/
- RFC 5280 - X.509 PKI:https://datatracker.ietf.org/doc/html/rfc5280