自签名SSL证书以及nginx配置https服务
服务器SSL的认证流程
单向认证
-
客户端发起建立HTTPS连接请求,将SSL协议版本的信息发送给服务端
-
服务器端将本机的公钥证书发送给客户端
-
客户端读取公钥证书,取出服务端公钥
-
客户端生成一个随机数(秘钥R),用刚才得到的服务器公钥去加密这个随机数行程秘文,发送给服务器
-
服务器用自己的私钥去解密这个秘文,得到秘钥R
-
客户端和服务端在后续的通讯过程中就是用这个秘钥R进行通信
双向认证
-
客户端发起建立HTTPS连接请求,将SSL协议版本的信息发送给服务端
-
服务器端将本机的公钥证书发送给客户端
-
客户端读取公钥证书,取出服务端公钥
-
客户端将客户端公钥证书发送给服务端
-
服务器端解密客户端公钥证书,拿到客户端公钥
-
客户端发送自己支持的加密方案给服务端
-
服务端根据自己和客户端的能力,选择一个双方都能接受的加密方式,使用客户端的公钥加密后发送给客户端
-
客户端使用自己的私钥解密加密方案,生成一个随机数R,使用服务器公钥加密之后传给服务端
-
服务端用自己的私钥去解密这个秘文,得到秘钥R
-
客户端和服务端在后续的通讯过程中就是用这个秘钥R进行通信
不难发现双向认证会比单项认证更安全,当然性能肯定是不如单向
自签名SSL证书
需要生成的证书文件
-
服务端公钥证书:server.crt
-
服务端私钥证书:server-privatekey.pem
-
客户端公钥证书:client.crt
-
客户端私钥证书:client-privatekey.pem
-
客户端集成证书(包括公钥和私钥,用于浏览器访问场景):client.p12
在开始生成这一系列证书之前,需要先生成一个CA根证书,通过这个CA根证书颁发服务器公钥和客户端公钥,假装我们是正规的CA机构(手动狗头)
自建CA
-
创建私钥privatekey.pem
openssl genrsa -out privatekey.pem
如果不指定
-out
参数2048bit
的私钥会直接在命令行打印-out
为存储路径 -
根据私钥生成一个新的证书请求文件
openssl req -key privatekey.pem -new -out ca.csr
-
-new
生成一个新的证书请求 -
-out
存储路径 -
-key
指定读取私钥的文件路径,这里使用了上一步中生成的私钥文件,如果不指定会先初始化一个私钥
执行该命令后根据提示完善一些信息
-
-
-
Country Name:国家,这里限制输入两个字符,中国是CN
-
State or Province Name:州或者省份
-
Locality Name:城市
-
Organization Name:组织,可以采用公司名
-
Organizational Unit Name:组织单位,有些ca机构没有该内容
-
Common Name:公用名,这里填域名,没有域名的话用服务器的ip
-
Email Address:邮箱,这里我回车跳过了
-
A challenge password:请求文件的密码,可以直接回车跳过
如果不想要在对话框中依次输入信息,可以执行下面的命令
openssl req -key privatekey.pem -new -out ca.csr -subj /C=cn/ST=guangdong/L=guangzhou/O=testcompany/OU=testdepartment/CN=test.com
-
-
创建根证书
openssl x509 -req -in ca.csr -out ca.crt -signkey privatekey.pem -CAcreateserial -days 365
x509
是一个多功能的证书命令。可以用来展示证书信息、转换证书格式、像mini CA
一样签名证书请求或者修改证书信任设置-
-in
输入文件的读取路径 -
-out
输出文件的存储路径 -
-signkey
私钥文件路径 -
-CAcreateserial
避免没有CA serial number file(该文件只有一行,包含偶数个十六进制的字符)时候的报错。没有的话这里会自动创建一个。 -
-days
证书有效天数
-
生成服务器端证书
-
生成证书私钥
openssl genrsa -out server-privatekey.pem
-
使用私钥生成服务器端证书的请求文件
openssl req -key server-privatekey.pem -new -out server.csr -subj /C=cn/ST=guangdong/L=guangzhou/O=testcompany/OU=testdepartment/CN=test.com
这里我直接沿用了CA证书时候的参数,不然开启SSL双向认证的时候无法正常请求
-
生成服务器端证书
openssl x509 -req -in server.csr -out server.crt -signkey server-privatekey.pem -CA ca.crt -CAkey privatekey.pem -CAcreateserial -days 365
大部分参数在生成CA证书的时候都有使用,这里说明一下两个之前未使用到的参数
-
-CA
使用的CA证书 -
-CAkey
使用的CA证书私钥
-
如果不使用SSL双向认证的话,到这里就可以了,服务端开启ssl有服务端证书server.crt
和服务端证书server-privatekey.pem
就够了,nginx配置如下
server {
#SSL 默认访问端口号为 443
listen 9090 ssl;
#请填写绑定证书的域名
#server_name cloud.tencent.com;
#请填写证书文件的相对路径或绝对路径
ssl_certificate cert/server.crt;
#请填写私钥文件的相对路径或绝对路径
ssl_certificate_key cert/server-privatekey.pem;
# ssl_client_certificate cert/client.crt;
# ssl_verify_client on;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# ...
# ...
}
生成客户端证书
生成客户端证书的过程基本上和生产服务端证书一致
-
生成客户端证书私钥
openssl genrsa -out client-privatekey.pem
-
使用证书私钥生成客户端证书请求文件
openssl req -key client-privatekey.pem -new -out client.csr -subj /C=cn/ST=guangdong/L=guangzhou/O=testcompany/OU=testdepartment/CN=test.com
沿用了CA证书时候的参数
-
生成客户端证书
openssl x509 -req -in client.csr -out client.crt -signkey client-privatekey.pem -CA ca.crt -CAkey privatekey.pem -CAcreateserial -days 365
-
生成p12格式的证书
openssl pkcs12 -export -clcerts -in client.crt -inkey client-privatekey.pem -out client.p12
pkcs12
命令用于生成或者转换p12文件-
-export
生成pkcs#12文件 -
-clcerts
只输出客户端证书 -
-in
输入文件 -
-inkey
私钥 -
-out
输出
-
nginx配置
server {
#SSL 默认访问端口号为 443
listen 443 ssl;
#请填写绑定证书的域名
#server_name cloud.tencent.com;
#请填写证书文件的相对路径或绝对路径
ssl_certificate cert/server.crt;
#请填写私钥文件的相对路径或绝对路径
ssl_certificate_key cert/server-privatekey.pem;
#客户端证书
ssl_client_certificate cert/client.crt;
#校验客户端证书
ssl_verify_client on;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# ...
# ...
}
这里开启了校验客户端证书,校验的话可以注释掉ssl_verify_client on;
到这里想要访问服务的话就必须要在客户端导入clien.p12证书,否则客户端请求的时候就会报错