别闹!自签名证书!

1,032 阅读6分钟

程序员英语这本书虽然事实证明确实写的不怎么样,但是开头的一些内容还是值得参考的,比如其中的一道思考题:自签名证书会带来哪些危害。

既然说起这个,当然要从最简单的 HTTPS 说起。

为什么我们需要 HTTPS

理论上而言,HTTPS 即通信加密,可以预防窃听和中间人攻击,当然,对于大多数用户和网站而言,最重要的是避免了各层的劫持。

Google 有总结曰:

  • 善意的或恶意的入侵者会利用您的网站和用户之间传输的每个未受保护的资源。
  • 许多入侵者都会查看汇总的行为以识别您的用户。
  • HTTPS 不仅可阻止您的网站被滥用,也是许多先进功能不可或缺的一部分,可作为类似应用功能(如服务工作线程)的实现技术。

HTTPS 是怎么工作的

说了半天,一定还是会好奇,HTTPS 到底是怎么工作的?(如果不好奇的请直接跳至下一节 QvQ)

简单的来说 HTTPS 的 S,就是 SSL/ TLS,SSL 是 TLS 的前身,基本上我们当成同一个 (S)看就行,换言之,HTTPS = HTTP + SSL / TLS,在 TCP 层到 HTTP 层之间加了一层 SSL。

如图所示,在 HTTP 网站通讯中,由于没有一个三方认证的过程:

你完全无法得知,你收到的结果是否是被篡改后的结果,当然,更无法保证,即使没动过的数据,是不是会被窃听。

我们叫图中那位黑客「中间人」,也就会造成上文所说的中间人攻击。

因此后来,大家就想到了,只要手握一份密钥,是否就天下我有了?

常见的加密有两种:对称加密和非对称加密——但是我们实际上发现,无论用对称加密还是非对称加密,密钥一泄露,还是没办法(在非对称加密中,公钥本身是公开的,只要截取私钥返回,需要公钥解密的部分,照样的截获数据)。

于是乎,我们又想到了一种升级的加密方式:对称与非对称结合。

然后就变成了上图中的加密方式,我先用非对称加密的方式传输密钥,然后用对称加密传输数据,这样就可以避免了传输过程中对称加密密钥泄露和公钥公开导致的截获数据两个问题了——但是,怎么证明你是个好人呢?

于是,终于找到了一个可信的三方机构:证书发布机构。

浏览器会在发起请求时帮你检验这个网站证书中的信息是否合法,是否是由授信机构发布的,如果不合法,那么就会报错,如果合法,那么就用对应颁发者的 CA 公钥解密,对服务器证书的签名解密。

之后使用 Hash 算法计算得到的证书和服务器发来的证书对应 hash 是否一致,如果一直,代表没有被冒充。

之后读取证书中的密钥,用于后续加密通讯。

最终,我们的整个过程都不怕窃听篡改了——不过,可能有个让人困惑的问题,我的操作系统是怎么拥有这么多 CA 公钥的。

实际上,顶级的 CA 屈指可数,那些其他签发商,其实是被间接信任的,正好在前几天,Let's Encrypt 发布了一条消息,说明他们未来会被所有主要的程序直接信任,而过去,他们一直是被间接信任的,是由于浏览器和操作系统信任 IdenTrust,而 IdenTrust 信任他们,因此他们才被信任:

Browsers and operating systems have not, by default, directly trusted Let’s Encrypt certificates, but they trust IdenTrust, and IdenTrust trusts us, so we are trusted indirectly. IdenTrust is a critical partner in our effort to secure the Web, as they have allowed us to provide widely trusted certificates from day one.

如何为你的网站升级 HTTPS

说到升级,当然要说到 Let's Encrypt,他们提供了免费可靠的 SSL 证书,同时前一阵开始提供免费的泛域名证书(意思是之前我们只提供针对 www.codesky.me 的证书,但是之后他们提供 *.codesky.me 的证书)。

实际上,使用 certbot 可以帮助你最轻松的部署 Let's Encrypt 的证书:certbot.eff.org/lets-encryp…

当然,你可以自己使用自带的证书和私钥配置证书,这里只以 Nginx 为例:

server {
    listen              443 ssl;
    server_name         www.example.com;
    ssl_certificate     www.example.com.crt;
    ssl_certificate_key www.example.com.key;
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    ...
}

简单几步,配置完成。

我可以使用自签名证书吗?

当然,你自己可以使用 openssl 生成一个证书,但是按照我们所讲的过程,这个证书是不受信任的,所以会以下提示:

图中是 12306 网站对于 https 的处理,当然,他非常的有觉悟,给大家提供了根证书的下载:

当然,你也可以选择信任他,绕过这一限制,但是与此同时,就意味着你承担了 HTTPS 所想要规避的所有问题。如果是有软件或者应用希望你信任他们的证书,也需要权衡再三:

作为一个可信的中间人,他们依旧是一个中间人,如果这个中间人变得不再可靠,那么传输也就不再可靠了,另一方面,即使他们并不想做什么,不完善的服务器管理制度也会导致密钥泄露,让你的通讯无处遁形。

HTTPS 对现有网站会有影响吗?

HTTPS 如果对网站有影响,那么很多网站可能就会开始考虑上不上了,尽管答案很简单——利大于弊。

目前笔者所关注到的弊端无非就是:企业证书的昂贵,以及 HTTPS 需要校验证书,这多了一步 SSL,因此也就拖延了一些速度,另外 HTTP -> HTTPS 转换的时候可能也会增加耗时(直接访问 HTTPS 就不会有这个烦恼啦)。

另外,HTTPS 可能对你的 SEO 有意想不到的效果,目前 Google 和百度都有书面文字表示他们会对 HTTPS 的站点优先收录:webmasters.googleblog.com/2014/08/htt…

但是比起其他问题来说,HTTPS 更给人一种可靠,靠谱的感觉,所以为什么不来一个 HTTPS 呢?

当然,万一你的用户还在使用 IE6 呢——

(注:IE6 并不是不支持 HTTPS,而是不支持 SNI,不支持意味着只能一个 IP 对应一个域名一个证书,很明显在现代网站构建中这是一个不合理的设计,详情可以阅读:https和SNI

参考资料