肝不完这份HTTP八股文的你,再强大也是假的!

·  阅读 2537
肝不完这份HTTP八股文的你,再强大也是假的!

关于网络模型

OSI 网络模型

  • 应用层,给用户提供应用功能;
  • 表示层,负责把数据转换成兼容另一个系统能识别的格式;
  • 会话层,负责建立、维持、同步会话;
  • 传输层,负责端到端的数据传输;
  • 网络层,寻址、路由;
  • 数据链路层,负责数据的封帧和差错检测,以及 MAC 寻址;
  • 物理层,负责在物理网络中传输数据帧;

OSI 模型实在太复杂,提出的也只是概念理论上的分层,并没有提供具体的实现方案。

TCP/IP 网络模型

应用层

用层只需要专注于为用户提供应用功能,比如 HTTP、FTP。应用层是不用去关心数据是如何传输的,就类似于,我们寄快递的时候,只需要把包裹交给快递员,我们不需要关心快递是如何被运输的。应用层是工作在操作系统中的用户态,传输层及以下则工作在内核态。

传输层

传输层为应用层提供网络支持。传输层的报文中会携带端口号,因此接收方可以识别出该报文是发送给哪个应用。

网络层

网络层最常使用的是 IP 协议(Internet Protocol),IP 协议会将传输层的报文作为数据部分,再加上 IP 包头组装成 IP 报文,如果 IP 报文大小超过 MTU(以太网中一般为 1500 字节)就会再次进行分片

img

IP 地址分成两种意义:

  • 一个是网络号,负责标识该 IP 地址是属于哪个「子网」的;
  • 一个是主机号,负责标识同一「子网」下的不同主机;

除了寻址能力, IP 协议还有另一个重要的能力就是路由。两台设备通过很多网关、路由器、交换机等众多网络设备连接起来,数据包到达一个网络节点,就需要通过路由算法决定下一步走哪条路径。

IP 的寻址作用是告诉我们去往下一个目的地该朝哪个方向走,路由则是根据「下一个目的地」选择路径。寻址更像在导航,路由更像在操作方向盘

网络接口层

接下来要交给网络接口层,在 IP 头部的前面加上 MAC 头部,并封装成数据帧。MAC 头部包含了接收方和发送方的 MAC 地址等信息。

网络接口层主要为网络层提供「链路级别」传输的服务,负责在以太网、WiFi 这样的底层网络上发送原始数据包,工作在网卡这个层次,使用 MAC 地址来标识网络上的设备。

输入URL后发生了什么?

简单的网络模型

DNS 解析

在域名中,越靠右的位置表示其层级越高。实际上域名最后还有一个点,比如 www.server.com. ,这个最后的一个点代表根域名。

域名的层级关系类似一个树状结构:

  • 根 DNS 服务器(.)
  • 顶级域 DNS 服务器(.com)
  • 权威 DNS 服务器(server.com)

DNS 树状结构

任何 DNS 服务器就都可以访问根域 DNS 服务器了。只要能够找到任意一台 DNS 服务器,就可以通过它找到根域 DNS 服务器,然后再一路顺藤摸瓜找到位于下层的某台目标 DNS 服务器。

域名解析的工作流程:

浏览器会先看自身有没有对这个域名的缓存,如果有,就直接返回,如果没有,就去问操作系统,操作系统也会去看自己的缓存,如果有,就直接返回,如果没有,再去 hosts 文件看,也没有,才会去问「本地 DNS 服务器」。

  1. 客户端首先会发出一个 DNS 请求,问 www.server.com 的 IP 是啥,并发给本地 DNS 服务器(也就是客户端的 TCP/IP 设置中填写的 DNS 服务器地址)。
  2. 本地域名服务器收到客户端的请求后,如果缓存里的表格能找到 www.server.com,则它直接返回 IP 地址。如果没有,本地 DNS 会去问它的根域名服务器:“老大, 能告诉我 www.server.com 的 IP 地址吗?” 根域名服务器是最高层次的,它不直接用于域名解析,但能指明一条道路。
  3. 根 DNS 收到来自本地 DNS 的请求后,发现后置是 .com,说:“www.server.com 这个域名归 .com 区域管理”,我给你 .com 顶级域名服务器地址给你,你去问问它吧。”
  4. 本地 DNS 收到顶级域名服务器的地址后,发起请求问“老二, 你能告诉我 www.server.com 的 IP 地址吗?”
  5. 顶级域名服务器说:“我给你负责 www.server.com 区域的权威 DNS 服务器的地址,你去问它应该能问到”。
  6. 本地 DNS 于是转向问权威 DNS 服务器:“老三,www.server.com对应的IP是啥呀?” server.com 的权威 DNS 服务器,它是域名解析结果的原出处。为啥叫权威呢?就是我的域名我做主。
  7. 权威 DNS 服务器查询后将对应的 IP 地址 X.X.X.X 告诉本地 DNS。
  8. 本地 DNS 再将 IP 地址返回客户端,客户端和目标建立连接。

域名解析的工作流程

协议栈

img

应用程序(浏览器)通过调用 Socket 库,来委托协议栈工作。协议栈的上半部分有两块,分别是负责收发数据的 TCP 和 UDP 协议,这两个传输协议会接受应用层的委托执行收发数据的操作。 IP 协议控制网络包收发操作,数据会被切分成一块块的网络包,而将网络包发送给对方的操作就是由 IP 负责的。

IP 中还包括 ICMP 协议和 ARP 协议。

  • ICMP 用于告知网络包传送过程中产生的错误以及各种控制信息。
  • ARP 用于根据 IP 地址查询相应的以太网 MAC 地址。

IP 下面的驱动程序负责控制网卡硬件,而最下面的网卡则负责完成实际的收发操作,也就是对网线中的信号执行发送和接收操作。

TCP

HTTP 是基于 TCP 协议传输的。在 HTTP 传输数据之前,首先需要 TCP 建立连接,称为三次握手。三次握手目的是保证双方都有发送和接收的能力

  • MSS:除去 IP 和 TCP 头部之后,一个网络包所能容纳的 TCP 数据的最大长度。

数据会被以 MSS 的长度为单位进行拆分,在每个被拆分的数据加上 TCP 头信息,组装好 TCP 报文之后,交给 IP 模块来发送数据。

远程定位 -- IP

TCP 模块在执行连接、收发、断开等各阶段操作时,都需要委托 IP 模块将数据封装成网络包发送给通信对象。IP 头部里面需要有源地址 IP目标地址 IP

两点传输 -- MAC

生成了 IP 头部之后,接下来网络包还需要在 IP 头部的前面加上 MAC 头部。MAC 头部是以太网使用的头部,它包含了接收方和发送方的 MAC 地址,用于两点之间的传输

MAC 发送方和接收方如何确认?

发送方的 MAC 地址获取就比较简单了,MAC 地址是在网卡生产时写入到 ROM(只读存储器) 里的,只要将这个值读取出来写入到 MAC 头部就可以了。

每个主机都有自己的 ARP 高速缓存表,记录着 IP 与 MAC 地址的对应关系。客户端先查找自己的高速缓存表,如果没有,需要发送 ARP 请求报文广播查询,报文中有客户端的 iP 与 MAC 和服务端的 IP,服务端发现 IP 相符,便将客户端的 IP、MAC 记录到自己的高速缓存表中,然后发送 ARP 响应告知自己的 MAC 地址。客户端收到并记录到高速缓存表中。

注:IP 与 MAC 的对应关系并不是永久的(如主机可能会更换网卡)

IP 用于标识网络号与主机号(MAC 不能区分网络)

多个主机连接在同一个广播信道上时,就需要唯一标识 MAC 地址(MAC 地址是网络上各接口的唯一标识,而不是设备的唯一标识,例如一个主机有无线网卡和无线网卡)

出口 -- 网卡

网络包只是存放在内存中的一串二进制数字信息,没有办法直接发送给对方。因此,我们需要将数字信息转换为电信号,才能在网线上传输,也就是说,这才是真正的数据发送过程。负责执行这一操作的是网卡,要控制网卡还需要靠网卡驱动程序。网卡驱动获取网络包之后,会将其复制到网卡内的缓存区中,接着会在其开头加上报头和起始帧分界符,在末尾加上用于检测错误的帧校验序列。最后网卡会将包转为电信号,通过网线发送出去。

送别者--交换机

交换机的设计是将网络包原样转发到目的地。交换机工作在 MAC 层,也称为二层网络设备

首先,电信号到达网线接口,交换机进行接收,接下来交换机将电信号转换为数字信号。

然后通过包末尾校验错误,如果没问题则放到缓冲区。这部分操作基本和计算机的网卡相同,但交换机的工作方式和网卡不同:交换机的端口不具有 MAC 地址,而网卡有, 网卡会核对 MAC 地址,不是的话会丢弃;交换机则是直接接收并存放到缓冲区。

然后交换机表查找 MAC 地址,然后将信号发送到相应的端口

出境大门--路由器

路由器与交换机的区别

路由器转发的工作原理和交换机类似,也是通过查表判断包转发的目标。

不过在具体的操作过程上,路由器和交换机是有区别的。

  • 因为路由器是基于 IP 设计的,路由器的各个端口都具有 MAC 地址和 IP 地址(从这个意义上来说,它和计算机的网卡是一样的)
  • 交换机是基于以太网设计的,交换机的端口只记录mac地址与端口的绑定关系

网络包经过交换机之后,现在到达了路由器,并在此被转发到下一个路由器或目标设备。

路由器端口会接收发给自己的以太网包,然后路由表查询转发目标(路由器也有高速缓存表),将包发送出去。接下来,下一个路由器会将包转发给再下一个路由器,经过层层转发之后,网络包就到达了最终的目的地。

在网络包传输的过程中,源 IP 和目标 IP 始终是不会变的,一直变化的是 MAC 地址,因为需要 MAC 地址在以太网内进行两个设备之间的包传输。

到达服务器

网络分层模型

数据包抵达服务器后,服务器会先扒开数据包的 MAC 头部,查看是否和服务器自己的 MAC 地址符合,符合就将包收起来。

接着继续扒开数据包的 IP 头,发现 IP 地址符合,根据 IP 头中协议项,知道自己上层是 TCP 协议。

于是,扒开 TCP 的头,里面有序列号,需要看一看这个序列包是不是我想要的,如果是就放入缓存中然后返回一个 ACK,如果不是就丢弃。TCP头部里面还有端口号, 服务器正在监听这个端口号。

于是,服务器自然就知道是 HTTP 进程想要这个包,于是就将包发给 HTTP 进程。服务器的 HTTP 进程看到,原来这个请求是要访问一个页面,于是就把这个网页封装在 HTTP 响应报文里。

客户端收到之后,向服务器发起了 TCP 四次挥手,至此双方的连接就断开了。

总结

有可靠传输的 TCP、有远程定位功能的 IP、有指明下一站位置的 MAC 等,经过每一层都要加一层头部,使得数据包能在交换机和路由器的转发下,抵达到了目的地。

HTTP

HTTP:超文本传输协议

如何理解?

HTTP 是一个在计算机世界里专门在「两点」之间「传输」文字、图片、音频、视频等「超文本」数据的「约定和规范」。

状态码

 五大类 HTTP 状态码

200:一切正常

204:响应体为空

206:应用于断点续传,返回的只是部分资源

301:永久重定向,原来的资源已经不存在

302:临时重定向,资源还在,但暂时用另一个 URL

301 和 302 都会在响应头里使用 Location 字段,指明跳转的 URL,浏览器会自动重定向

304:用于协商缓存

400:客户端的请求有误,很笼统

403:服务器禁止客户端访问

404:没找到资源

500:服务端出错,很笼统

501:即将开业,敬请期待

502:通常是服务器作为网关或者代理时返回,服务器正常,但后端服务器出错

503:服务器很忙,无法响应

常见字段

Host

域名

例: Host: www.A.com
复制代码

Content-Length

服务器在返回数据时,会有 Content-Length 字段,表明本次回应的数据长度。

Content-Length: 1000
复制代码

Connection

最常用于客户端要求服务器使用 TCP 持久连接

img

HTTP/1.1 默认持久连接,但为了兼容老版本的 HTTP,需要指定 Connection 值为 Keep-alive

Connection: keep-alive
复制代码

一个可以复用的 TCP 连接就建立了,直到客户端或服务器主动关闭连接。但是,这不是标准字段。

Content-Type

服务器回应时,告诉客户端,本次数据是什么格式。

img

Content-Encoding

内容压缩方式

img

GET/POST 区别

本质没有啥区别,只是由于http协议规定和浏览器或者服务器的限制,导致他们在应用层面上体现形式不同。

参数区别

GET 请求的参数位置一般是写在 URL 中,URL 规定只能支持 ASCII,所以 GET 请求的参数只允许 ASCII 字符 ,而且浏览器会对 URL 的长度有限制( HTTP 协议本身对 URL 长度并没有做任何规定)。

根据 RFC 规范,POST 的语义是根据请求载荷(报文body)对指定的资源做出处理。POST 请求携带数据的位置一般是写在请求体中, 浏览器不会对 body 大小做限制。

安全、幂等、可缓存

  • 在 HTTP 协议里,所谓的「安全」是指请求方法不会「破坏」服务器上的资源。
  • 所谓的「幂等」,意思是多次执行相同的操作,结果都是「相同」的。

GET 的语义是请求获取指定的资源。GET 安全、幂等、可缓存

POST 的语义是根据载荷对指定的资源做出处理。POST 不安全、不幂等、大多数情况不可缓存。

上面是从 RFC 规范定义的语义来分析的。

但是实际过程中,开发者不一定会按照 RFC 规范定义的语义来实现 GET 和 POST 方法。

HTTP缓存

强缓存

位于 disk cache

  • Cache-Control, 是一个相对时间;
  • Expires,是一个绝对时间;

Cache-Control的优先级高于 Expires

Cache-control 选项更多,设置更精细,所以建议使用 Cache-Control 来实现强缓存。具体的实现流程如下:

  • 当浏览器第一次请求访问服务器资源时,服务器会在返回这个资源的同时,在 Response 头部加上 Cache-Control,Cache-Control 中设置了过期时间大小;
  • 浏览器再次请求访问服务器中的该资源时,会先通过请求资源的时间与 Cache-Control 中设置的过期时间大小,来计算出该资源是否过期,如果没有,则使用该缓存,否则重新请求服务器;
  • 服务器再次收到请求后,会再次更新 Response 头部的 Cache-Control。

协商缓存

通过服务端告知客户端是否可以使用缓存的方式被称为协商缓存(即 304)

第一种:

请求头部中的 If-Modified-Since 字段与响应头部中的 Last-Modified 字段实现,这两个字段的意思是:

  • 响应头部中的 Last-Modified:标示这个响应资源的最后修改时间;
  • 请求头部中的 If-Modified-Since:当资源过期了,发现响应头中具有 Last-Modified 声明,则再次发起请求的时候带上 Last-Modified 的时间,服务器收到请求后发现有 If-Modified-Since 则与被请求资源的最后修改时间进行对比(Last-Modified),如果最后修改时间较新(大),说明资源又被改过,则返回最新资源,HTTP 200 OK;如果最后修改时间较旧(小),说明资源无新修改,响应 HTTP 304 走缓存。

第二种:

请求头部中的 If-None-Match 字段与响应头部中的 ETag 字段,这两个字段的意思是:

  • 响应头部中 Etag:唯一标识响应资源;
  • 请求头部中的 If-None-Match:当资源过期时,浏览器发现响应头里有 Etag,则再次向服务器发起请求时,会将请求头If-None-Match 值设置为 Etag 的值。服务器收到请求后进行比对,如果资源没有变化返回 304,如果资源变化了返回 200。

Etag 可以更加准确地判断文件内容是否被修改,避免由于时间篡改导致的不可靠问题,且优先级更高。

注意

协商缓存的两个字段都需要配合强缓存中 Cache-control 字段来使用,只有在未能命中强制缓存的时候,才能发起带有协商缓存字段的请求

缓存总结

img

HTTP 特性

优点

简单、灵活易扩展、跨平台

1. 简单

HTTP 基本的报文格式就是 header + body,头部信息也是 key-value 简单文本的形式。

2. 灵活易扩展

HTTP协议里的各类请求方法、URI/URL、状态码、头字段等每个组成要求都没有被固定死,都允许开发人员自定义和扩充

同时 HTTP 由于是工作在应用层( OSI 第七层),则它下层可以随意变化

HTTPS 也就是在 HTTP 与 TCP 层之间增加了 SSL/TLS 安全传输层,HTTP/3 甚至把 TCP 层换成了基于 UDP 的 QUIC。

双刃剑

无状态

好处:不需要额外的资源记录状态,减轻服务器负担

坏处:完成需要验证用户身份的操作时很麻烦(所以有了 cookie )

明文传输

好处: F12 或 Wireshark ,方便调试。

坏处:信息裸奔

不安全

无状态导致无法验证身份

明文传输导致被窃听

无法验证报文是否被篡改

HTTP 1.1 性能

1 基于 TCP/IP

2「请求 - 应答」的通信模式

所以性能的关键就在这两点里。

长连接

不需要进行无谓的连接与断开 TCP 连接

队头阻塞

「请求 - 应答」模式导致队头阻塞,好比塞车

相比 HTTP 1.0 优势

支持 长连接 + 管道传输

需优化的地方

  • 头部未经压缩就发送,首部信息越多延迟越大。只能压缩 Body 的部分;
  • 发送过长的首部。每次互相发送相同的首部造成的浪费较多;
  • 服务器是按请求的顺序响应的,如果服务器响应慢,会招致客户端一直请求不到数据,也就是队头阻塞;

HTTP 2 的优化

HTTP 2 基于 HTTPS ,所以 HTTP/2 是安全的。

HTT/1 ~ HTTP/2

头部压缩

HTTP/2 会压缩头部,通过「静态表、动态表、Huffman 编码」共同完成。

HPACK 算法:在客户端和服务器同时维护一张头部信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。

静态表编码

HTTP/2 为高频出现在头部的字符串和字段建立了一张静态表,它是写入到 HTTP/2 框架里的,不会变化。

Huffman 编码的原理是将高频出现的信息用「较短」的编码表示,从而缩减字符串长度。在统计大量的 HTTP 头部后,HTTP/2 根据出现频率将 ASCII 码编码为了 Huffman 编码表。

动态表编码

不在静态表范围内的头部字符串就要自行构建动态表,它的 Index 从 62 起步,会在编码解码的时候随时更新。

二进制帧

将 HTTP/1 的文本格式改成二进制格式传输数据,二进制数据使用位运算能高效解析。

HTTP/2 二进制帧的结构(帧头,帧数据)

img

帧的类型一般分为数据帧控制帧两类。标志位用于携带简单的控制信息,比如:空行,流的优先级。流标识符(Stream ID)的作用是用来标识该 Frame 属于哪个 Stream,接收方可以根据这个信息从乱序的帧里找到相同 Stream ID 的帧,从而有序组装信息。

帧数据存放的是通过 HPACK 算法压缩过的 HTTP 头部和包体。

并发传输

HTTP/1.1 的实现是基于请求-响应模型的。同一个连接中,HTTP 完成一个事务(请求与响应),才能处理下一个事务。如果响应迟迟不来,那么后续的请求是无法发送的,也造成了队头阻塞的问题。

HTTP/2 通过 Stream 这个设计,多个 Stream 复用一条 TCP 连接,达到并发的效果,解决了 HTTP/1.1 队头阻塞的问题,提高了 HTTP 传输的吞吐量。

img

  • 1 个 TCP 连接包含多个 Stream
  • Stream 里可以包含多个 Message,Message 对应 HTTP/1 中的请求或响应,由 HTTP 头部和包体构成;
  • Message 里包含多个 Frame,Frame 是 HTTP/2 最小单位,以二进制压缩格式存放 HTTP/1 中的内容(头部和包体);

HTTP 消息可以由多个 Frame 构成,以及 1 个 Frame 可以由多个 TCP 报文构成。

在 HTTP/2 连接上,不同 Stream 的帧是可以乱序发送的(因此可以并发不同的 Stream ) ,因为每个帧的头部会携带 Stream ID 信息,所以接收端可以通过 Stream ID 有序组装成 HTTP 消息,而同一 Stream 内部的帧必须是严格有序的

HTTP/2 还可以对每个 Stream 设置不同优先级,比如客户端访问 HTML/CSS 和图片资源时,希望服务器先传递 HTML/CSS,再传图片,那么就可以通过设置 Stream 的优先级来实现,以此提高用户体验。

服务器推送

一定程度上改善了传统的「请求 - 应答」工作模式,服务端不再是被动地响应,可以主动向客户端发送消息,这样就减少消息传递次数。

img

怎么实现的?

客户端发起的请求,必须使用的是奇数号 Stream,服务器主动的推送,使用的是偶数号 Stream。服务器在推送资源时,会通过 PUSH_PROMISE 帧传输 HTTP 头部,并通过帧中的 Promised Stream ID 字段告知客户端,接下来会在哪个偶数号 Stream 中发送包体。

img

如上图,在 Stream 1 中通知客户端 CSS 资源即将到来,然后在 Stream 2 中发送 CSS 资源,注意 Stream 1 和 2 是可以并发的。

HTTP 2 缺陷

HTTP/2 通过 Stream 的并发能力,解决了 HTTP/1 队头阻塞的问题,看似很完美了,但是 HTTP/2 还是存在“队头阻塞”的问题,只不过问题不是在 HTTP 这一层面,而是在 TCP 这一层。

HTTP/2 是基于 TCP 协议来传输数据的,TCP 是字节流协议,TCP 层必须保证收到的字节数据是完整且连续的,这样内核才会将缓冲区里的数据返回给 HTTP 应用,那么当「前 1 个字节数据」没有到达时,后收到的字节数据只能存放在内核缓冲区里,只有等到这 1 个字节数据到达时,HTTP/2 应用层才能从内核中拿到数据,这就是 HTTP/2 队头阻塞问题。

HTTP 3

HTTP/2 队头阻塞的问题是因为 TCP,所以 HTTP/3 把 HTTP 下层的 TCP 协议改成了 UDP!

HTTP/1 ~ HTTP/3

QUIC 特点

UDP 是不需要连接的,也就不需要握手和挥手的过程,所以天然的就比 TCP 快。QUIC 协议,具有类似 TCP 的连接管理、拥塞窗口、流量控制的网络特性,相当于将不可靠传输的 UDP 协议变成“可靠”的了,所以不用担心数据包丢失的问题。

无队头阻塞

当某个流发生丢包时,只会阻塞这个流,其他流不会受到影响,因此不存在队头阻塞问题。这与 HTTP/2 不同,HTTP/2 只要某个流中的数据包丢失了,其他流也会因此受影响。

img

更快的建立连接

对于 HTTP/1 和 HTTP/2 协议,TCP 和 TLS 是分层的,分别属于内核实现的传输层、openssl 库实现的表示层,因此它们难以合并在一起,需要分批次来握手,先 TCP 握手,再 TLS 握手

HTTP/3 只需要 1 RTT,握手的目的是为确认双方的「连接 ID」,连接迁移就是基于连接 ID 实现的。

HTTP/3 的 QUIC 协议并不是与 TLS 分层,而是QUIC 内部包含了 TLS,它在自己的帧会携带 TLS 里的“记录”,再加上 QUIC 使用的是 TLS/1.3,因此仅需 1 个 RTT 就可以「同时」完成建立连接与密钥协商。

TCP HTTPS(TLS/1.3) 和 QUIC HTTPS

连接迁移

基于 TCP 传输协议的 HTTP 协议,由于是通过双方 IP + 端口 确定一条 TCP 连接,那么当移动设备的网络从 4G 切换到 WIFI 时,意味着 IP 地址变化了,那么就必须要断开连接,然后重新建立连接。而建立连接的过程包含 TCP 三次握手和 TLS 四次握手的时延,以及 TCP 慢启动的减速过程,给用户的感觉就是网络突然卡顿了一下,因此连接的迁移成本是很高的。

QUIC 通过连接 ID来标记通信的两个端点。因此即使移动设备的网络变化后,导致 IP 地址变化了,只要仍保有上下文信息(比如连接 ID、TLS 密钥等),就可以“无缝”地复用原连接,消除重连的成本,没有丝毫卡顿感,达到了连接迁移的功能。

HTTP 层面优化

动态表是具有时序性的,如果首次出现的请求发生了丢包,后续的收到请求,对方就无法解码出 HPACK 头部,因为对方还没建立好动态表,因此后续的请求解码会阻塞到首次请求中丢失的数据包重传过来。

QUIC 会有两个特殊的单向流,一个用来发送字典,一个用来响应,以此同步双方的动态表,编码方收到解码方确认更新的通知后,才使用动态表编码 HTTP 头部。

HTTPS

HTTP 与 HTTPS 网络层

与 HTTP 区别

1 在 TCP 和 HTTP 之间加入了 SSL/TLS 安全协议

2 TCP 三次握手之后还需进行 SSL/TLS 握手

3 HTTP 的端口号是 80,HTTPS 的端口号是 443

4 HTTPS 需要向 CA 申请证书

如何解决安全问题

混合加密防止窃听

摘要+数字签名校验数据完整性

把服务器公钥放入证书来验证身份

数子证书工作流程

SSL/TLS 协议基本流程:

  • 客户端向服务器索要并验证服务器的公钥。
  • 双方协商生产「会话秘钥」。
  • 双方采用「会话秘钥」进行加密通信。

前两步也就是 SSL/TLS 的建立过程,也就是 TLS 握手阶段。

基于 RSA 的 TLS 握手过程

img

第一次握手

客户端打招呼,发送 TLS 版本号、支持的密码套件、随机数

第二次握手

服务端打招呼,发送确认支持的 TLS 版本号,选择密码套件,生成随机数、证书

第三次握手

验证证书:

  • 客户端会使用同样的 Hash 算法获取该证书的 Hash 值 H1;
  • 使用浏览器和操作系统中集成的 CA 的公钥解密证书签名内容,得到一个 Hash 值 H2 ;
  • 最后比较 H1 和 H2,如果值相同,则为可信赖的证书,否则则认为证书不可信。

生成随机数,并用公钥加密,并告知服务端开始使用会话密钥加密内容,然后把之前所有发送的数据做个摘要,用会话密钥加密,让服务器验证。

第四次握手

同样告诉客户端开始用会话密钥通信,并做摘要。

最后,双方都没问题,就用「会话密钥」加解密 HTTP 通信内容。

RSA 缺陷

不支持前向保密

因为客户端传递随机数给服务端时使用的是公钥加密的,所以一旦服务端的私钥泄漏了,过去被第三方截获的所有 TLS 通讯密文都会被破解。

ECDHE 握手过程

ECDHE 算法在每次握手时都会生成一对临时的公钥和私钥,也就是“一次一密”,即使黑客花大力气破解了这一次的会话密钥,也只是这次通信被攻击。

第一次握手

客户端打招呼,发送使用的 TLS 版本号、支持的密码套件列表,以及生成的随机数。

第二次握手

服务端打招呼,消息里面有服务器确认的 TLS 版本号、随机数、选择的密码套件、证书。

下面到了与 RSA 区分的地方:

  • 选择椭圆曲线(基点也就定好了)
  • 生成随机数作为服务端椭圆曲线的私钥,保留在本地;
  • 根据基点 G 和私钥计算出服务端的椭圆曲线公钥,这个会公开给客户端(并对公钥签名,防止被篡改)

第三次握手

客户端校验证书。生成随机数作为私钥,计算出公钥发送给服务端。

到这里,双方都可以用对方的公钥、自己的私钥和椭圆曲线计算出坐标(x,y),x 是一样的。

**用「客户端随机数 、服务端随机数 、 x 」**生成会话密钥(为了避免伪随机数)

告诉服务端改用对称加密通信,然后做摘要并用会话密钥签名让服务器验证。

第四次握手

告诉客户端改用对称加密,并摘要和签名。

与 RSA 区别

  • RSA 密钥协商算法「不支持」前向保密,ECDHE 密钥协商算法「支持」前向保密;
  • 使用了 RSA 密钥协商算法,TLS 完成四次握手后,才能进行应用数据传输,而对于 ECDHE 算法,客户端可以不用等服务端的最后一次 TLS 握手,就可以提前发出加密的 HTTP 数据,节省了一个消息的往返时间;

客户端验证证书流程

img

证书信任链问题

我们向 CA 申请的证书一般不是根证书签发的,而是由中间证书签发的。

img

TLS 1.3 优化

算法精简,保证安全

TLS1.2 在十来年的应用中陆续发现了很多的漏洞和加密算法的弱点,所以 TLS1.3 就在协议里修补了这些不安全因素。

TLS 1.2 密码套件非常复杂,难以选择,而现在的 TLS1.3 里只有 5 个套件,无论是客户端还是服务器都不会再犯“选择困难症”了。

TLS1.3 在协议里明确废除 RSA ,只使用 ECDHE,在标准层面保证了“前向安全”。

提升性能

简化了握手过程,完成握手只需要一个消息往返,提升了性能。

客户端在 Client Hello 消息里带上了支持的椭圆曲线,以及这些椭圆曲线对应的公钥。服务端收到后,选定一个椭圆曲线等参数,然后返回消息时,带上服务端这边的公钥。经过这 1 个 RTT,双方手上已经有生成会话密钥的材料了,于是客户端计算出会话密钥,就可以进行应用数据的加密传输了。

分类:
前端
收藏成功!
已添加到「」, 点击更改