使用 OpenSSL 建立私有 CA:3 使用者證書

sparkdev發表於2019-02-20

OpenSSL 建立私有 CA 三部曲:
使用 OpenSSL 建立私有 CA:1 根證書
使用 OpenSSL 建立私有 CA:2 中間證書
使用 OpenSSL 建立私有 CA:3 使用者證書

在前文《使用 OpenSSL 建立私有 CA:2 中間證書》中我們介紹瞭如何建立中間證書,並生成證書鏈。本文我們將介紹如何為應用生成使用者證書(web 站點的 ssl 證書),並把證書部署到應用伺服器上和客戶端上。說明:本系列文章的演示環境為 Ubuntu 18.04,OpenSSL 的版本為 1.1.0g。

目標

為區域網中的站點 bigxa 建立 ssl 證書並部署。

準備使用者證書的配置檔案

在 myca 目錄下建立 bigxa 目錄,然後建立配置檔案 bigxa/bigxa.cnf,編輯其內容如下:

# OpenSSL to generate a certificate signing requests(csr) configuration file.
# v1

[ req ]
# Options for the `req` tool (`man req`).
# use prompt config control user interactive
prompt = no
input_password = 123456

default_bits        = 2048
distinguished_name  = req_distinguished_name
string_mask         = utf8only

# SHA-1 is deprecated, so use SHA-2 instead.
default_md          = sha256

# Extension to add when the -x509 option is used.
#x509_extensions     = v3_ca
req_extensions     = v3_req

[ req_distinguished_name ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
countryName                     = CN
stateOrProvinceName             = ShaanXi
localityName                    = Xian
organizationName                = PowerCity Ltd
organizationalUnitName          = Star
commonName = bigxa
emailAddress                    = ljfpower@163.com

[ v3_req ]
subjectAltName = DNS:bigxa

該配置檔案主要通過 [ req_distinguished_name ] 段來設定證書的資訊,請注意 [ v3_req ] 段中的 subjectAltName 資訊,如果你為區域網中的 IP 地址生成 https 證書,就必須要設定 subjectAltName。

建立祕鑰

進入 bigxa 目錄:

$ cd bigxa 

建立目錄 private csr certs:

$ mkdir private csr certs

執行下面的命令重建私鑰:

$ openssl genrsa -out private/bigxa.key.pem 2048

注意,這裡我們沒有使用 -aes256 選項,這樣建立的祕鑰不包含密碼。如果要建立 web 伺服器用的 ssl 證書,一定不要為祕鑰設定密碼!否則在每次重啟 web 服務的時候都需要輸入密碼!同樣也把祕鑰的許可權設定為 400:

$ chmod 400 private/bigxa.key.pem

此時當前目錄為 myca/bigxa。

建立 Certificate Signing Requests(csr)

對於建立站點的 https 型別的證書,必須在配置檔案中設定  Common Name 為 fully qualified domain name(也就是 網站的域名,或者是區域網中的機器名或 IP)。我們的 web 伺服器機器名為 bigxa,所以在配置檔案中設定 Common Name 為 bigxa,同時設定 subjectAltName 為 DNS:bigxa。注意,Common Name 不能與根 CA 和中間 CA 的 Common Name 相同。

使用下面的命令生成 csr:

$ openssl req -config bigxa.cnf \
    -key private/bigxa.key.pem \
    -new -sha256 \
    -out csr/bigxa.csr.pem

用下面的命令來驗證已經生成的 csr:

$ openssl req -text -noout -in csr/bigxa.csr.pem

注意確認下圖中的關鍵資訊 CN = bigxa:

還有 Subject Alternative Name:

建立使用者證書

因為我們在 powerca.cnf 中新增了 copy_extensions   = copy,所以在使用 csr 生成使用者證書時可以直接使用中間證書的配置檔案(powerca/powerca.cnf)而不用修改。下面先回到 myca 目錄下,然後生成使用者證書:

$ cd ..
$ openssl ca -config powerca/powerca.cnf \
    -extensions server_cert -days 1000 -notext -md sha256 \
    -in bigxa/csr/bigxa.csr.pem \
    -out bigxa/certs/bigxa.cert.pem

這次輸入的密碼為 powerca 祕鑰的保護密碼:123456。
如果發生 "TXT_DB error number 2" 的錯誤,把 powerca/db/index 檔案中相同名稱的記錄刪除即可。這個檔案是 OpenSSL CA 工具儲存資料的資料庫:

證書生成後我們把它的許可權修改為 444:

$ chmod 444 bigxa/certs/bigxa.cert.pem

驗證證書

先通過下面的命令來驗證使用者證書中的基本資訊:

$ openssl x509 -text -in bigxa/certs/bigxa.cert.pem -noout

圖中顯示證書頒發機構為 NickLi Power CA,可用日期為 2018-11-27 至 2021-8-23 號,證書的 Common Name 為 bigxa。還有一些 X509 協議相關的資訊:

CA:FALSE 表示該證書不能用作中間證書了,SSL Server 表示該證書可以用來支援 HTTPS 協議,最後確認 Subject Alternative Name 為:DNS:bigxa。
最後通過下面的命令驗證證書的合法性:

$ openssl verify -CAfile powerca/certs/powerca-chain.cert.pem bigxa/certs/bigxa.cert.pem

自動建立使用者證書

如果手動建立每個使用者證書還是挺繁瑣的,我們可以把這個過程自動化掉。在 myca 目錄下建立 usercert 目錄:

$ mkdir usercert

把 bigxa/bigxa.cnf 拷貝到 usercert 目錄下:

$ cp bigxa/bigxa.cnf usercert/usercert.csr.cnf

在 usercert 目錄下建立 private csr certs 三個目錄:

$ mkdir usercert/{private,csr,certs}

然後在 myca 目錄下建立指令碼檔案 certhelper.sh,編輯其內容如下:

#!/bin/bash
# ./certhelper.sh yourhostname
# if hostname is IP, should add the second paramerter "ip"
# ./certhelper.sh 10.3.2.33 ip

set -ex
# demo: check string is empty
if [ -z "$1" ]; then
    echo the first parameter is empty.
    echo plese add hostname as parameter
    exit 2
fi
cname="$1"
ctype="DNS"

if [ ! -z "$2" ]; then
    if [ "$2" = "ip" ]; then
        ctype="IP"
    fi  
fi

sed -i "s/^commonName.*/commonName = ${cname}/g" usercert/usercert.csr.cnf
sed -i "s/^subjectAltName.*/subjectAltName = ${ctype}:${cname}/g" usercert/usercert.csr.cnf

openssl genrsa -out usercert/private/${cname}.key.pem 2048
chmod 400 usercert/private/${cname}.key.pem

openssl req -config usercert/usercert.csr.cnf \
    -key usercert/private/${cname}.key.pem \
    -new -sha256 \
    -out usercert/csr/${cname}.csr.pem

openssl ca -batch -config powerca/powerca.cnf \
    -passin pass:123456 \
    -extensions server_cert -days 3000 -notext -md sha256 \
    -in usercert/csr/${cname}.csr.pem \
    -out usercert/certs/${cname}.cert.pem

openssl x509 -noout -text -in usercert/certs/${cname}.cert.pem
openssl verify -CAfile powerca/certs/powerca-chain.cert.pem usercert/certs/${cname}.cert.pem

cat usercert/certs/${cname}.cert.pem usercert/private/${cname}.key.pem > /tmp/temp.${cname}.certkey.pem
cat /tmp/temp.${cname}.certkey.pem powerca/certs/powerca-chain.cert.pem > usercert/${cname}.ha.pem

然後在 myca 目錄下執行該指令碼就可以了:

$ ./certhelper.sh bigxa
$ ./certhelper.sh 10.32.2.22 ip

生成的證書會儲存在 usercert 目錄下。

把證書部署到 web 伺服器

為了建立 HTTPS 站點,我們需要為 web 伺服器 bigxa 配置 ssl 證書。所需的檔案為 powerca-chain.cert.pem、bigxa.key.pem 和 bigxa.cert.pem。筆者的站點通過 HAProxy 做了負載均衡,所以在 HAProxy 的配置中新增 SSL 證書就可以了。具體的做法是通過下面的命令合成 HAProxy 所需的證書檔案:

$ cat bigxa/certs/bigxa.cert.pem bigxa/private/bigxa.key.pem > bigxa/temp.certkey.pem
$ cat bigxa/temp.certkey.pem powerca/certs/powerca-chain.cert.pem > bigxa/bigxa.ha.pem

把 bigxa.ha.pem 放置在 bigxa 機器上的 /etc/ssl/private/ 目錄中,所有者和組都設定為 haproxy。最後在 HAProxy 的配置檔案 /etc/haproxy/haproxy.cfg 中設定 ssl 證書的路徑:

bind *:443 ssl crt /etc/ssl/private/usercert.ha.pem

這樣 web 伺服器端的配置就完成了。

把證書鏈安裝到客戶端

Firefox 支援直接匯入 pem 格式的證書鏈,直接匯入這個檔案就可以了。但是 windows 中需要使用 p12(pfx) 等格式,需要把 powerca-chain.cert.p12 安裝到信任的根證書列表中,然後 IE 和 chrome 就可以正常識別到根證書了。

總結

本系列文章主要介紹如何在區域網中建立私有 CA,並用來頒發內網中使用的數字證書。內容以操作步驟為主,目的是讓朋友們拷貝了就能立即使用。如果要了解數字證書的理論知識以及相關概念,建議閱讀更專業的資料。

參考:
OpenSSL Certificate Authority
《openssl-cookbook》

相關文章