Mr Shang

我是一个勤劳的码农,每天在技术的牧场辛勤劳作


导航栏
 » 首页
 » 分类浏览
 » 关于我
 » 我的Github
 » RSS订阅
Group 59

HTTPS

18 Aug 2020 » java, http

由于 HTTP 天生“明文”的特点,整个传输过程完全透明,任何人都能够在链路中截获、修改或者伪造请求 / 响应报文,数据不具有可信性。仅凭 HTTP 自身是无力解决的,需要引入新的 HTTPS 协议。

一、HTTPS是什么?

1.1 HTTPS概念

​ HTTPS就是“HTTP over SSL/TLS”,让 HTTP 运行在了安全的 SSL/TLS 协议上,收发报文不再使用 Socket API,而是调用专门的安全接口。HTTPS默认端口号 443(HTTP默认端口是80),请求 - 应答模式、报文结构、请求方法、URI、头字段、连接管理等等都完全沿用 HTTP。所以适用于HTTP的技术和优化策略,大部分都适用于HTTPS。

https vs  http

https request

1.2 什么是“安全”

​ 如果通信过程具备了四个特性,就可以认为是“安全”的,这四个特性是:机密性、完整性,身份认证和不可否认。

机密性(Secrecy/Confidentiality)是指对数据的“保密”,只能由可信的人访问,对其他人是不可见的“秘密”,简单来说就是不能让不相关的人看到不该看的东西。我们之前一直用的 Wireshark ,实际上也是利用了 HTTP 的没有机密性的特点,捕获了传输过程中的所有数据。

完整性(Integrity,也叫一致性)是指数据在传输过程中没有被篡改,不多也不少,“完完整整”地保持着原状。机密性虽然可以让数据成为“秘密”,但不能防止黑客对数据的修改,黑客可以替换数据,调整数据的顺序,或者增加、删除部分数据,破坏通信过程。

身份认证(Authentication)是指确认对方的真实身份,也就是“证明你真的是你”,保证消息只能发送给可信的人。如果通信时另一方是假冒的网站,那么数据再保密也没有用,黑客完全可以使用冒充的身份“套”出各种信息,加密和没加密一样。

不可否认(Non-repudiation/Undeniable),也叫不可抵赖,意思是不能否认已经发生过的行为。使用前三个特性,可以解决安全通信的大部分问题,但如果缺了不可否认,那通信的事务真实性就得不到保证,有可能出现“老赖”。

​ 所以,只有同时具备了机密性、完整性、身份认证、不可否认这四个特性,通信双方的利益才能有保障,才能算得上是真正的安全。HTTPS就拥有四个特性,因此通信过程是安全的。HTTPS是如何实现这些特性的呢?其中一个核心的要素就是SSL/TLS。

二、 SSL/TLS

2.1 SSL和TLS

​ SSL 即安全套接层(Secure Sockets Layer),由网景公司于 1994 年发明,有 v2 和 v3 两个版本,而 v1 因为有严重的缺陷从未公开过。

​ SSL 发展到 v3 时已经证明了它自身是一个非常好的安全通信协议,于是互联网工程组 IETF 在 1999 年把它改名为 TLS(传输层安全,Transport Layer Security),正式标准化,版本号从 1.0 重新算起,所以 TLS1.0 实际上就是 SSLv3.1。

​ 目前应用的最广泛的 TLS 是 1.2,而之前的协议(TLS1.1/1.0、SSLv3/v2)都已经被认为是不安全的,各大浏览器将在今年(2020)年开始逐步停止支持,接下来的内容都是基于 TLS1.2。

​ TLS 由记录协议、握手协议、警告协议、变更密码规范协议、扩展协议等几个子协议组成,综合使用了对称加密、非对称加密、身份认证等许多密码学前沿技术。

​ 浏览器和服务器在使用 TLS 建立连接时需要选择一组恰当的加密算法来实现安全通信,这些算法的组合被称为“密码套件”(cipher suite,也叫加密套件)。下面展示了密码套件信息,可以看一下,对 TLS 和密码套件有个感性的认识。

https suites

可以看到,TLS版本 是 1.2,客户端和服务器都支持非常多的密码套件,而最后协商选定的是“ECDHE-RSA-AES256-GCM-SHA384”。 TLS 的密码套件命名非常规范,格式很固定。基本的形式是“密钥交换算法 + 签名算法 + 对称加密算法 + 摘要算法”,比如上述密码套件的意思就是:“握手时使用 ECDHE 算法进行密钥交换,用 RSA 签名和身份认证,握手后的通信使用 AES 对称算法,密钥长度 256 位,分组模式是 GCM,摘要算法 SHA384 用于消息认证和产生随机数。”

2.2 OpenSSL

​ 说到 TLS,就不能不谈到 OpenSSL,它是一个著名的开源密码学程序库和工具包,几乎支持所有公开的加密算法和协议,已经成为了事实上的标准,许多应用软件都会使用它作为底层库来实现 TLS 功能,包括常用的 Web 服务器 Apache、Nginx 等。

​ OpenSSL 目前有三个主要的分支,1.0.2 和 1.1.0 都已于2019年底停止维护,最新的长期支持版本是 1.1.1。

三、 HTTPS如何实现安全通信

3.1 机密性

​ 实现机密性最常用的手段是“加密”(encrypt),就是把消息用某种方式转换成没有明显排列规则和可读性的文本,只有掌握特殊“钥匙”的人才能再转换出原始文本。这里的“钥匙”就叫做“密钥”(key),加密前的消息叫“明文”(plain text/clear text),加密后的文本叫“密文”(cipher text),使用密钥还原明文的过程叫“解密”(decrypt),是加密的反操作,加密解密的操作过程依据的原理就是“加密算法”。按照密钥的使用方式,加密可以分为两大类:对称加密和非对称加密。

3.1.1 对称加密

“对称加密”就是指加密和解密时使用的密钥都是同一个,是“对称”的。只要保证了密钥的安全,那整个通信过程就可以说具有了机密性。

symmetric

TLS 里有非常多的对称加密算法可供选择,比如 RC4、DES、3DES、AES、ChaCha20 等,但从安全角度考虑前面几种不推荐使用,目前常用的只有 AES 和 ChaCha20。

对称加密看上去好像完美地实现了机密性,但其中有一个很大的问题:如何把密钥安全地传递给对方,术语叫“密钥交换”。因为在对称加密算法中只要持有密钥就可以解密。如果你和网站约定的密钥在传递途中被黑客窃取,那他就可以在之后随意解密收发的数据,通信过程也就没有机密性可言了。

如果说“把密钥再加密一下发过去”,但传输“加密密钥的密钥”又成了新问题。这就像是“鸡生蛋、蛋生鸡”,可以无限递归下去。只用对称加密算法,是无法解决密钥交换的问题的。

3.1.2 非对称加密

非对称加密有两个密钥,一个叫“公钥”(public key),一个叫“私钥”(private key)。两个密钥是不同的,“不对称”,公钥可以公开给任何人使用,而私钥必须严格保密。

公钥和私钥有个特别的“单向”性,虽然都可以用来加密解密,但公钥加密后只能用私钥解密,反过来,私钥加密后也只能用公钥解密。

非对称加密可以解决“密钥交换”的问题。网站秘密保管私钥,在网上任意分发公钥,你想要登录网站只要用公钥加密就行了,密文只能由私钥持有者才能解密。而黑客因为没有私钥,所以就无法破解密文。

非对称加密算法的设计要比对称算法难得多,在 TLS 里只有很少的几种,比如 DH、DSA、RSA、ECC 等。

RSA 可能是其中最著名的一个,几乎可以说是非对称加密的代名词,它的安全性基于“整数分解”的数学难题,使用两个超大素数的乘积作为生成密钥的材料,想要从公钥推算出私钥是非常困难的。

10 年前 RSA 密钥的推荐长度是 1024,但随着计算机运算能力的提高,现在 1024 已经不安全,普遍认为至少要 2048 位。

ECC(Elliptic Curve Cryptography)是非对称加密里的“后起之秀”,它基于“椭圆曲线离散对数”的数学难题,使用特定的曲线方程和基点生成公钥和私钥,子算法 ECDHE 用于密钥交换,ECDSA 用于数字签名。

目前比较常用的两个曲线是 P-256(secp256r1,在 OpenSSL 称为 prime256v1)和 x25519。P-256 是 NIST(美国国家标准技术研究所)和 NSA(美国国家安全局)推荐使用的曲线,而 x25519 被认为是最安全、最快速的曲线。

比起 RSA,ECC 在安全强度和性能上都有明显的优势。160 位的 ECC 相当于 1024 位的 RSA,而 224 位的 ECC 则相当于 2048 位的 RSA。因为密钥短,所以相应的计算量、消耗的内存和带宽也就少,加密解密的性能就上去了,对于现在的移动互联网非常有吸引力。

3.1.3 HTTPS的加密选择

非对称加密没有“密钥交换”的问题,只用非对称加密来实现机密性可行吗?理论上是可行的,但因为它们都是基于复杂的数学难题,运算速度很慢,即使是 ECC 也要比 AES 差上好几个数量级。如果仅用非对称加密,虽然保证了安全,但通信速度大大降低,几乎没有实用性。

下面对比了 AES 和 RSA 这两种算法的性能某一次测试的结果:

aes_128_cbc enc/dec 1000 times : 0.97ms, 13.11MB/s

rsa_1024 enc/dec 1000 times : 138.59ms, 93.80KB/s
rsa_1024/aes ratio = 143.17

rsa_2048 enc/dec 1000 times : 840.35ms, 15.47KB/s
rsa_2048/aes ratio = 868.13

可以看到,RSA 的运算速度是非常慢的,2048 位的加解密大约是 15KB/S(微秒或毫秒级),而 AES128 则是 13MB/S(纳秒级),差了几百倍。

目前 TLS 里使用的混合加密方式,过程是这样的:

在通信刚开始的时候使用非对称算法,比如 RSA、ECDHE,首先解决密钥交换的问题。

然后用随机数产生对称算法使用的“会话密钥”(session key),再用公钥加密。因为会话密钥很短,通常只有 16 字节或 32 字节,对速度敏感度不高。

对方拿到密文后用私钥解密,取出会话密钥。这样,双方就实现了对称密钥的安全交换,后续就不再使用非对称加密,全都使用对称加密。

mixed cypher

这样混合加密就解决了对称加密算法的密钥交换问题,而且安全和性能兼顾,完美地实现了机密性。

3.2 完整性

实现完整性的手段主要是摘要算法(Digest Algorithm),也就是常说的散列函数、哈希函数(Hash Function)。可以把摘要算法近似地理解成一种特殊的压缩算法,它能够把任意长度的数据“压缩”成固定长度、而且独一无二的“摘要”字符串,就好像是给这段数据生成了一个数字“指纹”。

摘要算法实际上是把数据从一个“大空间”映射到了“小空间”,所以就存在“冲突”(collision,也叫碰撞)的可能性,就如同现实中的指纹一样,可能会有两份不同的原文对应相同的摘要。好的摘要算法必须能够“抵抗冲突”,让这种可能性尽量地小。

3.3 身份认证

身份认证实际上就是“公钥的信任”问题。因为谁都可以发布公钥,我们还缺少防止黑客伪造公钥的手段。

找一个公认的可信第三方,让它作为“信任的起点”,构建起公钥的信任链。这个“第三方”就是我们常说的 CA(Certificate Authority,证书认证机构)。它具有极高的可信度,由它来给各个公钥签名,用自身的信誉来保证公钥无法伪造,是可信的。

CA 对公钥的签名认证也是有格式的,不是简单地把公钥绑定在持有者身份上就完事了,还要包含序列号、用途、颁发者、有效时间等等,把这些打成一个包再签名,完整地证明公钥关联的各种信息,形成“数字证书”(Certificate)。

3.4 不可否认

不可否认性靠数字签名解决,内容摘要算法得到摘要,私钥加密摘要,对方使用对应公钥解密,得到摘要,再和自己得到的服务器提供的原文摘要对比,一致说明这个内容就是原服务器提供的,由证书说明了服务器的身份。

四、 使用Wireshark抓取HTTPS数据

4.1 设置环境

  • windows系统

首先,你需要在 Windows 的设置里新增一个系统变量“SSLKEYLOGFILE”,设置浏览器日志文件的路径,比如“D:\http_study\www\temp\sslkey.log”。

win env

然后在 Wireshark 里设置“Protocols-TLS”(较早版本的 Wireshark 里是“SSL”),在“(Pre)-Master-Secret log filename”里填上刚才的日志文件。

win wireshark

  • Macos系统

使用下面的命令打开Chrome浏览器

export SSLKEYLOGFILE=$PWD/keylog.log
open -n /Applications/Google\ Chrome.app

注意: $PWD可以换成一个本机具体的路径

然后在 Wireshark 里设置“Protocols-TLS”(较早版本的 Wireshark 里是“SSL”),在“(Pre)-Master-Secret log filename”里填上刚才的日志文件。

mac wireshark

4.2 抓取数据

后续的操作与抓取http相同。比如抓取实验环境的某次访问,截图如下:

wire shark

五、 WAF

因为 HTTP 是一个开放的协议,Web 服务都运行在公网上,任何人都可以访问,所以天然就会成为黑客的攻击目标。面对黑客攻击手段,应该怎么防御呢?这就要用到“网络应用防火墙”(Web Application Firewall)了,简称为“WAF”。

WAF 也是一种“防火墙”,但它工作在七层,看到的不仅是 IP 地址和端口号,还能看到整个 HTTP 报文,所以就能够对报文内容做更深入细致的审核,使用更复杂的条件、规则来过滤数据。WAF 就是一种“HTTP 入侵检测和防御系统”。

waf

WAF 都能干什么呢?通常一款产品能够称为 WAF,要具备下面的一些功能:

  • IP 黑名单和白名单,拒绝黑名单上地址的访问,或者只允许白名单上的用户访问;
  • URI 黑名单和白名单,与 IP 黑白名单类似,允许或禁止对某些 URI 的访问;
  • 防护 DDoS 攻击,对特定的 IP 地址限连限速;
  • 过滤请求报文,防御“代码注入”攻击;
  • 过滤响应报文,防御敏感信息外泄;
  • 审计日志,记录所有检测到的入侵操作。

Nginx可以通过修改配置文件,加上JS 代码(新版本才能支持),就能够实现基本的 WAF 功能。

六、 HTTP vs HTTPS

HTTP通信过程是不安全的,那我们在应用开发的时候,需要全部升级升HTTPS吗?

HTTPS 连接大致上可以划分为两个部分,第一个是建立连接时的非对称加密握手,第二个是握手后的对称加密报文传输。

在 TCP 建连之后,正式数据传输之前,HTTPS 比 HTTP 增加了一个 TLS 握手的步骤,这个步骤最长可以花费两个消息往返,也就是 2-RTT。而且在握手消息的网络耗时之外,还会有其他的一些“隐形”消耗,比如:

  • 产生用于密钥交换的临时公私钥对(ECDHE);
  • 验证证书时访问 CA 获取 CRL 或者 OCSP;
  • 非对称加密解密处理“Pre-Master”。

在最差的情况下,也就是不做任何的优化措施,HTTPS 建立连接可能会比 HTTP 慢上几百毫秒甚至几秒,这其中既有网络耗时,也有计算耗时。

从上面的数据可以看出来,在微服务架构体系下,服务越多,消耗越高,升级的成本是巨大的。那有没有什么好的方式,既兼顾安全性,又能保证性能呢?答案是有的,可以使用“网关”+网络隔离的方式实现。具体来说,就是所有的服务部署到内网环境,所有需要与外部进行安全通信的,都通过网关来实现。结构如下图:

gateway

© Mr Shang - niceshang[#]outlook.com - Powered by Jekyll.