工作以后,旅行除了缓解工作 PTSD 症状,还有了另一层意义:检验自己作为一个社会人的社会功能是否还正常,避免和社会生活脱节。


  • 🎯 打造私有 CA,Part 1:手搓根 CA
  • 打造私有 CA,Part 2:手搓子 CA、签发服务证书

随着国内对安全越来越重视(整活越来越多),即使是企业内网的在线服务,也对 HTTPS 有了强烈的需求。HTTPS 的两个主要任务是验证通信端身份、提供安全传输通道,其中身份的验证依赖于 PKI 体系(背景知识请参考前面一篇博文 Web 安全,Part 1:PKI 扫盲),简单来说,就是依赖于证书,公认的权威可信机构颁发的证书就是互联网世界的合法身份,但这个证书通常需要 💰。

除了找权威机构申请正式证书,如果不需要在互联网上公开受信,也可以自己生成,自己生成的证书在操作系统和浏览器中没有信任锚点,没有权威第三方背书,默认情况下是不受信任的。

对于内网,企业能去购买有公信力的证书固然好(人傻钱多?🤔),但对于自己能控制的环境,如果执着于使用公网受信的证书,也有点杀鸡用牛刀。企业的内网环境,主要还是开发、测试、辅助办公应用,随着这几年 RESTful 风格接口的流行,采用 http 协议的场景也越来越多,有了 http,那下一步走向 https 也就是顺理成章的事 —— 早做准备不吃亏。

如果选择自己提供证书,有两种选择:

  • 自签名证书(使用自己的私钥签名的证书)
  • 使用私有 CA 签名证书(使用 CA 的私钥签名的证书,当然私有根 CA 的证书一定是自签名证书)

对于企业来说,如果选择一事一议,每次生成一个自签名证书,因为系统的建设、管理、维保、运维的方式各异,建设、管理、维保、运维的人员也各不相同,这样的作法会导致混乱,难以进行有效管理,并且存在填补微观层面安全漏洞的同时又引入一个体系层面的漏洞,很难说哪个风险更大。

更好的做法是搭建一套私有 CA,私有 CA 的好处有以下几点:

  • 在各种操作系统/浏览器环境中一次性下好信任锚(CA 根证书),以后私有 CA 签出的任何证书都不必再在客户端重新执行受信操作;
  • 信任完全受企业自己控制;
  • 让零散的工作进入企业的工作视野,避免推诿或遗漏;
  • 便于对证书进行统一管理(如签发/吊销证书),消灭漏网之鱼,消除混乱;
  • 便于对证书操作动作进行标准化和自动化,降低操作风险和相关人员心智负担;
  • 更好地顺应企业、行业,甚至国家的发展趋势。

下面我们就使用 OpenSSL 来搭建一套 mini Private CA,我的本地环境是 Fedora Workstation 36。

1、准备相关路径

mkdir root-ca
cd root-ca
mkdir certs db private
chmod 700 private
touch db/index
echo 1001 > db/serial
echo 1001 > db/crlnumber
touch root-ca.conf

2、根 CA 配置文件 root-ca.conf

# 定义一些接下来的配置里用到的变量
[default]
name          = root-ca
domain_suffix = example.com
aia_url       = http://$name.$domain_suffix/$name.crt
crl_url       = http://$name.$domain_suffix/$name.crl
ocsp_url      = http://ocsp.$name.$domain_suffix:9080
default_ca    = ca_default
name_opt      = utf8,esc_ctrl,multiline,lname,align

# CA 的 DN 名
[ca_dn]
countryName       = "GB"
organizationName  = "Example"
commonName        = "Root CA"

# CA 的关键配置项
[ca_default]
home              = .
database          = $home/db/index
serial            = $home/db/serial
crlnumber         = $home/db/crlnumber
certificate       = $home/$name.crt
private_key       = $home/private/$name.key
RANDFILE          = $home/private/random
new_certs_dir     = $home/certs
unique_subject    = no
copy_extensions   = none
default_days      = 3650
default_crl_days  = 365
default_md        = sha256
policy            = policy_c_o_match

# 字段要求
[policy_c_o_match]
countryName             = match
stateOrProvinceName     = optional
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

# 生成 CA 自己的自签名证书请求的配置项
[req]
default_bits        = 4096
encrypt_key         = yes
default_md          = sha256
utf8                = yes
string_mask         = utf8only
prompt              = no
distinguished_name  = ca_dn
req_extensions      = ca_ext

[ca_ext]
basicConstraints      = critical,CA:true
keyUsage              = critical,keyCertSign,cRLSign
subjectKeyIdentifier  = hash

# 用于签发子 CA 证书
[sub_ca_ext]
authorityInfoAccess     = @issuer_info
authorityKeyIdentifier  = keyid:always
basicConstraints        = critical,CA:true,pathlen:0
crlDistributionPoints   = @crl_info
extendedKeyUsage        = clientAuth,serverAuth
keyUsage                = critical,keyCertSign,cRLSign
nameConstraints         = @name_constraints
subjectKeyIdentifier    = hash

[crl_info]
URI.0 = $crl_url

[issuer_info]
caIssuers;URI.0 = $aia_url
OCSP;URI.0      = $ocsp_url

# 限制 CA 可用于的域名
[name_constraints]
permitted;DNS.0=example.com
permitted;DNS.1=example.org
excluded;IP.0=0.0.0.0/0.0.0.0
excluded;IP.1=0:0:0:0:0:0:0:0/0:0:0:0:0:0:0:0

# OCSP 证书的一些关键配置
[ocsp_ext]
authorityKeyIdentifier  = keyid:always
basicConstraints        = critical,CA:false
extendedKeyUsage        = OCSPSigning
keyUsage                = critical,digitalSignature
subjectKeyIdentifier    = hash

3、生成根 CA 私钥和证书请求

openssl req -new \
  -config root-ca.conf \
  -out root-ca.csr \
  -keyout private/root-ca.key

4、生成自签名根 CA 证书

openssl ca -selfsign \
  -config root-ca.conf \
  -in root-ca.csr \
  -out root-ca.crt \
  -extensions ca_ext

5、生成 CRL

CRLCertificate Revocation List)就是证书吊销列表。

openssl ca -gencrl \
  -config root-ca.conf \
  -out root-ca.crl

试试吊销 1002 证书

openssl ca \
  -config root-ca.conf \
  -revoke certs/1002.pem \
  -crl_reason keyCompromise

6、签发 OCSP 服务证书

生成 OCSPOnline Certificate Status Protocol)服务的私钥和证书请求

openssl req -new \
  -newkey rsa:2048 \
  -subj "/C=GB/O=Example/CN=OCSP Root Responder" \
  -keyout private/root-ocsp.key \
  -out root-ocsp.csr

使用根 CA 证书签发 OCSP 证书

openssl ca \
  -config root-ca.conf \
  -in root-ocsp.csr \
  -out root-ocsp.crt \
  -extensions ocsp_ext \
  -days 365

7、验证 OCSP 功能

用 openssl 直接起一个 OCSP 监听服务

openssl ocsp \
  -port 9080 \
  -index db/index \
  -rsigner root-ocsp.crt \
  -rkey private/root-ocsp.key \
  -CA root-ca.crt \
  -text

发起一个证书验证请求,验证 root-ocsp.crt 证书状态

openssl ocsp \
  -issuer root-ca.crt \
  -cert root-ocsp.crt \
  -VAfile root-ocsp.crt \
  -url http://127.0.0.1:9080

现在有了根 CA,下一篇就基于根 CA 创建子 CA,并使用子 CA 来签发实际的服务证书,如网站证书。


Reference:


0 条评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注