Debian OpenSSL 搭建 CA 证书服务:签发、吊销与客户端信任
1. 服务介绍
CA(Certificate Authority,证书颁发机构)用于签发、验证和吊销数字证书。企业内网可以用自建 CA 为 HTTPS、LDAPS、SMTPS、VPN、域控及其他 TLS 服务签发证书,避免每台服务都依赖外部证书。客户端导入 CA 根证书后,便可验证由该 CA 签发的服务证书。
本文以 Debian 环境为例,完成 OpenSSL CA 初始化、生成根证书、签发服务证书、查看证书、吊销证书、生成吊销列表(CRL)和客户端信任配置。
2. 准备运行环境
• 操作系统:Debian 系 Linux,实验命令按 Debian 的 apt 方式执行。
• 操作账号:root,或具备 sudo 权限的管理员账号。
• 软件包:openssl、ca-certificates。
• 网络条件:CA 服务器、证书使用服务器和客户端之间网络可达;客户端 DNS、系统时间正常。
• 实验角色:CA 服务器负责签发和吊销证书,服务端生成私钥与 CSR,客户端导入 CA 根证书。
• 文件约定:本文使用 /CA 保存 CA 数据,使用 /tmp/tls-lab 保存服务端申请文件;生产环境应使用权限更严格的目录。
安装前确认系统版本和软件源:
bash
cat /etc/os-release
apt-get update
apt-get install -y openssl ca-certificates
openssl version -a
3. 相关知识
• **证书链**:客户端通常需要信任根证书;服务端证书中的 Issuer 应指向签发它的 CA,存在中间 CA 时还要正确提供中间证书。
• **私钥保护**:CA 私钥可以签发证书,权限应限制为 CA 管理账号可读,不能上传到公开仓库或直接发给客户端。
• **有效期与系统时间**:证书校验依赖客户端和服务端时间。时间偏差、证书过期或尚未生效,都会导致 TLS 校验失败。
• **SAN 优先**:现代客户端主要校验证书的 Subject Alternative Name(SAN),不能只填写 CN。为域名和 IP 使用证书时,应把实际访问名称写入 SAN。
• **序列号和索引**:CA 使用 serial 分配证书序列号,index.txt 记录已签发证书。删除或手工修改这些文件,可能导致后续签发和吊销失败。
• **吊销与 CRL**:吊销证书后,需要重新生成 CRL,并让使用方能获取或加载最新 CRL;仅执行吊销命令,不代表所有客户端立即完成吊销检查。
• **配置文件路径**:Debian 默认配置常见于 /etc/ssl/openssl.cnf。复制到 /CA/openssl.cnf 后,应同步检查 [ CA_default ] 中的 dir、database、certificate、private_key 等路径。
4. 实验步骤
4.1 初始化 CA 目录
创建 CA 数据目录、索引文件和序列号文件:
bash
mkdir -p /CA/{certs,crl,newcerts,private,csr}
touch /CA/index.txt
echo 1000 > /CA/serial
echo 1000 > /CA/crlnumber
chmod 700 /CA/private
cp -f /etc/ssl/openssl.cnf /CA/openssl.cnf
修改配置文件中的 CA 路径,使配置与实验目录一致:
bash
vim /CA/openssl.cnf

4.2 设置 CA 路径和基础文件
检查 CA 配置中以下路径是否指向 /CA:
ini
[ CA_default ]
dir = /CA
database = $dir/index.txt
new_certs_dir = $dir/newcerts
certificate = $dir/cacert.pem
serial = $dir/serial
crlnumber = $dir/crlnumber
crl = $dir/crl.pem
private_key = $dir/private/cakey.pem

再次确认 CA 数据目录和证书保存路径:
bash
ls -ld /CA /CA/private /CA/newcerts
ls -l /CA/index.txt /CA/serial /CA/crlnumber



4.3 生成 CA 私钥和根证书
CA 私钥是整个信任链的核心。生成后限制文件权限:
bash
openssl genrsa -out /CA/private/cakey.pem 2048
chmod 600 /CA/private/cakey.pem

使用 CA 私钥生成自签名根证书。-days 3650 表示有效期约十年,生产环境应按安全策略设置:
bash
openssl req -new -x509 \
-key /CA/private/cakey.pem \
-sha256 -days 3650 \
-out /CA/cacert.pem \
-config /CA/openssl.cnf

也可以在交互式命令中显式指定主题信息:
bash
openssl req -new -x509 \
-key /CA/private/cakey.pem \
-out /CA/cacert.pem \
-days 3650 -sha256

检查根证书文件和权限:
bash
ls -l /CA/cacert.pem /CA/private/cakey.pem
openssl x509 -in /CA/cacert.pem -noout -subject -issuer -dates
4.4 服务端生成私钥和证书申请文件
在服务端创建申请目录,私钥只保留在服务端:
bash
mkdir -p /tmp/tls-lab
cd /tmp/tls-lab
openssl genrsa -out server.key 2048
chmod 600 server.key

生成 CSR。CN 应填写主要访问名称,生产环境还应在配置中加入 SAN:
bash
openssl req -new \
-key server.key \
-out server.csr \
-config /CA/openssl.cnf

也可以直接指定主题,适合实验环境快速生成:
bash
openssl req -new -key server.key -out server.csr \
-subj "/C=CN/ST=Beijing/L=Beijing/O=Example/OU=IT/CN=server.example.com"

CA 与服务端申请信息应按实验要求填写。若国家、组织或域名不同,应检查 OpenSSL 配置中的默认值和 SAN 配置:
bash
openssl req -in server.csr -noout -subject -text


4.5 CA 签发服务端证书
把 server.csr 传到 CA 服务器后,在 CA 服务器执行签名。实验环境可使用 openssl x509:
bash
openssl x509 -req -in /tmp/tls-lab/server.csr \
-CA /CA/cacert.pem \
-CAkey /CA/private/cakey.pem \
-CAcreateserial \
-out /tmp/tls-lab/server.crt \
-days 365 -sha256

若需要由 CA 索引文件统一管理签发记录,可使用 openssl ca:
bash
openssl ca -config /CA/openssl.cnf \
-in /tmp/tls-lab/server.csr \
-out /tmp/tls-lab/server.crt \
-days 365 -batch

签发完成后,将 server.crt 和 CA 根证书分别放到服务端、客户端要求的位置;服务端私钥不能随证书申请文件一起公开分发:
bash
cp /tmp/tls-lab/server.crt /etc/ssl/certs/server.crt
cp /CA/cacert.pem /etc/ssl/certs/ca-cert.pem
chmod 644 /etc/ssl/certs/server.crt /etc/ssl/certs/ca-cert.pem

4.6 查看证书详细信息
查看证书主题、签发者、有效期、序列号和扩展项:
bash
openssl x509 -in /tmp/tls-lab/server.crt -noout -text
openssl x509 -in /tmp/tls-lab/server.crt \
-noout -serial -subject -issuer -dates

4.7 吊销证书并生成 CRL
确认需要吊销的证书序列号,再执行吊销操作。先备份 CA 索引文件:
bash
cp -a /CA/index.txt /CA/index.txt.bak
openssl ca -config /CA/openssl.cnf \
-revoke /tmp/tls-lab/server.crt

吊销前查看证书内容,核对主题和序列号,避免吊销错误证书:
bash
openssl x509 -in /tmp/tls-lab/server.crt \
-noout -serial -subject -issuer

生成最新 CRL:
bash
openssl ca -config /CA/openssl.cnf \
-gencrl -out /CA/crl.pem
chmod 644 /CA/crl.pem


查看已吊销证书:
bash
openssl crl -in /CA/crl.pem -noout -text

4.8 配置客户端信任 CA
把 CA 根证书复制到客户端的信任目录。Debian 系客户端执行以下命令:
bash
cp /path/to/cacert.pem /usr/local/share/ca-certificates/lab-ca.crt
update-ca-certificates

确认系统信任库已生成 CA 链接:
bash
ls -l /etc/ssl/certs | grep lab-ca
openssl verify -CApath /etc/ssl/certs /tmp/tls-lab/server.crt

5. 验证结果
按 CA、证书链和实际 TLS 服务分别验证:
bash
openssl x509 -in /CA/cacert.pem -noout -text
openssl x509 -in /tmp/tls-lab/server.crt \
-noout -dates -issuer -subject
openssl verify -CAfile /CA/cacert.pem /tmp/tls-lab/server.crt
openssl crl -in /CA/crl.pem -noout -text
如果证书链验证成功,说明签发关系正确;如果服务已启用 TLS,再从客户端检查服务端实际返回的证书:
bash
openssl s_client -connect 127.0.0.1:443 \
-servername server.example.com \
-CAfile /etc/ssl/certs/ca-certificates.crt \
</dev/null 2>/dev/null | grep -E "Verify return code|subject=|issuer="
重点检查:
• Verify return code: 0 (ok)。
• 证书 Not Before、Not After 覆盖当前时间。
• subjectAltName 包含客户端实际访问的域名或 IP。
• issuer 指向预期 CA,客户端信任库包含 CA 根证书。
• 吊销后的证书已出现在 CRL,服务和客户端按策略加载最新吊销列表。
6. 常见问题
• unable to get local issuer certificate:客户端缺少根证书或中间证书,先检查信任库和服务端证书链。
• certificate verify failed:检查系统时间、证书有效期、域名/SAN 和 CA 文件路径。
• openssl ca 报数据库或序列号错误:检查 /CA/index.txt、/CA/serial、/CA/crlnumber,不要随意删除生产 CA 数据。
• 私钥权限过宽:将 CA 私钥和服务端私钥权限收紧,并限制备份文件访问范围。