迈向HTTPS(五)来之StackOverflow的迁移经验

Stack Overflow 是世界上最大的问答网站,大部分码农必须依赖它,最近他们也全部迁移到了 HTTPS,写了一篇很长的文章来说这个事情,非常具有实践性,这篇文章没有讲 HTTPS 的概念,而是强调他们是如何进行迁移的。从一篇博文的角度来说,很难优雅的描述这么复杂的一个事情,他们从三个部分来描述这个事情,分别是基础架构、应用层代码、犯过的一些错误。

面临的挑战

Stack Overflow 从 2013 年就开始考虑迁移到 HTTPS 了,也就是说这个项目从准备到上线一共花了四年的事情,原因在哪儿呢?第一点是项目优先级的问题,Stack Overflow 不是电商系统也不是银行系统,它的数据都可以任意下载,所以安全并不是最重要的事情,相对其他工作来说,优先级低了不少。

第二点原因就是这个工作非常复杂,有很多的依赖性。有上百个域名,而且还有四级域名(比如 meta.gaming.stackexchange.com);允许用户上传内容(比如嵌入 YouTube 的视频);只有一个数据中心(需要考虑延迟的问题);有广告(这些广告本身可能没有 HTTPS);有很多 HTTP 的 API(很难让用户迁移);用了 websockets,对性能要求很高,支持 HTTPS 可能会让性能受损。

最终他们还是选择支持 HTTPS 了,原因在于有很多不同的角色在 Stack Overflow 上工作,需要保证他们的安全、隐私不被泄漏;另外 Google 搜索排名会优先对待 HTTPS 协议的网站(虽然不知道具体的影响是什么);最重要的迁移原因居然是性能(想想 HTTP/2)。

复杂的证书

Stack Overflow 为什么不使用 Let’s Encrypt 呢,因为 Let’s Encrypt 适合单个域名或几个域名的网站,而且它也不支持通配符的证书。而想下 Stack Overflow,每新增一个问答类别,就会增加一个域名。域名有上百个,更可怕的是还有四级域名。

假如不把所有域名证书进行合并,那么每部署一个问答类别,就要新弄一个证书,另外居然有 2% 的客户不支持 SNI(潜台词这些用户不能丢失,不能丢失就只能为新增的网站部署新的 IP 地址),SNI 是什么就不解释了,假如你使用虚拟主机(IP 资源有限),那么有些用户可能就永不了你的 HTTPS 网站了。

另外不使用 Let’s Encrypt 的原因就是希望自己控制证书,因为需要将证书部署在负载均衡设备上(Stack Overflow 用的是 HAproxy)、CDN/proxy 上;未来 Stack Overflow 可能还会支持 HPKP。

最终他们选择了 DigiCert 的证书,可以称之为多域名统配型证书,大部分域名使用同一个证书,原因上面也讲了,为了管理方便,并且为了兼容不支持 SNI 的用户。

什么是多域名通配型证书?他们有很多一级子域名,比如 askubuntu.com 和 serverfault.com,为了放在一个证书中,就必须选择多域名证书;而很多一级子域名又可能有很多子域名,为了方便可以选择通配型证书,比如一个证书可以支持 boardgames.stackexchange.com 和 gaming.stackexchange.com(可能还有其他的)。

比较麻烦的是他们居然有四级域名(他们称为 second place 服务),比如有 meta.gaming.stackexchange.com、meta.boardgames.stackexchange.com 等等,而通配符只能允许“通配”一级,比如不允许meta.*.stackexchange.com通配符。最终的方案就是统一规划 second place,选择标准的域名 *.meta.stackexchange.com 来提供服务,假如是老的访问方式就进行 301 跳转,你可以访问 http://meta.gaming.stackexchange.com 看看。

在这个迁移改造中也引出一个新问题,在登录的时候是给顶级域名种植 Cookie,它的子域名会继承,这样是有一些风险的,所以需要移除一些域名,举个例子,他们是使用 SendGrid 发送邮件的,里面的引用地址都是假如是 sg-links.stackoverflow.com(CNAME 到 SendGrid),那么就会发送 stackoverflow.com 的 Cookie 到 SendGrid 上,带来了安全问题。所以剥离 sg-links.stackoverflow.com 域名至 sg-links.stackoverflow.email

另外用户可能很奇怪 Stack Overflow 的官方博客为什么使用 stackoverflow.blog 域名,道理很简单,就是为了避免 Cookie 带来的安全问题,另外官方博客使用的证书也是独立的,使用的是 Let’s Encrypt 的证书,这是很好的一个思路。

HTTP/2

在传统的观点中,HTTPS 是影响性能的,但是这个观点已经过时了,大部分网站支持 HTTPS 的下一步就是支持 HTTP/2。其实 HTTP/2 协议本身是不需要加密的,但是很多浏览器为了实现一些功能,需要一条加密的通道,所以演变成 HTTP/2 必须构建在 HTTPS 上面。

HTTP/2 在性能上有很多优势,其中有个特性和证书有关,就是 HTTP/2 能够推送内容到不同的域名,只要证书符合两个条件:

  • 这些域名最终能够解析到同一个 IP 地址
  • 这些不同的域名有相同的证书

而 stackoverflow.com 和 cdn.sstatic.net(自己的 CDN?怎么能解析到相同的地址) 解析的 IP 地址是相同的,证书也是同一个,这将为将来实现 push 打下了基础。另外强调一句,Stack Overflow 的迁移动力永远是性能而非安全性。

HAproxy

选择 HAproxy 作为负载均衡而非 Nginx 就因为其简单、专注。HAProxy 1.5 版本后支持 OpenSSL,一些配置说明如下:

  • 运行的是 4 颗 CPU,其中一个处理到后端的请求,另外的处理 HTTPS 的逻辑
  • HAproxy 通过 abstract named socket 连接后端
  • 转发到后端的时候,会通过一个 Header 头来标识是不是 HTTPS 的请求
  • 选择的密钥套件标准来之 Mozilla

CDN/Proxy

对于一个大型网站来说,服务器不是第一位的,重要的是解决延迟问题,但这受限与光速,而云技术能够改善,这时候 CDN 可以出场了,Stack Overflow 只有一个数据中心,所以很迫切使用 CDN,尤其在部署 HTTPS 以后,需要通过减少延迟来抵消 HTTPS 带来的性能消耗(主要是握手协议)。

Stack Overflow 混用了 Cloudflare 和 Fastly 这两个 CDN。CDN 的功能主要就是处理 HTTPS 的握手、防止 DDoS 攻击、一些 CDN 功能、离用户最近。

个人没有使用 CDN 的经验,包括 Global DNS 的概念,所以这里没有看的太明白,最终选择 Fastly 的原因在于他们的服务比较适合,比较定制化,尤其 Varish 的 VCL 配置非常的灵活。当然不是说 Cloudflare 不好,他自己的博客就使用了 Cloudflare 的 CDN。

另外自己未来也要了解下负载均衡和 CDN 的相关知识,这也和 Stack Overflow 的架构有关,这也要看下其他相关的博客文章。

全局登录

虽然 Stack Overflow 有很多域名,但是他是中心化的服务,不管你访问那个域名,最终执行的就是 w3wp.exe 这个进程,通过不同的 Host Header 来进行不同的处理。简单的说所有的网站可以运行在一个服务器上,能够快速的进行扩展。

全局登录从应用层角度来说是非常重要的事情,所以优先提一下,在早期的 Stack Overflow 中,不同的网站种植不同域名的 Cookie,对于用户来说这个体验很不好,你本质上是一个网站,在不同的问答区切换却要登录多次。

他们通过全局登录解决了这个问题(其实和 HTTPS 没有啥关系,只是在迁移过程中,重新规划了域名体系),全局登录的技术方案其实就是在用户从某个问答切换到另外个问答的时候,执行一个图片加载操作,进行 Token 的校验和 Cookie 的处理。

HTTPS 开发环境

从我个人角度来说,当部署 HTTPS 后,本地开发环境是否也要部署 HTTPS 呢,这还有挑战性,因为你假如在本地全面部署 HTTPS (尤其将证书放在本地,这很有风险),Stack Overflow 是如何做的?

Stack Overflow 的开发环境是使用的 IIS,它有个工具能够很好的部署本地开发环境。本地开发环境用的域名和证书都和线上是不一样的(有可能自建证书)。

另外在本地开发环境尽量保持和线上环境是一致的,举两个例子,第一不建议使用 /content 加载资源,因为这会隐藏一些线上会遇到的问题(比如 CORS),大部分人喜欢在本地搭建完整的环境(比如线上有 5 个域名,而开发环境只有 1 个域名),让自己的开发环境部署在一台机器上是个很不好的实践。

第二个例子就是假如开发环境不使用 HTTPS ,可能会遇到 HTTPS 降级的问题,比如不发送 referer 。

来自用户的混合内容

HTTPS 协议要求加载的资源必须全部是 HTTPS 协议的,不建议加载 HTTP 协议的资源,但是 Stack Overflow 允许用户提交自己的内容(比如图片和视频),他们是如何解决这问题的?

其实处理策略很简单,就是用户最新提交的内容必须是 HTTPS,堵住了新增内容就要处理历史数据了。这里通过图片来说明下。他们发现 90%+ 的图片存储在 stack.imgur.com 上了,这个转换工作很简单,不用做任何的数据分析。然后他们分析了其他内容,发现很多引入的资源本身就直接支持 HTTPS(还是国外走的比较前),基本的处理规则就是假如外部资源直接支持 HTTPS 就使用,假如不支持 HTTPS 就进行转换(不是数据层的转换)。

为什么 Stack Overflow 不通过 Porxy 来统一处理图片,主要是带宽和存储的问题,另外图片也有版权问题,不应该通过 Proxy 转换,这涉及到版权问题。另外很多老帖子其实不是经常访问,即使加载不了 HTTPS 的资源,也没有多大的问题。

301 问题

301 可能会影响 Google 收集,所以务必注意 canonical 指令,第二个问题就是注意 301 版本的问题,不能什么情况下都进行 301 跳转,比如 POST 请求不能跳转,作者写了个处理 301 规则的伪代码,可以借鉴下。

Websockets

在 Stack Overflow 上很多地方用到了 Websockets,比如通知类信息,支持 SSL 也很简单,就是将 ws:// 协议变更为 wss:// 协议,假如不转换可能也有混合内容的问题,另外老的代理处理 ws:// 协议有些问题。

另外 websockets 非常消耗内存,尤其为了支持 TLS 恢复功能(减少两次握手),用在 TLS 会话缓存占用内存非常大。

一些错误

(1)不要使用 Protocol-Relative URLs

很多开发者在支持 HTTP 和 HTTPS 的时候,为了引入元素(比如图片),喜欢使用 //example.com 这样的方式,但是 Stack Overflow 认为是错误的(至少这个观点适合他们),因为不仅仅是页面会引入图片,在邮件和 API 中也会引入图片资源,但是他们不会有效执行 //example.com 这样的方式,所以 Stack Overflow 建议使用绝对路径,他们通过两个全局变量来实现。

(2)301 Caching

可能会有死循环问题,需要注意。

最后

  • TLS 1.0, 1.1, 1.2 协议支持,未来会支持 TLS 1.3 ,另外也即将废弃 TLS 1.0
  • 不支持 SSL v2, v3,因为有安全问题
  • 选择什么密钥套件,对于 CDN 使用 Fastly’s default suite,对于负载均衡使用 Mozilla’s Modern compatibility suite
  • CDN 到后端也是使用 HTTPS 协议(真安全)
  • 支持前向加密
  • 不支持 HPKP
  • 不支持 SNI,为了 HTTP/2 的性能
  • 不支持 IE6,因为不支持 SSL 协议,大部分码农也不使用 IE6
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容