在企业内网、测试环境或私有服务中,使用公共 CA 签发的证书不仅成本高昂,还可能带来安全风险。搭建私有 CA(Certificate Authority)可以完全掌控证书生命周期,实现内部服务的 HTTPS 加密和双向认证(mTLS)。本文将详细介绍如何使用 OpenSSL 搭建私有 CA 并签发内部证书。

什么是私有 CA

私有 CA 是组织内部自行搭建和维护的证书颁发机构,与 Let’s Encrypt、DigiCert 等公共 CA 类似,但不向外部公开。私有 CA 通常用于:

  • 内网 HTTPS:内部系统之间的安全通信
  • 开发测试:模拟生产环境的 HTTPS 流程
  • mTLS 双向认证:验证客户端和服务端双方身份
  • 物联网设备:无法访问公共 CA 的嵌入式设备

搭建私有 CA 架构

典型的私有 CA 采用两级结构:

  1. 根 CA(Root CA):信任的起点,长期有效(10-20 年),离线存储
  2. 颁发 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

最佳实践

  1. 根 CA 离线存储:签发完成后断开网络,长期存档
  2. 最小权限原则:不同服务使用不同的证书
  3. 证书有效期:终端证书不超过 1 年,颁发 CA 不超过 3 年
  4. 安全存储:私钥使用硬件安全模块(HSM)或加密存储
  5. 定期轮换:建立证书到期提醒机制
  6. 备份策略: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