当前位置: 首页 > news >正文

Nginx开启OCSP Stapling

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

0x00 一个问题

最近我们需要将某个站点从http切换到https。在测试的时候,我们发现一些使用IE浏览器的用户,首次打开https的页面需要20s左右的时间,但是使用Chrome的用户却没有这个情况。

0x10 OCSP简介

我们知道每一张SSL证书都有一个有效期,但是有些证书会因为种种原因,在有效期之内就被废除了。那么对于浏览器来说,当它从一个站点获取证书时就需要验证此证书是否已经被废除。在过去,为了达到这个目的,浏览器会定期更新证书吊销列表(CRL)。这个列表会列出所有已经失效的证书,如果获取的证书在这个列表中,那么对不起,你的这张证书就不被浏览器信任了。但是这种方式有着很明显的缺陷:一个是列表会越来越大,无论是保存还是查询都会变得越来越慢;另一个是更新实时性差,如果一个证书被吊销,只有等到下次更新CRL时浏览器才会知道,这段时间内就有安全问题。

为了解决CRL的这些不足,在线证书状态协议(OCSP,Online Certificate Status Protocol)出现了。通过OCSP,浏览器可以在线向CA证书颁发机构查询证书的有效性。这样,浏览器就无需在本地维护一张表,同时由于是在线查询,实时性得到保障。然而,这种方式也有自己的问题:客户端在任何协商前必须等待OCSP的请求返回!细心点的读者已经想到,如果此时浏览器无法访问到对应的CA证书颁发机构,那么就会出现文章开头的问题。没错,IE浏览器正是使用OCSP来对证书进行验证。由于我们的测试环境无法访问公网,所以IE在一开始就会因无法获取到CA的返回而保持等待状态,直至超时。而Chrome则默认关闭了OCSP验证,取而代之的是Google自己的实现方式(CRLSets,一种类似CRL的实现),因此没有出现这个问题。

0x20 OCSP Stapling

OCSP Stapling则解决了上述的问题。服务端主动通过OCSP获得证书状态,并随着证书一起发送给客户端,这样客户端就可以跳过自己去验证的步骤,以提高SSL握手的效率。

0x30 验证OCSP Stapling状态

你可以用Wireshark抓包或者到SSL Labs来查询自己站点的OCSP Stapling是否启用,也可以用我下面介绍的openssl命令行方式来轻松完成任务。

由于CentOS 6自带的openssl是1.0.1版本,而我希望能使用最新版本的openssl,所以我们先去Openssl官网下载最新的源码包编译安装,当前我能下载到的最新版本是1.1.0d。

目前主流的浏览器在建立TLS时,会发送一个status_request扩展,告诉服务器想得到OCSP Response。在openssl命令行中,加入-status参数有同样的效果。如果服务器启用了SNI,那么还需要加入-servername参数指定你需要查询的域名:

bash$ openssl s_client connect xyz.cn:443 -servername www.xyz.cn -status -tlsextdebug < /dev/null 2&>1|grep -i "ocsp response"

如果结果是下面这样,那就是开启了OCSP Stapling:

OCSP response: 
OCSP Response Data:
    OCSP Response Status: successful (0x0)
    Response Type: Basic OCSP Response

而如果是这样,显然没开启:

OCSP response: no response sent

0x40 Nginx配置OCSP Stapling

Nginx中与OCSP Stapling相关的有以下几个配置项:

ssl_stapling    on;
ssl_stalping_verify    on;
ssl_trusted_certificate    /path/to/chain.pem;

注意此功能需要Nginx版本1.3.7以上。

前两个都好理解,最后一个是什么证书呢?

其实这里应该是一个完整的证书链,按照从上到下的顺序应该包括站点证书、中间证书(1张或多张)、根证书。证书服务商在你购买证书时会告诉你站点证书和中间证书,或者如果你忘了,也可以通过openssl命令行轻松获取:

bash$ openssl s_client connect xyz.cn:443 -showcerts < /dev/null 2&>1

显示结果如下(省略部分内容):

CONNECTED(00000003)
depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
verify error:num=20:unable to get local issuer certificate
---
Certificate chain
 0 s:/C=CN/ST=Jiangsu/L=Nanjing/O=XYZ Insurance Co.,Ltd./OU=R&D Dept./CN=*.xyz.cn
   i:/C=US/O=GeoTrust Inc./CN=GeoTrust SSL CA - G3
-----BEGIN CERTIFICATE-----
MIIE6zCCA9OgAwIBAgIQMnPsmcfMo25b3nxFKihPCzANBgkqhkiG9w0BAQsFADBE
......
qjmhhFFHbLiqCpP2HTvh
-----END CERTIFICATE-----
 1 s:/C=US/O=GeoTrust Inc./CN=GeoTrust SSL CA - G3
   i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
-----BEGIN CERTIFICATE-----
MIIETzCCAzegAwIBAgIDAjpvMA0GCSqGSIb3DQEBCwUAMEIxCzAJBgNVBAYTAlVT
......
zNSS
-----END CERTIFICATE-----
 2 s:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
   i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
-----BEGIN CERTIFICATE-----
MIIDfTCCAuagAwIBAgIDErvmMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT
.....
b8ravHNjkOR/ez4iyz0H7V84dJzjA1BOoa+Y7mHyhD8S
-----END CERTIFICATE-----
---
Server certificate
subject=/C=CN/ST=Jiangsu/L=Nanjing/O=XYZ Insurance Co.,Ltd./OU=R&D Dept./CN=*.xyz.cn
issuer=/C=US/O=GeoTrust Inc./CN=GeoTrust SSL CA - G3
---
......

    Start Time: 1487731515
    Timeout   : 7200 (sec)
    Verify return code: 20 (unable to get local issuer certificate)
    Extended master secret: no
---
DONE

这样我们就得到了站点证书(0)和中间证书(1、2)。从最后一张中间证书可以看到根证书的颁发机构为Equifax Secure Certificate Authority。此时我们可以到根证书颁发机构的网站下载到此根证书,也可以从操作系统中导出:

Equifax根证书

上面的返回内容中有一个报错信息:Verify return code: 20 (unable to get local issuer certificate),这是因为我们没有指定根证书。在得到根证书后,我们可以再次执行上面的命令,并加入-CAfile root.pem选项:

bash$ openssl s_client connect xyz.cn:443 -showcerts < /dev/null 2&>1

将会显示:Verify return code: 0 (ok)

接下来,我们将站点证书保存为site.pem,中间证书保存为intermediate.pem,根证书保存为root.pem,然后再将这三种证书按序保存为chain.pem:

bash$ cat site.pem intermediate.pem root.pem > chain.pem

这样就能完成Nginx的OCSP Stapling配置了。

0x50 参考:

【1】从无法开启 OCSP Stapling 说起

【2】RFC5280

转载于:https://my.oschina.net/plutonji/blog/843211

相关文章:

  • linux学习笔记
  • Linux常用命令——挂载 mount
  • 【SGE】任务显示 T 状态,qstat -j 报错 can not find an unused add_grp_id
  • NTP server
  • nginx访问控制
  • python 继承基础
  • 前端开发中同步和异步的区别
  • Powershell IE自动登录
  • 二维平面内的碰撞检测【一】
  • vue2.0开发聊天程序(四) 完整体验一次Vue开发(下)
  • BZOJ 2244: [SDOI2011]拦截导弹 [CDQ分治 树状数组]
  • Jquery里live事件移除原因
  • Java NIO中的通道Channel(一)通道基础
  • java栈与队列面试题
  • java中正则表达式的使用
  • [译] 理解数组在 PHP 内部的实现(给PHP开发者的PHP源码-第四部分)
  • 【140天】尚学堂高淇Java300集视频精华笔记(86-87)
  • 【node学习】协程
  • cookie和session
  • Go 语言编译器的 //go: 详解
  • httpie使用详解
  • Java编程基础24——递归练习
  • Java深入 - 深入理解Java集合
  • NSTimer学习笔记
  • Odoo domain写法及运用
  • React-flux杂记
  • Vue全家桶实现一个Web App
  • Vue--数据传输
  • - 概述 - 《设计模式(极简c++版)》
  • 关于extract.autodesk.io的一些说明
  • 腾讯视频格式如何转换成mp4 将下载的qlv文件转换成mp4的方法
  • Oracle Portal 11g Diagnostics using Remote Diagnostic Agent (RDA) [ID 1059805.
  • 06-01 点餐小程序前台界面搭建
  • 选择阿里云数据库HBase版十大理由
  • ${ }的特别功能
  • (JSP)EL——优化登录界面,获取对象,获取数据
  • (附源码)springboot车辆管理系统 毕业设计 031034
  • (附源码)springboot家庭装修管理系统 毕业设计 613205
  • (附源码)springboot优课在线教学系统 毕业设计 081251
  • (每日持续更新)jdk api之FileFilter基础、应用、实战
  • (三)docker:Dockerfile构建容器运行jar包
  • (四)【Jmeter】 JMeter的界面布局与组件概述
  • (提供数据集下载)基于大语言模型LangChain与ChatGLM3-6B本地知识库调优:数据集优化、参数调整、Prompt提示词优化实战
  • (一)Java算法:二分查找
  • (转)JVM内存分配 -Xms128m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=512m
  • (转)setTimeout 和 setInterval 的区别
  • (转载)从 Java 代码到 Java 堆
  • ***详解账号泄露:全球约1亿用户已泄露
  • .L0CK3D来袭:如何保护您的数据免受致命攻击
  • .NET Core 成都线下面基会拉开序幕
  • .Net Core与存储过程(一)
  • .NET Framework Client Profile - a Subset of the .NET Framework Redistribution
  • .NET Standard / dotnet-core / net472 —— .NET 究竟应该如何大小写?
  • .NET 自定义中间件 判断是否存在 AllowAnonymousAttribute 特性 来判断是否需要身份验证
  • .netcore 6.0/7.0项目迁移至.netcore 8.0 注意事项