SSL协议最初是在Netscape浏览器中应用,用来保证经过Web进行电子商务交易的安全性,电子商务的安全性要求采用加密技术来保护客户的我的资料,以及认证用户,保证数据完整性,以确保交易安全。为了实现这一目标,SSL协议在应用层实现,直接在TCP层之上(
图4-1 ),使得在它上面的协议(HTTP,电子邮件,即时通信,和许多其余应用)在网络操通讯时,操做不变,同时提供通讯安全。html
若是正确的使用SSL,第三方只能推断链接的两端地址、加密类型,以及数据频率和发送的大概数据量,但没法读取或修改任何实际数据。web
图4-1 传输层安全(TLS)算法
当SSL协议被IETF标准化时,它被改名为传输层安全(TLS)。许多人常常TLS和SSL名称互换使用,但在技术上,它们是不一样的,由于各自描述了不一样版本的协议。浏览器
SSL 2.0是第一个公开发布版本的协议,但因为发现了一些安全漏洞,它很快就被SSL 3.0取代。因为SSL协议是Netscape专有的协议,IETF制定了一个新的标准规范协议(RFC 2246),被称为TLS 1.0,最终升级到了TLS 3.0。缓存
|
TLS和SSL 3.0之间的差异不是很是大,但仍是有一些差异的,在TLS 1.0和SSL 3.0之间不能进行互操做。安全 |
|
|
-- TLS协议 - RFC 2246服务器 |
TLS1.0在1999年1月正式发布,随后两个新的版本被发布,TLS1.1在2006年4月发布,TLS1.2在2008年8月发布,主要解决了一些安全漏洞以及扩展协议能力。虽然SSL 3.0内部实现和后续TLS版本很是类似,许多客户继续支持支持SSL 3.0和TLS 1.0 - 我相信有很好的理由升级到较新的版本,以保护用户免受已知的攻击!cookie
TLS被设计成在一个可靠的传输协议如TCP之上运行。然而,它也被改编运行在数据报协议之上(如UDP)。RFC 6347中定义的数据报传输层安全(DTLS)协议就是基于TLS协议,在保留数据报的传输模式前提下,可以提供TLS相似的安全保证。网络
TLS协议的目的是为在其之上运行的全部应用提供三种服务:加密,身份认证,数据完整性。从技术上说,你不须要在了解任何细节的状况下使用这三个服务。您可能只接受证书,而不验证其真实性,但你应该清楚地意识到这样作的安全风险和影响。在实际应用中,一个安全的Web应用程序通常都会应用这三个特性。session
加密
一种用来混淆从一台计算机到另外一个计算机之间信息的机制
认证
一种对提供的身份信息检验其合法性的机制
完整性
一种侦测信息是否被篡改和伪造的机制
为了创建一个安全的加密的数据通道,链接双方必须协商后续的加密算法,以及加密密钥。TLS协议制定了一个清晰的握手序列来进行这些交换,咱们将在“TLS握手”章节进行详细讨论
。TLS在实际中应用普遍的一个主要缘由是它巧妙的握手过程,握手过程使用了公共密钥加密(也称为非对称密钥加密)技术,通讯双方能够在以前没有任何消息交互的状况下进行共享密钥协商,并且密钥的协商能够在未加密的通道上执行。
做为TLS握手的一部分,该协议还容许通讯的两端互相验证对方的身份。应用到浏览器中,这个认证机制,容许客户端验证服务器是他们声称的身份(例如你的银行),而不是有人只是经过伪造的名称或者IP地址 - 这验证主要基于第三方证书颁发机构和信任链。此外,服务器还能够选择性地验证客户端的身份 - 例如,一个公司的代理服务器能够验证全部员工,每一个人均可以有本身的公司签署的证书。
最后,除了用户认证和加密外,TLS协议还提供了它本身的消息分片机制,且采用消息认证码(MAC)对每个分片消息进行签名。MAC算法是一个单向的哈希加密函数(一个很是高效的校验码),HASH函数密钥由两端进行协商。每当一个TLS记录被发送,生成的MAC值,将附加在该消息中,接收端采用相同的方法计算和验证所发送的MAC值,以确保消息的完整性和真实性。
三种方式结合起来,就构成了web上安全通讯的基础。全部现代的Web浏览器都提供了各类加密算法,可以用来验证客户端和服务器,透明地执行每一条消息的完整性检查。
网络代理,中间服务器,TLS,web上的新协议
HTTP的成功和可扩展性建立了一个充满活力的生态系统,在这个生态系统中包含各类代理和中间服务器:高速缓存服务器,安全网关,web加速器,内容过滤器,和其余许多服务器。在某些场景下,咱们都知道他们的存在(显式代理),而在不少状况下,这些代理对最终用户是彻底透明的。
不幸的是,这些中间或者代理服务器也带来了一些小问题:一些代理服务器在不能解析的状况下可能只是转发HTTP的扩展,可是有一些代理服务器却盲目的去处理了数据,即便他们不该该处理。另外,一些安全服务器会错误的把正常流量当作恶意流量。
在实际应用中,若是不采用标准HTTP语义和80端口的作法,每每致使不可靠的网络部署:某些客户端不会有任何问题,而另外一些可能会失败或者发生不可预知的行为 - 例如,在同一客户端可能在不一样网络之间的切换时可能出现不一样的结果。
因为这些状况的存在,新的协议和HTTP扩展,譬如WebSocket,SPDY,其余扩展,一般依赖于创建的HTTPS隧道,来绕过中间代理,并提供一个可靠的部署模型:加密隧道混淆了全部的数据,使中间服务器不可见。这解决了眼前的问题,但它有一个缺点就是是不可以充分利用中间服务器提供的服务,譬如:身份验证,缓存,安全扫描,等等。
这就是为何大多数的WebSocket指南会告诉你使用HTTPS来传送数据到移动客户端 - 缘由就是上面所述。随着时间的推移,中间服务器逐步升级,其能够识别出新的协议,HTTPS部署也将变得不那么必要了 - 除非您的会话实际须要TLS提供的加密,身份认证,完整性校验等功能!
在客户端和服务器开始基于TLS进行应用程序数据交换以前,双方必须先协商好加密的通讯隧道:客户端和服务器必须协商好TLS协议的版本,加密套件,若有必要,还须要验证证书。不幸的是,每个步骤都须要在客户端和服务器之间进行数据交互,这将增长了TLS链接的延迟(
图4-2 )。
图4-2 TLS握手协议
图4-2假设纽约和伦敦之间的单向传播延迟为28ms,在前面章节中讨论的TCP链接的例子同样-
见表1-1 。
0 ms |
TLS运行在TCP基础之上,这意味着咱们必须首先完成TCP 三次握手“ ,这须要一个完整的来回交互(RTT)。 |
56 ms |
TCP链接创建后,客户端发送一些协商信息,如TLS协议版本,支持的密码套件的列表,和其余TLS选项。 |
84 ms |
服务器挑选TLS协议版本,在加密套件列表中挑选一个密码套件,附带本身的证书,并将响应返回给客户端。可选的,服务器也能够发送对客户端的证书认证请求和其余TLS扩展参数。 |
112 ms |
假设双方协商好一个共同的TLS版本和加密算法,客户端使用服务器提供的证书,生成新的对称密钥,并用服务器的公钥进行加密,并告诉服务器切换到加密通讯流程。到如今为止,全部被交换的数据都是以明文方式传输,除了对称密钥外,它采用的是服务器端的公钥加密。 |
140 ms |
服务器用本身的私钥解密客户端发过来的对称密钥,并经过验证MAC检查消息的完整性,并返回给客户端一个加密的“Finished”的消息。 |
168 ms |
客户端采用对称密钥解密消息,并验证MAC,若是一切OK,加密隧道就创建好了。应用程序数据就能够发送了。 |
一个新的TLS链接须要两个往返“完整的握手”。或者,可使用“简短握手”,这只须要一个来回-参见“TLS会话恢复” 。
协商一个安全TLS通讯隧道是一个复杂的过程,很容易犯错。好消息是,上述复杂的工做都已经由服务器和浏览器替咱们作了,全部咱们须要作的是提供和配置证书。
尽管浏览器和服务器替咱们完成了复杂的工做,当咱们的Web应用程序没有必要进行加密通讯时,咱们须要牢记每TLS链接将须要额外的两个TCP往返 - 在应用程序能够进行交换数据前,这是一个比较长的延迟!若是管理的很差,经过TLS传输数据可能增长几百ms的延迟,固然不太可能达到上千ms的延迟。
公钥加密 vs 对称加密
公钥加密仅用于会话建立TLS隧道的过程当中。服务器提供公钥给客户端,客户端产生一个对称密钥,采用服务器的公钥加密,加密后的对称密钥,返回给服务器。而后,服务器用本身的私钥进行解密对称密钥。
使用由客户端生成的共享密钥的对称密钥加密法将其用于后续客户端和服务器之间的全部通讯。这么作的主要缘由是为了提高性能 - 非对称加密算法的计算复杂度高不少。想理解这个差别,若是您的计算机上安装了OpenSSL,你能够运行下面的测试:
须要注意的是两次测试之间没法直接对比:RSA测试经过对不一样长度的密钥进行一组数据进行测试,而AES性能测量的是每秒加密的字节数。尽管如此,它应该很容易地看到,推荐的1024或2048位密钥长度的RSA运算(全TLS握手),可能成为瓶颈。
确切的性能受使用的硬件,CPU核数量,TLS版本,服务器的配置,和其它因素的影响。不要受市场宣传误导,也不要相信过期的基准测试!始终在本身的硬件上作性能测试。
两个网络节点可能使用一个自定义的应用程序协议进行互相通讯。解决这个问题的方法之一是在肯定协议的前期,给它分配一个众所周知的端口(例如,端口80用于HTTP,TLS的端口443),并配置全部客户端和服务器使用它。然而,在实践中,这是一个缓慢和不切实际的过程:每一个端口的分配必须批准,更糟的,防火墙及其余中间服务器每每只容许使用80和443进行通讯。
结果是,为了咱们自定义协议更加容易部署,咱们必须复用80或443端口,经过额外的机制来协商应用协议。80端口被保留用于HTTP,HTTP规范提供了一个特殊的Upgrade流程来完成这个目标。然而,使用Upgrade可能带来额外的网络往返延迟,并在实际应用中每每由于许多中间服务器的存在是不可靠的,- 参考“代理,中间服务器,TLS协议和网络上的新协议“章节。
HTTP升级流程的一个例子能够参考“高效的HTTP 2.0升级和发现”章节 。
解决的办法是,使用端口443,这是保留给HTTPS会话(运行于TLS之上)。端到端的加密隧道使数据加密经过各类中间服务器,而不被篡改,这能够快速和可靠的方式实现和部署任意的应用程序协议。然而,使用TLS解决了可靠性,咱们仍然须要一种方式来协商应用协议!
HTTPS会话,固然,复用了HTTP的升级机制来执行协商,可是这带来了一个额外完整的往返延迟(RTT)。若是咱们把协议协商做为TLS握手自己的一部分呢?
正如它的名字所暗示的,应用层协议谈判(ALPN)是一个TLS扩展,支持在TLS握手( 图4-2 )过程当中进行协议协商,从而省去经过HTTP升级流程所需的额外往返延迟。具体地,过程以下:
服务器可能只响应其中一个协议,若是它不支持任何客户端要求的协议,那么它可能选择停止链接。其结果是,TLS握手完成后,安全隧道创建好了,客户端和服务端也协商好了所使用的应用协议 - 它们能够当即开始通讯。
ALPN节约了HTTP升级交换的必要性,节省了一个额外的往返延迟。然而,请注意,TLS握手自己依旧必须被执行,所以ALPN协商不会比采用HTTP升级流程创建的未加密的通道快。相反,它只是确保经过TLS进行应用协议协商不会更慢 。
NPN和ALPN的历史关系
NPN(Next Protocol Negotiation)是一个TLS扩展,是Google提供的SPDY中的一部分,以实如今TLS握手中进行应用协议协商。听起来是否是很熟悉?最终的结果是和ALPN功能至关。
ALPN是NPN扩展的修订和IETF批准版本。在NPN中,服务器宣告它支持的协议,而后由客户端选择并确认协议。在ALPN,这个过程正好倒过来,客户端宣称其支持的协议,服务器选择并确认协议。改变的理由是,ALPN能够和其余比较接近的协商标准保持最大程度的一致性。
换句话说,ALPN是NPN的继任者,NPN已被弃用。依赖于NPN协商的客户端和服务器必须进行升级,使用ALPN。
任意两个TCP端之间均可以创建加密的TLS隧道:客户端只须要知道对端的IP地址就能够创建链接,并执行TLS握手。可是,若是服务器须要部署多个独立的网站,每一个与本身的TLS证书,但使用同一个IP地址 - 请问如何处理?棘手的问题,答案是不行。
为了解决上述问题,SNI(服务器名称指示)扩展被引入到TLS协议中,它容许客户端在握手开始指示他想要链接的主机名。服务器检查SNI主机名,选择适当的证书,并继续握手。
TLS,HTTP和专用IP
TLS + SNI工做流程和HTTP的Host头域宣告流程是相同的,客户端在头域中指示它要请求的Host:同一IP地址可能会部署许多不一样domain,SNI和Host都是用来区分不一样的Host或者Domain。
不幸的是,许多老的客户端(例如,大多数在Windows XP上运行的IE浏览器,Android 2.2,和其余一些浏览器)不支持SNI。所以,若是您须要为这些老客户提供TLS,那么你可能须要为每一个主机的专用IP地址。
完整的TLS握手须要额外延迟和计算,为全部须要安全通讯的应用带来了严重的性能损耗。为了帮助减小一些性能损耗,TLS提供恢复机制,或多个链接之间共享相同的协商密钥数据。
“会话标识符”(RFC 5246)恢复机制在SSL 2.0中首次被引入,它容许服务器在“ServerHello消息”中构建和发送一个32字节的会话标识符,做为“ServerHello”消息的一部分。
在服务器内部,服务器维护一个会话ID和其对应的协商参数的缓存。反过来,客户端也同时存储会话ID信息,在后续的会话中,能够在“ClientHello”消息中携带session ID信息,指示服务器它保存了session ID对应的密钥和加密算法等信息,而且能够重用这些信息。假设在客户端和服务器都能在它们各自的缓存中找到共享的会话ID参数,那么缩减的握手(
图4-3 )就能够进行了。不然,开始一个新的会话协商,这将产生一个新的会话ID。
图4-3 缩减的TLS握手协议
借助会话标识符,咱们可以减小一个完整的往返,以及用于协商的共享密钥的公钥加密算法开销。这让咱们能快速的创建安全链接,而不损失安全性。
在实际应用中,大多数Web应用程序试图经过创建到同一个主机的多个链接并行获取资源,这使得会话恢复成为必不可少的一个优化项,其能够减小延迟,计算成本。
大多数现代浏览器都会有意的等待第一TLS链接完成后,再打开到同一台服务器的新链接:后续TLS链接,能够重复使用的SSL会话参数,以免握手的延迟和损耗。
然而,“会话标识符”机制的一个限制就是要求服务器为每一个客户端建立和维护一个会话缓存。这会为服务器上带来几个问题,对于一些天天同时几万,甚至几百万的单独链接的服务器来讲:因为缓存session ID所须要的内存消耗将很是大,同时还有session ID清除策略的问题。这对一些流量大的网站来讲不是一个简单的任务,理想的状况下,使用一个共享的TLS会话缓存能够得到最佳性能。
上述问题没有是不可能解决的,许多高流量的网站成功的使用了会话标识符。可是,对任何多服务主机的部署,会话标识符方案须要一些认真的思考和好的系统架构,以确保良好的的会话缓存。
为了解决上面的会话缓存带来的服务器部署问题,“Sesion Ticket”(RFC 5077)取代机制被引入,目标是消除服务器须要维护每一个客户端的会话状态缓存的要求。相反,若是客户指示它支持Session Ticket,在TLS握手的最后一步中服务器将包含一个“New Session Ticket”信息,包含了一个加密通讯所须要的信息,这些数据采用一个只有服务器知道的密钥进行加密。
这个Session Ticket由客户端进行存储,并能够在随后的一次会话中添加到 ClientHello消息的SessionTicket扩展中-所以,全部的会话信息只存储在客户端上,Session Ticket仍然是安全的,由于它是由只有服务器知道的密钥加密的。
Session Identifiers和Session Ticket机制一般分别被称为“会话缓存”和“无状态恢复”机制。无状态恢复的主要改进是消除服务器端的会话缓存,从而简化了部署,它要求客户在每个新的会话开始时提供Session Ticket - 直到Ticket过时。
在实际应用中,在一组负载平衡服务器中部署Session Ticket,也须要仔细考虑:全部的服务器都必须用相同的会话密钥,或者可能须要额外的机制,按期轮流在全部服务器上的共享密钥。
身份验证是创建每一个TLS链接一个重要的组成部分。毕竟,TLS能够与任何端经过一个加密的隧道进行通讯,包括攻击者,除非咱们能够确信和咱们通讯的对方是可信任的,否则全部的加密工做都是无效的。要了解咱们如何验证对方的身份,让咱们来看看一个Alice和Bob之间简单的身份验证工做流程:
信任是上述通讯的一个重要组成部分。具体来讲,公钥加密算法容许咱们使用发送方的公钥来验证其用私钥签名的消息,但这个验证是基于信任的基础上。在上面的交换过程当中,Alice和Bob能够亲自交换他们的公钥,由于他们互相了解对方,他们肯定他们的交换没有被第三方冒名顶替 - 也许他们甚至经过另外一种方式来验证他们的身份,秘密(物理)握手,经过他们已经创建的握手!
接下来,Alice从她从未见过的Charlie那里接收到一条消息,但Charlie声称本身是Bob的朋友。事实上,Chralie为了证实他是Bob的朋友,Charlie请求Bob用他的私钥对本身的公钥进行签名,并在消息中附带了这个签名(
图4-4 )。在这种状况下,Alice首先检查Bob对Charlie公钥的签名。她知道Bob的公钥,所以她能够确认Bob确实对Charlie的公钥签名了。由于她信任Bob对Charlie的签名,她接受该消息,并対Charlie的消息进行相似完整性检查,以确保它确实是从Charlie发送过来的。
图4-4 Alice,Bob和Charlie的信任链
咱们刚才所作的过程就是创建信任链:Alice信任Bob,Bob信任Charlie,信任被传递,Alice决定信任Charlie。只要信任链中没有人被攻破,咱们可以构建和扩大信任的名单。
web和您的浏览器上的身份认证遵循了上面一样的步骤。这时你可能会问:你的浏览器该信任谁,当你使用浏览器是该信任谁?这个问题至少有三个答案:
手动指定的用户证书
每个浏览器和操做系统都提供了手动导入任何您信任的证书的机制。如何得到证书,并验证其完整性彻底取决于你。
证书颁发机构
证书颁发机构(CA)是一个值得信赖的第三方的机构(全部者),其证书值得信任。
浏览器和操做系统
每一个操做系统和大多数浏览器都包含了知名的证书颁发机构的列表。所以,你也能够信任这个软件的供应商,提供并维护的信任列表。
在实际应用中,手动验证为每个网站的证书(尽管你能够,若是你是这样的倾向)是不切实际。所以,最多见的解决方案是借助(
图4-5 )证书颁发机构(CA)作这项工做 :在浏览器中指定哪些CA是可信任(根CA证书),CA负责验证你访问的每一个网站,并进行审核,以确认这些证书没有被滥用或受损害。若是任何网站违反了CA的证书的安全性规定,那么CA有责任撤销其证书。
图4-5 CA数字证书签发
基本上每个浏览器,均可以让你检查安全链接的信任链( 图4-6 ) -一般是经过点击URL旁边的锁形图标。
图4-6 igvita.com的证书信任链(谷歌浏览器,V25)
信任链中的锚点就是证书签发机构的根证书,在上面的例子中就是是 StartCom Certification Authority。每个浏览器会预先置入一个受信任的证书颁发机构(“根证书”)列表,在上面的例子中,浏览器信任和可以验证StartCom的根证书。所以,经过浏览器,浏览器供应商,StartCom证书颁发机构的信任传递链,咱们扩展到信任咱们访问的站。
每个操做系统供应商和每个浏览器都提供了一个默认信任的证书颁发机构列表。若是你很好奇,你能够经过搜索引擎搜索和查看这些清单。
在实践中,有数百个知名的和受信任的证书颁发机构,这也是系统的一个大麻烦。大量的CA致使了对您的浏览器的信任链大面积潜在的攻击。
偶尔证书的颁发机构可能须要撤销或做废证书,这可能因为证书的私钥被攻破了,证书颁发机构自己被攻破,或者其余一些正常的缘由譬如证书替换、证书签发机构发生变化,等等。为了解决这个问题,证书自己包含了检查是否已吊销的逻辑(
图4-7 )。所以,为了确保信任链不会受到攻击影响,每一个节点均可以检查每一个证书的状态,连同签名。
图4-7 CRL和OCSP(谷歌浏览器,V25为igvita.com)
证书撤销列表(CRL)是在RFC 5280中定义的,它制定了一个简单的机制来检查每一个证书的状态:每一个证书颁发机构维护并按期发布一份吊销证书序列号列表。任何人想验证一个证书,他能够从证书颁发机构下载吊销列表,并检查序列号是否在吊销列表中 - 若是找到,那么证书已经被撤销。
CRL文件自己能够按期公布,或在每次更新时都公布,CRL文件能够经过HTTP,或任何其余文件传输协议传输。该名单也是由CA签名,一般容许以指定的时间间隔缓存。在实际应用中,这个流程运行得很好,但也有一些场景CRL机制可能存在缺陷:
为了解决CRL机制的一些缺陷,在线证书状态协议(OCSP)在RFC 2560中被制定,它提供了一个实时执行证书状态检查的机制。不一样于CRL,其包含了全部被撤销序列号,而OCSP只须要客户端传进序列号,就能够直接验证证书链。
所以,OCSP机制消耗更少的带宽,并可以提供实时验证。然而,没有任何机制是完美的!OCSP要求进行实时查询也引入了几个问题:
在实际应用中,CRL和OCSP机制是互补的,大多数证书机构同时提供两种机制。
更重要的部分是客户端的支持和行为:一些浏览器发布本身的CRL列表,另一些从CA中获取CRL文件并缓存它。一样,有些浏览器会进行实时的OCSP检查,但当OCSP请求失败时,浏览器的行为又各自有一些区别。若是你好奇,能够检查一下您的浏览器和操做系统的证书吊销设置!
TLS和下面的IP或TCP层比较起来没有什么本质不一样,全部TLS会话内的数据交换采用了一个良好定义的协议(
图4-8 )。TLS记录协议主要用来识别TLS中消息的类型(经过“Content Type”字段的数据来识别握手,Alert或数据),以及每一个消息的完整性保护和验证。
图4-8 TLS记录协议结构
一个传输数据的典型流程以下:
一旦上述步骤完成后,加密的数据被向下传递到TCP层进行传输。在接收端,采用反向相同的工做流程:使用协商的加密算法对数据进行解密,验证MAC,提取的应用数据给应用层。
另外一个好消息,全部上述的处理都是TLS层自己处理,对大多数应用程序是彻底透明的。然而,TLS记录协议引入了几个你应该知道的影响:
应用程序应该挑选合适的TLS记录大小,若是你能够去设置,这也能够是一个重要的优化。记录过小致使分帧过多,容易产生较大的开销,而记录过大,则在TCP层须要从新分块而后在接收端从新拼装,数据才能够被TLS层处理,并传递到您的应用层。
因为网络协议的分层架构,应用程序经过TLS和直接经过TCP运行对比,没有什么不一样。所以,应用层基本上不用或者进行少许的修改,就能够经过TLS传输数据。也就是说,“TCP优化”的最佳实践彻底能够用于TLS。
可是,你应该检查TLS部署:如何以及在哪里部署服务器,TLS记录的大小和内存缓冲区大小,证书大小,是否支持缩减握手,等等。服务器上这些参数配置若是正确,可让用户体验产生较大的积极影响,也能够下降您的运营成本。
创建和维护一个加密的通道,通讯双方都引入了额外的一些计算成本。具体来讲,首先是“TLS握手”中使用的不对称(公钥)加密算法 。而后,一旦创建了共享密钥的通讯通道后,后续数据都采用对称密钥来加密。
正如咱们前面提到的,公钥加密与对称密钥加密相比,须要消耗更多的CPU计算,web流行早期,每每须要额外的硬件来执行“SSL负载分担”。好消息是,这一切再也不须要。如今硬件已经发生了翻天覆地的变化,这些CPU运算已经变得微不足道了,之前须要额外硬件才能完成的运算,如今彻底能够在CPU上直接完成了。譬如Facebook和Google这些大型公司,正为数以百万计的用户提供TLS服务,全部必要的TLS协商和CPU运算都在普通的硬件中执行。
|
2010年1月,Gmail缺省状况下采用HTTPS提供一切服务。此前,HTTPS只是做为一个可选项,但如今咱们全部的用户都使用HTTPS来保护他们的电子邮件安全。为了作到这一点,咱们没有部署额外的机器,也没有部署特别的硬件。对咱们产品前置机来讲,SSL / TLS帐户的CPU的负载小于1%,每一个链接占用不到10 KB的的内存,不到2%的网络开销。许多人认为SSL / TLS须要花费大量的CPU运算时间,咱们但愿上面的数字(首次公开),将有助于消除你们的误解。 若是你如今中止往下阅读,你只须要记住一件事:SSL / TLS不不属于CPU消耗型操做。 |
|
|
- Adam Langley (Google) |
|
咱们已经使用硬件和软件负载平衡器大规模的部署了TLS服务。咱们发现,目前基于软件的TLS实现,彻底能够运行在普通的CPU上,其速度已经足够快的用来处理繁重的HTTPS流量负载了,无需借助专用加密硬件。咱们全部HTTPS服务都是使用运行在普通硬件上的软件。 |
|
|
- Doug Beaver (Facebook) |
尽管如此,“TLS会话恢复”等技术仍然是重要的优化,这将有助于下降计算成本和公共密钥加密TLS握手带来的延迟-你没有必要去无谓增长你的CPU负荷,在没有任何须要的前提下。
提及优化CPU负荷,咱们还须要确保SSL库升级到最新的版本,并采用他们来创建你的Web服务器或代理服务器!例如,最近版本的OpenSSL取得了显着的性能改进,没准,你的系统默认的OpenSSL库早已过期。
TLS链接的延迟,不管是新的链接或恢复链接,都是优化须要重点考虑的一个领域。首先,咱们前面描述过,每个TCP链接以“三次握手”开始 ,这须要一个完整的往返(SYN
/ SYN-ACK包)。接着, 是“TLS握手”,最多须要两个额外的往返(RTT),或一个往返,若是使用“TLS会话恢复” 的话。
在最坏的状况下,在任何应用程序交换数据以前,TCP和TLS链接过程须要三个完整的往返!以咱们前面的例子做参考,客户端在在纽约,服务器在伦敦,一个完整的往返是56ms(
表1-1 ),这意味着一个完整的TCP和TLS创建至少有168ms的延迟,若是采用TLS会话恢复则至少有112ms的往返延迟。更糟的是,两端之间的传播延迟越高,TLS链接的延迟也是越大,56 ms绝对是一个很乐观的数字!
由于TLS会话运行在TCP之上。“TCP优化”,的全部优化建议一样也适用于TLS。若是TCP链接复用对于未加密传输来讲是一个重要的考虑因素,那么它对经过TLS进行数据传输的应用来讲,一样也是一个关键的优化
- 若是你能避免作握手,尽可能避免。若是你确实要执行握手操做,那么你可能须要了解一下“提早终止”的技术。
正如咱们在第1章中讨论的那样,咱们不能指望减小数据包的传播延迟,毕竟他们已是光速级了。然而,咱们可能没法使咱们的包传输更快,但咱们可让他们的传输更短的距离!提早终止是一个简单的技术,将您的服务器更贴近用户(
图4-9 ),使每一个客户端和服务器之间的往返延迟成本降到最低。
图4-9 提早终止客户端链接
作到这一点最简单的方法是在世界各地部署服务器,并复制或缓存您的数据和服务,而不是让每用户漂洋过海链接到您的主服务器。固然,这也正是许多CDN提供的服务。然而,使用地理上分布的服务器不能阻止咱们继续优化。
采用靠近客户端的服务器来代理创建TLS会话,这意味着TCP和TLS握手往返能够更快,延迟大大下降。反过来,这个服务器能够再与主服务器之间创建一个安全的长链接,并代理全部传入的请求和主服务器返回的响应数据。
简而言之,将服务器移到离客户更近的地方,加速TCP和TLS握手过程!大多数CDN提供商提供这项服务,若是你喜欢冒险,你也能够用最少的成本部署本身的基础设施:利用几个数据中心的提供的分布全球的云服务器,在这些云服务器上配置代理服务器用来转发到你服务器的请求,同时添加基于地理的DNS负载均衡,一切OK了。
未缓存源获取
CDN或代理服务器缓存资源所采用的技术方案,可能须要基于不一样用户进行定制,或者因为一些请求中包含了私有数据致使没法缓存,所以不可能在CDN中缓存全部的资源,就是俗称的“未缓存源获取“。
虽然当数据缓存在基于地理分布的世界各地服务器中时,CDN的性能达到最优,未缓存起源获取仍然提供了一个很是重要的优化:客户端与附近的服务器之间创建TLS链接,这仍是能够显着减小握手延迟。反过来,CDN或本身的代理服务器,能够保持一个“活链接池”来转发源服务器的数据,让你提供一个快速响应给客户端。
事实上,做为一种优化技术,一些CDN在通讯的两端附近都提供了CDN服务器!客户端与附近的CDN节点创建TLS链接,而后这个CDN节点将请求中转到靠近源服务器的CDN节点,而后请求再被转发到原服务器。在CDN网络中增长的这额外一跳容许通讯经由优化的CDN骨干网络路由,它能够进一步下降客户端和原始服务器之间的延迟。
在靠近用户的地方创建链接,是一种重要的优化手段,这将为您的用户在全部的状况降低低延迟。可是,传输再少的数据也快不过什么都不传输。启用的TLS会话缓存和无状态恢复,可让你在重复链接时消除一个完整的往返。
TLS会话缓存技术依赖的会话标识符,在SSL 2.0中被引入,目前已经被大多数的客户端和服务器支持。可是,若是您要配置您的SSL / TLS服务器,不要理所固然的认为这些在默认状况下都是支持的。事实上,在默认状况下,大多数服务器都是关闭的 - 你须要了解这一点!你应该仔细检查并验证您的配置:
另外,若是客户端和服务器都支持Session Ticket,则全部的会话数据将被存储在客户端上,上述步骤就没有必要了 - 一切都简单明了了。然而,由于Session Ticket是TLS中一个相对较新的扩展,并不是全部的客户端都支持。在实际应用中,为了得到最佳性能,你最好同时启用两种方案,对支持Session Ticket的客户端采用Session Ticket方案,而对旧客户端采用会话标识做为备选方案。这些方案都不是排他性的,他们能够很好的一块儿工做。
全部经过TLS传输的应用数据在都是封装在记录协议中( 图4-8 )。每一个记录的最大大小是16KB,并根据所选择的加密算法,每一个记录将添加20-40字节的额外头域,MAC,和可选的填充数据。若是记录随后被装入到一个TCP数据包中,那么咱们还须要添加IP头和TCP头:20字节的IP头,20字节的TCP头(不带任何选项)。其结果是,每个记录都有60〜100字节的潜在开销。对于一个典型的以太网最大传输单元(MTU)大小1500字节,这样的数据包结构至少有6%的性能损耗。
记录越小,越高的帧开销。然而,简单地将记录大小设置为最大尺寸(16 KB)也未必是一个好主意!若是一条记录跨越多个TCP包,TLS层必须等待全部的TCP报文到达以后,它才能对数据进行解密(
图4-10 )。若是其中某些TCP报文丢失,从新排序,或因为拥塞控制而阻塞,那么TLS记录的其他片断都要放在缓冲区中,直到所有收到后才能够解码,从而致使额外的延迟。在实际应用中,这些延迟浏览器能够为浏览器带来了比较严重的性能瓶颈,浏览器通常倾向于收到一个字节处理一个字节。
图4-10 Wireshark抓包 11,211字节的TLS记录分红了8个TCP Segments
小记录产生更多冗余开销,大记录产生延迟,没有一个“彻底准确”的记录大小。然而,对于Web应用程序来讲,主要都是经过浏览器进行访问,最佳作法很简单:每一个TCP数据包正好包含一个TLS记录,TLS记录应该尽可能占据整个TCP最大段大小(MSS)。换句话说,不要使TLS记录跨越多个TCP数据包,并在TLS记录中填充尽量多的数据。基于下面的原则来肯定最佳TLS记录大小:
假设一个正常的1500字节MTU,这留给TLS记录的就是在IPv4下大概1420字节,IPv6下1400字节。考虑到将来的需求,最好使用IPv6的大小:若是您的MTU是1400字节,TLS记录还要少一些。
不幸的是,咱们在应用层很难去控制TLS记录大小的配置。相反,这一般是TLS服务器的一个设置,设置多是一个编译器的常量或者标志 - 如何更新此值的详细信息,请检查您的服务器文档。
若是您的服务器正在处理大量的TLS链接,那么最大限度地减小每一个链接内存使用量也是一个重要的优化。默认状况下,流行的如OpenSSL库将为每一个链接分配最多50 KB的内存,但根据TLS记录大小,你能够检查文档或源代码看看如何调整这个值,这是一个不错的内存优化点。谷歌的服务器将他们的OpenSSL的缓冲区减小到了约5 KB。
一个不为人知的TLS特性就是在其纪录协议中已经内置支持无损数据压缩:压缩算法在TLS握手过程当中协商,数据在加密应用以前进行压缩。然而,在实际应用中,你应该在你的服务器上禁用TLS压缩,有如下几个缘由:
重复压缩会同时在服务器和客户端浪费CPU时间,另外,安全漏洞的影响也是至关的严重 - 所以须要禁用压缩TLS。在实际应用中,大多数的浏览器都是禁用TLS压缩的,不过,你应该明确的在您的服务器上明确的禁用,以保护您的用户。
相反,咱们不该该依赖于TLS的压缩,而是应该在应用层配置Gzip,使全部文本型资源采用gzip方式传输,而对其余格式如图像,视频和音频应该去选取最佳的压缩格式。
验证信任链要求浏览器遍历证书链,从网站证书,并递归地验证证书的父证书,直到达到一个受信任的根证书。所以,首先你应该作的优化就是验证服务器是否包含了执行握手时的全部中间证书。若是服务器缺失了中间的某个证书,许多浏览器将仍然工做,但他们将被迫暂停下来,自行去获取中间证书、验证它,而后继续 - 这可能须要新的DNS查找,TCP链接,一个HTTP GET请求,又增长了数百ms的延迟。
浏览器如何知道从哪里获取中间证书?一般子证书中会包含父证书的地址。
相反,确保你的证书链中不要包含没必要要的证书!或者,更广泛的是,你应该最大限度地减小您的证书链的大小。回想一下,服务器证书在“TLS握手”期间发送 ,这时有可能处于在一个新的TCP链接中的前期阶段,它正在应用“慢启动”算法。若是证书链超过TCP的初始拥塞窗口(
图4-11 ),咱们会在不经意间添加了又一往返握手:证书长度超出拥塞窗口大小,并致使服务器中止并等待客户端的ACK,而后再继续。
图4-11 Wireshark抓包 一个5323 byte的TLS证书链
图4-11的证书链是超过5 KB,将超过不少旧服务器的初始拥塞窗口大小,并带来另外一个往返延迟。一个可能的解决方案是增长初始拥塞窗口大小-请参阅“增长TCP的初始拥塞窗口” 。此外,你应该检查一下是否可能减小证书的大小: