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 整体流程回顾

来,我画张图帮你理一理整个流程:

私有CA搭建与证书签发流程 根CA 自签名证书 + 根密钥 中间CA 由根CA签发 服务器证书 由中间CA签发 根CA:离线保存 私钥加密存储,仅在签发中间CA时使用 平时断网、锁保险柜 中间CA:在线服务 负责日常证书签发 即使泄露,可吊销并重新签发

4.8 避坑指南

最后,分享几个我踩过的坑:

  • 密钥权限:私钥文件一定要 chmod 400,目录 chmod 700。我曾经图省事设成644,结果被扫描工具扫出来了。
  • 密码管理:根CA的密码别用简单密码。我见过有人设成 123456……嗯,后来被审计抓了个典型。
  • 时间同步:CA服务器必须启用NTP。证书有效期依赖时间,时间不准会导致证书验证失败。
  • 备份策略:根CA的 private/ 目录要离线备份。我习惯每月刻一张光盘锁保险柜。

核心要点:

  • 根CA离线,中间CA在线
  • 私钥权限必须严格限制
  • 证书链要完整验证
  • 定期检查证书有效期