Python部落(python.freelycode.com)组织翻译,禁止转载,欢迎转发。
注:本文共分五部分,其他四部分在今日推送的其他文章中。
今天,我们在Stack Overflow上默认部署了HTTPS。 所有流量现在都被重定向到https://,Google链接将在接下来的几周内更改。 激活这个功能真的是如翻转开关一样简单(功能标志),但为做到这一点已经花了好几年的时间。 到目前为止,HTTPS是所有问答网站的默认设置。
过去两个月,我们一直在Stack Exchange网络中推出HTTPS。 Stack Overflow是最后一个站点,并且是迄今为止最大的站点。 这对我们而言是一个巨大的里程碑,但决不是最终的结果。 还有更多的工作要做,我们将会介绍。 但终点已近在眼前,万岁!
友好提醒:这是漫长的旅程的故事。 故事很长,所以你会看到滚动条显示的非常小。 虽然堆栈交换/溢出在我们遇到的问题中并不是唯一的,但两种问题同时发生却相当罕见。 我希望您能找到我们的尝试,磨难,错误,胜利,甚至一些开源项目的一些细节,这些项目一直都是有帮助的。 很难将这样一个错综复杂的依赖关系链构造成一个按时间顺序排列的帖子,所以我将分析一下主题:基础设施,应用程序代码,错误等。
我认为首先列出使我们的情况有点独特的问题,是很有帮助的:
我们有数百个域名(很多网站和其他服务)
许多二级域名(stackoverflow.com,stackexchange.com,askubuntu.com等)
许多第4级网域(例如meta.gaming.stackexchange.com)
我们允许用户提交和嵌入内容(例如图片和YouTube视频在帖子中)
我们从一个数据中心提供服务(延迟到单一来源)
我们有广告(和广告网络)
我们使用websockets,在任何机器上都有超过500,000活跃连接
我们有DDoSed(代理)
我们有许多网站和应用程序通过HTTP API进行通信(代理问题)
我们痴迷性能(也许有点太多)
由于这篇文章有点疯狂,为方便起见可以通过下面连接访问:
开始
快速规格
基础设施
证书
子元(meta.*.stackexchange.com)
性能:HTTP / 2
HAProxy:提供HTTPS
CDN /代理:快速反击云计算延迟
准备代理:客户端计时
CloudFlare
Railgun
Fastly
全球DNS
测试
应用程序/代码
准备应用程序
全域登录
本地HTTPS开发
混合内容
来自用户
来自我们
重定向(301s)
WebSockets
未知数
错误
协议相对URL
API和.internal
301缓存
帮助中心SNAFU
开源
下一步
HSTS预加载
聊天
今天
开始
早在2013年我们就开始考虑在Stack Overflow上部署HTTPS。所以显而易见的问题是:现在是2017年。这4年时间都在做什么? 几乎任何IT项目延迟无非两个原因:依赖和优先级。 老实说,Stack Overflow的信息并不像很多其他数据那样有价值(安全)。 我们不是银行,我们不是医院,我们不处理信用卡付款,我们甚至在四分之一的时间内通过HTTP和torrent发布我们的大部分数据库。 这意味着从安全的角度来看,它并不像其他情况那样高优先级。 与大多数相比,我们还有更多的依赖关系,这是部署HTTPS时一些巨大问题的一个非常独特的组合。 如稍后您会看到的,一些域名问题也是永久性的。
造成问题的最大领域是:
用户内容(用户可以上传图片或指定网址)
广告网络(合同和支持)
从单个数据中心托管(延迟)
数百个域,多级(证书)
好的,为什么要在我们的网站上使用HTTPS? 好吧,数据不是唯一需要安全的事情。 我们拥有通过网络访问网站的各种级别的版主,开发人员和员工。 我们希望保护他们与网站的通信。 我们希望确保每个用户的浏览历史。 有些人每天都在恐惧中生活,知道有人会发现他们秘密地喜欢独处。 谷歌也提升了HTTPS网站的排名(虽然我们不知道多少)。
对了,还有性能。 我们喜欢性能。 我喜欢性能。 你喜欢性能。 我的狗爱性能。 让我们有一个性能拥抱。 那很好,谢谢。 听起来不错吧。
快速说明
有些人只是想要结论,所以在这里快速问答(我们喜欢Q&A!):
问:你支持哪些协议?
答:TLS 1.0,1.1,1.2(注意:快速有一个TLS 1.0和1.1的弃用计划)。 TLS 1.3支持即将到来
问:您是否支持SSL v2,v3?
答:不,这些都是坏的,不安全的协议。每个人都应尽快禁用他们。
问:你支持哪些密码?
答:在CDN,我们使用Fastly的默认套件
答:在我们的负载平衡器,我们使用Mozilla的现代兼容性套件
问:通过HTTPS快速连接到原点?
答:是的,如果CDN请求是HTTPS,则原始请求是HTTPS。
问:你是否支持保密?
答:是的
问:你是否支持HSTS?
答:是的,我们现在正在Q&A网站上升级。一旦完成,我们将其移动到边缘。
问:您是否支持HPKP?
答:不,我们可能不会。
问:你支持SNI吗?
答:不,我们有HTTP / 2性能原因的组合通配符证书(详情如下)。
问:你在哪里获得证书?
答:我们使用DigiCert,他们已经很棒了。
问:你是否支持IE 6?
答:迁移到HTTPS让我们彻底放弃了IE6。 IE 6不支持TLS(默认 - 虽然可以启用1.0),但是我们不支持SSL。通过301重定向到位,大多数IE6用户无法再访问Stack Overflow。当TLS 1.0被删除时,就真的没有IE6用户了。
问:你使用什么负载均衡器?
答:HAProxy(它在内部使用OpenSSL)。
问:HTTPS的动机是什么?
答:人们不断攻击我们的管理后台地址,如stackoverflow.com/admin.php。
证书
我们来谈论证书,因为有很多的错误信息。我已经无法统计有多少人在说他安装了证书并且已经准备好使用HTTPS了。再看一下你的滚动条的小尺寸,如果我同意的话可以猜测一下。我们更喜欢SWAG方法进行猜测。
我们得到的最常见的问题是:“为什么不使用Let’s Encrypt?
答:因为他们在这里不适合。Let’s Encrypt正在做一件好事。我希望他们坚持下去。如果您使用的是单一网域或只有少数网域,对于各种场景来说,这是一个很好的选择。我们根本不是这样。Stack Exchange有数百个域。Stack Exchange不提供通配符。这两件事情是相互矛盾的。每次部署新的问答网站(或任何其他服务)时,我们都必须获得证书(或两个)。这使部署变得非常复杂,或者a)丢弃非SNI客户端(大约2%的流量)或者b)需要更多的IP空间。
我们要控制证书的另一个原因是我们需要在本地负载平衡器和CDN /代理提供程序上安装完全相同的证书。除非我们能够做到这一点,否则我们无法在所有情况下干净地进行故障转移(远离代理)。通过HPKP(HTTP公钥固定)固定证书的任何人都将无法验证。我们正在评估是否部署HPKP,但是我们已经为以后部署做好了准备。
我很吃惊我们的主要证书包含了所有的带通配符的主域名。这看起来像下图这样:
为什么这样做? 好吧,为了公平起见,DigiCert是根据要求为我们做这件事的人。 为什么每一次变化都要忍受手动合并证书的痛苦? 首先,因为我们想支持尽可能多的人。 这包括不支持SNI的客户端(例如,从一开始Android 2.3就是一件大事情)。 而且还因为HTTP/2和现实。 我们会很快介绍。
证书:Child Metas(meta.*.stackexchange.com)
Stack Exchange网络的原则之一就是有一个地方可以谈论每个问答网站。 我们称之为“second place”。 例如,meta.gaming.stackexchange.com用来谈论有关game.stackexchange.com。 那么为什么会这样呢? 好吧,我们今天的主题不是这个。 我们只关心这个域名。 一共4层。
前面我已经介绍过了,但是我们在哪里结束了? 首先问题是:* .stackexchange.com覆盖了games.stackexchange.com(和其他几百个网站),但并不包括meta.gaming.stackexchange.com。 RFC 6125(第6.4.3节)规定:
客户端不应尝试匹配显示的标识符,其中通配符不应用来匹配除最左边标签之外的标签(例如,不应这样匹配bar.*.example.net)。
这意味着我们不能像meta.*.stackexchange.com这样使用通配符。 那么我们该怎么办?
选项1:部署SAN证书
我们需要3个证书(每个限制为100个域),我们需要使用3个IP,我们会使新的站点启动复杂化(直到该方案被改变)
我们必须在CDN /代理处为这3个定制证书支付费用
我们必须为meta.*方案下的每个子元素都有一个DNS条目
由于DNS的规则,我们实际上必须为每个站点添加DNS条目,使站点启动和维护复杂化。
选项2:将所有域移动到* .meta.stackexchange.com?
我们有一个痛苦的举动,但它是一次性,简化了所有维护和证书
我们必须建立一个全域登录系统(这里的细节)
此解决方案还创建了一个includeSubDomains HSTS预加载问题(详细信息)
选项3:我们已经做得够好了,关闭它们
这一个是最简单的,但没有被批准
我们建立了一个全域登录系统,后来移动了这个子域名(有301s),现在他们正处于新的地方。例如https://gaming.meta.stackexchange.com。在这样做之后,我们意识到HSTS预加载列表的一个问题有多么简单,因为这些域已经存在。我会在近期结束,因为它仍在进行中。请注意,这里的问题像
meta.pt.stackoverflow.com一样反映在我们的过程中,但是由于只有4个非英文版本的Stack Overflow存在,所以它们的规模很有限。
哦,这又造成了另一个问题。通过将Cookie移动到顶级域,并依靠子域继承,我们现在不得不移动域。例如,我们使用SendGrid在我们的新系统中发送电子邮件(现在推出)。从stackoverflow.email发送的链接指向sg-links.stackoverflow.email(CNAME指向他们)的链接的原因是,您的浏览器不会发送任何敏感的Cookie。如果是sg-links.stackoverflow.com(或stackoverflow.com下的任何内容),您的浏览器将发送我们的cookies给他们。这是新事物的一个具体例子,但是我们的DNS下还有其他不托管的服务。这些子域中的每一个都必须被移动或退出,以从我们的认证域名下移走,否则我们将把cookies发送到不属于我们的服务器。做所有这些工作只是为了防止在最后将cookie泄漏到其他服务器,那是很丢脸的。
我们试图在一个实例中通过在一段时间内代理我们的一个Hubspot属性来解决这个问题,剥离cookie。但不幸的是,Hubspot使用Akamai,它开始将我们的HAProxy实例视为机器人,并以每周几种方式阻止它。前3次很有趣。所以无论如何,这真的没有奏效。它变得如此糟糕,我们永远不会再做。
你可能好奇为什么我们在https://stackoverflow.blog/上有Stack Overflow Blog?是的,安全。它托管在外部服务上,以便营销团队和其他人可以更快地迭代。为了方便这一点,我们需要从cookied的域名中除去。
元子域遇到的上述问题也发生在HSTS,预加载和includeSubDomains指令。但是,我们会看到为什么以后会变成无实际意义。
性能:HTTP/2
很久以前都会认为HTTPS速度较慢。 以前是的。 但时代在变。 我们不是在单纯谈论HTTPS了。 我们在谈论使用HTTP/2的HTTPS。 虽然HTTP/2不需要加密,但它实际上是有效的。 这是因为大多数浏览器需要安全连接才能实现其大部分功能。 您可以一整天争论规范和规则,但浏览器是我们所有人的现实,我希望他们会把它称为HTTPS/2,并为大家节省了大量时间。 亲爱的浏览器厂商,还不算太迟。 请听听理由,你是我们唯一的希望!
HTTP/2具有很多的性能优势,特别是有机会在询问用户之前向用户推送资源。 我不会详细的写这些好处,Ilya Grigorik已经做了一个非常棒的介绍。 作为一个快速的概述,最大的优化(对我们)包括:
请求/响应复用
服务器推送
标题压缩
流优先级
更少的原始连接
嘿等一下,那个证书怎么办?
HTTP/2的一个鲜为人知的功能是,只要满足某些标准,就可以将内容推送到同一个域中:
来源解析为相同的服务器IP地址。
来源由相同的TLS证书覆盖
所以,我们来看看我们目前的DNS:
嘿嘿嘿,那些IP匹配,他们有相同的证书!这意味着我们可以获得HTTP/2服务器的所有优势,而不会对HTTP/1.1用户造成影响。 HTTP/2得到推送,HTTP/1.1获得域分片(通过sstatic.net)。我们还没有部署服务器推送,但是这一切都在准备中。
所以在性能方面,HTTPS只是一种手段。我还算满意,我可以说,我们的主要驱动力是性能,而不是网站的安全性。我们希望安全,但是在我们的情况下,单是安全性不足以评判在我们的网络上部署HTTPS所用的时间投资。当您结合上述所有因素时,我们可以证明完成此项工作所需的大量时间和精力。在2013年,HTTP/2并不是很大的事情,但随着支持的增加而改变,最终也成为我们为HTTPS投入时间的驱动力。
另外值得一提的是,在部署过程中,HTTP/2规模发生了很大变化。网络从SPDY移动到HTTP/2,从NPN到ALPN。我不会覆盖所有,因为我们在这过程中没有做任何事情。我们只是看着并受益匪浅,但网络巨人正在推动所有这一切。如果你好奇,Cloudflare可以很好的记录这些进步。
HAProxy:提供HTTPS
我们在2013年在HAProxy中部署了初始HTTPS支持。为什么选择HAProxy?因为我们已经在使用它,并且在2013年(在2014年发布为GA)中添加了1.5版本的支持。我们有一段时间,在HAProxy前面的nginx(你可以在最后一篇博文中看到)。但是更简单的往往更好,消除了很多conntrack,部署和一般的复杂性问题通常是一个好主意。
我不会在这里覆盖很多细节,因为没有太多的东西要覆盖。从1.5开始,HAProxy通过OpenSSL本身支持HTTPS,配置很简单。我们的配置亮点是:
运行4个进程
1专用于HTTP/前端处理
2-4专用于HTTPS协商
HTTPS前端通过抽象命名的套接字连接到HTTP后端。这大大降低了开销。
每个前端或“层”(我们有4:主,辅,Websockets和dev)具有相应的:443个监听器。
我们在转发到网络层以指示连接如何进入时,附加请求标头(并且将发送 - 发送 - 不错尝试)。
我们使用Mozilla推荐的现代兼容性加密套件。注意:这不是我们CDN运行的套件。
HAProxy是一个比较简单的第一步,它支持:443端点和有效的SSL证书。回想起来,这只是所需努力的一小部分。
上面描述的是逻辑布局...我们将在下面介绍一下这块:
英文原文:https://nickcraver.com/blog/2017/05/22/https-on-stack-overflow/
译者:jianli