博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
带你使用Nginx实现HTTPS双向验证
阅读量:6137 次
发布时间:2019-06-21

本文共 7778 字,大约阅读时间需要 25 分钟。

https单向验证应用广泛想必大家都很熟悉,我已经在一篇博文中分享过,这次来看看Nginx如何实现双向验证。

单向验证与双向验证的区别:

单向验证: 指客户端验证服务器端证书,服务器并不需要验证客户端证书。

双向验证:指客户端验证服务器端证书,而服务器也需要通过CA的公钥证书来验证客户端证书。

详细的握手过程:

单向验证

浏览器发送一个连接请求给安全服务器。

1、服务器将自己的证书,以及同证书相关的信息发送给客户浏览器。

2、客户浏览器检查服务器送过来的证书是否是由自己信赖的CA中心所签发的。如果是,就继续执行协议;如果不是,客户浏览器就给客户一个警告消息:警告客户这个证书不是可以信赖的询问客户是否需要继续。

3、接着客户浏览器比较证书里的消息,例如域名和公钥,与服务器刚刚发送的相关消息是否一致,如果是一致的,客户浏览器认可这个服务器的合法身份。

4、浏览器随机产生一个用于后面通讯的“通话密钥”,然后用服务器的公钥对其加密,然后将加密后的“预主密码”传给服务器。

5、服务器从客户发送过来的密码方案中,选择一种加密程度最高的密码方案,用服务器的私钥加密后通知浏览器。

6、浏览器针对这个密码方案,接着用服务器的公钥加过密后发送给服务器。

7、服务器接收到浏览器送过来的消息,用自己的私钥解密,获得。

8、服务器、浏览器接下来的通讯都是用对称密码方案,使用相同的对称密钥。

双向验证

1、浏览器发送一个连接请求给安全服务器。

2、服务器将自己的证书,以及同证书相关的信息发送给客户浏览器。

3、客户浏览器检查服务器送过来的证书是否是由自己信赖的CA中心所签发的。如果是,就继续执行协议;如果不是,客户浏览器就给客户一个警告消息:警告客户这个证书不是可以信赖的询问客户是否需要继续。

4、接着客户浏览器比较证书里的消息,例如域名和公钥,与服务器刚刚发送的相关消息是否一致,如果是一致的,客户浏览器认可这个服务器的合法身份。

5、服务器要求客户的身份认证,用户可以建立一个随机数然后对其进行数字签名,将这个含有签名的随机数和客户自己的证书以及加密过的“预主密码”一起传给服务器。

6、服务器必须检验客户证书和签名随机数的合法性,具体的合法性验证过程包括:客户的证书使用日期是否有效,为客户提供证书的CA 是否可靠,发行CA 的公钥能否正确解开客户证书的发行CA的数字签名,检查客户的证书是否在证书废止列表(CRL)中。检验如果没有通过,通讯立刻中断;如果验证通过,服务器将用自己的私钥解开加密的“预主密码”,然后执行一系列步骤来产生主通讯密码(客户端也将通过同样的方法产生相同的主通讯密码)。

7、客户浏览器告诉服务器自己所能够支持的通讯对称密码方案。

8、服务器从客户发送过来的密码方案中,选择一种加密程度最高的密码方案,用客户的公钥加过密后通知浏览器。

9、浏览器针对这个密码方案,选择一个通话密钥,接着用服务器的公钥加过密后发送给服务器。

10、服务器接收到浏览器送过来的消息,用自己的私钥解密,获得通话密钥。

11、服务器、浏览器接下来的通讯都是用对称密码方案,使用相同的对称密钥。

一、自建CA,签署证书

# openssl 配置文件路径vim /etc/pki/tls/openssl.cnf# 下面只列出配置文件中和自建CA有关的几个关键指令dir             = /etc/pki/CA # CA的工作目录database        = $dir/index.txt # 签署证书的数据记录文件new_certs_dir   = $dir/newcerts # 存放新签署证书的目录serial          = $dir/serial # 新证书签署号记录文件certificate     = $dir/ca.crt # CA的证书路径private_key     = $dir/private/cakey.pem # CA的私钥路径

使用openssl制作CA的自签名证书

# 切换到CA的工作目录cd /etc/pki/CA# 制作CA私钥(umask 077; openssl genrsa -out private/cakey.pem 2048)# 制作自签名证书openssl req -new -x509 -key private/cakey.pem  -out ca.crt # 生成数据记录文件,生成签署号记录文件,给文件一个初始号。touch index.txttouch serialecho '01'> serial# 自建CA完成

准备服务器端证书

# 制作服务器端私钥(umask 077; openssl genrsa -out server.key 1024)# 制作服务器端证书申请指定使用sha512算法签名 (默认使用sha1算法)openssl req -new -key server.key -sha512 -out server.csr# 签署证书openssl ca -in server.csr -out server.crt -days 3650

准备客户端证书

# 制作客户端私钥(umask 077; openssl genrsa -out kehuduan.key 1024)# 制作客户端证书申请openssl req -new -key kehuduan.key -out kehuduan.csr# 签署证书openssl ca -in kehuduan.csr -out kehuduan.crt -days 3650

注意事项:

1、制作证书时会提示输入密码,设置密码可选,服务器证书和客户端证书密码可以不相同。

2、服务器证书和客户端证书制作时提示输入省份、城市、域名信息等,需保持一致。

3、以下信息根证书需要和客户端证书匹配,否则可能出现签署问题。

             countryName = match

             stateOrProvinceName = match
             organizationName = match
             organizationalUnitName = match

如何指定签署证书的签名算法

 openssl req xx  -[digest]      Digest to sign with (see openssl dgst -h for list)

查看使用的签名算法:

# 使用-sha256指定算法openssl req -new -key server.key -sha256 -out server.csr

二、提供Nginx配置文件

server {        listen       443;        server_name  pro.server.com;        ssi on;        ssi_silent_errors on;        ssi_types text/shtml;        ssl                  on;        ssl_certificate      /data/server/nginx/ssl/self/server.crt;        ssl_certificate_key  /data/server/nginx/ssl/self/server.key;        ssl_client_certificate /data/server/nginx/ssl/self/ca/ca.crt;        ssl_verify_client on;        ssl_protocols    TLSv1 TLSv1.1 TLSv1.2;        ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-RC4-SHA:!ECDHE-RSA-RC4-SHA:ECDH-ECDSA-RC4-SHA:ECDH-RSA-RC4-SHA:ECDHE-RSA-AES256-SHA:!RC4-SHA:HIGH:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!CBC:!EDH:!kEDH:!PSK:!SRP:!kECDH;        ssl_prefer_server_ciphers On;        index index.html index.htm index.php;        root /data/www;        location ~ .*\.(php|php5)?$        {                #fastcgi_pass  unix:/tmp/php-cgi.sock;                fastcgi_pass  127.0.0.1:9000;                fastcgi_index index.php;                include fastcgi.conf;        }        location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$        {                expires 30d;        }        location ~ .*\.(js|css)?$        {                expires 1h;        }###this is to use open website lianjie like on apache##        location / {                if (!-e $request_filename) {                        rewrite ^(.*)$ /index.php?s=$1 last;                        break;                }                 keepalive_timeout  0;        }        location ~ /.svn/ {        deny all;        }###end##        include /data/server/nginx/conf/rewrite/test.conf;        access_log /log/nginx/access/access.log; }

客户端证书格式转换

# 将文本格式的证书转换成可以导入浏览器的证书openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.p12

三、将证书导入浏览器,这里以Chrome为例

1、在浏览器窗口右上角找到设置

2、在设置窗口中找到高级设置

3、找到管理证书

4、点击导入证书,然后选择证书路径就可以了

5、在导入证书之后就可以正常访问到服务器数据了

6、如果没有成功导入客户端证书就访问服务器的话,那么服务器验证客户端证书这步就会失败,然后返回如下错误

由于用的是自签证书不被公有CA信任,所以https那里会有红叉。

附加内容: 如何配置级联证书链

(2016/11/08)

为什么我之前写这篇的时候没有写上,而是之后加上这块呢?

因为之前做的实验用的是自签名证书,所谓的自签名证书就是CA也是自己做,自己给自己发证。

那么我们在签发服务端证书和客户端证书的时候,是由自己所创建的根级CA下发的。 不存在一级、二级代理CA的概念。在Nginx上配置校验客户端证书时,只需要制定根级CA的证书就够了。

但是在实际运用过程中,我们很可能会在CA代理机构,申请受信任的证书,这个机构很可能就会是代理CA,也就是由根级CA授权的下级CA,有数字证书的签发资格。

举个例子,假如有一个二级代理CA签发了一个证书,那么当需要校验这个证书的合法性时,需要用到签发这个证书的二级代理CA的证书来校验。 那么二级代理CA的证书是否又可信呢? 那么就需要给二级代理CA发证的,一级代理CA的证书来校验,层层递进,直到根CA证书。这就是级联证书的校验模式。

这时候在配置Nginx校验客户端证书时,只指定给发证的二级代理CA的证书就不行了。 还需要跟上能校验二级代理CA证书的根CA证书。

在HTTPS双向验证中,指定CA证书来校验客户端证书时,是用于校验整个信任域。 比如: 你的顶级域名是 baidu.com。 那么任何 xxx.baidu.com 的证书都可以被信任。

假设在startSSL申请了一个SSL证书

使用者: test.baidu.com

颁发者: StartCom Class 1 DV Server CA

打开这个CA证书可以看到,它上面还有一级,它的颁发者是 StartCom Certification Authority

然后再打开这个CA的证书,查看颁发者和使用者都相同,那它应该就是根级CA了。

test.baidu.com 作为客户端证书,Nginx配置校验:

1、打开代理CA和根级CA的证书,复制代理CA证书中的内容,贴到根CA证书内容的下方,保存;

2、提供Nginx配置文件

server {        listen       443;        server_name  test.baidu.com;        ssl                  on;        ssl_certificate        /alidata/server/nginx/ssl/server.baidu.com.crt;        ssl_certificate_key    /alidata/server/nginx/ssl/server.key;        ssl_verify_depth 2;        ssl_client_certificate /alidata/server/nginx/ssl/ca/ca_and_proxyca.crt;        ssl_verify_client on;        ssl_protocols    TLSv1 TLSv1.1 TLSv1.2;        ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-RC4-SHA:!ECDHE-RSA-RC4-SHA:ECDH-ECDSA-RC4-SHA:ECDH-RSA-RC4-SHA:ECDHE-RSA-AES256-SHA:!RC4-SHA:HIGH:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!CBC:!EDH:!kEDH:!PSK:!SRP:!kECDH;        ssl_prefer_server_ciphers on;        index index.html index.htm index.php;        root /alidata/www/default;}

部分重点配置解释:

ssl_verify_client on 开启客户端身份校验

ssl_client_certificate 指定用于校验客户端证书的CA的证书,如果是代理级CA,那么需要把内容并在一起。

ssl_verify_depth 指定校验深度

证书常见的三种格式,pem、der、pkcs12

pem 格式也就是文本格式,可以直接用文本编辑器打开看到证书内容的,这也是最常见的格式。

der 这种格式无法直接通过文本编辑器打开查看内容,通常用在JAVA环境。

pkcs12 用于导入浏览器的格式

格式转换:

# pem 转 deropenssl x509 -inform pem -in certificate.crt -out certificate.cer -outform DER# pem 格式的证书有含私钥的,和不含私钥的。# der 转 pemopenssl x509 -inform der -in certificate.cer -out certificate.pem# 私钥转化 der 转 pemopenssl rsa -inform DER -outform PEM -in privatekey.der -out privatekey.pem# pem 转 pkcs12openssl pkcs12 -export -in Cert.pem -out Cert.p12 -inkey key.pem# pkcs12 转 pemopenssl pkcs12 -nocerts -nodes -in cert.p12 -out private.pemopenssl pkcs12 -clcerts -nokeys -in cert.p12 -out cert.pem# P7B 转换为 PEM (P7B格式一般出现在windows server和tomcat中,无私钥)openssl pkcs7 -print_certs -in incertificat.p7b -out outcertificate.cer# PFX 转换为PEM (PFX格式一般出现在windows server中)#提取私钥openssl pkcs12 -in certname.pfx -nocerts -out key.pem -nodes#提取证书openssl pkcs12 -in certname.pfx -nokeys -out cert.pem# 从pem私钥中提取公钥openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

转载地址:http://abkya.baihongyu.com/

你可能感兴趣的文章
InfoQ趋势报告:DevOps 和云计算
查看>>
舍弃Python,为什么知乎选用Go重构推荐系统?
查看>>
在soapui上踩过的坑
查看>>
MySQL的字符集和字符编码笔记
查看>>
ntpd同步时间
查看>>
must implement java.io.Serializable hessian
查看>>
Microsoft Licenses Flash Lite for Windows Mobile Users
查看>>
HDOJ 2020 绝对值排序
查看>>
HDOJ/HDU 2560 Buildings(嗯~水题)
查看>>
Maven编译时跳过Test
查看>>
Spring Boot 整合Spring Security 和Swagger2 遇到的问题小结
查看>>
[20170628]12C ORA-54032.txt
查看>>
除以2
查看>>
高可用集群原理解析
查看>>
Nginx配置URL转向tomcat
查看>>
极客Web前端开发资源大荟萃#001
查看>>
让div固定在某个位置
查看>>
Java开发环境Docker镜像
查看>>
从无到有,WebService Apache Axis2初步实践
查看>>
任务调度(一)——jdk自带的Timer
查看>>