应用层http/https笔记

本文最后更新于:16 天前

1. HTTP 前沿

上一个文章我们讲了传输层,接下来开始说说应用层协议,那么最常见的协议就是HTTP协议,我们就从HTTP开始。

首先 http://www.budongshu.cn 是一个URL,叫做统一资源定位符 ,之所以叫做统一,是因为它是有格式的

  • HTTP :这个叫做协议

  • www.budongshu.cn: 表示一个域名,在互联网上一个位置

还有更详细的URLhttp://budongshu.cn/archives/ 正因为它是统一的,所以浏览器知道如何进行统一的处理

2. HTTP 请求准备

浏览器会将www.budongshu.cn 这个域名发送给DNS服务器,让它解析为IP地址。有关DNS解析过程后面会说,最后会解析成IP地址,然后建立TCP连接

因为我们知道HTTP是基于TCP协议的,TCP建立连接,经过三次握手,这个前面我们说过,还有目前http协议大部分都是1.1,默认是开启Keep-Alive的,这样建立连接,就可以多次请求中复用,毕竟TCP建立连接还是挺费劲的。

3. HTTP 请求的构建

建立了连接以后,浏览器就要发送 HTTP 的请求。

3.1 第一部分 请求行

在请求行中,URL 就是 http://www.163.com ,版本为 HTTP 1.1。这里要说一下的,就是方法。方法有几种类型。

请求方法:

GET: 获取数据

POST: 新建数据

PUT: 更新数据

PATCH: 局部更新( 比如只更改数据库里表的一个字段,只更新这字段。但PUT会更新整个库)

DELETE: 删除数据

3.2 首部字段

  • Accept-Charset: 表示客户端可以接受的字符集。防止传过来的是另外的字符集,从而导致出现乱码。

  • Content-Type:是指正文的格式。例如,我们进行 POST 的请求,如果正文是 JSON,那么我们就应该将这个值设置为 JSON。

  • Cache-control:是用来控制缓存的。当客户端发送的请求中包含 max-age 指令时,如果判定缓存层中,资源的缓存时间数值比指定时间的数值小,那么客户端可以接受缓存的资源;当指定 max-age 值为 0,那么缓存层通常需要将请求转发给应用集群。

  • If-Modified-Since:也就是说,如果服务器的资源在某个时间之后更新了,那么客户端就应该下载最新的资源;如果没有更新,服务端会返回“304 Not Modified”的响应,那客户端就不用下载了,也会节省带宽。

4. HTTP请求的发送

HTTP 协议是基于 TCP 协议的,所以它使用面向连接的方式发送请求,通过 stream 二进制流的方式传给对方。当然,到了 TCP 层,它会把二进制流变成一个个报文段发送给服务器。

[源地址] [目标地址] [IP头] 通过ARP协议请求目标mac地址,然后不算通过ARP请求MAC地址,替换头部MAC地址找到目标机器

解析IP地址符合,根据IP头中协议项, 解析TCP的头,里面序列号,看一下是不是我想要的,如果是放去缓存中返回ACK,如果不是丢弃

TCP头里面还有端口好,发现是HTTP的服务器监听的端口,于是将包发给HTTP服务器,HTTP进程看到,把请求结果返回给客户端

5. HTTP 返回的构建

HTTP 的返回报文也是有一定格式的。这也是基于 HTTP 1.1 的。

  • 状态码:
    • 200: 请求正常
    • 301: 跳转URL改变
    • 304: 跳转URL不改变
    • 404: 找不到页面
    • 5xx: 服务器端错误
    • 499: 客户端主动断开
  • 返回首部的key-value (跟上面请求构建差不多)

6. HTTP 2.0

HTTP 协议也在不断的进化过程中,在 HTTP1.1 基础上便有了 HTTP 2.0

HTTP1.1 通信问题

HTTP 1.1 在应用层以纯文本的形式进行通信。每次通信都要带完整的 HTTP 的头,而且不考虑 pipeline 模式的话,每次的过程总是像上面描述的那样一去一回。这样在实时性、并发性上都存在问题。

为了解决这些问题,HTTP 2.0 会对 HTTP 的头进行一定的压缩,将原来每次都要携带的大量 key value 在两端建立一个索引表,对相同的头只发送索引表中的索引。

另外,HTTP 2.0 协议将一个 TCP 的连接中,切分成多个流,每个流都有自己的 ID,而且流可以是客户端发往服务端,也可以是服务端发往客户端。它其实只是一个虚拟的通道。流是有优先级的。

HTTP 2.0 还将所有的传输信息分割为更小的消息和帧,并对它们采用二进制格式编码。常见的帧有 Header 帧,用于传输 Header 内容,并且会开启一个新的流。再就是 Data 帧,用来传输正文实体。多个 Data 帧属于同一个流。

通过这两种机制,HTTP 2.0 的客户端可以将多个请求分到不同的流中,然后将请求内容拆成帧,进行二进制传输。这些帧可以打散乱序发送, 然后根据每个帧首部的流标识符重新组装,并且可以根据优先级,决定优先处理哪个流的数据。

假设我们的一个页面要发送三个独立的请求,一个获取 css,一个获取 js,一个获取图片 jpg。如果使用 HTTP 1.1 就是串行的,但是如果使用 HTTP 2.0,就可以在一个连接里,客户端和服务端都可以同时发送多个请求或回应,而且不用按照顺序一对一对应。

HTTP 2.0 成功解决了 HTTP 1.1 的队首阻塞问题,同时,也不需要通过 HTTP 1.x 的 pipeline 机制用多条 TCP 连接来实现并行请求与响应;减少了 TCP 连接数对服务器性能的影响,同时将页面的多个数据 css、js、 jpg 等通过一个数据链接进行传输,能够加快页面组件的传输速度。

7. QUIC 协议的“城会玩”

HTTP 2.0 虽然大大增加了并发性,但还是有问题的。因为 HTTP 2.0 也是基于 TCP 协议的,TCP 协议在处理包时是有严格顺序的。

当其中一个数据包遇到问题,TCP 连接需要等待这个包完成重传之后才能继续进行。虽然 HTTP 2.0 通过多个 stream,使得逻辑上一个 TCP 连接上的并行内容,进行多路数据的传输,然而这中间并没有关联的数据。一前一后,前面 stream 2 的帧没有收到,后面 stream 1 的帧也会因此阻塞。

诞生Google 的 QUIC 协议 基于UDP

7.1 机制一:自定义连接机制

以一个 64 位的随机数作为 ID 来标识,而且 UDP 是无连接的,所以当 IP 或者端口变化的时候,只要 ID 不变,就不需要重新建立连接。

7.2 机制二:自定义重传机制

QUIC 也有个序列号,是递增的。任何一个序列号的包只发送一次,下次就要加一了。例如,发送一个包,序号是 100,发现没有返回;再次发送的时候,序号就是 101 了;如果返回的 ACK 100,就是对第一个包的响应。如果返回 ACK 101 就是对第二个包的响应,RTT 计算相对准确。

但是这里有一个问题,就是怎么知道包 100 和包 101 发送的是同样的内容呢?QUIC 定义了一个 offset 概念。QUIC 既然是面向连接的,也就像 TCP 一样,是一个数据流,发送的数据在这个数据流里面有个偏移量 offset,可以通过 offset 查看数据发送到了哪里,这样只要这个 offset 的包没有来,就要重发;如果来了,按照 offset 拼接,还是能够拼成一个流

7.3 机制三:无阻塞的多路复用

image-20201206202048376

同 HTTP 2.0 一样,同一条 QUIC 连接上可以创建多个 stream,来发送多个 HTTP 请求。但是,QUIC 是基于 UDP 的,一个连接上的多个 stream 之间没有依赖。这样,假如 stream2 丢了一个 UDP 包,后面跟着 stream3 的一个 UDP 包,虽然 stream2 的那个包需要重传,但是 stream3 的包无需等待,就可以发给用户。

7.4 机制四:自定义流量控制

但是 QUIC 的窗口是适应自己的多路复用机制的,不但在一个连接上控制窗口,还在一个连接中的每个 stream 控制窗口。

QUIC 的 ACK 是基于 offset 的,每个 offset 的包来了,进了缓存,就可以应答,应答后就不会重发,中间的空档会等待到来或者重发即可,而窗口的起始位置为当前收到的最大 offset,从这个 offset 到当前的 stream 所能容纳的最大缓存,是真正的窗口大小。

image-20201206213410386

8 HTTPS 协议

8.1 对称加密

在对称加密算法中,加密和解密使用的密钥是相同的,也就是说,加密和解密使用的是同一个密钥。因此,对称加密算法要保证安全性的话,密钥要做好保密。只能让使用的人知道,不能对外公开

但是对称加密第一次再互联网传输密钥的时候,可能会有被窃取的风险,所以不太安全

对称加密效率高,但是解决不了密钥传输问题

8.2 非对称加密

在非对称加密算法中,加密使用的密钥和解密使用的密钥是不相同的。一把是作为公开的公钥,另一把是作为谁都不能给的私钥。公钥加密的信息,只有私钥才能解密。私钥加密的信息,只有公钥才能解密。

非对称加密可以解决这个密钥传输问题但是效率不高

8.3 数字证书

非对称加密需要通过证书和权威机构来验证公钥的合法性,由权威部门颁发的称为证书,这个权威机构我们称为 CA( Certificate Authority)

8.3.1 证书内容

  • Public-key 是公钥内容
  • Subject 就是证书颁发给谁
  • Issuer 也即证书是谁颁发
  • Signature Algorithm 是签名算法
  • Validity 是证书期限

证书安全性

权威机构会给证书 卡一个章 称为签名算法

8.3.2 签名算法:

签名算法大概是这样工作的:一般是对信息做一个 Hash 计算,得到一个 Hash 值,这个过程是不可逆的,也就是说无法通过 Hash 值得出原来的信息内容。在把信息发送出去时,把这个 Hash 值加密后,作为一个签名和信息一起发出去。

除此之外,还有一种证书,称为 Self-Signed Certificate,就是自己给自己签名。这个给人一种“我就是我,你爱信不信”的感觉。这里我就不多说了。

8.4 https 流程

image-20201206204530173

如果客户端不相信这个证书,内部会有这样的验证流程

当然你不相信这个证书,于是你从自己信任的 CA 仓库中,拿 CA 的证书里面的公钥去解密外卖网站的证书。如果能够成功,则说明外卖网站是可信的。这个过程中,你可能会不断往上追溯 CA、CA 的 CA、CA 的 CA 的 CA,反正直到一个授信的 CA,就可以了。

8.5 重放与篡改

其实,这里还有一些没有解决的问题,例如重放和篡改的问题。

没错,有了加密和解密,黑客截获了包也打不开了,但是它可以发送 N 次。这个往往通过 Timestamp 和 Nonce 随机数联合起来,然后做一个不可逆的签名来保证。

Nonce 随机数保证唯一,或者 Timestamp 和 Nonce 合起来保证唯一,同样的,请求只接受一次,于是服务器多次收到相同的 Timestamp 和 Nonce,则视为无效即可。

如果有人想篡改 Timestamp 和 Nonce,还有签名保证不可篡改性,如果改了用签名算法解出来,就对不上了,可以丢弃了。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!