1
https://konklone.com/post/switch-to-https-now-for-free#
https://theintercept.com/2014/11/20/non-profit-plans-encrypt-entire-web-free/
https://www.youtube.com/watch?time_continue=179&v=Gas_sSB-5SU
Let’s Encrypt Demo
https://www.youtube.com/watch?v=0JioB7rNpvI
https://www.eff.org/
电子前哨基金会: Electronic Frontier Foundation( EFF)
非盈利组织
电子前哨基金会是一个国际知名的法律援助公益组织,旨在宣传互联网版权和监督执法机构,总部设在美国。它的使命是 参与和支持那些旨在促使公众了解更多有关计算机和通信领域发展带来的机遇与挑战的教育活动。1
Let’s Encrypt is a new Certificate Authority:
It’s free, automated, and open.Get Started (Public Beta)
2. TLS/SSL 原理
HTTPS 协议的主要功能基本都依赖于 TLS/SSL 协议,本节分析安全协议的实现原理。
TLS/SSL 的功能实现主要依赖于三类基本算法:散列函数 Hash、对称加密和非对称加密,其利用非对称加密实现身份认证和密钥协商,对称加密算法采用协商的密钥对数据加密,基于散列函数验证信息的完整性。
散列函数 Hash,常见的有 MD5、SHA1、SHA256,该类函数特点是函数单向不可逆、对输入非常敏感、输出长度固定,针对数据的任何修改都会改变散列函数的结果,用于防止信 息篡改并验证数据的完整性;对称加密,常见的有 AES-CBC、DES、3DES、AES-GCM等,相同的密钥可以用于信息的加密和解密,掌握密钥才能获取信息,能够防止信息窃听,通信方式是1对 1;非对称加密,即常见的 RSA 算法,还包括 ECC、DH 等算法,算法特点是,密钥成对出现,一般称为公钥(公开)和私钥(保密),公钥加密的信息只能私钥解开,私钥加密的信息只能公钥解开。因此掌握公钥的不同 客户端之间不能互相解密信息,只能和掌握私钥的服务器进行加密通信,服务器可以实现1对多的通信,客户端也可以用来验证掌握私钥的服务器身份。
在信息传输过程中,散列函数不能单独实现信息防篡改,因为明文传输,中间人可以修改信息之后重新计算信息摘要,因此需要对传输的信息以及信息摘要进 行加密;对称加密的优势是信息传输1对1,需要共享相同的密码,密码的安全是保证信息安全的基础,服务器和 N 个客户端通信,需要维持 N 个密码记录,且缺少修改密码的机制;非对称加密的特点是信息传输1对多,服务器只需要维持一个私钥就能够和多个客户端进行加密通信,但服务器发出的信息能 够被所有的客户端解密,且该算法的计算复杂,加密速度慢。
结合三类算法的特点,TLS 的基本工作方式是,客户端使用非对称加密与服务器进行通信,实现身份验证并协商对称加密使用的密钥,然后对称加密算法采用协商密钥对信息以及信息摘要进行加密通信,不同的节点之间采用的对称密钥不同,从而可以保证信息只能通信双方获取。
3. PKI 体系
3.1 RSA 身份验证的隐患
身份验证和密钥协商是 TLS 的基础功能,要求的前提是合法的服务器掌握着对应的私钥。但 RSA 算法无法确保服务器身份的合法性,因为公钥并不包含服务器的信息,存在安全隐患:
客户端 C 和服务器 S 进行通信,中间节点 M 截获了二者的通信;
节点 M 自己计算产生一对公钥 pub_M 和私钥 pri_M;
C 向 S 请求公钥时,M 把自己的公钥 pub_M 发给了 C;
C 使用公钥 pub_M 加密的数据能够被 M 解密,因为 M 掌握对应的私钥 pri_M,而 C 无法根据公钥信息判断服务器的身份,从而 C 和 M 之间建立了”可信”加密连接;
中间节点 M 和服务器S之间再建立合法的连接,因此 C 和 S 之间通信被M完全掌握,M 可以进行信息的窃听、篡改等操作。
另外,服务器也可以对自己的发出的信息进行否认,不承认相关信息是自己发出。
因此该方案下至少存在两类问题:中间人攻击和信息抵赖。
3.2 身份验证-CA 和证书
解决上述身份验证问题的关键是确保获取的公钥途径是合法的,能够验证服务器的身份信息,为此需要引入权威的第三方机构 CA。CA 负责核实公钥的拥有者的信息,并颁发认证”证书”,同时能够为使用者提供证书验证服务,即 PKI 体系。
基本的原理为,CA 负责审核信息,然后对关键信息利用私钥进行”签名”,公开对应的公钥,客户端可以利用公钥验证签名。CA 也可以吊销已经签发的证书,基本的方式包括两类 CRL 文件和 OCSP。CA 使用具体的流程如下:
服务方 S 向第三方机构CA提交公钥、组织信息、个人信息(域名)等信息并申请认证;
CA 通过线上、线下等多种手段验证申请者提供信息的真实性,如组织是否存在、企业是否合法,是否拥有域名的所有权等;
如信息审核通过,CA 会向申请者签发认证文件-证书。
证书包含以下信息:申请者公钥、申请者的组织信息和个人信息、签发机构 CA 的信息、有效时间、证书序列号等信息的明文,同时包含一个签名;
签名的产生算法:首先,使用散列函数计算公开的明文信息的信息摘要,然后,采用 CA 的私钥对信息摘要进行加密,密文即签名;
客户端 C 向服务器 S 发出请求时,S 返回证书文件;
客户端 C 读取证书中的相关的明文信息,采用相同的散列函数计算得到信息摘要,然后,利用对应 CA 的公钥解密签名数据,对比证书的信息摘要,如果一致,则可以确认证书的合法性,即公钥合法;
客户端然后验证证书相关的域名信息、有效时间等信息;
客户端会内置信任 CA 的证书信息(包含公钥),如果CA不被信任,则找不到对应 CA 的证书,证书也会被判定非法。
在这个过程注意几点:
申请证书不需要提供私钥,确保私钥永远只能服务器掌握;
证书的合法性仍然依赖于非对称加密算法,证书主要是增加了服务器信息以及签名;
内置 CA 对应的证书称为根证书,颁发者和使用者相同,自己为自己签名,即自签名证书;
证书=公钥+申请者与颁发者信息+签名;
3.3 证书链
如 CA 根证书和服务器证书中间增加一级证书机构,即中间证书,证书的产生和验证原理不变,只是增加一层验证,只要最后能够被任何信任的CA根证书验证合法即可。
服务器证书 server.pem 的签发者为中间证书机构 inter,inter 根据证书 inter.pem 验证 server.pem 确实为自己签发的有效证书;
中间证书 inter.pem 的签发 CA 为 root,root 根据证书 root.pem 验证 inter.pem 为自己签发的合法证书;
客户端内置信任 CA 的 root.pem 证书,因此服务器证书 server.pem 的被信任。
服务器证书、中间证书与根证书在一起组合成一条合法的证书链,证书链的验证是自下而上的信任传递的过程。
二级证书结构存在的优势:
减少根证书结构的管理工作量,可以更高效的进行证书的审核与签发;
根证书一般内置在客户端中,私钥一般离线存储,一旦私钥泄露,则吊销过程非常困难,无法及时补救;
中间证书结构的私钥泄露,则可以快速在线吊销,并重新为用户签发新的证书;
证书链四级以内一般不会对 HTTPS 的性能造成明显影响。
证书链有以下特点:
同一本服务器证书可能存在多条合法的证书链。
因为证书的生成和验证基础是公钥和私钥对,如果采用相同的公钥和私钥生成不同的中间证书,针对被签发者而言,该签发机构都是合法的 CA,不同的是中间证书的签发机构不同;不同证书链的层级不一定相同,可能二级、三级或四级证书链。
中间证书的签发机构可能是根证书机构也可能是另一个中间证书机构,所以证书链层级不一定相同。
3.4 证书吊销
CA 机构能够签发证书,同样也存在机制宣布以往签发的证书无效。证书使用者不合法,CA 需要废弃该证书;或者私钥丢失,使用者申请让证书无效。主要存在两类机制:CRL 与 OCSP。
(a) CRL
Certificate Revocation List, 证书吊销列表,一个单独的文件。该文件包含了 CA 已经吊销的证书序列号(唯一)与吊销日期,同时该文件包含生效日期并通知下次更新该文件的时间,当然该文件必然包含 CA 私钥的签名以验证文件的合法性。
证书中一般会包含一个 URL 地址 CRL Distribution Point,通知使用者去哪里下载对应的 CRL
以校验证书是否吊销。该吊销方式的优点是不需要频繁更新,但是不能及时吊销证书,因为 CRL 更新时间一般是几天,这期间可能已经造成了极大损失。(b) OCSP
Online Certificate Status Protocol,
证书状态在线查询协议,一个实时查询证书是否吊销的方式。请求者发送证书的信息并请求查询,服务器返回正常、吊销或未知中的任何一个状态。证书中一般也会
包含一个 OCSP 的 URL 地址,要求查询服务器具有良好的性能。部分 CA 或大部分的自签 CA (根证书)都是未提供 CRL 或 OCSP
地址的,对于吊销证书会是一件非常麻烦的事情。4. TLS/SSL握手过程
4.1 握手与密钥协商过程
基于 RSA 握手和密钥交换的客户端验证服务器为示例详解握手过程。
1. client_hello
客户端发起请求,以明文传输请求信息,包含版本信息,加密套件候选列表,压缩算法候选列表,随机数,扩展字段等信息,相关信息如下:
支持的最高TSL协议版本version,从低到高依次 SSLv2 SSLv3 TLSv1 TLSv1.1 TLSv1.2,当前基本不再使用低于 TLSv1 的版本;
客户端支持的加密套件 cipher suites 列表, 每个加密套件对应前面 TLS 原理中的四个功能的组合:认证算法 Au
(身份验证)、密钥交换算法 KeyExchange(密钥协商)、对称加密算法 Enc (信息加密)和信息摘要 Mac(完整性校验);支持的压缩算法 compression methods 列表,用于后续的信息压缩传输;
随机数 random_C,用于后续的密钥的生成;
扩展字段 extensions,支持协议与算法的相关参数以及其它辅助信息等,常见的 SNI 就属于扩展字段,后续单独讨论该字段作用。
2. server_hello+server_certificate+sever_hello_done
server_hello, 服务端返回协商的信息结果,包括选择使用的协议版本 version,选择的加密套件 cipher suite,选择的压缩算法 compression method、随机数 random_S 等,其中随机数用于后续的密钥协商;
server_certificates, 服务器端配置对应的证书链,用于身份验证与密钥交换;
server_hello_done,通知客户端 server_hello 信息发送结束;
3.证书校验
客户端验证证书的合法性,如果验证通过才会进行后续通信,否则根据错误情况不同做出提示和操作,合法性验证包括如下:
证书链的可信性 trusted certificate path,方法如前文所述;
证书是否吊销 revocation,有两类方式离线 CRL 与在线 OCSP,不同的客户端行为会不同;
有效期 expiry date,证书是否在有效时间范围;
域名 domain,核查证书域名是否与当前的访问域名匹配,匹配规则后续分析;
4. client_key_exchange+change_cipher_spec+encrypted_handshake_message
client_key_exchange,合法性验证通过之后,客户端计算产生随机数字 Pre-master,并用证书公钥加密,发送给服务器;
此时客户端已经获取全部的计算协商密钥需要的信息:两个明文随机数 random_C 和 random_S 与自己计算产生的 Pre-master,计算得到协商密钥;
enc_key=Fuc(random_C, random_S, Pre-Master)
change_cipher_spec,客户端通知服务器后续的通信都采用协商的通信密钥和加密算法进行加密通信;
encrypted_handshake_message,结合之前所有通信参数的 hash 值与其它相关信息生成一段数据,采用协商密钥 session secret 与算法进行加密,然后发送给服务器用于数据与握手验证;
5. change_cipher_spec+encrypted_handshake_message
服务器用私钥解密加密的 Pre-master 数据,基于之前交换的两个明文随机数 random_C 和 random_S,计算得到协商密钥:enc_key=Fuc(random_C, random_S, Pre-Master);
计算之前所有接收信息的 hash 值,然后解密客户端发送的 encrypted_handshake_message,验证数据和密钥正确性;
change_cipher_spec, 验证通过之后,服务器同样发送 change_cipher_spec 以告知客户端后续的通信都采用协商的密钥与算法进行加密通信;
encrypted_handshake_message, 服务器也结合所有当前的通信参数信息生成一段数据并采用协商密钥 session secret 与算法加密并发送到客户端;
6. 握手结束
客户端计算所有接收信息的 hash 值,并采用协商密钥解密 encrypted_handshake_message,验证服务器发送的数据和密钥,验证通过则握手完成;
7. 加密通信
开始使用协商密钥与算法进行加密通信。
注意:
服务器也可以要求验证客户端,即双向认证,可以在过程2要发送 client_certificate_request 信息,客户端在过程4中先发送 client_certificate与certificate_verify_message 信息,证书的验证方式基本相同,certificate_verify_message 是采用client的私钥加密的一段基于已经协商的通信信息得到数据,服务器可以采用对应的公钥解密并验证;
根据使用的密钥交换算法的不同,如 ECC 等,协商细节略有不同,总体相似;
sever key exchange 的作用是 server certificate 没有携带足够的信息时,发送给客户端以计算 pre-master,如基于 DH 的证书,公钥不被证书中包含,需要单独发送;
change cipher spec 实际可用于通知对端改版当前使用的加密通信方式,当前没有深入解析;
alter message 用于指明在握手或通信过程中的状态改变或错误信息,一般告警信息触发条件是连接关闭,收到不合法的信息,信息解密失败,用户取消操作等,收到告警信息之后,通信会被断开或者由接收方决定是否断开连接。
4.2 会话缓存握手过程
为了加快建立握手的速度,减少协议带来的性能降低和资源消耗(具体分析在后文),TLS 协议有两类会话缓存机制:会话标识 session ID 与会话记录 session ticket。
session ID 由服务器端支持,协议中的标准字段,因此基本所有服务器都支持,服务器端保存会话ID以及协商的通信信息,Nginx 中1M 内存约可以保存4000个 session ID 机器相关信息,占用服务器资源较多;
session ticket 需要服务器和客户端都支持,属于一个扩展字段,支持范围约60%(无可靠统计与来源),将协商的通信信息加密之后发送给客户端保存,密钥只有服务器知道,占用服务器资源很少。
二者对比,主要是保存协商信息的位置与方式不同,类似与 http 中的 session 与 cookie。
二者都存在的情况下,(nginx 实现)优先使用 session_ticket。
握手过程如下图:
注意:虽然握手过程有1.5个来回,但是最后客户端向服务器发送的第一条应用数据不需要等待服务器返回的信息,因此握手延时是1*RTT。
1. 会话标识 session ID
如果客户端和服务器之间曾经建立了连接,服务器会在握手成功后返回 session ID,并保存对应的通信参数在服务器中;
如果客户端再次需要和该服务器建立连接,则在 client_hello 中 session ID 中携带记录的信息,发送给服务器;
服务器根据收到的 session ID 检索缓存记录,如果没有检索到货缓存过期,则按照正常的握手过程进行;
如果检索到对应的缓存记录,则返回 change_cipher_spec 与 encrypted_handshake_message 信息,两个信息作用类似,encrypted_handshake_message 是到当前的通信参数与 master_secret的hash 值;
如果客户端能够验证通过服务器加密数据,则客户端同样发送 change_cipher_spec 与 encrypted_handshake_message 信息;
服务器验证数据通过,则握手建立成功,开始进行正常的加密数据通信。
2. 会话记录 session ticket
如果客户端和服务器之间曾经建立了连接,服务器会在 new_session_ticket 数据中携带加密的 session_ticket 信息,客户端保存;
如果客户端再次需要和该服务器建立连接,则在 client_hello 中扩展字段 session_ticket 中携带加密信息,一起发送给服务器;
服务器解密 sesssion_ticket 数据,如果能够解密失败,则按照正常的握手过程进行;
如果解密成功,则返回 change_cipher_spec 与 encrypted_handshake_message 信息,两个信息作用与 session ID 中类似;
如果客户端能够验证通过服务器加密数据,则客户端同样发送 change_cipher_spec与encrypted_handshake_message 信息;
服务器验证数据通过,则握手建立成功,开始进行正常的加密数据通信。
4.3 重建连接
重建连接 renegotiation 即放弃正在使用的 TLS 连接,从新进行身份认证和密钥协商的过程,特点是不需要断开当前的数据传输就可以重新身份认证、更新密钥或算法,因此服务器端存储和缓存的信息都可以保 持。客户端和服务器都能够发起重建连接的过程,当前 windows 2000 & XP 与 SSL 2.0不支持。
1. 服务器重建连接
服务器端重建连接一般情况是客户端访问受保护的数据时发生。基本过程如下:
(a) 客户端和服务器之间建立了有效 TLS 连接并通信;
(b) 客户端访问受保护的信息;
(c) 服务器端返回 hello_request 信息;
(d) 客户端收到 hello_request 信息之后发送 client_hello 信息,开始重新建立连接。2. 客户端重建连接
客户端重建连接一般是为了更新通信密钥。
客户端和服务器之间建立了有效 TLS 连接并通信;
客户端需要更新密钥,主动发出 client_hello 信息;
服务器端收到 client_hello 信息之后无法立即识别出该信息非应用数据,因此会提交给下一步处理,处理完之后会返回通知该信息为要求重建连接;
在确定重建连接之前,服务器不会立即停止向客户端发送数据,可能恰好同时或有缓存数据需要发送给客户端,但是客户端不会再发送任何信息给服务器;
服务器识别出重建连接请求之后,发送 server_hello 信息至客户端;
客户端也同样无法立即判断出该信息非应用数据,同样提交给下一步处理,处理之后会返回通知该信息为要求重建连接;
客户端和服务器开始新的重建连接的过程。
4.4 密钥计算
上节提到了两个明文传输的随机数 random_C 和 random_S 与通过加密在服务器和客户端之间交换的 Pre-master,三个参数作为密钥协商的基础。本节讨论说明密钥协商的基本计算过程以及通信过程中的密钥使用。
1.计算 Key
涉及参数 random client 和 random server, Pre-master, Master secret, key material, 计算密钥时,服务器和客户端都具有这些基本信息,交换方式在上节中有说明,计算流程如下:
客户端采用 RSA 或 Diffie-Hellman 等加密算法生成 Pre-master;
Pre-master 结合 random client 和 random server 两个随机数通过 PseudoRandomFunction(PRF)计算得到 Master secret;
Master secret 结合 random client 和 random server 两个随机数通过迭代计算得到 Key material;
以下为一些重要的记录,可以解决部分爱深入研究朋友的疑惑,copy的材料,分享给大家:
(a) PreMaster secret 前两个字节是 TLS 的版本号,这是一个比较重要的用来核对握手数据的版本号,因为在 Client
Hello 阶段,客户端会发送一份加密套件列表和当前支持的 SSL/TLS
的版本号给服务端,而且是使用明文传送的,如果握手的数据包被破解之后,攻击者很有可能串改数据包,选择一个安全性较低的加密套件和版本给服务端,从而对
数据进行破解。所以,服务端需要对密文中解密出来对的 PreMaster 版本号跟之前 Client Hello
阶段的版本号进行对比,如果版本号变低,则说明被串改,则立即停止发送任何消息。(copy)(b) 不管是客户端还是服务器,都需要随机数,这样生成的密钥才不会每次都一样。由于 SSL 协议中证书是静态的,因此十分有必要引入一种随机因素来保证协商出来的密钥的随机性。
对于 RSA 密钥交换算法来说,pre-master-key 本身就是一个随机数,再加上 hello 消息中的随机,三个随机数通过一个密钥导出器最终导出一个对称密钥。
pre master 的存在在于 SSL 协议不信任每个主机都能产生完全随机的随机数,如果随机数不随机,那么 pre master
secret 就有可能被猜出来,那么仅适用 pre master secret
作为密钥就不合适了,因此必须引入新的随机因素,那么客户端和服务器加上 pre master secret
三个随机数一同生成的密钥就不容易被猜出了,一个伪随机可能完全不随机,可是三个伪随机就十分接近随机了,每增加一个自由度,随机性增加的可不是一。2.密钥使用
Key 经过12轮迭代计算会获取到12个 hash 值,分组成为6个元素,列表如下:
mac key、encryption key 和 IV 是一组加密元素,分别被客户端和服务器使用,但是这两组元素都被两边同时获取;
客户端使用 client 组元素加密数据,服务器使用 client 元素解密;服务器使用 server 元素加密,client 使用 server 元素解密;
双向通信的不同方向使用的密钥不同,破解通信至少需要破解两次;
encryption key 用于对称加密数据;
IV 作为很多加密算法的初始化向量使用,具体可以研究对称加密算法;
Mac key 用于数据的完整性校验;
4.4 数据加密通信过程
对应用层数据进行分片成合适的 block;
为分片数据编号,防止重放攻击;
使用协商的压缩算法压缩数据;
计算 MAC 值和压缩数据组成传输数据;
使用 client encryption key 加密数据,发送给服务器 server;
server 收到数据之后使用 client encrytion key 解密,校验数据,解压缩数据,重新组装。
注:MAC值的计算包括两个 Hash 值:client Mac key 和 Hash (编号、包类型、长度、压缩数据)。
4.5 抓包分析
关于抓包不再详细分析,按照前面的分析,基本的情况都能够匹配,根据平常定位问题的过程,个人提些认为需要注意的地方:
抓包 HTTP 通信,能够清晰的看到通信的头部和信息的明文,但是 HTTPS 是加密通信,无法看到 HTTP 协议的相关头部和数据的明文信息,
抓包 HTTPS 通信主要包括三个过程:TCP 建立连接、TLS 握手、TLS 加密通信,主要分析 HTTPS 通信的握手建立和状态等信息。
client_hello
根据 version 信息能够知道客户端支持的最高的协议版本号,如果是 SSL 3.0 或 TLS 1.0 等低版本协议,非常注意可能因为版本低引起一些握手失败的情况;
根据 extension 字段中的 server_name 字段判断是否支持SNI,存在则支持,否则不支持,对于定位握手失败或证书返回错误非常有用;
会话标识 session ID 是标准协议部分,如果没有建立过连接则对应值为空,不为空则说明之前建立过对应的连接并缓存;
会话记录 session ticke t是扩展协议部分,存在该字段说明协议支持 sesssion ticket,否则不支持,存在且值为空,说明之前未建立并缓存连接,存在且值不为空,说明有缓存连接。
server_hello
根据 TLS version 字段能够推测出服务器支持的协议的最高版本,版本不同可能造成握手失败;
基于 cipher_suite 信息判断出服务器优先支持的加密协议;
ceritficate:服务器配置并返回的证书链,根据证书信息并于服务器配置文件对比,判断请求与期望是否一致,如果不一致,是否返回的默认证书。
alert
告警信息 alert 会说明建立连接失败的原因即告警类型,对于定位问题非常重要。
5.HTTPS 性能与优化
5.1 HTTPS 性能损耗
前文讨论了 HTTPS 原理与优势:身份验证、信息加密与完整性校验等,且未对 TCP 和 HTTP 协议做任何修改。但通过增加新协议以实现更安全的通信必然需要付出代价,HTTPS 协议的性能损耗主要体现如下:
1. 增加延时
分析前面的握手过程,一次完整的握手至少需要两端依次来回两次通信,至少增加延时2 RTT,利用会话缓存从而复用连接,延时也至少1 RTT*。
2. 消耗较多的 CPU 资源
除数据传输之外,HTTPS 通信主要包括对对称加解密、非对称加解密(服务器主要采用私钥解密数据);压测 TS8 机型的单核
CPU:对称加密算法AES-CBC-256 吞吐量 600Mbps,非对称 RSA 私钥解密200次/s。不考虑其它软件层面的开销,10G
网卡为对称加密需要消耗 CPU 约17核,24核CPU最多接入 HTTPS 连接 4800;静态节点当前10G 网卡的 TS8 机型的 HTTP 单机接入能力约为10w/s,如果将所有的 HTTP 连接变为HTTPS连接,则明显 RSA 的解密最先成为瓶颈。因此,RSA 的解密能力是当前困扰 HTTPS 接入的主要难题。
5.2 HTTPS 接入优化
1. CDN 接入
HTTPS 增加的延时主要是传输延时 RTT,RTT 的特点是节点越近延时越小,CDN 天然离用户最近,因此选择使用 CDN 作为
HTTPS 接入的入口,将能够极大减少接入延时。CDN 节点通过和业务服务器维持长连接、会话复用和链路质量优化等可控方法,极大减少 HTTPS
带来的延时。2. 会话缓存
虽然前文提到 HTTPS
即使采用会话缓存也要至少1*RTT的延时,但是至少延时已经减少为原来的一半,明显的延时优化;同时,基于会话缓存建立的 HTTPS
连接不需要服务器使用RSA私钥解密获取 Pre-master 信息,可以省去CPU
的消耗。如果业务访问连接集中,缓存命中率高,则HTTPS的接入能力讲明显提升。当前 TRP
平台的缓存命中率高峰时期大于30%,10k/s的接入资源实际可以承载13k/的接入,收效非常可观。3. 硬件加速
为接入服务器安装专用的 SSL 硬件加速卡,作用类似 GPU,释放 CPU,能够具有更高的 HTTPS
接入能力且不影响业务程序的。测试某硬件加速卡单卡可以提供 35k 的解密能力,相当于175核
CPU,至少相当于7台24核的服务器,考虑到接入服务器其它程序的开销,一张硬件卡可以实现接近10台服务器的接入能力。4. 远程解密
本地接入消耗过多的 CPU 资源,浪费了网卡和硬盘等资源,考虑将最消耗 CPU
资源的RSA解密计算任务转移到其它服务器,如此则可以充分发挥服务器的接入能力,充分利用带宽与网卡资源。远程解密服务器可以选择 CPU
负载较低的机器充当,实现机器资源复用,也可以是专门优化的高计算性能的服务器。当前也是 CDN 用于大规模HTTPS接入的解决方案之一。5. SPDY/HTTP2
前面的方法分别从减少传输延时和单机负载的方法提高 HTTPS 接入性能,但是方法都基于不改变 HTTP 协议的基础上提出的优化方法,SPDY/HTTP2 利用 TLS/SSL 带来的优势,通过修改协议的方法来提升 HTTPS 的性能,提高下载速度等。
1
在HTTPS项目的开展过程中明显感觉到目前国内互联网对HTTPS并不是很重视,其实也就是对用户隐私和网络安全不重视。本文从保护用户隐私的 角度出发,简单描述现在存在的用户隐私泄露和流量劫持现象,然后进一步说明为什么HTTPS能够保护用户安全以及HTTPS使用过程中需要注意的地方。
国外很多网站包括google,facebook,twitter都支持了全站HTTPS,而国内目前还没有一家大型网站全站支持HTTPS(PC端的 微信全部使用了HTTPS,但是PC端用户应该不多)。甚至一些大型网站明显存在很多HTTPS使用不规范或者过时的地方。比如支付宝使用的是 tls1.0和RC4,而京东(quickpay.jd.com)竟然还使用着SSL3.0这个早就不安全并且性能低下的协议,其他很多网站的HTTPS 登陆页面也存在着不安全的HTTP链接,这个也为黑客提供了可乘之机。
由于篇幅关系,文中几乎没有详细描述任何细节,后面有时间我再一一整理成博客发表出来。同时由于水平有限,本文肯定存在很多错误,希望大家不吝赐教。本 文的大部分内容都能从互联网上搜索到,有些地方我也标明了引用,可以直接跳转过去。但是全文都是在我自己理解的基础上结合开发部署过程中的一些经验和测试 数据一个字一个字敲出来的,最后决定将它们分享出来的原因是希望能和大家多多交流,抛砖引玉,共同推进中国互联网的HTTPS发展。
本文不会科普介绍HTTPS、TLS及PKI,如果遇到一些基本概念文中只是提及而没有描述,请大家自行百度和google。本文重点是想告诉大家HTTPS没有想像中难用可怕,只是没有经过优化。
中国互联网全站使用HTTPS的时代已经到来。
1,用户隐私泄露的风险很大
人们的生活现在已经越来越离不开互联网,不管是社交、购物还是搜索,互联网都能带给人们很多的便捷。与此同时,用户“裸露”在互联网的信息也越来越多,另一个问题也日益严重,那就是隐私和安全。
几乎所有的互联网公司都存在用户隐私泄露和流量劫持的风险。BAT树大招风,这方面的问题尤其严重。比如用户在百度搜索一个关键词,“人流”,很快就会有 医院打电话过来推销人流手术广告,不知情的用户还以为是百度出卖了他的手机号和搜索信息。同样地,用户在淘宝搜索的关键词也很容易被第三方截获并私下通过 电话或者其他广告形式骚扰用户。而QQ和微信呢,显然用户不希望自己的聊天内容被其他人轻易知道。为什么BAT不可能出卖用户隐私信息给第三方呢?因为保 护用户隐私是任何一个想要长期发展的互联网公司的安身立命之本,如果用户发现使用一个公司的产品存在严重的隐私泄露问题,显然不会再信任该公司的产品,最 终该公司也会因为用户大量流失而陷入危机。所以任何一家大型互联网公司都不可能因为短期利益而出卖甚至忽视用户隐私。
那既然互联网公司都知道用户隐私的重要性,是不是用户隐私就得到了很好的保护呢?现实却并不尽如人意。由于目前的WEB应用和网站绝大部分是基于 HTTP协议,国内没有任何一家大型互联网公司采用全站HTTPS方案来保护用户隐私(排除支付和登陆相关的网站或者页面以及PC端的微信)。因为 HTTP协议简单方便,易于部署,并且设计之初也没有考虑安全性,所有内容都是明文传输,也就为现在的安全问题埋下了隐患。用户在基于HTTP协议的 WEB应用上的传输内容都可以被中间者轻易查看和修改。
比如你在百度搜索了一个关键词“https“,中间者通过tcpdump或者wireshark等工具就很容易知道发送请求的全部内容。wireshark的截图如下:
这里所谓的中间者是指网络传输内容需要经过的网络节点,既有硬件也有软件,比如中间代理服务器、路由器、小区WIFI热点、公司统一网关出口等。这里 面最容易拿到用户内容的就是各种通信服务运营商和二级网络带宽提供商。而最有可能被第三方黑客动手脚的就是离用户相对较近的节点。
中间者为什么要查看或者修改用户真实请求内容呢?很简单,为了利益。常见的几种危害比较大的中间内容劫持形式如下:
- 获取无线用户的手机号和搜索内容并私下通过电话广告骚扰用户。为什么能够获取用户手机号?呵呵,因为跟运营商有合作。
- 获取用户帐号cookie,盗取帐号有用信息。
- 在用户目的网站返回的内容里添加第三方内容,比如广告、钓鱼链接、植入木马等。
总结来讲,由于HTTP明文传输,同时中间内容劫持的利益巨大,所以用户隐私泄露的风险非常高。
2,HTTPS能有效保护用户隐私
HTTPS就等于HTTP加上TLS(SSL),HTTPS协议的目标主要有三个:
- 数据保密性。保证内容在传输过程中不会被第三方查看到。就像快递员传递包裹时都进行了封装,别人无法知道里面装了什么东西。
- 数据完整性。及时发现被第三方篡改的传输内容。就像快递员虽然不知道包裹里装了什么东西,但他有可能中途掉包,数据完整性就是指如果被掉包,我们能轻松发现并拒收。
- 身份校验。保证数据到达用户期望的目的地。就像我们邮寄包裹时,虽然是一个封装好的未掉包的包裹,但必须确定这个包裹不会送错地方。
通俗地描述上述三个目标就是封装加密,防篡改掉包,防止身份冒充,那TLS是如何做到上述三点的呢?我分别简述一下。
2.1 数据保密性
2.1.1 非对称加密及密钥交换
数据的保密性主要是通过加密完成的。加密算法一般分为两种,一种是非对称加密(也叫公钥加密),另外一种是对称加密(也叫密钥加密)。所谓非对称加密就是指加密和解密使用的密钥不一样,如下图:
HTTPS使用非对称加解密主要有两个作用,一个是密钥协商,另外可以用来做数字签名。所谓密钥协商简单说就是根据双方各自的信息计算得出双方传输内容时对称加解密需要使用的密钥。
公钥加密过程一般都是服务器掌握私钥,客户端掌握公钥,私钥用来解密,公钥用来加密。公钥可以发放给任何人知道,但是私钥只有服务器掌握,所以公钥加解
密非常安全。当然这个安全性必须建立在公钥长度足够大的基础上,目前公钥最低安全长度也需要达到2048位。大的CA也不再支持2048位以下的企业级证
书申请。因为1024位及以下的公钥长度已经不再安全,可以被高性能计算机比如量子计算机强行破解。计算性能基本会随着公钥的长度而呈2的指数级下降。既然如此为什么还需要对称加密?为什么不一直使用非对称加密算法来完成全部的加解密过程?主要是两点:
- 非对称加解密对性能的消耗非常大,一次完全TLS握手,密钥交换时的非对称解密计算量占整个握手过程的95%。而对称加密的计算量只相当于非对称加密的0.1%,如果应用层数据也使用非对称加解密,性能开销太大,无法承受。
- 非对称加密算法对加密内容的长度有限制,不能超过公钥长度。比如现在常用的公钥长度是2048位,意味着待加密内容不能超过256个字节。
目前常用的非对称加密算法是RSA,想强调一点的就是RSA是整个PKI体系及加解密领域里最重要的算法。如果想深入理解HTTPS的各个方面,RSA是必需要掌握的知识点。它的原理主要依赖于三点:
- 乘法的不可逆特性。即我们很容易由两个乘数求出它们的积,但是给定一个乘积,很难求出它是由哪两个乘数因子相乘得出的。
- 欧拉函数。欧拉函数是小于或等于n的正整数中与n互质的数的数目
- 费马小定理。假如a是一个整数,p是一个质数,那么是p的倍数。
这篇中文博客对RSA的原理解释得比较清楚易懂:RSA算法原理。
RSA算法是第一个也是目前唯一一个既能用于密钥交换又能用于数字签名的算法。另外一个非常重要的密钥协商算法是diffie-
hellman(DH).DH不需要预先知道通信双方的信息就能完成密钥的协商,它使用一个素数P的整数乘法群以及原根G,理论依据就是离散对数。openssl目前只支持如下密钥交换算法:RSA,DH,ECDH, DHE,ECDHE。各个算法的性能和对速度的影响可以参考后面章节,由于篇幅有限,具体实现不再做详细介绍。
2.1.2 对称加密
对称加密就是加密和解密都使用的是同一个密钥。如下图:
采用非对称密码算法的密钥协商过程结束之后就已经得出了本次会话需要使用的对称密钥。对称加密又分为两种模式:流式加密和分组加密。流式加密现在常用的就是RC4,不过RC4已经不再安全,微软也建议网站尽量不要使用RC4流式加密。支付宝可能没有意识到这一点,也可能是由于其他原因,他们仍然在使用RC4算法和TLS1.0协议。
一种新的替代RC4的流式加密算法叫ChaCha20,它是google推出的速度更快,更安全的加密算法。目前已经被android和chrome采用,也编译进了google的开源openssl分支—boring ssl,并且nginx 1.7.4也支持编译boringssl。我目前还没有比较这种算法的性能,但部分资料显示这个算法对性能的消耗比较小,特别是移动端提升比较明显。
分组加密以前常用的模式是AES-CBC,但是CBC已经被证明容易遭受BEAST和LUCKY13攻击。目前建议使用的分组加密模式是AES-GCM,不过它的缺点是计算量大,性能和电量消耗都比较高,不适用于移动电话和平板电脑。尽管如此,它仍然是我们的优先选择。
2.2 数据完整性
这
部分内容相对比较简单,openssl现在使用的完整性校验算法有两种:MD5或者SHA。由于MD5在实际应用中存在冲突的可能性比较大,所以尽量别采
用MD5来验证内容一致性。SHA也不能使用SHA0和SHA1,中国山东大学的王小云教授在2005年就牛逼地宣布破解了SHA-1完整版算法。建议使
用SHA2算法,即输出的摘要长度超过224位。2.3 身份验证和授权
这里主要介绍的就是PKI和数字证书。数字证书有两个作用:
- 身份验证。确保客户端访问的网站是经过CA验证的可信任的网站。
- 分发公钥。每个数字证书都包含了注册者生成的公钥。在SSL握手时会通过certificate消息传输给客户端。
这里简单介绍一下数字证书是如何验证网站身份的。
证书申请者首先会生成一对密钥,包含公钥和密钥,然后把公钥及域名还有CU等资料制作成CSR格式的请求发送给RA,RA验证完这些内容之后(RA会请独立的第三方机构和律师团队确认申请者的身份)再将CSR发送给CA,CA然后制作X.509格式的证书。
那好,申请者拿到CA的证书并部署在网站服务器端,那浏览器访问时接收到证书后,如何确认这个证书就是CA签发的呢?怎样避免第三方伪造这个证书?
答案就是数字签名(digital signature)。数字签名可以认为是一个证书的防伪标签,目前使用最广泛的SHA-RSA数字签名的制作和验证过程如下:
- 数字签名的签发。首先是使用哈希函数对证书数据哈希,生成消息摘要,然后使用CA自己的私钥对证书内容和消息摘要进行加密。
- 数字签名的校验。使用CA的公钥解密签名,然后使用相同的签名函数对证书内容进行签名并和服务端的数字签名里的签名内容进行比较,如果相同就认为校验成功。
图形表示如下:
数字签名签发 数字签名校验
这里有几点需要说明:
- 数字签名签发和校验使用的密钥对是CA自己的公私密钥,跟证书申请者提交的公钥没有关系。
- 数字签名的签发过程跟公钥加密的过程刚好相反,即是用私钥加密,公钥解密。
- 现在大的CA都会有证书链,证书链的好处一是安全,保持根CA的私钥离线使用。第二个好处是方便部署和撤销,即如何证书出现问题,只需要撤销相应级别的证书,根证书依然安全。
- 根CA证书都是自签名,即用自己的公钥和私钥完成了签名的制作和验证。而证书链上的证书签名都是使用上一级证书的密钥对完成签名和验证的。
- 怎样获取根CA和多级CA的密钥对?它们是否可信?当然可信,因为这些厂商跟浏览器和操作系统都有合作,它们的公钥都默认装到了浏览器或者操作系统环境里。比如firefox就自己维护了一个可信任的CA列表,而chrome和IE使用的是操作系统的CA列表。
数字证书的费用其实也不高,对于中小网站可以使用便宜甚至免费的数字证书服务(可能存在安全隐患),像著名的verisign公司的证书一般也就几千到几万块一年不等。当然如果公司对证书的需求比较大,定制性要求高,可以建立自己的CA站点,比如google,能够随意签发google相关证书。
3,HTTPS对速度和性能的影响
既然HTTPS非常安全,数字证书费用也不高,那为什么互联网公司不全部使用HTTPS呢?原因主要有两点:
- HTTPS对速度的影响非常明显。每个HTTPS连接一般会增加1-3个RTT,加上加解密对性能的消耗,延时还有可能再增加几十毫秒。
- HTTPS对CPU计算能力的消耗很严重,完全握手时,web server的处理能力会降低至HTTP的10%甚至以下。
下面简单分析一下这两点。
3.1 HTTPS对访问速度的影响
我用一张图来表示一个用户访问使用HTTPS网站可能增加的延时:
HTTPS增加的延时主要体现在三个阶段,包含了上图所示的2和3阶段。
- 302跳转。为什么需要302?因为用户懒。我想绝大部分网民平时访问百度时都是输入www.baidu.com或者baidu.com吧?很少有输入http://www.baidu.com访问百度搜索的吧?至于直接输入https://www.baidu.com来访问百度的HTTPS服务的就更加少了。所以为了强制用户使用HTTPS服务,只有将用户发起的HTTP请求www.baidu.com302成https://www.baidu.com。这无疑是增加一个RTT的跳转延时。
- 上图第三阶段的SSL完全握手对延时的影响就更加明显了,这个影响不仅体现在网络传输的RTT上,还包含了数字签名的校验,由于客户端特别是移动端的计算性能弱,增加几十毫秒的计算延时是很常见的。
- 还
有一个延时没有画出来,就是证书的状态检查,现在稍微新一点的浏览器都使用ocsp来检查证书的撤销状态,在拿到服务器的证书内容之后会访问ocsp站点
获取证书的状态,检查证书是否撤销。如果这个ocsp站点在国外或者ocsp服务器出现故障,显然会影响这个正常用户的访问速度。不过还好ocsp的检查
周期一般都是7天一次,所以这个对速度的影响还不是很频繁。
另外chrome默认是关闭了ocsp及crl功能,最新版的firefox开启了这个功能,如果ocsp返回不正确,用户无法打开访问网站。实际测试发现,在没有任何优化的情况下,HTTPS会增加200ms以上的延时。
那是不是对于这些延时我们就无法优化了呢?显然不是,部分优化方式参考如下:
- 服务器端配置HSTS,减少302跳转,其实HSTS的最大作用是防止302 HTTP劫持。HSTS的缺点是浏览器支持率不高,另外配置HSTS后HTTPS很难实时降级成HTTP。
- 设置ssl session 的共享内存cache. 以nginx为例,它目前只支持session cache的单机多进程共享。配置如下:
- ssl_session_cache shared:SSL:10m;
如
果是前端接入是多服务器架构,这样的session cache是没有作用的,所以需要实现session
cache的多机共享机制。我们已经在nginx 1.6.0版本上实现了多机共享的session cache。多机session
cache的问题必须要同步访问外部session
cache,比如redis。由于openssl目前提供的API是同步的,所以我们正在改进openssl和nginx的异步实现。- 配
置相同的session ticket key,部署在多个服务器上,这样多个不同的服务器也能产生相同的 session
ticket。session ticket的缺点是支持率不广,大概只有40%。而session id是client
hello的标准内容,从SSL2.0开始就被全部客户支持。
- ssl_session_tickets on;
- ssl_session_ticket_key ticket_keys;
- 设置ocsp stapling file,这样ocsp的请求就不会发往ca提供的ocsp站点,而是发往网站的webserver。ocsp的配置和生成命令如下:
- ssl_stapling on;
- ssl_stapling_file domain.staple;
- 上面是nginx配置,如下是ocsp_stapling_file的生成命令:
- openssl s_client -showcerts -connect yourdomain:443 < /dev/null | awk -v c=-1 ‘/—–BEGIN CERTIFICATE—–/{inc=1;c++} inc {print > (“level” c “.crt”)} /—END CERTIFICATE—–/{inc=0}’
- for i in level?.crt;
- do
- openssl x509 -noout -serial -subject -issuer -in “$i”;
- echo;
- done
- openssl ocsp -text -no_nonce -issuer level1.crt -CAfile CAbundle.crt -cert level0.crt -VAfile level1.crt -url $ocsp_url -respout domain.staple ,
其中$ocsp_url等于ocsp站点的URL,可以通过如下命令求
出:for i in level?.crt; do echo “$i:”; openssl x509 -noout -text -in “$i” | grep OCSP; done,
如果是证书链,一般是最底层的值。- 优先使用ecdhe密钥交换算法,因为它支持PFS(perfect forward secrecy),能够实现false start。
- 设置tls record size,最好是能动态调整record size,即连接刚建立时record size设置成msg,连接稳定之后可以将record size动态增加。
- 如果有条件的话可以启用tcp fast open。虽然现在没有什么客户端支持。
- 启
用SPDY。SPDY是强制使用HTTPS的,协议比较复杂,需要单独的文章来分析。可以肯定的一点是使用SPDY的请求不仅明显提升了HTTPS速度,
甚至比HTTP还要快。在无线WIFI环境下,SPDY比HTTP要快50ms左右,3G环境下比HTTP要快250ms。3.2 HTTPS 对性能的影响
HTTPS为什么会严重降低性能?主要是握手阶段时的大数运算。其中最消耗性能的又是密钥交换时的私钥解密阶段(函数是rsa_private_decryption)。这个阶段的性能消耗占整个SSL握手性能消耗的95%。
前面提及了openssl密钥交换使用的算法只有四种:rsa, dhe, ecdhe,dh。dh由于安全问题目前使用得非常少,所以这里可以比较下前面三种密钥交换算法的性能,具体的数据如下:
上图数据是指完成1000次握手需要的时间,显然时间数值越大表示性能越低。图片和测试方法都可以参考原文,地址如下:http://vincent.bernat.im/en/blog/2011-ssl-perfect-forward-secrecy.html。
密钥交换步骤是SSL完全握手过程中无法绕过的一个阶段。我们只能采取如下措施:
- 通过session cache和session ticket提升session reuse率,减少完全握手(full handshake)次数,提升简化握手(abbreviated handshake)率。
- 出于前向加密和false start的考虑,我们优先配置ecdhe用于密钥交换,但是性能不足的情况下可以将rsa配置成密钥交换算法,提升性能。
openssl 自带的工具可以计算出对称加密、数字签名及HASH函数的各个性能,所以详细数据我就不再列举,读者可以自行测试 。
结论就是对称加密RC4的性能最快,但是RC4本身不安全,所以还是正常情况下还是采用AES。HASH函数MD5和SHA1差不多。数字签名是ecdsa算法最快,但是支持率不高。
事实上由于密钥交换在整个握手过程中消耗性能占了95%,而对称加解密的性能消耗不到0.1%,所以server端对称加密的优化收益不大。相反,由于客户端特别是移动端的CPU计算能力本来就比较弱,所以对称加密和数字签名的优化主要是针对移动客户端。
poly1350是google推出的号称优于aes-gcm的对称加密算法,适用于移动端,可以试用一下。
最后经过测试,综合安全和性能的最优cipher suite配置是: ECDHE-RSA-AES128-GCM-SHA256.
如果性能出现大幅度下降,可以修改配置,提升性能但是弱化了安全性,配置是:rc4-md5,根据openssl的规则,密钥交换和数字签名默认都是使用rsa。
4,HTTPS的支持率分析
分析了百度服务器端一百万的无线访问日志(主要为手机和平板电脑的浏览器),得出协议和握手时间的关系如下:
tls协议版本客户端使用率握手时间 ms
tls 1.224.8%299.496
tls 1.10.9%279.383
tls 1.074%307.077
ssl 3.00.3%484.564从上表可以发现,ssl3.0速度最慢,不过支持率非常低。tls 1.0支持率最广泛。
加密套件和握手时间的关系如下:
加密套件客户端使用率握手时间
ECDHE-RSA-AES128-SHA58.5%294.36
ECDHE-RSA-AES128-SHA25621.1%303.065
DHE-RSA-AES128-SHA16.7%351.063
ECDHE-RSA-AES128-GCM-SHA2563.7%274.83显然DHE对速度的影响比较大,ECDHE的性能确实要好出很多,而AES128-GCM对速度也有一点提升。
通过tcpdump分析client hello请求,发现有56.53%的请求发送了session id。也就意味着这些请求都能通过session cache得到复用。其他的一些扩展属性支持率如下:
tls扩展名支持率
server_name76.99%
session_tickets38.6%
next_protocol_negotiation40.54%
elliptic_curves 90.6%
ec_point_formats90.6%这几个扩展都非常有意义,解释如下:
server_name,,即 sni (server name indicator),有77%的请求会在client hello里面携带想要访问的域名,允许服务端使用一个IP支持多个域名。
next_protocol_negotiation,即NPN,意味着有40.54%的客户端支持spdy.
session_tickets只有38.6%的支持率,比较低。这也是我们为什么会修改nginx主干代码实现session cache多机共享机制的原因。
elliptic_curves即是之前介绍的ECC(椭圆曲线系列算法),能够使用更小KEY长度实现DH同样级别的安全,极大提升运算性能。
5,结论
现在互联网上HTTPS的中文资料相对较少,同时由于HTTPS涉及到大量协议、密码学及PKI体系的知识,学习门槛相对较高。另外在具体的实践过程中
还有很多坑和待持续改进的地方。希望本文对大家有一些帮助,同时由于我本人在很多地方掌握得也比较粗浅,一知半解,希望大家能多提意见,共同进步。最后,为了防止流量劫持,保护用户隐私,大家都使用HTTPS吧,全网站支持。事实上,HTTPS并没有那么难用和可怕,只是你没有好好优化。
1
1
1
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx