HTTPS 握手过程

在讨论 CDN 之前,我们需要先完成 HTTP 请求的握手。如果一个请求发往 443 端口,那么我们就需要按 HTTPS 协议进行握手。这时就涉及到一个问题,如何识别这个请求对应的主机?在 HTTP 请求中,客户端发起 GET 或者 POST 请求,在头部会有一个 Host 字段,对应值就是访客输入的域名。例如访问 http://90.cx/ 的请求头是这样:

GET / HTTP/1.1
Host: 90.cx
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36

我们都知道 HTTPS 的作用就是加密数据,加密的过程是这样的:

  1. 客户端发起 HTTPS 连接;
  2. 服务器返回证书(公钥)
  3. 客户端产生随机密码并使用公钥加密;
  4. 以下省略……

涉及到密码学的知识这里不多讲,只说涉及到我们开发的技术细节。在发起 HTTPS 请求的时候,上面那一串 GET 数据也是要保护的,因此服务器必需先给证书。这时问题就来了,我们还不知道用户访问的是哪个域名,如何提供对应的证书?在以前,主机商要求使用 HTTPS 的网站都必需购买独立 IP,就是这个原因。

可是我们是 CDN 厂商啊,节点是分散的啊,这怎么能忍?因此有了 SNI(Server Name Indication 服务器名称指示)。从 Windows Vista 开始的系统,都已经支持 SNI 了。而 XP 环境下,许多用户使用的是 360、猎豹等国产多核浏览器,非 IE 内核也是支持 SNI 的。

有了 SNI 扩展,在第一步发起 HTTPS 连接的时候,客户端将会发送对应的域名给服务器的 443 端口。服务器收到之后检查对应域名的证书返回给客户端完成支持。

在标准 Nginx 中,都是通过配置文件的方式实现的证书载入和更新。但是作为 CDN 厂商我们是无法容忍 reload 的。因此我们二次开发 Nginx 完成动态证书支持,将证书和私钥全部存放到 CDN 节点的内存中,当用户请求 Hostker&主机壳 的 CDN 时,我们不需要查询配置文件,直接读取域名并在内存中找到对应的证书和私钥完成握手过程。

用户对某个域名进行增加、删除证书和私钥操作时,我们会直接把对应操作下发到全网 CDN 节点,直接操作内存进行修改。同样不需要接触 Nginx 的配置文件,节省的 reload 过程可以让操作生效时间非常短,通常在 1 分钟内就可以完成全网部署。

完成 HTTPS 握手之后,就可以进入 CDN 处理了。

下一篇《解密 Hostker&主机壳 CDN——Nginx篇

发表评论

电子邮件地址不会被公开。 必填项已用*标注

This site uses Akismet to reduce spam. Learn how your comment data is processed.