在服务器上启用HTTP公钥固定扩展的教程

公钥固定(Public Key Pinning)是指一个证书链中必须包含一个白名单中的公钥,也就是说只有被列入白名单的证书签发机构(CA)才能为某个域名*.example.com签发证书,而不是你的浏览器中所存储的任何 CA 都可以为之签发。本文讲述了这种机制的背景知识,并提供了 Apache、 Lighttpd 和 NGINX 上的配置范例。
HTTP 公钥固定扩展

用你使用的银行做个例子,它一直使用 CA 公司 A 为其签发证书。但是在当前的证书体系下,CA 公司 B、CA 公司 C 和 NSA 的 CA 都能给你的银行创建证书,而你的浏览器会毫无疑虑的接受它们,因为这些公司都是你所信任的根 CA。

如果你的银行实现了 HPKP 并固定了它们的第一个中级证书(来自 CA 公司 A),那么浏览器将不会接受来自CA 公司 B 和 CA 公司 C 的证书,即便它们也有一个有效的信任链。HPKP 也允许你的浏览器将这种违例行为报告给该银行,以便银行知道被伪造证书攻击了。

HTTP 公钥固定扩展是一个从2011年开始开发的针对 HTTP 用户代理(即浏览器)的公钥固定标准。它由 Google 发起,甚至在 Chrome 中实现的固定机制可以使用一个人工维护的网站公钥固定列表,这个列表包含了固定的几个网站的公钥签名。(LCTT 译注:Chrome 和 FireFox 32 及以后版本都支持公钥固定机制,并使用内置的人工维护的公钥固定列表数据,这些数据随着浏览器软件的更新而更新,主要包括几个大型站点。目前还只有 Chrome 38+ 支持通过 HTTP 响应头传递公钥固定信息。)

以下是 HPKP 的几个功能简述:

  • HPKP 是在 HTTP 层面设置的,使用 Public-Key-Pins (PKP)响应头。
  • 该规则的保留周期通过 max-age 参数设置,单位是秒。
  • PKP 响应头只能用于正确的安全加密通讯里面。
  • 如果出现了多个这样的响应头,则只处理第一个。
  • 固定机制可以使用includeSubDomains参数扩展到子域。
  • 当接收到一个新的 PKP 响应头时,它会覆盖之前存储的公钥固定和元数据。
  • 公钥固定是用哈希算法生成的,其实是一个“主题公钥信息(SKPI)”指纹。

本文首先会介绍一些 HPKP 工作的原理,接下来我们会展示给你如何得到需要的指纹并配置到 web 服务器中。
SPKI 指纹 - 理论

通常来说,对证书进行哈希是一个显而易见的解决方案,但是其实这是错的。不能这样做的原因是 CA 证书可以不断重新签发:同一个公钥、主题名可以对应多个证书,而这些证书有不同的延展或失效时间。浏览器从下至上地在证书池中构建证书链时,另外一个版本的证书可能就替代匹配了你原本所期望的证书。

举个例子,StartSSL 有两个根证书:一个是以 SHA1 签名的,另外是一个是 SHA256。如果你希望固定住 StartSSL 作为你的 CA,那么你该使用哪个证书呢?你也许可以使用这两个,但是如果我不告诉你,你怎么会知道还有一个根证书呢?

相反地,对公钥进行哈希则不会有这个问题:

浏览器假定子证书是固定不动的:它总是证书链的起点。子证书所携带的签名一定是一个有效的签名,它来自其父证书给这个证书专门签发的。这就是说,父证书的公钥相对于子证书来说是固定的。所以可推论公钥链是固定的。

唯一的问题是你不能固定到一个交叉认证的根证书上。举个例子,GoDaddy 的根证书是 Valicert 签名的,这是为了让那些不能识别 GoDaddy 根证书的老客户可以信任其证书。然而,你不能固定到 Valicert 上,因为新的客户在证书链上发现了 GoDaddy 证书就会停止上溯(LCTT 译注:所以就找不到固定信息了)。

此外,我们是对 SubjectPublicKeyInfo(SPKI)进行哈希而不是对公钥位串。SPKI 包括了公钥类型、公钥自身及其相关参数。这很重要,因为如果对公钥进行哈希就有可能导致发生曲解攻击。对于一个 Diffie-Hellman 公钥而言:如果仅对公钥进行哈希,而不是对完整的 SPKI,那么攻击者可以使用同样的公钥而让客户端将其解释为其它组。同样地,这样也有可能强制将一个 RSA 密钥当成 DSA 密钥解释等等。

固定在哪里

你应该固定在什么地方?固定你自己的公钥并不是一个最好的办法。你的密钥也许会改变或撤销。你也许会使用多个证书,经常轮换证书的话密钥就改变了。也许由于服务器被入侵而撤销证书。

最容易但是不是太安全的方法是固定第一个中级 CA 证书。该证书是签名在你的网站证书之上的,所以签发该证书的 CA 的公钥肯定是在证书链上的。

采用这种方法你可以从同一个 CA 更新你的证书而不用担心固定信息不对。如果该 CA 发行了一个不同的根证书,也许你会遇到一些问题,对此并没有太好的解决方案。不过你可以通过如下做法来减轻这种问题的影响:

从一个不同的 CA 申请一个备用的证书,并固定该备份。

RFC 里面说你至少需要做两个固定。一个是当前连接所使用的证书链上的,另外一个是备份的。

另外的固定是对备份公钥的,它可以是来自另外一个给你签发证书的不同 CA 的 SKPI 指纹。

在这个问题上还有一种更安全的方法,就是事先创建好至少三个独立的公钥(使用 OpenSSL,参见此页 了解 Javascript OpenSSL 命令生成器),并将其中两个备份到一个安全的地方,离线存储、不要放到网上。

为这三个证书创建 SPKI 指纹并固定它们,然后仅使用第一个作为当前的证书。当需要时,你可以使用备份密钥之一。不过你需要让 CA 给你做签名来生成证书对,这可能需要几天,依你的 CA 的工作情况而定。

对于 HPKP 来说这没有问题,因为我们使用的是公钥的 SPKI 哈希,而不是证书。失效或不同的 CA 签名链并不影响。

如果你按照上述方法生成并安全存储了至少三个独立的密钥,并固定它们,也可以防止你的 CA 撤销你的网站证书并签发一个假证书时出现问题。
SPKI 指纹

可以使用如下的 OpenSSL 命令来生成 SPKI 指纹,它出现在 RFC 草案 中:

代码如下:

openssl x509 -noout -in certificate.pem -pubkey | \
    openssl asn1parse -noout -inform pem -out public.key;
    openssl dgst -sha256 -binary public.key | openssl enc -base64

结果:

代码如下:

klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=

上面输入的 certificate.pem 文件是本站(https://raymii.org)的证书链中第一个证书。(在写本文时, COMODO RSA Domain Validation Secure Server CA, 序列号 2B:2E:6E:EA:D9:75:36:6C:14:8A:6E:DB:A3:7C:8C:07 )。

你也需要同样对你的另外两个备份公钥生成指纹。
故障

在写本文时(2015/1),唯一支持 HPKP 的浏览器(chrome)有一个严重的问题:Chrome 并不能够区分 HSTS 和 HPKP 响应头中的 max-age 和 includeSubdomains 参数。也就是说,如果你的 HSTS 和 HPKP 设置了不同的 max-age 和 includeSubdomains 参数,它们会互相搞乱。关于这个故障的更多信息参见:https://code.google.com/p/chromium/issues/detail?id=444511。感谢 Scott Helme(https://scotthelme.co.uk)发现并告诉我这个 Chromium 项目的问题。
Web 服务器配置

下面你可以看到三个主流 Web 服务器的配置方法。这只是一个 HTTP 响应头,绝大多数 Web 服务器都可以设置它。它只需要设置到 HTTPS 网站上。

下面的例子固定到 COMODO RSA Domain Validation Secure Server CA 及备份的 Comodo PositiveSSL CA 上,30天失效期,包括所有的子域。
Apache

编辑你的 Apache 配置文件(如 /etc/apache2/sites-enabled/website.conf 或 /etc/apache2/httpd.conf),并添加下列行到你的 VirtualHost 中:

代码如下:

# 如需要,载入 headers 模块。
    LoadModule headers_module modules/mod_headers.so
    Header set Public-Key-Pins "pin-sha256=\"klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=\"; pin-sha256=\"633lt352PKRXbOwf4xSEa1M517scpD3l5f79xMD9r9Q=\"; max-age=2592000; includeSubDomains"

Lighttpd

Lighttpd 更简单一些,将下列行添加到你的 Lighttpd 配置文件(如 /etc/lighttpd/lighttpd.conf):

代码如下:

server.modules += ( "mod_setenv" )
    $HTTP["scheme"] == "https" {
        setenv.add-response-header  = ( "Public-Key-Pins" => "pin-sha256=\"klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=\"; pin-sha256=\"633lt352PKRXbOwf4xSEa1M517scpD3l5f79xMD9r9Q=\"; max-age=2592000; includeSubDomains")
    }

NGINX

NGINX 的配置更简短。添加以下行到你的 HTTPS 配置的 server 块中:

add_header Public-Key-Pins 'pin-sha256="klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY="; pin-sha256="633lt352PKRXbOwf4xSEa1M517scpD3l5f79xMD9r9Q="; max-age=2592000; includeSubDomains';

报告功能

HPKP 报告功能允许浏览器报告任何违例给你。

如果你在响应头中添加了附加的 report-uri="http://example.org/hpkp-report" 参数,并用该 URI 处理接收到的数据的话,客户端会在发现违例时发送报告给你。这个报告是以 POST 方式发送到你指定的 report-uri 上,并以类似下面的 JSON 格式:

代码如下:

{
        "date-time": "2014-12-26T11:52:10Z",
        "hostname": "www.example.org",
        "port": 443,
        "effective-expiration-date": "2014-12-31T12:59:59",
        "include-subdomains": true,
        "served-certificate-chain": [
            "-----BEGINCERTIFICATE-----\nMIIAuyg[...]tqU0CkVDNx\n-----ENDCERTIFICATE-----"
        ],
        "validated-certificate-chain": [
            "-----BEGINCERTIFICATE-----\nEBDCCygAwIBA[...]PX4WecNx\n-----ENDCERTIFICATE-----"
        ],
        "known-pins": [
            "pin-sha256=\"dUezRu9zOECb901Md727xWltNsj0e6qzGk\"",
            "pin-sha256=\"E9CqVKB9+xZ9INDbd+2eRQozqbQ2yXLYc\""
        ]
    }

非强制,只报告

HPKP 也可以设置为非强制的,可以使用 Public-Key-Pins-Report-Only 来只发送违例报告给你。

这样可以让你在网站不可访问或 HPKP 配置不正确时不固定,之后你可以将这个响应头改为 Public-Key-Pins 来强制固定。

(0)

相关推荐

  • 高性能WEB开发 nginx HTTP服务器篇

    第一篇:HTTP服务器 因tomcat处理静态资源的速度比较慢,所以首先想到的就是把所有静态资源(JS,CSS,image,swf) 提到单独的服务器,用更加快速的HTTP服务器,这里选择了nginx了,nginx相比apache,更加轻量级, 配置更加简单,而且nginx不仅仅是高性能的HTTP服务器,还是高性能的反向代理服务器. 目前很多大型网站都使用了nginx,新浪.网易.QQ等都使用了nginx,说明nginx的稳定性和性能还是非常不错的. 1. nginx 安装(linux) htt

  • iis的http 500内部服务器错误的解决

    IIS500错误,是因为微软的一个BUG所造成的.下面是解决办法: 主要是由于IWAM账号(在我的计算机即是IWAM_MYSERVER账号)的密码错误造成了HTTP 500内部错误. 在详细分析HTTP500内部错误产生的原因之前,先对IWAM账号进行一下简要的介绍:IWAM账号是安装IIS5时系统自动建立的一个内置账号,主要用于启动进程之外的应用程序的Internet信息服务.IWAM账号的名字会根据每台计算机NETBIOS名字的不同而有所不同,通用的格式是IWAM_MACHINE,即由"IW

  • 提示“处理URL时服务器出错”和“HTTP 500错误“的解决方法

    其实这种情况都是因为大家表达问题不清而造成的. 下面讲讲这两种错误的原因: 1.处理URL时服务器出错,请和系统管理员联系! 只要在服务器上的IIS设置里选上"向客户端发送文本错误信息"这一项,那么页面上出现的任何错误都会显示"处理URL时服务器出错,请和系统管理员联系!"这一句话,所以这时你需要做的就是联系服务器管理员,将这一选项去掉,或者是将网站下载到本地进行调试.光靠这一条信息向人求助是得不到任何帮助的,因为大家看不到详细的错误信息.  2.HTTP 500错

  • 在服务器上启用HTTP公钥固定扩展的教程

    公钥固定(Public Key Pinning)是指一个证书链中必须包含一个白名单中的公钥,也就是说只有被列入白名单的证书签发机构(CA)才能为某个域名*.example.com签发证书,而不是你的浏览器中所存储的任何 CA 都可以为之签发.本文讲述了这种机制的背景知识,并提供了 Apache. Lighttpd 和 NGINX 上的配置范例. HTTP 公钥固定扩展 用你使用的银行做个例子,它一直使用 CA 公司 A 为其签发证书.但是在当前的证书体系下,CA 公司 B.CA 公司 C 和 N

  • 在Windows服务器上启用TLS 1.2及TLS 1.2基本原理介绍

    首先在这个网站上测试一下自己的服务器究竟处于什么水平. https://www.ssllabs.com/ssltest/ 测试结果显示是支持SSL3.0的并且不支持TLS 1.2.证书使用SHA1签名算法不够强.这点比较容易接受,因为Windows服务器默认并没有开启TLS1.2. 要提高服务器的评级,有3点需要做. 使用SHA256签名算法的证书. 禁用SSL3.0,启用TLS1.2 禁用一些弱加密算法. 由于目前服务器使用的证书是近3年前购买的,正好需要重新购买,顺便就可以使用SHA256签

  • 在服务器上启用HTTPS的详细教程

    现在,你应该能在访问https://konklone.com的时候,在地址栏里看到一个漂亮的小绿锁了,因为我把这个网站换成了HTTPS协议.一分钱没花就搞定了. 为什么要使用HTTPS协议: 虽然SSL并不是无懈可击的,但是我们应该尽可能提高窃听成本 加密通讯不应心存侥幸,所有连接都应被加密 福利: 使用了HTTPS之后,如果网站的访客是从其他已经使用了HTTPS的网站上跳转过来,你就能在Google Analytics中获取更完整的来源信息(比如Hacker News). 本文将为您说明,如何

  • 在服务器上配置仅使用HTTPS通信的教程

    HTTP 严格传输安全(HSTS)是一种安全功能,web 服务器通过它来告诉浏览器仅用 HTTPS 来与之通讯,而不是使用 HTTP.本文会说明如何在 Apache2.Nginx 和 Lighttpd 上如何启用 HSTS.在主流的 web 服务器上测试通过: Nginx 1.1.19. Lighttpd 1.4.28 和 Apache 2.2.22 ,环境为 Ubuntu 12.04. Debian 6 & 7 和 CentOS 6,只需要调整部分参数就可以工作在其它的发行版上. 什么是 HT

  • 在服务器上安装python3.8.2环境的教程详解

    在服务器上安装python3.8.2环境 官网3.8.2下载地址 https://www.python.org/downloads/release/python-382/ 下载安装 下载好了之后上传到服务器上 或者在服务器上通过命令下载 wget https://www.python.org/ftp/python/3.8.2/Python-3.8.2.tgz 执行安装 解压文件 tar -xvzf Python-3.8.2.tgz 进入文件的目录 cd Python-3.8.2 添加配置文件 配

  • 在Apache服务器上启用GZip压缩静态内容的方法

    为了优化网站的访问速度,我们可以通过对静态内容进行压缩,从而减少网页加载的时间,大大节省用户的带宽.在这篇文章中,我将介绍如何使用Apache和.htaccess文件进行静态内容压缩. 首先让我介绍一下,我们可以使用两种不同的方法压缩内容:GZip 和 deflate. 介绍 GZip方法在早期的apache版本中使用(在Apache 1.3之前).但在那之后apache引入了deflate方法,相比GZip并没有太大的效果(但仍是非常好的).然而,GZip在apache 1.3之后不再提供更多

  • 在 Windows服务器中启用/禁用SMBv1、SMBv2和SMBv3的方法

    本文介绍如何在 SMB 客户端和服务器组件上启用/禁用服务器消息块 SMBv1.SMBv2 和 SMBv3. 注意:建议由专业技术工程师完成以下操作. 禁用 SMBv2 和 SMBv3 的影响 我们建议不要禁用 SMBv2 或 SMBv3.禁用 SMBv2 或 SMBv3 只能作为临时故障排除措施.请勿使 SMBv2 或 SMBv3 保持禁用状态. 禁用 SMBv2 的影响 在 Windows 7 和 Windows Server 2008 R2 中,禁用 SMBv2 会停用以下功能: 请求复合

  • windows服务器上的iis Gzip压缩功能启用

    如果压缩动态文件(PHP,asp,aspx)就不需要了,因为它的页面是每次都动态生成的,压缩完就放弃.然后在IIS管理器中,"网站"上面右键-属性,不是下面的某个站点,而是整个网站.进入"服务"标签,选上启用动态内容压缩,静态内容压缩. 然后选中网站下面那个服务器扩展,新建一个服务器扩展.名字无所谓,下面的添加文件的路径是: c:\windows\system32\inetsrv\gzip.dll,然后启用这个扩展. 这时候静态内容是可以压缩的,但是对于动态内容,a

  • 在Web服务器上如何启用并运行FTP服务

    如果要允许用户在站点中上载或下载文件,就需要在 Web 服务器上设置 FTP.无论站点是位于 Intranet 还是位于 Internet 上,使用 FTP 在所提供的位置中上载和下载文件的原理是相同的.您需要将文件放在 FTP 服务器上的目录中,以便用户可以建立 FTP 连接并通过 FTP 客户端或启用 FTP 的 Web 浏览器进行文件传输.本文介绍在 Web 服务器上如何启用并运行 FTP 服务. 安装 IIS 7.0 中的 FTP 若要设置 FTP 站点,必须先通过Windows Ser

  • Tomcat在Linux服务器上的BIO、NIO、APR模式设置方法

    一.BIO.NIO.AIO 先了解四个概念: 同步 : 自己亲自出马持银行卡到银行取钱(使用同步IO时,Java自己处理IO读写). 异步 : 委托一小弟拿银行卡到银行取钱,然后给你(使用异步IO时,Java将IO读写委托给OS处理,需要将数据缓冲区地址和大小传给OS(银行卡和密码),OS需要支持异步IO操作API). 阻塞 : ATM排队取款,你只能等待(使用阻塞IO时,Java调用会一直阻塞到读写完成才返回). 非阻塞 : 柜台取款,取个号,然后坐在椅子上做其它事,等号广播会通知你办理,没到

随机推荐