Certificate Transparency 那些事

胡绪宜 8年前
   <p>最近本站 HTTPS 方面有两个变化:一是本站域名(imququ.com)加入了 Chrome 的 HSTS Preload List,从 Chrome 49 开始生效;二是我给本站 HTTPS 证书启用了 Certificate Transparency 策略。HSTS Preload List 在我之前的文章中写过,更多介绍及申请如何加入请点这里。本文主要介绍 Certificate Transparency。</p>    <h3>Certificate Transparency 是什么?</h3>    <p>HTTPS 网站的身份认证是通过证书信任链完成的,浏览器从站点证书开始递归校验父证书,直至出现信任的根证书(根证书列表一般内置于操作系统,Firefox 则自己维护)。然而,受信任的 CA(证书颁发机构)有好几百个,他们成为整个网站身份认证过程中一个较大的攻击面。实际上,目前由于 CA 失误导致错误签发证书;以及个别 CA 出于某些目的(如监控加密流量)故意向第三方随意签发证书这两种情况时有发生。</p>    <p>无论是 CA 无意或有意签发出来的「非法证书」,都能通过目前的证书链校验机制的验证。这些 CA 签发的「非法证书」相比自签名的「无效证书」,更难被发现,即使被发现依靠现有机制也很难快速消除影响。</p>    <p>另外,域名所有者的管理不善也可能导致域名配置被第三方控制,从而第三方能够向 CA 申请你网站的证书(特别是 DV 类型的证书)。这种情况,发现和处理同样很麻烦。</p>    <p>而 <a href="/misc/goto?guid=4959662581647549836" rel="nofollow,noindex">Certificate Transparency</a> 就是为了解决这些问题诞生的,它可以直译为证书透明度,由 Google 主导,并由 IETF 标准化为 <a href="/misc/goto?guid=4959662581728559350" rel="nofollow,noindex">RFC6962</a> 。Certificate Transparency 的目标是提供一个开放的审计和监控系统,可以让任何域名所有者或者 CA 确定证书是否被错误签发或者被恶意使用,从而提高 HTTPS 网站的安全性。</p>    <p>Certificate Transparency 整套系统由三部分组成:1)Certificate Logs;2)Certificate Monitors;3)Certificate Auditors。完整的工作原理可以看官方文档: <a href="/misc/goto?guid=4959662581809167875" rel="nofollow,noindex">How Certificate Transparency Works</a> 。</p>    <p>简单说来,证书所有者或者 CA 都可以主动向 Certificate Logs 服务器提交证书,所有证书记录都会接受审计和监控。支持 CT 的浏览器(目前只有 Chrome)会根据 Certificate Logs 中证书状态,作出不同的反应。CT 不是要替换现有的 CA 设施,而是做为补充,使之更透明、更实时。</p>    <p>Certificate Logs 服务器由 Google 或 CA 部署, <a href="/misc/goto?guid=4959662581899970021" rel="nofollow,noindex">这个页面</a> 列举了目前已知的服务器。合法的证书提交到 CT Logs 服务器之后,服务器会返回 signed certificate timestamp(SCT),要启用 CT 就必须用到 SCT 信息。</p>    <h3>如何启用 Certificate Transparency</h3>    <p>根据官方文档,启用 CT 有三种方案,分别介绍如下:</p>    <p>1)通过 X.509v3 扩展</p>    <p>CA 先预签证书,并将证书提交到 CT Logs 服务器得到 SCT 信息,然后 CA 将 SCT 做为预签证书的扩展再次签名,这样就得到了一个含有 SCT 扩展的证书。通过查看 TLS 握手阶段中的 Certificate 响应可以看到 SCT 信息(OID 1.3.6.1.4.1.11129.2.4.3):</p>    <p><img src="https://simg.open-open.com/show/7287c102a0fb60435f13484fb77d4c2f.png"></p>    <p>2)通过 TLS 扩展</p>    <p>我们也可以自己提交证书给 CT Logs 服务器,得到 SCT 并存起来。然后通过配置 Web Server,使其能在 TLS 握手阶段的 Server Hello 响应中启用 signed_certificate_timestamp 扩展,传递 SCT 信息。具体配置方法后面再介绍,这里先来看下这个扩展长什么样:</p>    <p><img src="https://simg.open-open.com/show/8f482ff33b924ae856ab670b94c4fe24.png"></p>    <p>当然,只有客户端在 Client Hello 请求中包含了 signed_certificate_timestamp 扩展时,服务端才需要给出对应的 SCT 回应。</p>    <p>3)通过 OCSP Stapling</p>    <p>还有一种做法是,CA 按照普通流程完成证书签发后,再将证书提交到 CT Logs 服务器得到 SCT,然后改造 OCSP(Online Certificate Status Protocol,在线证书状态协议)服务,将 SCT 信息包含到 OCSP 响应中。服务端启用 OCSP Stapling(OCSP 封套)后,就可以在证书链中包含证书的 OCSP 查询结果,其中就包含 SCT 信息。</p>    <p>简单对比一下三种方案:</p>    <table>     <thead>      <tr>       <th> </th>       <th>CA 成本</th>       <th>开发者成本</th>       <th>备注</th>      </tr>     </thead>     <tbody>      <tr>       <td>X.509v3 扩展</td>       <td>高(需要实时提交证书并等待返回 SCT、签署两次证书)</td>       <td>无</td>       <td>DigiCert 支持这种方案( <a href="/misc/goto?guid=4959662581982153740" rel="nofollow,noindex">via</a> )</td>      </tr>      <tr>       <td>TLS 扩展</td>       <td>无</td>       <td>高(需要自己提交证书、编译 Web Server 加入 CT 模块、修改配置等)</td>       <td>任何证书都可以使用这种方案</td>      </tr>      <tr>       <td>OCSP Stapling</td>       <td>中(需要异步提交证书取回 SCT、改造 OCSP 服务)</td>       <td>中(需要启用 Web Server 的 OCSP Stapling)</td>       <td>Let's Encrypt 计划支持这种方案( <a href="/misc/goto?guid=4959662582071409886" rel="nofollow,noindex">via</a> )</td>      </tr>     </tbody>    </table>    <p>通过 TLS 扩展启用 CT 是最普适的方案,接下来简单介绍下在 Nginx 中如何操作:</p>    <p>1)获取 SCT 文件</p>    <p>通过 <a href="/misc/goto?guid=4959662582156901616" rel="nofollow,noindex">ct-submit</a> 这个模块,可以方便地将证书提交给 CT Logs 服务器并得到 SCT 响应。这个模块需要 go 语言的支持:</p>    <pre>  apt-get install golang    wget -O ct-submit.zip -c https://github.com/grahamedgecombe/ct-submit/archive/v1.0.0.zip  unzip ct-submit.zip  cd ct-submit-1.0.0  go build  </pre>    <p>编译成功后,当前目录会出现名为 ct-submit-1.0.0 的可执行文件。接着就可以提交了:</p>    <pre>  ./ct-submit-1.0.0 ct.googleapis.com/aviator <~/www/ssl/chained.pem >~/www/scts/aviator.sct  ./ct-submit-1.0.0 ct1.digicert-ct.com/log <~/www/ssl/chained.pem >~/www/scts/digicert.sct  </pre>    <p>以上代码分别向 Google 和 Digicert 的服务器提交了证书,更多可用的服务器可以在 <a href="/misc/goto?guid=4959662581899970021" rel="nofollow,noindex">这个页面</a> 找到。</p>    <p>chained.pem 是我的站点证书和中间证书,最开始是站点证书,之后是中间证书。</p>    <p>2)编译 Nginx,加入 CT 模块</p>    <p>要让 Nginx 支持发送 signed_certificate_timestamp 这个 TLS 扩展,需要加入 <a href="/misc/goto?guid=4959662582247989507" rel="nofollow,noindex">nginx-ct</a> 这个模块。nginx-ct 需要与 OpenSSL 1.0.2+ 或者 BoringSSL 4fac72e+ 一起编译,不支持 LibreSSL。推荐使用 CloudFlare Patch 过的 OpenSSL( <a href="/misc/goto?guid=4959656369863908716" rel="nofollow,noindex">via</a> ):</p>    <pre>  git clone https://github.com/cloudflare/sslconfig  wget -O openssl.zip -c https://github.com/openssl/openssl/archive/OpenSSL_1_0_2-stable.zip  unzip openssl.zip  mv openssl-OpenSSL_1_0_2-stable/ openssl  cd openssl && patch -p1 < ../sslconfig/patches/openssl__chacha20_poly1305_cf.patch     cd ../    wget -c http://nginx.org/download/nginx-1.9.10.tar.gz  tar zxf nginx-1.9.10.tar.gz    wget -O nginx-ct.zip -c https://github.com/grahamedgecombe/nginx-ct/archive/v1.0.0.zip  unzip nginx-ct.zip    ./configure --add-module=../nginx-ct-1.0.0 --with-openssl=../openssl --with-http_v2_module --with-http_ssl_module  </pre>    <p>然后 make 并 make install 就搞定了。 make install 之前记得先停掉 nginx 服务,不然很可能需要手动杀死之前的 nginx 进程。</p>    <p>3)修改配置</p>    <p>最后,修改 Nginx 配置,加入以下两行并重启服务即可:</p>    <pre>  ssl_ct               on;  ssl_ct_static_scts   /your/path/to/scts;  </pre>    <h3>Certificate Transparency 与 Chrome</h3>    <p>最后,说了这么多,如何不启用 CT 会有什么后果呢?实际上,对大部分网站影响都不大。首先 CT 策略目前只有 Chrome 支持;其次 Chrome 也知道现在支持 CT 的网站并不多,所以对于没有提供 SCT 信息的 HTTPS 网站也没有太大的影响。</p>    <p>对于使用 EV 证书的网站,如果没有按要求提供 SCT 信息,从 2015 年 1 月 1 日开始,Chrome 不会显示小绿条(详细要求可以看 <a href="/misc/goto?guid=4959662582365067950" rel="nofollow,noindex">这个页面</a> )。一般 EV 证书提供商都会把 SCT 信息嵌入到证书之中,大家如果有 EV 证书可以检查一下。万一证书里没有嵌入 SCT 信息,那最好通过 TLS 扩展的方式启用 CT,不然买了 EV 证书,Chrome 不给显示小绿条还是挺亏的。</p>    <p>对于其它类型的证书(OV、DV 等),如果没有提供 SCT 信息,最新的 Chrome 只是会在点击地址栏小绿锁时给出说明,内容如下:</p>    <p>The server did not supply any Certificate Transparency information.服务器未提供任何 Certificate Transparency 信息。</p>    <p>Chrome 的这个提示内容有过调整,之前是这样的:</p>    <p>The identity of this website has been verified by XXX but does not have public audit records.该网站的身份已通过 XXX 的认证,但没有公开审核记录。</p>    <p>而提供 SCT 信息之后,Chrome 的提示是这样的:</p>    <p>The server supplied valid Certificate Transparency information.服务器提供了有效的 Certificate Transparency 信息。</p>    <p>本站截图如下:</p>    <p><img src="https://simg.open-open.com/show/654e8eee01b62fb002bf9a90c1af1c8c.png"></p>    <p>本文先写到这里。明天我就要回家过年了,祝大家新春快乐,吉祥如意~</p>    <p>本文链接: <a href="/misc/goto?guid=4959662582447599042" rel="nofollow,noindex">https://imququ.com/post/certificate-transparency.html</a> , <a href="/misc/goto?guid=4959662582536497559" rel="nofollow,noindex">参与评论</a> 。</p>    <p>-- EOF --</p>    <p>发表于 2016-02-03 21:59:06 ,并被添加「HTTPS、Nginx」标签,最后修改于 2016-02-03 21:59:06 。</p>    <p>本站部署于「 <a href="/misc/goto?guid=4958975655827797837" rel="nofollow,noindex">阿里云 ECS</a> 」。如果你也要购买阿里云服务,可以使用我的九折推荐码  <strong> <em>NY1Z0E</em> </strong> (限新用户),多谢支持!</p>    <p> </p>    <p>来自: <a href="/misc/goto?guid=4959662581555621417" rel="nofollow">https://imququ.com/post/certificate-transparency.html</a></p>    <p> </p>