面试又问我https?不如我们抓个包看看吧!

前言

本文原载于我的博客,地址:https://blog.guoziyang.top/archives/57/

面试官:HTTPS协议了解吗?

我:了解的了解的(内心OS:不就是HTTP的加密版本吗)

面试官:那你可以说一下HTTPS的握手流程吗?

我:……

面试官:今天就先到这儿吧,你先回去等通知吧。

真悲哀,又凉了。

你是否也是像我一样,熟记各个框架的使用,各种源码信手拈来,却最后总是会败在这些基础的东西上?你是否觉得网络上的https讲解都太形而上,枯燥无聊,看完一遍也记不下来?

那我们就亲自抓包看一看吧,亲眼看一看https的握手流程。

本次环境使用macos下的wireshark进行抓包。

关于https

在开始抓包之前,有必要先进行一些https的简单介绍。

https的出现主要是为了解决http明文传输的问题,如果http传输的信息包含有像密码之类的敏感数据,那么任何拦截到数据包的人都可以很轻易地获取到这些信息,拦截者慎之可以任意修改数据,这是很危险的,

https对于http的问题,主要进行了如下的改进:

  • 解决窃听风险,数据加密传输
  • 解决篡改风险,增加了信息校验,数据一旦被篡改就会被发现
  • 解决伪装风险,可以进行身份校验

那么HTTPS是如何做到这一点的呢?

公所周知,HTTP在网络的五层模型中处于应用层,基于传输层的TCP。而HTTPS则是在应用层的HTTP的下层又加入了一层SSL/TLS加密层,http的数据要经过ssl加密后才会交给tcp。

至于加密原理,这里不做赘述。只提一句,HTTPS的信息加密和解密,基于对称加密算法,并不是基于非对称加密。加密和解密是使用的同一个密钥。但是,这样是有风险的,如果在交换密钥的时候(这时候还没有进行加密,肯定是明文的)密钥被拦截,那也是非常危险的,所以在https的握手期间,密钥交换过程是基于非对称加密的。

这时有人就会问,那既然非对称加密这么好,明文传输都不怕被拦截,那为什么整个HTTPS的信息加密不基于非对称加密呢?原因在于,虽然非对称加密在安全性几乎无可挑剔,但是有一个很致命的缺点,那就是资源消耗大,且速度慢,如果完全使用非对称加密的话,那上5G就非常必要的(笑)。

抓包

为了保留第一次握手的数据,我在抓包之前清理了浏览器缓存。

此次抓包使用我的主页https://guoziyang.top作为抓包对象,在wireshark中可以设置拦截器ip.addr == 服务器ip地址 and tcp.port == 443,过滤掉一些不必要的包。

抓包结果如下:

2020-06-06-3.06.14.png

我们来逐步分析https的握手。

TCP三次握手

由于HTTPS也是基于TCP进行传输的,那么TCP建立连接就需要进行三次握手,和HTTP不同的是,如果只输入域名进行访问的话,默认和目标服务器的443端口建立连接,而HTTP是和80端口。

478、482和483三个TCP包对应着三次握手的过程,SYN、SYNACK和ACK,很常规,和HTTP一样,就不说了,大家应该都懂。

下面就是HTTPS协议的交互过程。

HTTPS握手过程

第一次握手

第一次握手是由客户端向服务器发送一个Client Hello包,对应着上图的No. 484包。

包的内容如下:

2020-06-06-3.18.18.png

字段很多,挑重点的看。注意这里看的是Handshake Protocol。

首先就说明了自己的TLS协议版本,Version: TLS 1.2声明的客户端的协议版本为TLS 1.2。在下方的Extension: supported_versions字段中,说明了支持的服务端使用的TLS版本:

2020-06-06-3.22.39.png

这里支持四个版本:TLS 1.0到1.3,即服务器可以使用这些版本的TLS。

接着出现了一个随机数,Random字段:

2020-06-06-3.26.17.png

这个字段由两个小字段组成,分别是一个四字节时间戳,和一个随机的字节数组,长28字节。random字段用于随后生成对话密钥,这个之后再说。

Cipher Suites字段,客户端声明了自己支持的加密协议套件,服务端可以使用这些加密算法和自己通信。注意这里说的是对称加密算法套件,是在正式传输数据时使用的对称加密。如下:

2020-06-06-3.31.11.png

注意一下这里的加密套件的命名方式,表示组成该套件的算法,一个完整的Cipher Suites至少需要四个算法,分别是认证算法(Au,用于身份验证)、密钥交换算法(KeyExchange,用于密钥协商)、对称加密算法(Enc,用于信息加密)和信息摘要算法(Mac,用于完整性校验)

第二次握手

服务器收到请求后,会先返回一个ACK(No. 489),接着才对客户端进行回应。应答包为Server Hello包。在这次抓包过程中,服务器将这次握手分成了两个包(也可以放在一个包里,也可以分成更多的包),第一个包 No. 545 如下:

2020-06-06-3.55.20.png

服务器首先也说明自己使用的加密协议版本Version: TLS 1.2,这个由服务器在客户端的提供的supported_versions中挑选,如果服务器没有可以使用的加密协议,就会主动关闭通信。

该包中也有一个Random字段,结构和第一次握手的包中的Random结构相同,用于后续生成对话密钥。

服务器会在客户端提供的加密套件Cipher Suites中挑选一个自己支持的,并告知客户端。在该包中,为Cipher Suite字段,这里可以看到,服务器选用的加密套件为TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

第二个包为No. 548:

2020-06-06-4.06.07.png

这里这个包名为Certificate, Server Key ExchangeServer Hello Done

Certificate包主要就用于服务器发送自己的域名证书供客户端校验,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6Rwv75Ls-1591435870773)(https://img.guoziyang.top/images/2020/06/06/2020-06-06-4.09.21.png)]

这里我的服务器发送了两个证书,一个是我自己的域名证书,另一个是Let's Encrypt Authority X3的证书,因为我的证书是从Let's Encrypt申请的,而Let's Encrypt不是根证书颁发机构,而是一个中级证书颁发机构,所以客户端还需要验证中级证书颁发机构的有效性。

Server Key Exchange用于发送自己的公钥,在该包中基本只有一个参数:EC Diffie-Hellman Server Params

2020-06-06-4.17.25.png

这一步,服务器会通过Diffie-Hellman算法生成一个密钥对,在这里使用的是圆锥曲线算法,在Named Curve中指明自己使用的圆锥曲线。具体算法感兴趣的同学可以去学习学习,这里就不多说了。

接着,服务器会将生成的密钥对中的公钥放在Pubkey字段发送给客户端,在Signature Algorithm字段中说明自己使用的签名算法,并将使用自己的私钥签名的数据存放在Signature字段中。

最后服务器会发送一个Server Hello Done包,这个包没有数据,仅仅通知客户端这次握手结束了。

第三次握手

在客户端将第三次握手的包发送给服务器之前,客户端会首先对服务器的域名证书进行校验,判断是否是有效的域名证书,例如域名是否一致、是否过期、是否是可信的CA颁发的等。如果是可信的,或者客户端选择忽略域名的有效性,那么客户端就会进行第三次握手,即上图的包No. 552:

2020-06-06-4.53.09.png

这时客户端已经拥有了三个数:客户端随机数、服务器随机数和服务器的Pubkey,客户端会将这三个参数使用Diffie-Hellman算法生成Premaster secret,即最终的密钥。

从这个包名可以看出,这次握手的目的有三个:Client Key ExchangeChange Cipher SpecEncrypted Handshake Message

Client Key Exchange过程中,类似Server Key Exchange,客户端同样生成一份自己的Pubkey。

Change Cipher Spec这个包没有数据,仅仅是提示服务器,表示以后的数据都会通过加密的方式发送,但实际上,这个包是无关紧要的,在TLS 1.3中被正式废弃。

Encrypted handshake message是一段加密的消息,是使用协商成功后的对称密钥加密发送的第一个消息。加密的内容是将之前所有的握手数据,计算md摘要后再进行PRF运算,最后再使用密钥进行加密,可用于服务端校验握手流程,判断是否有过中间人攻击。

第四次握手

第四次握手对应的包No. 588,由服务器发送给客户端,如下:

2020-06-06-5.06.59.png

在此之前,服务器也获取到了客户端的Pubkey,服务器也拥有了三个参数,于是也生成了最终密钥,至于为什么明明Pubkey不同,最终密钥相同的原因,可以去研究下Diffie-Hellman算法。

这个包四个功能:New Session TicketChange Cipher SpecEncrypted Handshake MessageApplication Data Protocol: http2

New Session Ticket这个包类似于cookie,当客户端重新连接的时候,可以携带上该参数,就无须重新进行握手的过程,而是可以直接使用之前协商的参数进行加密。

Change Cipher Spec和第三次握手一样,是一个无关紧要的包。Encrypted Handshake Message包的作用也和第三次握手类似,加密的是服务器的握手记录,用于给客户端校验。

最后一个包,Application Data Protocol,是服务器通知客户端HTTP协议的版本,这里我的服务器使用了HTTP 2。

End

完成了这个协商后,客户端和服务端都获取到了对称加密的密钥,就可以进行安全的通信了。而且这个密钥交换的过程也是安全的,这样,就建立了一个安全的通信信道。

猜你喜欢

转载自blog.csdn.net/qq_40856284/article/details/106590877