免费证书有免费证书的麻烦(有效期),付费证书有付费证书的缺点(需要资金)。
由于并不是任何时候都需要去找证书颁发机构购买数字证书,所以合理使用自签名证书(比如测试或者非公开环境)有时候也是一种可行的替代选择。
准备工作
- Windows 10 WSL Ubuntu 16.04
- OpenSSL
如果没有安装过 OpenSSL,只需要运行一下命令sudo apt install openssl
。
生成 CA 根证书
这一步需要做的是:
- 生成用于 CA 根证书的私钥
- 生成 CA 根证书(公钥)
生成证书的过程中程序会询问国家C
、州或省ST
、城市L
、组织O
之等信息,重要的是通用名Common Name
/CN
,这个填要签发证书的主域名 example.com
。
既然是自签证书,为了实现一劳永逸有效期自然越长越好,所以设置成 7305 天也就是 20 年。
至于为什么生成 ECC 证书不用 RSA 证书……体积小速度快,而且反正不是对外使用不需要考虑兼容性。
命令如下:
mkdir ca && cd ca
openssl ecparam -genkey -name prime256v1 -out ca.key
openssl req -new -x509 -days 7305 -key ca.key -out ca.crt
生成泛域名证书的签名请求
这一步需要做的是:
- 生成用于泛域名证书的私钥
- 生成证书签名请求(CSR)
生成 CSR 时会被询问同样的信息,操作方法相同。
命令如下:
openssl ecparam -genkey -name prime256v1 -out example.com.key
openssl req -new -sha256 -key example.com.key -out example.com.csr
使用 CA 根证书对泛域名证书签名
这一步需要做的是:
- 对泛域名证书签名
- 将 CA 根证书与泛域名证书合并成 fullchain 证书
新建 extended.ext
文件,最后一行的 subjectAltName
字段为证书的主域名+泛域名。
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
req_extensions = san
extensions = san
[ req_distinguished_name ]
countryName = JP
stateOrProvinceName = Chiba
localityName = Futtsu
[ SAN ]
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = DNS:example.com,DNS:*.example.com
使用这个 extended.ext
文件执行签名,有效期同样设成了 20 年。
openssl x509 -req \
-days 7305 \
-sha256 \
-CA ca.crt -CAkey ca.key -CAcreateserial \
-in example.com.csr -out cert.crt \
-extfile extended.ext -extensions SAN
最后将泛域名证书 cert.crt
与根证书 ca.crt
合并为 fullchain 证书。
cat cert.crt ca.crt > fullchain.crt
Nginx 部署
到此为止已经得到了需要的三个文件:
- example.com.key
- cert.crt
- fullchain.crt
当然生成证书仅仅是一项准备工作,将证书导出然后部署到服务器上才能发挥作用。为 Nginx 配置自签名证书的配置文件需要这样修改:
listen 443 ssl;
ssl_certificate /path/to/cert.crt;
ssl_certificate_key /path/to/example.com.key;
ssl_trusted_certificate /path/to/fullchain.crt;
根据需要可能还要写 http 跳转为 https 的配置,不过相较于为 Nginx 部署一般的证书没什么特殊区别。
参考来源: