TCP、HTTP和 HTTPS通信协议

215 阅读16分钟

TCP

作用:建立主机与主机之间端口与端口的连接

不同的服务运行在主机的不同端口上,其实就是服务与服务之间的通信

TCP协议的特点:

  1. 可靠传输:TCP 协议采用基于确认和重传的方式,保证数据的可靠传输。发送方在发送数据时,会等待接收方发送的确认信息,如果接收方在一定时间内没有回复确认信息,发送方会将数据重传,直到接收方收到正确的数据并发送确认信息为止。
  2. 有序交付:TCP 协议会保证数据的有序交付,即接收方会将接收到的数据按照正确的顺序组装起来,以保证数据的正确性和完整性。
  3. 流量控制:TCP 协议会根据网络状况和接收方的处理能力,调整发送方的发送速率,以避免网络拥塞和数据丢失。接收方通过维护一个滑动窗口来控制发送方的数据流量,根据自己的接收能力发送确认信息,从而实现流量控制。
  4. 拥塞控制:TCP 协议会根据网络拥塞的程度自适应地调整自己的发送速率,防止网络拥塞和数据丢失。TCP 协议会通过检测网络上的丢包情况和延迟情况,自动减小发送方的数据流量,从而避免网络拥塞和数据丢失。
  5. 全双工通信:TCP 协议是一种全双工通信协议,即发送方和接收方可以同时进行数据传输和接收,从而实现双向的通信和数据交换。

1和2通过序列号和接收号实现

3通过滑动窗口实现

三次握手的作用和四次挥手

三次握手

第一次握手: 向服务端请求建立连接

第二次握手:服务端允许建立连接

第三次握手:确定建立连接

TCP_3_HANDSHAKE

SYN和ACK都是TCP的标志位,用以控制连接的状态的,常见的有三:

  • SYN - 创建一个连接
  • FIN - 终结一个连接
  • ACK - 确认接收到的数据

为什么要三次握手而不是两次握手

这就跟Seq和ACK有关了请求建立连接的时候,发送方会生成一个随机的seq序列值,随机数的范围很大,以确保每一次连接的序列号是唯一的。

为什么要使初始序列唯一?

假设初始序列都为0,那么历史报文(此时上一次连接已断开),就有可能重新被接收方接收,造成数据混乱。

序列号标明了数据发送方第一个字节的起始位置,当然,这是根据初始序列的一个相对值。而接收端的确认号,则代表之前的数据已经正确接收,希望接收下一段的数据(X+1)。这样看,如果发送方迟迟接收不到确认信号,就会发起重传。那么如果只有两次握手,就只是发送方确认了接收方可以正确接收它的数据,接收方还没有确认发送方是否可以正确接收我的数据,是不合适的。

四次挥手

TCP四次挥手详解_第四次挥手fin等于几_Shirsen的博客-CSDN博客

第一次挥手: 发送方向接收方发起请求连接关闭(Fin=1)

第二次挥手: 接收方收到后,将剩余数据发送

第三次挥手:接收方发送完数据后,同意关闭(Fin=1) (此时,seq跟ack是不变的,因为发送方一直没有数据发送)

第四次挥手: 发送方确认连接关闭,接收方接收到后,关闭连接,发送方等待2MSL(最长报文段寿命的两倍),这个时间可以确保如果接收方接收不到确认,会重发同意关闭,以确保连接正常关闭。

滑动窗口机制

为什么要引入滑动窗口机制

通过上面我们知道,TCP的可靠连接是基于接收方的确认信号的,一个分包的传输应当以接收到接收方的确认信号为结束。但如果是接收到了确认信号才发送下一分包,就造成了效率的低下,因此,我们会希望即使没有接收到接收方的确认,也可以一次发送多个分包。

image-20230422034425572

拥塞窗口,拥塞窗口是发送方维护的一个窗口,是基于网络拥塞情况使用拥塞控制算法来实现的,如果网络一直不丢包,那么这个窗口就会越来越大,如果出现丢包,就会响应地减小。

在一次交互中,接收方根据自己的能力和网络拥塞情况,确定它的接收窗口大小,并在tcp头部字段中传递给发送方。发送根据接收方的接收方的接收窗口和拥塞窗口,选择较小的一个,确定自己的发送窗口,发送分包。如果发送过程中接收到接收方的确认分包,发送窗口也会滑动。

此时,发送方不会为每一个分包都发送确认信息,而是累计发送,例如接收了50个,就会发送51确认信息,发送方知道后,也会清除掉50个分包的计时器,明白50个分包其实都已经发送完成。如果中间出现了丢包,接收方的确认信号会到这个包为止,发送方接收到这个确认信号后,会往回滑动滑动窗口,重传数据包,这时会造成数据包重复。

重传算法,拥塞算法,往往需要通信双方做判断,而不是固定的情况。

UDP与TCP的比较

TCP是面向连接的,提供稳定传输和重传机制的传输层协议,而UDP是无连接的,其传输的特点是尽可能地将包发出去,而不去考虑其他的问题。

HTTP

特点

全称为超文本传输协议,默认端口是80。特点为:

  1. 以请求、应答的方式通信

  2. 无状态,不会记录之前的通信信息

  3. 可扩展语义: 通过添加或自定义http报文的头部字段,自定义状态码来实现特定需求

  4. 自描述信息:

    • Content-Type字段描述了消息体的媒体类型(MIME类型);
    • Content-Length字段描述了消息体的长度;
    • User-Agent字段描述了发送HTTP请求的客户端的信息;
    • Accept字段描述了客户端能够接受的媒体类型;
    • Cache-Control字段描述了缓存策略;
    • Connection字段描述了连接的属性,例如keep-alive或close等。

    利用头部字段的元数据,来表明报文的信息与属性

HTTP报文格式:

image-20230422163505070.png

起始行:

image-20230422163738317.png

image-20230422164911106.png

常见响应状态码:

200系列,服务器有响应需要的数据

200: 请求成功,返回响应

300系列,资源存在,告知用户需要到新地址拿取数据(location字段)

300: 请求一种资源,该资源有多种表现形式,请用于选择

301: 请求的资源已永久地移动到新的位置

302: 请求的资源已临时移动到新的位置

400系列,不知道资源存不存在,因客户端原因请求失败

400: 请求语法错误,服务器不理解

401: 请求需要用户验证

403: 服务器拒绝请求

404: 请求的资源不存在

500系列,不知道资源存不存在,因服务端原因请求失败

500: 服务器内部错误

502: 服务器作为网关或代理,从上游服务器收到无效响应;

503: 服务器暂时无法响应请求

头部字段

  1. 格式

    头部字段原则上一般不允许重复,除非语义允许,如set-Cookie

  2. 请求头常见头部字段

    1. Host:请求的主机名和端口号,用于告诉服务器请求的目标

    2. Accept:客户端期望接收的响应的MIME类型列表,用于告诉服务器客户端能够处理哪些数据类型。

      常见的MIME类型

      由类型/子类型构成

      1. text/plain:纯文本文件,例如TXT文件。
      2. text/html:HTML文档,例如网页。
      3. application/json:JSON数据。
      4. application/xml:XML数据。
      5. image/jpeg:JPEG图片。
      6. image/png:PNG图片。
      7. audio/mpeg:MP3音频文件。
      8. video/mp4:MP4视频文件。
    3. UserAgent:客户端的浏览器或其他应用程序的标识字符串,用于向服务器提供有关客户端的信息,例如浏览器类型、操作系统和版本号等。

    4. Content-Type:请求正文的MIME类型与编码格式(分号分割)

    5. Content-Length: 表示请求数据的长度(字节为单位,与编码有关)

    6. Authorization:包含用于验证客户端的凭据,例如用户名和密码等。

    7. Cookie:包含客户端的会话标识符,用于在多个请求之间维持会话状态。

      多个Cookie之间用分号隔开

    8. Referrer:包含发送请求的页面的URL,用于告诉服务器请求的来源。

      如果网站设置了防盗链,限制请求的来源,可以选择不设置这个字段

      Referrer字段是可以修改的,那么如果知道了正确的Referrer字段,就可以直接获取资源,所以它本身就不够安全,只是做一个简单的限制。

      <meta name="referrer" content="no-referrer" />

    9. Connecton: keep-alive/close

      控制TCP连接的,如果是keep-alive,那么请求响应完毕后,也不会关闭TCP连接,这样就提高了效率,不需要每次请求都重新建立连接。

  1. 响应头常见头部字段

    1. Content-Type: 指定响应内容的MIME类型,例如"text/html"、"application/json"等。

    2. Content-Length: 指定响应内容的长度,以字节为单位。

    3. Cache-Control: 控制响应的缓存行为,例如"max-age"、"no-cache"、"private"等。

      Cache-Control:控制缓存的行为,例如强制缓存或条件缓存等。

      • no-cache:指示浏览器不可以直接从缓存中读取资源,必须从服务器重新获取资源并在使用前验证其是否过期。
      • no-store:指示浏览器不可以将响应缓存,包括所有内容,包括明文和加密的内容。
      • max-age=<seconds>:指示响应可以被缓存的最大时间(以秒为单位),超过这个时间,浏览器必须重新获取资源。

      如果不显式的指定这一字段,那么客户端会格局ContenType选择缓不缓存,像一些图片、样式表和js链接,就可以缓存(但也应该设置过期),像json数据,就不会缓存,因为它修改地很频繁。

    4. Expires: 指定响应内容的过期时间,以GMT格式的日期字符串表示。

    5. Last-Modified: 指定响应内容的最后修改时间,以GMT格式的日期字符串表示。

    6. ETag: 指定响应内容的实体标签,用于缓存验证。

    7. Location: 指定重定向的目标URL。

    8. Set-Cookie: 指定在客户端保存的cookie信息。

    9. Access-Control-Allow-Origin: 指定允许跨域请求的源。

    10. Date: 日期字段

空行

空行用于分隔头部字段与数据部分。

其本质就是两个CRLF换行符,因为每个头部字段的结尾都是一个CRLF,那么要进行区分,表明下一部分是数据部分,所以用两个换行符做区分。

\r\n\r\n

HTTPS协议

为什么要有HTTPS协议

由于HTTP协议天生“明文”的特点,整个数据传输过程中数据是完全透明的,任何人都截获之后都可以伪造请求/响应报文,数据不具有可信性。因此就诞生了为安全而生的HTTPS协议。

如何实现

在HTTP层与TCP层之间,加入一层安全套接层 SSL/TLS

SSL和TLS都是安全层协议,网景公司发明的时候叫SSL,后来IETF将它改进更名为TLS(传输层安全),TLS 1.0是基于SSL 3.0开发的。目前基本上都是用的TLS,SSL/TLS不过是习惯性的叫法。至今已有三个版本(2018年发布1.8版本)

TCP协议为通信双方提供了可靠的信息传输服务,

对称加密

通信双方共享密钥,发送方的数据经过密钥加密后送到接收方,接收方再用密钥解密。

常见的对称加密算法包括DES、AES、RC4等,其中DES算法已经被认为是不安全的,而AES算法则是目前广泛应用的对称加密算法之一,其安全性得到了广泛认可。(DES是密钥长度为56位,如果计算能力足够强,可以被暴力破解,当然,破解密钥的方式还有很多)

注:对称加密的加密过程简单,但是其实并不够安全。因为对称加密是共享密钥,不管是客户端发密钥还是服务端发密钥,至少发密钥的时候信息是没有加密的,此时如果进行抓包,可以抓取到密钥信息。从而破解双方的通信信息

非对称加密

通信双方各维护一个公钥和一个私钥,其中公钥可以随意发送。发送方采用公钥加密的数据,接收方必须采用私钥才能解密。这就是对称加密算法,常见的非对称加密算法包括 RSA、Diffie-Hellman、ECC 等。其中,RSA 是最常用的非对称加密算法之一,可以用于数字签名、密钥交换等安全应用场景。

非对称加密算法的加密和解密过程使用不同的密钥进行,因此加密和解密的速度较慢。

HTTPS的加密过程

一般的服务器,像Nginx,是内置了TLS版本支持和加密算法的。在配置文件里选择就好了。

image-20230423155606363.png

客户端没有公钥和私钥

  1. 客户端发送Client Hello消息:客户端向服务器发送一个Client Hello消息,该消息包含支持的TLS版本、加密套件列表、随机数等信息。
  2. 服务器发送Server Hello消息:服务器从客户端的支持列表中选择一个加密套件,并向客户端发送一个Server Hello消息,该消息包含服务器选择的TLS版本、加密套件、随机数等信息。
  3. 服务器发送证书消息:如果服务器要求客户端进行身份验证,服务器将向客户端发送一个包含其数字证书的证书消息。
  4. 服务器发送Server Hello Done消息:服务器向客户端发送一个Server Hello Done消息,表示服务器已经完成了握手协议的第一阶段,并等待客户端的响应。
  5. 客户端发送客户端密钥交换消息:客户端生成自己的随机数,并使用服务器发送的公钥进行加密,生成一个Pre-master Secret,并将其发送给服务器。
  6. 客户端发送Change Cipher Spec消息:客户端向服务器发送一个Change Cipher Spec消息,表示客户端已准备好使用新的加密套件和密钥来保护通信数据。
  7. 客户端发送Finished消息:客户端使用Pre-master Secret和握手阶段中的所有随机数计算出一个Finished消息的摘要,并将其发送给服务器。
  8. 服务器发送Change Cipher Spec消息:服务器向客户端发送一个Change Cipher Spec消息,表示服务器已准备好使用新的加密套件和密钥来保护通信数据。
  9. 服务器发送Finished消息:服务器使用Pre-master Secret和握手阶段中的所有随机数计算出一个Finished消息的摘要,并将其发送给客户端。
  10. 握手完成:当客户端和服务器都收到了对方的Finished消息并验证通过后,握手协议完成,通信双方可以开始进行加密通信。

这个过程中其实涉及了三种加密算法

举例一个TLS1.2最常用的加密套件(加密套件就是加密算法的集合)

  1. RSA密钥交换算法: 服务器根据客户端发送过来的利用公钥加密的数据利用私钥进行解密的加密算法
  2. AES对称加密算法 : 服务端和客户端协商的利用两个随机数+预主密钥生成会话密钥的加密算法
  3. HMAC-SHA256消息认证算法: 在TLS握手过程中,当客户端和服务器协商出最终的会话密钥后,服务器会使用Pre-master Secret和握手阶段中的所有随机数计算出一个Finished消息的摘要,并将其发送给客户端。这个Finished消息用于验证在握手过程中交换的所有消息是否正确地传输,以及会话密钥是否正确地计算。客户端收到这个Finished消息后,也会使用同样的方式计算出一个Finished消息的摘要,然后将其与服务器发送的Finished消息进行比较,以验证握手过程的正确性。

SSL证书与CA机构

上方的似乎已经将HTTPS解释地不错了,但还有一个问题。即上面保护了通信过程中数据是保密的,但如果通信的对象本身就是不安全的呢?这时候,为了确保通信对象(服务器)是真实的,就出现了CA机构,CA机构为域名颁布SSL证书,证明它是真实的,而不是伪造的。

CA机构负责认证网站是真实的,一般不会确认网站是不是安全的

在申请SSL证书时,CA机构会对网站的身份进行严格的验证。这些验证包括域名验证、组织验证、个人验证等。只有在通过验证后,CA机构才会签发SSL证书。因此,SSL证书可以被视为网站的身份证明,它可以证明网站的身份是真实的,而不是伪造的。

如何确保证书不被伪造

要证明证书不是伪造的,所以要签名,客户端收到证书后,可以识别到证书的颁发机构,利用颁发机构的公钥进行计算得到哈希值,比较证书携带的SHA哈希值。

image-20230423171249320.png