基本概念
双向认证,顾名思义,客户端和服务器端都需要验证对方的身份,在建立HTTPS连接的过程中,握手的流程比单向认证多了几步。单向认证的过程,客户端从服务器端下载服务器端公钥证书进行验证,然后建立安全通信通道。双向通信流程,客户端除了需要从服务器端下载服务器的公钥证书进行验证外,还需要把客户端的公钥证书上传到服务器端给服务器端进行验证,等双方都认证通过了,才开始建立安全通信通道进行数据传输。
1. 原理
1.1 单向认证流程
单向认证流程中,服务器端保存着公钥证书和私钥两个文件,整个握手过程如下:
1.客户端发起建立HTTPS连接请求,将SSL协议版本的信息发送给服务器端;
2.服务器端将本机的公钥证书(server.crt)发送给客户端;
3.客户端读取公钥证书(server.crt),取出了服务端公钥;
4.客户端生成一个随机数(密钥R),用刚才得到的服务器公钥去加密这个随机数形成密文,发送给服务端;
5.服务端用自己的私钥(server.key)去解密这个密文,得到了密钥R
6.服务端和客户端在后续通讯过程中就使用这个密钥R进行通信了。
1.2 双向认证流程
客户端发起建立HTTPS连接请求,将SSL协议版本的信息发送给服务端;
1.服务器端将本机的公钥证书(server.crt)发送给客户端;
2.客户端读取公钥证书(server.crt),取出了服务端公钥;
3.客户端将客户端公钥证书(client.crt)发送给服务器端;
4.服务器端使用根证书(root.crt)解密客户端公钥证书,拿到客户端公钥;
5.客户端发送自己支持的加密方案给服务器端;
6.服务器端根据自己和客户端的能力,选择一个双方都能接受的加密方案,使用客户端的公钥加密8. 后发送给客户端;
7.客户端使用自己的私钥解密加密方案,生成一个随机数R,使用服务器公钥加密后传给服务器端;
8.服务端用自己的私钥去解密这个密文,得到了密钥R
9.服务端和客户端在后续通讯过程中就使用这个密钥R进行通信了。
以上内容全部摘抄自阿里云官方文档:文档
准备
需要的材料:openssl
Ubuntu/Debian/kali
sudo apt install openssl libssl-dev -y
CentOS/Fedora
sudo yum install openssl -y
第一步:生成根证书
openssl genrsa -out root.key 4096 #创建根证书私钥文件
openssl req -new -out root.csr -key root.key #创建证书请求文件
#参考参数:
#Country Name (2 letter code) [XX]:cn #国家代码,默认CN就行
#State or Province Name (full name) []:beijing #省份
#Locality Name (eg, city) [Default City]:beijing #城市
#Organization Name (eg, company) [Default Company Ltd]:linxi #组织名称
#Organizational Unit Name (eg, section) []:linxi-safe #组织内部机构
#Common Name (eg, your name or your servers hostname) []:root #根证书此字段为root且不建议更改,server和client此字段填写要设置HTTPs双向认证的域名
#Email Address []:test@test.com #邮箱
#A challenge password []: #密码,可不填
#An optional company name []: #直接掠过即可
openssl x509 -req -in root.csr -out root.crt -signkey root.key -CAcreateserial -days 3650 #创建10年有效期的根证书
注意:
- 根证书的Common Name字段root即可不建议更改且不能与server,client证书一样
- server,client证书Common Name字段一定要填写设置HTTPs双向认证的域名
- server,client证书除了Common Name字段其他一定要与根证书保持一致!!!
第二步:生成服务器证书
openssl genrsa -out server.key 4096 #创建根证书私钥文件
openssl req -new -out server.csr -key server.key #此处参考上面的填写方式
openssl x509 -req -in server.csr -out server.crt -signkey server.key -CA root.crt -CAkey root.key -CAcreateserial -days 3650 #创建10年有效期的服务器证书
第二步:生成客户端证书
openssl genrsa -out client.key 4096 #创建根证书私钥文件
openssl req -new -out client.csr -key client.key #此处参考上面的填写方式
openssl x509 -req -in client.csr -out client.crt -signkey client.key -CA root.crt -CAkey root.key -CAcreateserial -days 3650 #创建10年有效期的客户端证书
openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.p12 #生成p12格式的证书,此处需要填写两次密码
第三步:配置Nginx
在虚拟主机配置文件的server{}里添加以下配置以实现强制HTTPS:
if ($server_port !~ 443){
rewrite ^(/.*)$ https://$host$1 permanent;
}
文件末尾另起一行添加(在没有设置https的情况下):
server {
listen 443 ssl;
server_name 你的域名;
ssl_certificate 服务器证书的绝对路径;
ssl_certificate_key 服务器私钥的绝对路径;
ssl_client_certificate 根证书的绝对路径;
#开启客户端证书验证
ssl_verify_client on;
location / {
root 网站根目录的绝对路径;
index index.php index.html index.htm;
}
}
注意:如果客户端证书不是由根证书直接颁发的,配置中还需要加一个配置:ssl_verify_depth 1;
配置完成后需要重载Nginx配置:nginx -s reload
如果到了这一步nginx没有报错,那么恭喜你成功了!
最后一步:在Windows平台安装client.p12证书并进入网站测试
直接双击下载好的p12文件
点击下一页
点击下一页
输入密码
选择个人
点击完成
导入成功后重启浏览器,进入网站选择对应的证书即可
touch /etc/pki/CA/index.txt
echo 00 > /etc/pki/CA/crlnumber
openssl ca -gencrl -out client.crl -cert root.crt -keyfile root.key