阅读 839

https详解

前言

在跟着视屏学习了http的相关知识后,觉得有必要写一篇文章记录一下,加深印象并且方便日后查阅

http起源

说到http的起源不得不说万维网之父Tim Berners-Lee,在1990年10月提出http协议这个概念,并且在1991年Tim发表了一篇文章来描述之前提出的http协议,解释之前提出的实现过程,虽然不是某个机构发布,但是他已经被作为http的最开始版本http0.9版本

http0.9版本

http0.9版本实现的功能非常简单,只支持简单的GET请求,并且只传输纯文本,没有请求头和响应头,因为当时简单的使用场景,这些已经可以满足学术交流

http1.0

然后随着互联网的推动,显然http0.9已经不满足需要,我们需要一个功能更多的http版本来满足日常的使用场景,那么http1.0就呼之欲出了,http1.0新增功能如下

  • 增加了请求头和响应头
  • 支持多种类型的文件传输,不仅仅限制于纯文本
  • 新增POST, HEAD请求方法
  • 增加缓存机制和身份认证

缺点

虽然http1.0比http0.9更加的灵活,但还是有一些缺点如下

  • http1.0是短连接的,也就是说每一次请求的连接都是需要建立三次握手和四次分手,这样就很消耗性能,增加延迟性
  • http1.0没有host属性,如果一台物理机绑定了多台虚拟机之后,无法区分对应的虚拟机从而做出相应的逻辑

http1.1

由于以上的缺点和随着互联网进一步的发展我们需要一个更完善的http版本,此时http1.1就应运而生,http的灵活性如下

  • 增加长连接机制Connect:keep-alive,这样每一次的TCP连接之后,并不会马上断开,可以设置在固定时间或者并发量时候断开,这样的话多个请求就会复用同一个TCP连接,减少RTT数量,减少了延迟,RTT表示客户端发送数据包到接收服务器返回数据的往返时间,也就是说一个TCP的三次连接就是1.5个RTT。
  • 增加了host字段,可以区分不同虚拟机域名,从而实现了不同的逻辑
  • 增加range字段,允许了范围请求
  • 完善了缓存机制,增加了etag, last-modified等字段

缺点

虽然http1.1已经很优秀了,但是还是存在一些问题主要如下

  • 带宽不会被充分利用

带宽指的是网络可以发送或者接受最大字节数

由于http1.1可以开启多个TCP连接,chrome最多是6个,那么每一个TCP都会争取带宽资源,如果带宽资源不足时候,请求或者响应的速度就会变慢,一旦这个请求是重要文本的话比如js,css那么就会导致首页渲染延迟,并且TCP有一个特点就是慢启动,TCP的传输速度不是一下子就稳定,他是一个缓慢的过程,就像车子启动一样速度是慢慢增加的一段时间后速度才会稳定,100M宽带实际的传输速度是12.5M/s,但是最开始的几个请求的速度可能只有2.5M/s,带宽没有被充分利用。

  • 虽然有长连接但是服务端的返回还是有顺序的,这样如果一个请求的响应因为一些原因没有返回就会阻塞后面的响应,造成队头阻塞
  • 请求只能是客户端发起的,服务端不能推送消息
  • 请求头和响应头重复字段较多,浪费流量
  • 请求头和响应头不经过压缩就发送
  • 请求都是明文,不安全

http2.0

上面所说的http1.1虽然很灵活了,但是还是有很多的缺点,为了解决上面的问题,互联网技术的推动者们,又推出了http2.0(http2.0是建立在SPDY协议基础之上的,他是由goole推出解决http1.1缺点的新协议),但是后来放弃了,全身投入了http2.0的建设,下面看看http2.0解决的问题

  • http1.1的一个问题是TCP连接过多,带宽抢占和利用率不充分,所以http2.0采用的是一个域名下面,只建立一个TCP连接,域名下面的所有请求和响应都在这个TCP下面完成,很好的解决了上面的问题

  • http1.1最大的问题是队头阻塞,所以http2.0为了解决这个问题,推出了多路复用,就是一个TCP连接内并行发送请求和并行的接受响应,那么如何保证不乱序是一个关键问题,为了解决这个问题,也是http2.0最核心技术二进制分帧应运而生,二进制分帧率大致的原理如下:

    1:在TCP层确切的说在TSL层上面建立一个二进制分针帧层

    2:并行的请求通过二进制分帧层处理之后,生成一个个很小的数据流,这个数据流已经被二进制处理生成了0,1字节,并且会为每一个数据流生成一个帧ID,发送给服务器

    3:服务器拿到这个数据流根据帧ID组合起来,生成完整的信息,处理之后并行的发送响应数据

    4:响应数据经过二进制分帧层,又会被处理生成对应的帧ID,浏览器拿到这些数据继续根据帧ID组合完整的响应信息

  • http2.0支持头部压缩,减少了流量的浪费

  • http2.0强制开启加密传输,保障了传输的安全性

  • 可以设置优先级,这样在并行发送的时候,可以设置优先返回的数据

缺点

http2.0已经做的很好了,是互联网推动者的智慧的实现,然而还是存在问题,存在什么问题了还是阻塞问题,因为http2.0是建立一个TCP连接的,所以并行的请求数据包都在这一个TCP内,由于TCP的安全可靠机制,一旦一个请求的数据包丢失,响应就会停止,需要浏览器重新传入新的数据包,这样所有的请求都会阻塞,如果数据丢失的比较多的话,经过测试甚至还不如HTTP1.1。因为HTTP1.1的TCP是多个,一个阻塞了不会影响其他的TCP,http2.0的TCP是一个,一旦多个请求的数据包丢失,需要多个请求重新传包,其他请求的响应会被阻塞,所以HTTP2.0虽然做了很多优化,但是最害怕就是请求丢包的情况

http3.0

http3.0是一个还在计划的协议,想要推广还是需要一些时间的,上面我们说了无论http1.1还是http2.0都会有TCP协议的问题,如果去改TCP的话显然不现实,因为改变可能会引起其他的问题,那么http3.0就有了不同的思路,放弃了传统的TCP协议改为UDP的协议,这样就能够避开TCP的缺点,但是仅仅是用UDP还不够,因为UDP是有缺点的,所以我们需要在使用UDP的情况下,还要满足传入数据的可靠性,安全性等问题。下面是一个张http3.0的概念图 在UDP层上面增加了QUIC层,在这一层里面做了很多逻辑,目的是解决UDP本身自带的缺点,可以说http3.0是一个很完美的协议版本,这里有一篇文章介绍http3.0的文章,大家可以深入学习

https协议

https协议书是在TCP协议的基础之上在建立一层TSL(SSL)协议,用来对传输的报文进行加密,在讲解HTTPS加密之前,需要说一下对称加密和非对称加密。

对称加密

对称加密指的是信息交换用一个密钥来完成的,就是加密解密都是用的一个密钥,这种加密方式比较简单,快速。但是相对的不够安全

非对称加密

非对称加密很多网上的文章说的是信息交换需要两个钥匙完成的加密,分别是公钥和私钥。这种说法是没错的,只要信息交换需要两把钥匙的都可以叫非对称加密。但是了在讲解非对称加密的整个过程中,应该是有两对公私钥(也就是四把钥匙,客户端和服务器各两把钥匙,所以网上很多文章说非对称加密是两把钥匙的加密)。非对称加密还是有一点绕,下面用自己的话在描述一遍,过程如下

  • 客户端发送请求,提供自己的公钥给服务端,客户端保留自己的私钥
  • 服务端拿到了客户端的公钥,用客户端的公钥加密自己的公钥(服务端的),然后返回客户端
  • 因为服务端的公钥用客户端的公钥加密了,只能由客户端的私钥解密,客户端解密了拿到服务端的公钥
  • 现在客户端有了服务端的公钥和自己的私钥,服务端同理有了客户端的公钥和自己的私钥
  • 客户端和服务端接下来传输数据的时候,都用对方的公钥加密发送,对方都用自己的私钥解密,这样就达到了安全的作用

非对称加密比较复杂,需要的时间也比较多,但是无论是上述哪种加密,都不是最安全的,因为我们常常有一种攻击叫做中间人攻击

中间人攻击

中间人攻击就是可以截取客户端或者服务端的传输内容,进行纂改的攻击方式。对于对称加密,因为需要进行一次密钥的传递,这个传递很容易被第三方的服务器拦截,从而进行信息获取。对于非对称加密虽然拦截了客户端或者服务器的公钥没什么用,因为公钥的加密是需要私钥解密的,但是了,中间人攻击一般都是很厉害的,他可以拦截你的公钥,换成自己的公钥,那么你们所用的公钥都是中间人的,他自己有私钥,完全可以解密。

CA证书

既然HTTPS协议号称很安全,那么它的加密过程肯定不是这么简单的。HTPPS加密的其实是比较复杂,需要利用CA证书,为什么说CA证书是安全的了,那么就要看一下他的整个流程。

  • 服务端首先需要去CA认证机构购买证书,这一步是无法作假的,就像你去淘宝买东西,商家是不会被别人顶替的,在购买证书的时候,你需要提供自己的公钥,域名等一些信息。CA认证机构也会担起商家的责任,会在线上线下确认你的合法性,是否是正规的公司或者集体,然后才会给你颁发证书,一切验证,确认完毕之后,才会给你颁发证书。那么证书又包含了哪些东西了?

    1:证书包含了购买方的域名,公钥,CA认证机构的一些信息等信息

    2:包含一个数字签名,这个非常重要,数字签名是怎么来的了?首先CA机构会把上述1的一些信息生成一个摘要(该算法不可逆),然后利用自己CA机构的私钥加密这个摘要生成一个签名

  • 好了,服务端有了证书了,客户端建立请求服务端会把证书发送给客户端(后面会说),此时客户端会会验证该证书的合法性,一旦合法了,就能拿到服务器的公钥的,这是生成HTTPS会话密码的前提。

如何保证证书的合法性

我们的浏览器已经和很多证书机构合作,很多认证机构的根证书都会保留在我们的操作系统里面。如果没有的话,就得上传证书了。我们假如我们操作系统已经有了某一个认证机构的根证书。当他收到服务端发送过来的CA证书之后,根据该根证书拿到了这个证书的公钥,如果能解密,那么这个证书就是合法的,那么中间人攻击就不会获取到这个根证书么?上面已经说了,颁发证书没那么容易,需要线上线下调查确认的,所以不用担心中间人伪造证书的。

那么如何保证证书内容不被纂改

上面我们说了,证书合法性保证了之后,虽然黑客不会替换证书,但是他还是有能力纂改证书的,那么这个时候我们怎么保证证书没有被篡改了,这个时候证书里面的摘要就发挥了作用,如果中间人改变了证书内容,那么客户端根据自带的根证书在生成一个摘要,如果摘要和服务端发送给过来的摘要不一样就是被纂改了,那么有人会说中间改了证书信息,然后自己也把摘要换了,这个是没可能的,因为一旦你想动数字签名的内容,首先你得有对应的CA证书公钥才能解密签名替换摘要,一般不会有,因为上面说了你想得到根证书,需要CA机构认证,外一就算你得到了公钥,替换了摘要,但是签名是需要CA机构的私钥加密摘要生成的,CA机构的私钥一般的黑客肯定是没有的,所以这种情况我们认为是不可能实现的。

HTPPS握手

上面CA证书的讲解已经知道了,我们可以在非常安全的情况下,拿到服务器的公钥,那么HTPPS是不是利用这个公钥来当作对称加密的,进行信息加密传递的了?其实不是的,实际情况比这个复杂的多。CA证书只是HTTPS协议加密过程的一部分,所以下面我们主要讲解这个过程具体是什么样子的,先来看一张图片

解释

对上面的图进行一个大概的解释

  • HTPPS请求的时候第一个RTT就是正常的TCP三次握手的过程,这个前提是没有输入https://,下面会说
  • 因为HTPPS的网站别人输入网站名的时候不一定会输入HTTPS,这个时候后台就需要设置302跳转
  • 由于HTTPS的默认端口是443,那么就又得重新建立TCP三次握手
  • TSL握手第一阶段
  • TSL握手的第二阶段

TSL握手的第一阶段

Client Hello

在TSL握手第一阶段的时候。客户端首先发起Client Hello,这个请求包括了

  • 客户端支持的协议版本
  • 一个32位的随机数,用于后面的会话密钥生成
  • 可支持的加密套件,很重要

Server Hello

在接受到了Client Hello之后,服务器就得回复了

  • 确认通信的协议版本
  • 一个32位的随机数,用于后面的会话密钥生成
  • 确认了加密套件,很重要不同的加密套件会产生不同的动作

Server Certificate

这个过程就是上面说的服务器给客户端发送证书的过程,客户端拿到证书之后,首先确认证书的合法性,然后再看一下证书内容是否被纂改了。如果都是正常的话,那么就会获取证书里面的内容,拿到服务器的公钥,此时这里回答上面的一个问题,这个公钥并不是最终的会话加密的密钥,而是为了生成最终对称加密的密钥。这里的公钥其实是一个非对称加密的公钥,目的是为了加密预主密钥,所以HTTPS加密其实是一个包含了非对称加密和对称加密的过程,最终的通信加密其实是一个对称加密。

Server key Exchange

这个过程其实是很复杂的,它是可选的,主要根据最终确认的加密套件来觉决定的,分为RSA、ECDHE两种密钥交换方式,如果加密套件不属于下面DHE_DSS,DHE_RSA,ECDHE_ECDSA,ECDHE_RSA这几种就会直接跳过这个过程,如果属于的话,就会发送额外的数据,来确认密钥。 史上最完整的Tengine HTTPS原理解析、实践与调试 https握手流程详解这两篇文章有详细的讲解

Server Hello Done

这个告诉客户端这次的服务器发送已经完毕,等待客户端响应

TSL握手的第二阶段

Client key Exchange

这个阶段如果是在跳过Server key Exchange阶段的话,客户端会把自己上次请求发送过去的随机数和上次请求服务端发送过来的随机数,做一个整合生成预主密钥,然后利用服务器的公钥加密(此时服务器的公钥派上了用场了),然后发送给了服务器端。如果没有跳过Server key Exchange,那么这个预主密钥的生成,请看上面链接的两篇文章。

Change Cipher Spec

这个协议指的是告诉对方,我已经计算出来了(下面会讲,此时客户端有了预主密钥,客户端随机数,服务端随机数,有能力制做会话密钥了)

Client Finished

告诉服务端,我这边的信息已经发送完成了

Change Cipher Spec Message

告诉对方(客户端),我会用你发过来的预主密钥(服务端自己有私钥可以解密),加上你的随机数和我自己的随机数,生成一个相同的会话密钥的

Server Finished

告诉客户端,我这里也已经发送完毕

预主密钥,主密钥,会话密钥区别

  • 预主密钥主要是在TSL握手的第二阶段客户端生成的。
  • 主密钥是预主密钥,客户端随机数,服务端随机数通过PRE函数生成的
  • 会话密钥是由主密钥,客户端随机数,服务端随机数通过PRE函数生成的,TSL的对称密钥就是这个会话密码

参考文章

http 发展史 (http0.9、http1.0、http1.1、http2、http3) 梳理笔记

史上最完整的Tengine HTTPS原理解析、实践与调试

https握手流程详解

文章分类
前端
文章标签