4. CA搭建实战:从零开始搭一套私有CA
说实话,很多搞安全的同学对CA的理解都停留在「CA就是发证书的」这个层面。但真让你自己搭一套,很多人就懵了。我当年第一次搭CA的时候,也是踩了不少坑。今天咱们就手把手过一遍,把根CA和中间CA都搭起来。
4.1 准备工作:你需要什么
先说说环境。我习惯用Ubuntu 20.04/22.04 LTS,OpenSSL版本至少1.1.1以上。你拿CentOS也行,命令基本一样。
你需要准备:
- 一台Linux服务器(虚拟机就行)
- OpenSSL 1.1.1+
- 基本的文件目录结构
- 一颗耐心(这个最重要)
4.2 目录结构设计
我个人习惯把CA相关文件放在 /opt/ca 下。结构清晰,方便管理。
mkdir -p /opt/ca/{root-ca,intermediate-ca}
cd /opt/ca/root-ca
mkdir certs crl newcerts private
chmod 700 private
touch index.txt
echo 1000 > serial
解释一下这些目录的作用:
| 目录/文件 | 用途 |
|---|---|
certs/ |
存放已签发的证书 |
crl/ |
证书吊销列表 |
newcerts/ |
OpenSSL自动生成的证书副本 |
private/ |
CA私钥(权限必须700) |
index.txt |
证书数据库,记录已签发证书 |
serial |
下一个证书的序列号 |
private/ 目录权限一定要设为700。我曾经见过有人把私钥设成644,结果被同事拷走了……这种事出一次就够你喝一壶的。
4.3 配置OpenSSL主配置文件
OpenSSL的配置文件是核心。我一般直接改 /etc/ssl/openssl.cnf,或者复制一份到CA目录下。这里给个精简版:
# /opt/ca/root-ca/openssl.cnf
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = /opt/ca/root-ca
certs = $dir/certs
crl_dir = $dir/crl
new_certs_dir = $dir/newcerts
database = $dir/index.txt
serial = $dir/serial
RANDFILE = $dir/private/.rand
private_key = $dir/private/ca.key.pem
certificate = $dir/certs/ca.cert.pem
default_md = sha256
policy = policy_strict
[ policy_strict ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
default_bits = 4096
distinguished_name = req_distinguished_name
string_mask = utf8only
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
commonName = Common Name
emailAddress = Email Address
这里有个关键点:policy_strict 里的 match 表示根CA签发证书时,国家、省份、组织必须和根CA一致。这是安全要求,别乱改。
4.4 生成根CA密钥和证书
好,开始干正事。第一步,生成根CA的私钥:
cd /opt/ca/root-ca
openssl genrsa -aes256 -out private/ca.key.pem 4096
它会让你输一个密码。记住这个密码,丢了根密钥就废了。我习惯用密码管理器生成一个32位随机串,然后记在保险箱里。
然后生成根证书:
openssl req -config openssl.cnf \
-key private/ca.key.pem \
-new -x509 -days 7300 \
-sha256 -extensions v3_ca \
-out certs/ca.cert.pem
这里 -days 7300 是20年。根证书有效期长,但别设成永远,20年差不多了。
验证一下:
openssl x509 -noout -text -in certs/ca.cert.pem
看到 CA:TRUE 就对了。
4.5 搭建中间CA
根CA一般不直接签发服务器证书。为什么?你想想看,如果根密钥泄露了,整个信任链就完了。所以中间CA就是干这个活的——它替根CA干活,万一出事,吊销中间CA就行,根CA还能继续用。
先创建中间CA的目录结构:
cd /opt/ca/intermediate-ca
mkdir certs crl newcerts private csr
chmod 700 private
touch index.txt
echo 1000 > serial
中间CA的配置文件和根CA类似,但 policy 要宽松一些:
# /opt/ca/intermediate-ca/openssl.cnf
[ CA_default ]
dir = /opt/ca/intermediate-ca
# ... 其他路径类似,指向intermediate-ca目录
policy = policy_loose
[ policy_loose ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
生成中间CA的私钥和证书签名请求(CSR):
openssl genrsa -aes256 -out private/intermediate.key.pem 4096
openssl req -config openssl.cnf -new -sha256 \
-key private/intermediate.key.pem \
-out csr/intermediate.csr.pem
然后用根CA给中间CA的CSR签名:
cd /opt/ca/root-ca
openssl ca -config openssl.cnf -extensions v3_intermediate_ca \
-days 3650 -notext -md sha256 \
-in /opt/ca/intermediate-ca/csr/intermediate.csr.pem \
-out /opt/ca/intermediate-ca/certs/intermediate.cert.pem
这里 -days 3650 是10年。中间CA的有效期比根CA短,这是最佳实践。
4.6 验证证书链
证书签完了,得验证一下链是否完整:
openssl verify -CAfile /opt/ca/root-ca/certs/ca.cert.pem \
/opt/ca/intermediate-ca/certs/intermediate.cert.pem
看到 intermediate.cert.pem: OK 就说明链是通的。
把根证书和中间证书合并成一个链文件,后面给服务器用:
cat /opt/ca/intermediate-ca/certs/intermediate.cert.pem \
/opt/ca/root-ca/certs/ca.cert.pem > \
/opt/ca/intermediate-ca/certs/ca-chain.cert.pem
4.7 整体流程回顾
来,我画张图帮你理一理整个流程:
4.8 避坑指南
最后,分享几个我踩过的坑:
- 密钥权限:私钥文件一定要
chmod 400,目录chmod 700。我曾经图省事设成644,结果被扫描工具扫出来了。 - 密码管理:根CA的密码别用简单密码。我见过有人设成
123456……嗯,后来被审计抓了个典型。 - 时间同步:CA服务器必须启用NTP。证书有效期依赖时间,时间不准会导致证书验证失败。
- 备份策略:根CA的
private/目录要离线备份。我习惯每月刻一张光盘锁保险柜。
核心要点:
- 根CA离线,中间CA在线
- 私钥权限必须严格限制
- 证书链要完整验证
- 定期检查证书有效期