nginx 配置 https 的双向认证

5 条评论

SSL 的双向认证就是,客户端要获取服务端的证书,检查下服务端是不是我可以信任的主机,否则我就认为那个站点的内容不可信任,不应该去访问你(浏览器会告诉你),同时服务端也要检查客户端的证书,客户端如果不是服务端所信任的,那服务端也会认为,你不是我的合法用户,我拒绝给你提供服务。所以,要让 HTTPS 的双向认证顺利完成,就要在服务端给定一个证书,这个证书是浏览器可信任的,同时客户端(浏览器)也要发送给服务端一个证书,服务器端也要信任这个证书。

要想让浏览器纯自然地就去信任服务端的证书,那服务端所使用的证书就得是那几大已经被大家所信任的证书机构给他签名,不过一般要钱…不好

如果自己担当证书机构(Certificate Authority, CA)的角色的话,可以这么搞。

1、准备CA密钥

通常是在 linux 用 openssl 命令来搞,不过 Windows 下也可以,装个 Git 一般会带上 windows 的编译版本了。

openssl genrsa –out ca-key.pem 2048

2、生成CA证书请求

证书请求都是根据私钥来生成的

openssl req –new –key ca-key.pem –out ca-req.csr –days 3650

3、签名CA证书请求

使用自己的私钥来给这个CA证书请求签名

openssl x509 –req –in ca-req.csr –out ca-cert.pem –signkey ca-key.pem –days 3650

4、CA证书转换为DER格式

DER 格式似乎更加通用,iOS 直接认

openssl x509 –in ca-cert.pem –out ca.der –outform DER

现在,终于拿到了自己做 CA 需要的几个文件了,密钥 ca-key.pem,证书 ca-cert.pem,系统使用的 ca.der,接下来,要创建一个网站,就需要让 CA 给他签名一个证书了

6、准备网站密钥

网站自己也需要准备一个密钥,类似于 CA,假如这个网站的域名是 su.su

openssl genrsa –out su-key.pem 2048

7、生成网站证书请求

网站通过密钥生成证书请求,当然,这个请求一般是要提交给 CA,让 CA 进行签名的

openssl req –new –key su-key.pem –out su-req.csr –days 3650

8、CA签名网站证书请求

不是拿到 CA 的证书了就可以说自己是 CA 的,最重要的是,签名需要有 CA 密钥

openssl x509 –req –in su-req.csr –out su-cert.pem –days 3650 –CA ca-cert.pem –CAkey ca-key.pem –CAcreateserial

如果客户端(个人浏览器)信任 CA 的证书的话,那么他也就会信任由 CA 签名的网站证书,因此让浏览器信任 CA 的证书之后,客户端就自然信任服务端了,只要做单向认证的话,到这一步证书这一类材料就已经准备好了,但是双向认证就还要给客户端(个人的浏览器)准备一份证书,让服务端可以知道客户端也是合法的。假如让服务端也信任 CA 的证书,那 CA 签名的客户端证书也就能被信任了。

9、准备客户端私钥

不变的方法不需要解释

openssl genrsa –out qiyi-key.pem 2048

10、生成客户端证书请求

不变的方法不需要解释

openssl req –new –key qiyi-key.pem –out qiyi-req.csr –days 3650

11、CA签名客户端证书请求

不变的方法不需要解释

openssl x509 –req –in qiyi-req.csr –out qiyi-cert.pem –days 3650 –CA ca-cert.pem –CAkey ca-key.pem –CAcreateserial

12、客户端证书转换为DER格式

不变的方法不需要解释

openssl x509 –in qiyi-cert.pem –out qiyi.der –outform DER

13、客户端证书转换为 PKCS #12格式

全称应该叫做 Personal Information Exchange,通常以 p12 作为后缀

openssl pkcs12 –export –clcerts –in qiyi-cert.pem –inkey qiyi-key.pem –out qiyi.p12

14、配置 nginx

比如,类似下面这样一段

  1. server {
  2.     listen       443;
  3.     server_name  localhost su.su;
  4.     ssl                  on;
  5.     ssl_certificate      cert/su-cert.pem;
  6.     ssl_certificate_key  cert/su-key.pem;
  7.     ssl_client_certificate cert/ca-cert.pem;
  8.     ssl_session_timeout  5m;
  9.     ssl_verify_client on;
  10.     ssl_protocols  SSLv2 SSLv3 TLSv1;
  11.     ssl_ciphers  RC4:HIGH:!aNULL:!MD5;
  12.     ssl_prefer_server_ciphers   on;
  13.     location / {
  14.         root   html;
  15.         index  index.html index.htm;
  16.     }
  17. }

我没有使用 ssl-sesion-cache 是因为遇到了错误…

15、配置浏览器证书

浏览器首先需要信任自签名的 CA 证书,这样他就可以直接信任服务端提供的证书了,为了双向认证成功,浏览器还需要提供一个传送给服务端的证书,也就是上面制作的客户端证书,对于 IE 来讲,首先在 Internet Options 里选择 Content 选项卡,然后点击 Certificates,新窗口的 Trusted Root Certification Authorities 选项卡选择导入,选择制作好的 ca.cer;其次在 Personal 选项卡选择导入 qiyi.p12,当然,这里导入的时候还需要输入密码-.-

16、测试成果

当将一切都设置好,将 nginx 启动成功后,就可以打开 IE 来访问了,第一次访问,浏览器会询问双向认证时使用的证书,类似下图

sublime-crack-1

选择客户端证书

顺利打开,浏览器没有红色的警告提示,正常显示页面内容就大功告成了。

参考:

相关日志 Relate Posts

收藏与分享 : Twitter | Facebook | 微博 | 人人 | Google+ | PDF

“nginx 配置 https 的双向认证”5条留言

  1. 不错,沙发了,新年快乐^^

  2. 前几天倒在.NET数字强签名上了,不知道起衣同学有没有解决办法。
    想帮一组程序替换一下.NET的DLL库,把验证改为始终有效,但是改完签名之后,加载就提示出错了,改签名的话就会提示initializer throw exception了,不确定这个是数字签名无效还是程序内部检测什么导致的……
    目前只能够放弃了……

    • @littlewater 水水,没玩过哎 😥

    • =A= 那就有时间记得也要研究一下!=w=++

发表留言(Ctrl+Enter提交)