SAN(Subject Alternative Name) 是 SSL 标准 x509 中定义的一个扩展。使用了 SAN 字段的 SSL 证书,可以扩展此证书支持的域名,使得一个证书可以支持多个不同域名的解析。在OpenSSL中,通常通过配置`SubjectAltName字段实现, 可以包含email 地址,ip地址,正则匹配DNS主机名,等等。

首先,基于/etc/pki/tls/openssl.cnf创建一个临时配置文件, 并进行编辑。

cp /etc/pki/tls/openssl.cnf ~/tmp/openssl.cnf
vim ~/tmp/openssl.cnf

修改临时配置文件

#[ req ]标签下去掉注释
req_extetions = v3_req

#[ v3_req ]标签下修改subjectAltName
[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names

#在配置文件任意位置新建标签[ alt_names ]并添加下面的配置
[ alt_names ]
DNS.1 = *.example.cn
DNS.2 = www.example.com
DNS.3 = *.api.example.cn
DNS.4 = api.example.com
IP.1 = 192.168.1.1
IP.2 = 192.168.1.2

利用此配置文件生成多域名证书请求文件

openssl req -new -nodes -keyout server.key -out server.csr -config ~/tmp/openssl.cnf

查看证书请求的内容

openssl req -text -noout -in ustack.csr

可以看到此证书请求文件中会包含 Subject Alternative Names 字段,并包含之前在配置文件中填写的域名。

使用CA签发证书

openssl ca -policy policy_match -out server.crt -config ~/tmp/openssl.cnf -extensions v3_req -infiles server.csr

或者使用私钥签发证书

openssl x509 -req -days 3650 -in server.csr -signkey server.key
 -out server.crt -extensions v3_req -extfile ~/tmp/openssl.cnf

签署后查看证书内容

openssl x509 -text -noout -in server.crt

在实际使用时,可以将上面的命令分为两步:新建证书请求

openssl req -new -sha256 \
    -key server.key \
    -subj "/C=CN/ST=Hubei/L=Wuhan/O=Company/OU=Company/CN=*.example.com" \
    -reqexts SAN \
    -config <(cat /etc/pki/tls/openssl.cnf \
        <(printf "[SAN]\nsubjectAltName=DNS:*.example.cn,DNS:*.example.com")) \
    -out server.csr

其中,subj项可不要,在命令行提示时再填写。subj中各项的含义为:C  = Country; ST = State; L  = City; O  = Organization; OU = Organization Unit; CN = Common Name (证书所请求的域名); emailAddress = 证书管理员联系方式。

CA签发证书

openssl ca -in server.csr 
	-extensions SAN 	\
	-md sha256 \
	-keyfile ca.key \
	-cert ca.crt \
	-config <(cat /etc/pki/tls/openssl.cnf 
        <(printf "[SAN]\nsubjectAltName=DNS:*.example.cn,DNS:*.example.com")) \
	-out server.crt

注意:openssl默认要求服务器证书请求文件中的国家,省市要和CA证书一致,可在openssl.cnf中的[policy_match]标签下修改匹配策略。