HTTP概览
HTTP(Hypertext Transfer Protocol)是互联网上应用最为广泛的网络传输协议之一,主要用于在Web服务器和客户端浏览器之间传递数据。
HTTP协议基于请求与响应模式,一个HTTP事务由一个请求和一个响应组成。客户端(通常是浏览器)发出请求,服务器回送响应。
HTTP协议的主要内容包括超文本、传输和协议三部分。
- 超文本:指的是不仅可以传输文本数据,还可以传输图片、音频、视频等多媒体内容。超文本的特点在于可以通过超链接进行跳转,实现页面之间的互相关联。
- 传输:传输是指数据在网络中经过一系列物理介质从一个端系统传送到另一个端系统的过程。通常将传输数据包的一方称为请求方,将接收数据包的一方称为应答方。
- 协议:协议是指网络中传递和管理信息的规范。类似于人与人之间相互交流需要遵循一定的规矩,计算机之间的通信也需要共同遵守一定的规则,这些规则就称为协议。HTTP就是一种网络协议,它定义了客户端和服务器之间的通信格式和规则。
HTTP是一种无状态协议,这意味着协议本身不保存之前的请求或状态信息。每个请求都是独立的,服务器不会记忆之前的请求。
HTTP请求报文
HTTP请求报文是客户端发送给服务器的数据格式,用于请求特定资源或执行特定操作。
一个完整的HTTP请求报文由请求行(Request Line)、请求头部(Headers)、空行(空格符号),以及请求体(Body)组成。
下面是一个简单的HTTP请求报文的结构:
GET /index.html HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
[请求体,对于GET请求通常为空]
- 请求行包括请求方法(GET、POST等)、请求的资源路径(URI)、HTTP协议版本。
- 请求头部包括了一系列键值对,每个键值对对应一个请求头,包含了客户端的信息和请求的参数。
- 空行表示请求头结束,接下来是请求体,对于GET请求通常为空,而对于POST请求则包含要发送给服务器的数据。
HTTP请求方法
HTTP请求方法是客户端与服务器进行通信时,定义要对目标资源执行的操作类型的标准化方式。常见的HTTP请求方法包括以下几种:
方法 | 描述 | 用途 |
---|---|---|
GET | 从服务器获取资源 | 请求应该只用于获取数据,并且不应该有副作用,即不改变服务器状态 |
POST | 向服务器提交数据 | 用于发送数据,如表单数据,上传文件,可能会改变服务器状态 |
PUT | 将资源存储到服务器上 | 用于上传资源,存在则覆盖,不存在则创建新资源 |
DELETE | 从服务器删除资源 | 用于删除指定的资源 |
PATCH | 对资源进行部分修改 | 用于局部更新资源,只更新部分数据 |
HEAD | 仅请求获取响应头信息 | 类似于GET,但只返回响应头,不返回实际内容,用于获取资源元数据 |
OPTIONS | 获取目标资源支持的通信选项 | 用于获取支持的HTTP方法,服务器会在响应中返回所支持的方法 |
TRACE | 回显服务器收到的请求,用于测试或诊断 | 用于测试或诊断 |
CONNECT | 用于代理服务器,将连接转换为隧道 | 用于代理服务器,建立HTTP隧道连接 |
GET和POST的区别
GET和POST请求的主要区别:
用途上的区别:
GET通常用于请求服务器发送资源。用于查询操作,不应产生副作用,即不会改变资源的状态。
POST通常用于向服务器提交数据,例如提交表单或者上传文件。用于创建或更新资源,可能会引起资源状态的改变。
数据传输上的区别:
GET数据被附加在URL之后,以查询字符串的形式出现。数据大小有限制,因为URL的长度是有限制的(通常为2048个字符)。数据暴露在URL中,安全性较低。
POST数据被放置在HTTP请求的消息体(body)中。数据大小理论上不受限制,适用于传输大量数据。数据不会暴露在URL中,相对更安全。
缓存和历史记录上的区别:
GET请求可以被缓存。GET请求的URL会被保存在浏览器的历史记录中。
POST请求不会被缓存。POST请求不会保存在浏览器的历史记录中。
安全性和幂等性上的区别:
GET请求应该是幂等的,即多次执行同一个GET请求,资源的状态不会改变。由于数据在URL中暴露,所以安全性较低。
POST请求不是幂等的,多次执行可能会产生不同的结果。数据不在URL中,安全性相对较高。
HTTP请求头
HTTP请求头是在客户端向服务器发送请求时包含的一组键值对,用于传递额外的信息给服务器。这些信息通常包括客户端的一些环境参数、用户信息、请求的数据格式等。
HTTP请求头通常由键值对组成,每行一个键值对,键值对之间使用冒号分隔,如"Key: Value"。
常见的HTTP请求头包括:
- User-Agent:用于标识客户端的类型,操作系统,版本号等信息。
- Accept:指定客户端能够接收的内容类型。
- Content-Type:指定请求体的类型,常用于POST请求。
- Authorization:包含授权信息,用于验证客户端对资源的访问权限。
- Cookie:包含客户端的Cookie信息,用于跟踪会话状态。
- Referer:指明请求来源页面的URL。
- Host:指定请求的服务器的域名和端口号。
- Connection:指定连接类型,如保持长连接或立即关闭连接。
HTTP请求头可以帮助服务器更好地理解客户端的请求,并做出相应的处理。
同时,客户端也可以通过设置请求头来定制自己的请求行为,以满足特定的需求。
HTTP响应
HTTP响应是服务器向客户端返回的数据,用于响应客户端的请求。
一个完整的HTTP响应由状态行(Status Line)、响应头部(Headers)、空行和响应体(Body)组成。
下面是一个简单的HTTP响应的结构:
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1234
Connection: keep-alive
[响应体,包含了服务器返回的数据]
状态行包含了HTTP协议版本、状态码以及相应的状态消息。状态码指示了请求的处理结果,常见的状态码包括200(成功)、404(未找到资源)、500(服务器内部错误)等。
响应头部包含了一系列键值对,每个键值对对应一个响应头,包含了服务器返回的信息和响应的参数。
空行表示响应头结束,接下来是响应体,包含了服务器返回给客户端的实际数据。
HTTP响应体的内容可以是任意类型的数据,如HTML文档、JSON数据、图片等,具体内容取决于客户端的请求以及服务器的处理结果。
通过解析HTTP响应,客户端可以获取服务器返回的数据,并根据需要进行处理和展示。
HTTP响应状态码
HTTP响应状态码是服务器对客户端发起的请求所做出的响应的一部分,它指示了请求处理的结果。每个状态码都有特定的含义,用于告知客户端请求的执行情况。
以下是一些常见的HTTP响应状态码及其含义:
状态码类别 | 状态码 | 含义 |
---|---|---|
信息性状态码 | 100 | Continue:服务器已接收到请求的初始部分,客户端应继续请求。 |
成功状态码 | 200 | OK:请求成功。 |
201 | Created:请求已经被实现,且一个新资源已经依据请求而建立。 | |
204 | No Content:服务器成功处理了请求,但不需要返回任何实体内容。 | |
重定向状态码 | 301 | Moved Permanently:请求的资源已被永久移动到新位置。 |
302 | Found:请求的资源临时从不同的URI响应请求。 | |
客户端错误状态码 | 400 | Bad Request:服务器无法理解请求。 |
403 | Forbidden:服务器拒绝请求。 | |
404 | Not Found:请求的资源未找到。 | |
服务器错误状态码 | 500 | Internal Server Error:服务器遇到不可预知的错误。 |
503 | Service Unavailable:服务器当前无法处理请求,通常由于过载或维护。 |
重定向和转发的区别:
当服务器返回一个重定向响应(如HTTP状态码301、302)时,浏览器会接收到这个响应,并根据响应中的Location头字段的值自动进行新一轮的请求。这个过程对用户是可见的,我们会在浏览器的地址栏看到URL的变化。重定向总是由服务器端触发,然后由客户端(通常是浏览器)来执行新的请求。
转发通常是指服务器内部的请求转发,这个过程对用户是完全透明的。转发意味着请求的处理从一个组件转移到另一个服务器内部的组件,而用户的请求地址不会改变,用户对此过程无感知。转发只涉及服务器内部的处理,浏览器并不知道内部发生了转发。
HTTP响应头部
HTTP响应头部包含了服务器对客户端请求的响应信息,它提供了关于响应的元数据和参数。以下是一些常见的HTTP响应头部及其作用:
Date:指示响应的日期和时间,有助于客户端确定响应的时效性。
Server:包含了服务器使用的软件信息,如名称和版本号。
Content-Type:指示了响应体的MIME类型,告诉客户端如何解析响应体的内容。
Content-Length:指示了响应体的长度,以字节为单位。
Cache-Control:控制缓存的行为,包括缓存有效时间、是否允许缓存等。
Set-Cookie:在响应中设置cookie,用于在客户端存储会话信息等数据。
Location:在重定向响应中指示新的资源位置。
ETag:用于标识资源的实体标签,可用于缓存验证。
Content-Encoding:指示了响应体的编码方式,如gzip、deflate等,用于压缩传输内容。
Expires:指示了响应的过期时间,有助于浏览器判断是否需要重新请求资源。
这些响应头部为客户端提供了关于响应的各种元数据和指示,客户端可以根据这些信息来处理响应数据,控制缓存、解析内容、处理重定向等。 HTTP响应头部在客户端与服务器之间传递了丰富的信息,有助于确保通信的顺利进行。
HTTP 1.0
HTTP 1.0是1996年推出的第一个广泛使用的版本,定义在 1996 年的 RFC 1945 中,它奠定了现代Web的基础。然而,HTTP 1.0存在一些局限性:
- 短连接:每次请求后,HTTP 1.0会关闭TCP连接,导致每次请求都需要进行TCP的三次握手和四次挥手,效率不高。
- 缓存机制:HTTP 1.0使用If-Modified-Since和Expires头部信息作为缓存失效的标准。
- 不支持断点续传:HTTP 1.0在传输文件时,不支持断点续传,需要传输整个文件。
- IP地址绑定:HTTP 1.0假设每台计算机仅绑定一个IP地址,因此请求消息中的URL不包括主机名。
随着互联网的发展,HTTP 1.0的这些局限性促成了HTTP 1.1的诞生,它提供了更多改进,如持久连接、虚拟主机支持、更完善的缓存机制等。HTTP协议也在不断地演进中,后续的版本如HTTP/2和HTTP/3都在性能和安全性上做出了更多的优化。
HTTP/1.1
HTTP 1.1 在 1997 年由互联网工程任务组(IETF)发布,作为 RFC 2068 文档,后来经过更新,主要在 RFC 2616 中描述。HTTP 1.1 对之前的 HTTP 1.0 进行了多项改进,提高了性能和效率。
持久连接
持久连接(Persistent Connections),也称为keep-alive连接,是HTTP 1.1中默认的连接方式。除非显式地指定使用Connection: close
头,否则连接在响应完成后不会被关闭。
- Connection 头:使用
Connection
头可以控制连接的行为。例如,Connection: Keep-Alive
表示客户端或服务器希望保持连接,而Connection: close
表示请求/响应完成后应该关闭连接。 - Keep-Alive 头:在HTTP 1.0中,
Keep-Alive
头用于告知服务器客户端希望保持连接。在HTTP 1.1中,这个头不是必须的,因为持久连接是默认行为。
GET /index.html HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: Keep-Alive (可选,因为HTTP/1.1默认就是持久连接)
管道化
管道化允许客户端在不需要等待前一个请求的响应的情况下,发送多个请求到服务器。
管道化是在持久连接的基础上实现的,意味着在同一个TCP连接中可以发送多个请求,而不需要为每个请求单独建立连接。
管道化的工作原理
- 建立连接:客户端与服务器建立TCP连接。
- 发送请求:客户端通过这个连接发送第一个HTTP请求,然后立即发送第二个、第三个,以此类推,而不需要等待前一个请求的响应。
- 服务器响应:服务器按照接收请求的顺序返回响应。这意味着即使第二个请求比第一个请求处理得更快,它的响应也会在第一个请求的响应之后发送。
- 关闭连接:除非显式地指定使用
Connection: close
头,否则连接在所有响应完成后不会被关闭,客户端可以继续发送更多的请求。
注意事项
- 队头阻塞:如果任何一个请求失败或需要重试,它可能会阻塞后续请求的处理。这是因为服务器必须按照请求的顺序返回响应。
- 服务器和代理支持:并不是所有的服务器和代理都支持管道化。在某些情况下,即使客户端支持管道化,如果服务器或代理不支持,客户端也需要按照非管道化的方式工作。
- Expect 头:客户端可以使用
Expect: 100-continue
头来测试服务器是否愿意接受管道化的请求。
示例请求
GET /index.html HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3
GET /styles.css HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3
GET /script.js HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3
在这个例子中,客户端通过同一个连接发送了三个GET请求,分别请求HTML页面、CSS样式表和JavaScript脚本。服务器将按照接收请求的顺序返回响应。
管道化是HTTP 1.1中的一个重要特性,它可以提高Web性能,但在实际应用中可能会受到服务器和代理支持的限制。
分块传输编码
分块传输编码允许服务器将响应体分成多个小块(chunks)发送,而不需要事先知道整个响应体的内容大小。
这种机制特别适用于生成响应体数据大小未知或动态生成的情况,例如实时数据流或大型文件的上传。
分块传输编码的工作原理
- 初始化:当服务器需要使用分块传输编码发送响应时,它在响应头中设置
Transfer-Encoding
字段,并将其值设置为chunked
。这表明响应体将使用分块编码方式传输。 - 发送块:服务器将响应体分成多个块,并为每个块附加一个长度值(以十六进制表示)和一个可选的扩展(通常不使用),然后是块数据和一个结束的CRLF(回车换行)。
- 结束分块传输:当所有块都发送完毕后,服务器发送一个长度为0的块,表示分块传输结束。在最后一个块的后面,可以包含一些 trailers(后行头),这些是额外的HTTP头信息。
- 客户端处理:客户端接收到分块数据后,根据每个块的长度值来解析和重组响应体。
分块传输编码的格式
每个块由三部分组成:块长度、块数据和CRLF。块长度的计算不包括块长度值本身、任何前导的CRLF或块的结束CRLF。
注意事项
虽然分块传输编码是HTTP 1.1的一部分,但并不是所有客户端和服务器都支持它。
如果客户端或服务器在处理分块数据时遇到错误,可能需要重新发送整个响应。
示例响应
查看代码
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked
7
Mozilla
9
Developer
7
Network
0
在这个例子中,服务器发送了一个分块传输编码的响应。每个块之前都有一个十六进制的长度值,后面是相应长度的数据和一个CRLF。最后一个块的大小为0,表示分块传输结束。
分块传输编码是HTTP 1.1中一个强大的特性,它提供了一种灵活的方式来传输未知大小的数据。然而,随着HTTP/2的推出,分块传输编码的使用变得不那么常见了,因为HTTP/2使用了一种更高效的数据帧机制来处理流式传输。
Host 头部
Host 头部是 HTTP 1.1 协议中引入的一个重要请求头部,它用于指定请求的资源所在的主机名和端口号。在 HTTP 1.1 中,每个请求都必须包含一个 Host 头部,除非请求是针对一个没有特定主机名的服务器,例如在请求一个 IP 地址时。Host 头部使得一个服务器可以托管多个域名的网站,即所谓的虚拟主机(Virtual Hosting)。
Host 头部的工作原理
- 请求指定主机:客户端在发送 HTTP 请求时,会在请求头中包含一个 Host 字段,用于指定它所请求的资源的主机名和端口号。例如,当请求一个特定的网页时,Host 头部会包含该网页的域名。
- 服务器解析主机名:服务器接收到请求后,会解析 Host 头部来确定客户端请求的是哪个域名的资源。这样,服务器可以将请求分发到正确的网站,特别是在一台服务器上托管了多个网站时。
- 处理请求:一旦服务器确定了请求的主机名,它就会根据 Host 头部的值来处理请求,返回相应的响应。
Host 头部的格式:
Host 头部的格式通常如下:
Host: [host]:[port]
[host]
是请求的资源所在的主机名或 IP 地址。[port]
是可选的端口号,默认为 80(对于 HTTP)或 443(对于 HTTPS)。 如果请求的目标是默认端口,可以省略端口号部分。
例子
GET /index.html HTTP/1.1
Host: www.example.com
在这个例子中,客户端请求的是 www.example.com
的 index.html
页面。
注意事项
- 必须的头部:在 HTTP 1.1 中,如果一个请求没有包含 Host 头部,除了请求一个 IP 地址的情况外,服务器应该返回一个 400(Bad Request)状态码。
- 虚拟主机的支持:Host 头部是虚拟主机工作的基础,它允许服务器根据请求的主机名来决定应该提供哪个网站的内容。
- HTTPS 和代理:在使用 HTTPS 时,Host 头部应该包含在加密的请求中。此外,当请求通过代理服务器时,代理应该确保 Host 头部不会被修改或删除。
- 路径和主机名:Host 头部只包含主机名和端口号,不包括请求的路径。路径在请求行的 URL 部分指定。
Host 头部是现代 HTTP 通信中的一个关键组成部分,它使得服务器可以有效地处理来自多个域名的请求,并且是虚拟主机技术的基础。
范围请求
HTTP/1.1 的范围请求允许客户端只请求资源的一部分,而不是整个资源。这在对大文件进行传输时特别有用,例如,可以允许用户在下载大文件时只下载文件的特定部分,而不是整个文件。
范围请求的核心是客户端在请求头中包含 Range
字段,该字段指定了客户端想要请求资源的 byte 范围。例如,如果客户端想要请求一个视频文件的前 1000 个字节,它会发送一个带有 Range: bytes=0-999
的请求头。
范围请求的语法
范围请求的 Range
请求头可以使用以下语法:
- 单一范围:
Range: bytes=start-end
- 多重范围:
Range: bytes=start-end, start-end
其中start
和end
分别表示范围的起始和结束字节。
服务端响应
服务器收到范围请求后,会根据请求的范围检查资源:
- 如果范围有效,服务器会返回一个
206 Partial Content
的状态码,以及包含所请求范围内容的响应体。 - 如果范围无效或者无法满足(例如,请求的范围超出了资源的大小),服务器会返回
416 Range Not Satisfiable
状态码。 - 如果服务器不支持范围请求,它会返回整个资源,状态码为
200 OK
。
Content-Range 响应头
当服务器成功处理范围请求时,会在响应中包含 Content-Range
头,该头提供了实际发送的范围和资源总大小的信息。例如:
Content-Range: bytes start-end/total
这里 start-end
表示发送的范围,total
表示资源的总大小。
优势
范围请求的主要优势包括:
- 断点续传:用户可以在中断后,从上次中断的地方继续下载,而不是重新开始。
- 并行下载:客户端可以请求资源的不同部分,并并行下载,加快传输速度。
- 视频流媒体的缓冲:流媒体服务可以使用范围请求来只加载视频的特定部分,实现更有效的缓冲。
压缩传输
HTTP/1.1 压缩传输是指在网络中传输 HTTP 请求和响应时,对内容进行压缩以减少数据大小的过程。压缩可以显著减少网络延迟和带宽使用,从而提高网页加载速度和整体的用户体验。
HTTP/1.1 支持多种压缩算法,最常用的是 gzip、deflate 和 br(Brotli)。
压缩是如何工作的
当客户端向服务器发送请求时,它可以包含一个 Accept-Encoding
请求头,列出它支持的压缩算法。例如:
Accept-Encoding: gzip, deflate, br
这表示客户端可以接受 gzip、deflate 或 Brotli 压缩的响应。
服务器接收到请求后,如果它支持请求头中列出的任何压缩算法,并且认为压缩响应是有益的(即响应体足够大,压缩后可以显著减小大小),它会在发送响应时对响应体进行压缩,并在 Content-Encoding
响应头中指明使用了哪种压缩算法。例如:
Content-Encoding: gzip
客户端接收到压缩的响应后,会使用相应的解压缩算法对内容进行解压,以便可以正常处理和使用。
常见的压缩算法
- gzip: 一种使用 LZ77 压缩算法和霍夫曼编码的压缩格式。它是 HTTP 压缩传输中最广泛支持的算法之一。
- deflate: 另一种压缩算法,它也可以使用 LZ77 算法,但通常结合了其他压缩技术。deflate 有时会导致兼容性问题,因为它可以指代不同的事情,例如 zlib 格式。
- br (Brotli): 一种较新的压缩算法,由 Google 开发,旨在提供比 gzip 更好的压缩比。Brotli 特别适用于文本格式的数据压缩,例如 HTML、CSS 和 JavaScript 文件。
HTTP/2
HTTP/2是HTTP协议的第二个主要版本,它在2015年被正式标准化为RFC 7540。
HTTP/2的主要目标是提高网络性能,减少延迟,并提供更高的安全性。
与之前的HTTP/1.1相比,HTTP/2带来了一些重大的改进和变化。
二进制格式
在HTTP/2中,二进制格式的使用是对HTTP/1.x的一个重大改进。
在HTTP/1.x中,消息头和消息体都是文本形式( ASCII 码)的,这使得它们易于阅读和手工构造,但同时也带来了一些性能和解析上的问题。
HTTP/2采用了更加靠近 TCP/IP 的二进制格式,这种格式被称为“帧”(frames),HTTP/2所有的通信都是基于帧的。
帧是HTTP/2协议中的最小数据单位,每个帧都承载着特定类型的信息,如请求头、响应体、设置参数等。帧的设计允许HTTP/2实现多路复用、流控制和其他性能优化特性。
以下是HTTP/2帧的基本结构和组成部分:
- 帧头:每个帧都包含一个9字节长的帧头,帧头包含以下信息:
- 长度(3字节):表示帧载荷的长度,上限为2^14字节(16,384字节),如果需要传输更大的数据,则需要分片。
- 类型(1字节):指示帧的类型,如数据帧(DATA)、头部帧(HEADERS)、设置帧(SETTINGS)等。
- 标志(1字节):包含特定于帧类型的布尔标志,例如,数据帧可能包含结束流(END_STREAM)的标志。
- 流标识符(31位):用于多路复用,标识帧属于哪个流。流的标识符是奇数表示客户端到服务器的帧,偶数表示服务器到客户端的帧。0用于与连接级别相关的帧,如设置帧。
- 帧载荷:帧头后面是帧载荷,其内容和长度由帧头中的长度字段决定。不同类型的帧有不同的载荷结构。
下面是一些关键的帧类型及其用途:
- DATA帧:用于传输流的核心数据,如请求体或响应体。可以包含结束流(END_STREAM)的标志,表示该流的数据传输完成。
- HEADERS帧:用于传输HTTP头块,包括请求头或响应头。可以与DATA帧配合使用,以发送带有头的请求或响应。
- SETTINGS帧:用于交换连接级别的配置参数。客户端和服务器都可以发送设置帧来配置连接的行为。
- PRIORITY帧:用于指定流的优先级,允许客户端告诉服务器它对某些流的偏好。
- RST_STREAM帧:用于终止一个流,可能是由于错误或客户端/服务器不再需要该流。
- PUSH_PROMISE帧:由服务器发送,用于提示客户端它将推送的资源。
- PING帧:用于测量往返时间(RTT)或保持连接活跃。
- GOAWAY帧:用于启动连接关闭过程或通知对端不再接受新流。
- WINDOW_UPDATE帧:用于实现流控制,允许发送方告知接收方它可以处理更多数据。
- CONTINUATION帧:如果HEADERS帧太大,无法在一个帧中发送完毕,可以使用CONTINUATION帧来继续发送剩余的头部信息。
多路复用
多路复用(Multiplexing)是HTTP/2中的一个核心特性,它允许在同一个连接中同时发送多个请求和响应,而不会相互干扰。
这与HTTP/1.1中的行为有显著不同,后者通常在每个连接中顺序处理请求,导致了队头阻塞(Head-of-line blocking)的问题,限制了并发性和性能。
在HTTP/1.1中,为了提高并发性,浏览器通常会开启多个并行连接到服务器,但这并不是一个理想的解决方案,因为它会增加服务器的负载和延迟,并且受到浏览器对同一主机并发连接数量限制的影响。
HTTP/2的多路复用解决了这个问题,它通过以下方式实现:
- 流的概念:HTTP/2引入了“流”(Streams)的概念,每个流代表一个独立的请求和响应交换。每个流都有一个唯一的整数标识符,称为流ID。流ID用于在多路复用的连接中唯一地标识每个流,使得帧可以被正确地分配到对应的请求或响应中。
- 二进制帧:HTTP/2通信是基于帧的,每个帧都属于一个特定的流,并且包含帧头和载荷。帧头中包含流ID,使得接收方能够正确地将帧组装成完整的消息。
- 流的状态机:每个流都处于一个特定的状态,如空闲(Idle)、打开(Open)、半关闭(Half-Closed)或关闭(Closed)。流的状态变化由帧的类型和标志控制。例如,一个带有END_STREAM标志的数据帧会使得流进入半关闭状态。
- 流量控制:HTTP/2实现了基于流的流量控制机制,每个流都有自己的流量控制窗口,用于管理该流的数据传输。
- 帧的顺序和组装:在多路复用的连接中,帧可以在任何顺序到达。接收方根据帧头中的流ID将帧组装成完整的消息。即使帧在传输过程中乱序到达,接收方也能够按照流ID重新排序,确保请求和响应的正确性。
头部压缩
HTTP/2中的头部压缩旨在减少通过网络发送的HTTP头部的体积。
在HTTP/1.x中,每个请求和响应都包含了一组完整的头部,这些头部通常包含大量的冗余信息,如用户代理、接受类型、cookie等。这些冗余信息在多个请求之间重复发送,导致了不必要的带宽消耗。
HTTP/2使用了一种名为HPACK的压缩算法来压缩请求和响应头部。
HPACK的主要目标是在不牺牲安全性(例如,避免压缩注入攻击)的情况下,减少头部的传输开销。
HPACK算法的工作原理如下:
- 静态表:HPACK包含一个静态表,其中包含了一系列常见的HTTP头部字段。这个表是预定义的,并且被HTTP/2的实现所知。例如,:method: GET 就是一个静态表中的条目。
- 动态表:除了静态表之外,HPACK还使用动态表。动态表在连接开始时是空的,但随着请求和响应的交换,可以动态地添加新的条目。动态表允许发送方和接收方共同维护一个头部字段的索引,从而可以只发送索引值而不是完整的头部字段。
- 霍夫曼编码:HPACK使用霍夫曼编码来压缩头部字段的值。霍夫曼编码是一种根据字符出现频率来为字符分配不同长度编码的压缩技术,出现频率高的字符使用较短的编码,出现频率低的字符使用较长的编码。
- 索引和更新:当发送方想要发送一个头部字段时,它会检查该字段是否已经在静态表或动态表中。如果存在,发送方只需发送该字段的索引值。如果不存在,发送方可以发送字段的完整值,并将其添加到动态表中。动态表的大小是有限制的,因此会对条目进行老化或清除,以保持表的效率。
通过头部压缩,HTTP/2能够显著减少每个请求和响应的头部大小,从而减少总体传输数据量,提高网络性能。
服务器推送
服务器推送是HTTP/2的一个特性,允许服务器在客户端请求之前主动发送资源。它是通过PUSH_PROMISE
帧实现的,该帧包含预请求头和推送流ID。客户端可以决定是否接受推送的资源。服务器在推送流中发送数据帧,包含推送资源的实际内容。服务器推送的资源可以根据客户端的优先级设置来发送。服务器需要智能地决定何时推送资源,避免过度推送。
服务器推送的一个典型例子是当用户请求一个网页时,服务器在发送HTML文件的同时,主动推送该HTML文件中引用的CSS和JavaScript文件。这样,当浏览器解析HTML文件并发现需要这些资源时,它们已经在本地了,不需要再发起网络请求去下载,从而加快了网页的加载速度。
具体步骤如下:
- 用户通过浏览器发送一个请求到服务器,要求获取一个网页(例如 index.html)。
- 服务器开始处理这个请求,并且在准备发送index.html文件的内容时,服务器检查文件内容,发现其中包含了两个内联资源:main.css和script.js。
- 服务器发送一个
PUSH_PROMISE
帧给客户端,告诉客户端它打算推送main.css文件。这个帧中包含了请求main.css所需的所有HTTP头信息,以及一个流ID用于后续的数据传输。 - 服务器紧接着发送另一个
PUSH_PROMISE
帧,这次是针对script.js文件的。 - 客户端接收到这些
PUSH_PROMISE
帧后,检查自己的缓存。如果缓存中没有这些资源,或者这些资源的版本已经过期,客户端就准备接收这些推送的资源。 - 服务器开始在对应的流中发送main.css和script.js文件的数据帧。这些数据帧包含文件的实际内容。
- 一旦所有数据帧发送完毕,服务器会为每个流发送一个带有
END_STREAM
标志的数据帧,表示这个推送流结束了。 - 此时,客户端已经开始接收并处理main.css和script.js文件,当解析HTML文件时发现这些资源,它们已经就位,可以直接使用,从而避免了额外的网络延迟。
HTTP/3
HTTP/3是一种基于QUIC(Quick UDP Internet Connections)协议的新一代超文本传输协议,旨在取代基于TCP的HTTP/1和HTTP/2协议。QUIC是由Google设计开发的基于UDP的传输协议,结合了TCP和TLS的功能,并具有更快的连接建立和更好的拥塞控制机制。
QUIC协议
QUIC(Quick UDP Internet Connections)是一种基于UDP(User Datagram Protocol)的传输层协议,旨在提供更快的连接建立和数据传输速度。以下是QUIC协议的实现原理的简要概述:
连接建立: QUIC使用一个称为"0-RTT"(Zero Round Trip Time)的特性来加速连接建立过程。客户端可以在第一次连接时发送数据,而不必等待服务器确认。这是通过在初始连接中携带加密令牌实现的,该令牌由上一次连接的一些信息生成。
多路复用: QUIC支持在单个连接上同时传输多个数据流。这意味着一个QUIC连接可以同时处理多个HTTP请求,从而减少了连接建立和关闭的开销,并提高了整体的效率。
快速连接恢复: QUIC在网络切换或连接断开后可以更快地恢复连接,这是因为它在连接的生命周期中保留了更多的状态信息。这使得连接恢复过程更加快速,不需要像TCP那样重新执行三次握手过程。
拥塞控制: QUIC内置了一种拥塞控制算法,用于在网络拥塞时调整数据传输速率,以避免网络性能恶化。这种拥塞控制算法类似于TCP的拥塞控制算法,但是在实践中可能会有所不同。
安全性: QUIC使用TLS(Transport Layer Security)来加密数据传输,并提供身份验证和数据完整性保护。它还支持零RTT数据传输,这意味着在一些情况下可以实现更快的数据传输速度,但同时也带来了一些安全风险,需要适当的管理。
总的来说,QUIC通过优化连接建立、数据传输和连接恢复过程,以及提供更好的安全性和拥塞控制机制,来提供更快、更可靠的网络连接服务。
前向纠错
前向纠错(Forward Error Correction,FEC)是一种在数据传输过程中检测和纠正错误的技术。FEC通过在数据包中添加额外的冗余信息(也称为纠错码),使得接收方能够在不重传丢失数据包的情况下恢复出原始数据。这种技术特别适用于那些对延迟敏感的应用,如实时视频流和VoIP,因为它们不能承受重传丢失数据包所需的时间。
以下是前向纠错的一些详细信息:
- 纠错码:FEC使用纠错码(如奇偶校验位、海明码、Reed-Solomon码等)来检测和纠正错误。这些码通过在原始数据中添加额外的位来实现,这些位可以用来检测和修复一定数量的错误。
- 冗余数据包:在QUIC中,FEC可以用来生成冗余数据包。这些冗余数据包包含了原始数据包的一部分或全部内容,以及纠错码。如果原始数据包丢失,接收方可以使用冗余数据包和纠错码来恢复丢失的数据。
- 恢复能力:FEC的恢复能力取决于所使用的纠错码和添加的冗余度。更高的冗余度可以恢复更多的错误,但也会增加额外的带宽消耗。
- 实时性和可靠性:FEC可以提高数据传输的可靠性,因为它减少了重传丢失数据包的需要。这对于实时应用来说非常重要,因为重传可能会导致不可接受的延迟。
- 带宽效率:虽然FEC增加了额外的带宽消耗,但它可以减少因重传而导致的带宽浪费。在某些情况下,使用FEC可能会更有效地利用带宽。
- 适用性:FEC适用于那些丢包成本高于带宽成本的场景。例如,在移动网络或卫星通信中,丢包率可能较高,而带宽资源有限,这时FEC可以提供更好的性能。
- 配置和调整:实现FEC的系统通常允许管理员配置纠错码的类型和冗余度,以便根据特定的网络条件和应用需求进行优化。
- 与ARQ的比较:FEC与自动重传请求(Automatic Repeat reQuest,ARQ)是两种不同的错误恢复策略。ARQ通过重传丢失的数据包来恢复错误,而FEC则使用冗余数据来纠正错误。在实际应用中,FEC和ARQ可以结合使用,以提高数据传输的可靠性和效率。
零RTT连接建立
零RTT(Zero Round-Trip Time)连接建立是QUIC协议的一个重要特性,它允许在客户端和服务器之间快速恢复先前的加密会话,从而减少了建立新连接所需的往返次数。这对于减少延迟和提高用户体验特别有用,尤其是在需要快速建立连接的场景中,如Web浏览、在线游戏和实时通信。
以下是零RTT连接建立的详细说明:
- 初始握手:在第一次建立连接时,QUIC使用TLS 1.3进行加密握手。这个过程通常需要一到两个RTT,因为客户端和服务器需要交换密钥和其他安全参数。
- 会话密钥的存储:在初始握手完成后,客户端和服务器都会存储用于加密和解密数据的关键信息,包括会话密钥和服务器配置。这些信息在未来的连接中重用,以实现零RTT。
- 零RTT握手:当客户端需要重新连接到服务器时,它可以利用之前存储的信息来发送应用数据,而无需等待服务器的确认。客户端使用存储的会话密钥加密数据,并将其发送到服务器。
- 服务器的响应:服务器接收到客户端的零RTT数据后,会尝试使用存储的密钥信息解密数据。如果解密成功,服务器可以使用相同的密钥发送响应数据,从而实现零RTT通信。
- 安全性考虑:零RTT握手可能会受到重放攻击,因为攻击者可以拦截并重新发送客户端的零RTT数据。为了防止这种情况,QUIC在握手过程中使用一次性令牌和加密的地址验证,以确保数据的完整性和来源的真实性。
- 兼容性和优化:虽然零RTT可以提高性能,但并不是所有场景都适用。例如,如果客户端或服务器没有存储必要的会话信息,或者网络环境发生了变化,那么零RTT可能无法实现。在这种情况下,QUIC会回退到标准的握手过程。
连接迁移
连接迁移(Connection Migration)是QUIC协议的一个重要特性,它允许在网络条件发生变化时,如移动设备从Wi-Fi切换到移动数据网络,保持现有的网络连接,而不会中断正在进行的通信。这在TCP协议中是无法实现的,因为TCP连接是由四元组(源IP地址、源端口、目的IP地址、目的端口)标识的,任何这些元素的变化都会导致建立一个新的连接。
以下是连接迁移的一些详细说明:
- 连接标识:QUIC使用一个称为连接ID的唯一标识符来标识连接,而不是依赖四元组。即使在IP地址或端口发生变化时,只要连接ID保持不变,QUIC连接就能继续。
- 无缝切换:当设备的网络连接发生变化时,QUIC连接可以无缝地迁移到新的网络路径上,而不会影响用户正在进行的操作,如视频流媒体播放或在线游戏。
- 减少中断时间:在TCP中,网络切换可能导致连接中断,需要重新建立连接,这通常涉及一个完整的握手过程,可能会导致数百毫秒到数秒的延迟。QUIC的连接迁移可以显著减少这种中断时间。
多路复用
HTTP/3是下一代HTTP协议,它基于QUIC协议,而不是传统的TCP协议。在HTTP/3中,多路复用是其核心特性之一,它允许在单个连接中并行发送多个请求和响应,从而提高网络效率和性能。
以下是HTTP/3中多路复用的一些详细信息:
- 基于QUIC的多路复用:HTTP/3的多路复用是基于QUIC的流(Streams)概念的。QUIC流是独立的、有序的数据流,每个流可以携带一个HTTP请求和响应。这些流在单个QUIC连接中多路复用,而不是像HTTP/2那样在单个TCP连接中多路复用。
- 流独立性:在HTTP/3中,每个流都是独立的,一个流的阻塞或丢包不会影响其他流的传输。这与HTTP/2不同,在HTTP/2中,由于所有的流都在同一个TCP连接中,一个流的丢包可能会导致所有流的队头阻塞(Head-of-Line Blocking,HOLB)。
- 改进的队头阻塞抵抗:由于QUIC的连接迁移和前向纠错(FEC)等特性,HTTP/3能够更好地抵抗网络中的丢包和延迟问题,从而减少队头阻塞的影响。
- 请求和响应复用:HTTP/3允许多个请求和响应在单个连接中同时传输,这有助于减少建立新连接的开销,并提高网络的利用率。
- 零RTT握手:由于QUIC的加密握手可以与数据传输同时进行,HTTP/3可以实现零往返时间(Zero Round-Trip Time,0-RTT)的连接建立,这意味着请求可以在几乎没有延迟的情况下发送。
HTTPS
HTTPS(Hyper Text Transfer Protocol Secure)是一种安全的网络传输协议,它在传统的HTTP协议上加入了SSL/TLS加密层,用于网络上的安全通讯。
HTTPS通过公钥和私钥对传输的数据进行加密,确保数据在传输过程中的机密性和完整性,同时还能验证网站服务器的真实性,防止数据被非法篡改和窃取。
非对称加密用于初始通信的安全建立,解决了对称加密中如何安全地共享密钥的问题。
对称加密则用于实际的数据传输,因为其速度更快,适合处理大量数据。
SSL/TLS
SSL(Secure Sockets Layer)和TLS(Transport Layer Security)是用于在互联网上提供加密通信协议的两种安全技术。它们在传输层与应用层之间对网络连接进行加密,确保数据的机密性和完整性,同时还可以提供身份验证,防止中间人攻击和窃听。
SSL/TLS的历史
- SSL:由Netscape公司在1995年开发,最初的版本是SSL 1.0,但由于安全漏洞,没有公开发布。随后,Netscape发布了SSL 2.0和SSL 3.0。然而,随着时间的推移,SSL 2.0和SSL 3.0都暴露出了严重的安全问题,不再被认为是安全的。
- TLS:为了解决SSL协议中的安全问题,IETF(Internet Engineering Task Force)在1999年基于SSL 3.0设计了TLS 1.0。随后,TLS经历了多次更新,包括TLS 1.1、TLS 1.2和最新的TLS 1.3。
SSL/TLS的工作原理
SSL/TLS的工作原理可以分为几个关键部分:
- 握手协议:在数据传输开始之前,客户端和服务器之间进行握手,以协商加密算法、交换密钥和验证身份。这个过程包括多个步骤,如交换支持的加密套件、生成会话密钥、验证证书等。
- 记录协议:握手完成后,SSL/TLS使用记录协议来加密实际的数据传输。数据被分割成多个记录,每个记录都被加密和签名,以确保数据的机密性和完整性。
- 警报协议:用于在通信过程中发送警报消息,例如,如果一方检测到错误或安全问题,它会发送一个警报消息给另一方,从而终止连接。
- 密钥交换算法:SSL/TLS使用各种密钥交换算法来安全地交换密钥,如RSA、Diffie-Hellman(DH)、椭圆曲线Diffie-Hellman(ECDH)等。
- 加密算法:用于加密数据的算法,如AES(Advanced Encryption Standard)、ChaCha20等。
- 散列和消息认证码算法:用于提供数据完整性和认证的算法,如SHA-256、HMAC等。
握手协议
在TLS握手过程中,RSA可以作为一种密钥交换机制被使用。在TLS握手协议中,客户端和服务器需要协商出一个共享的密钥,用于后续的对称加密通信。RSA可以用于这个密钥交换过程,使得客户端和服务器能够安全地交换对称加密的密钥。
具体来说,在TLS握手过程中,服务器会向客户端发送其RSA公钥,客户端使用这个公钥来加密一个随机的预主密钥(PreMaster Secret),然后将加密后的预主密钥发送给服务器。服务器使用其私钥解密这个预主密钥,从而获得一个共享的对称密钥。这个对称密钥随后被用于加密实际的通信数据。
下面是TLS握手的详细步骤:
ClientHello:
客户端发送一个ClientHello消息到服务器,其中包含:
- 支持的TLS版本。
- 一个随机生成的客户端随机数(Client Random),用于后续的密钥生成。
- 支持的加密算法(如AES, ChaCha20等)。
- 支持的压缩方法。
ServerHello:
服务器响应一个ServerHello消息,其中包含:
- 选择的TLS版本。
- 一个随机生成的服务器随机数(Server Random),用于后续的密钥生成。
- 从客户端提供的选项中选出的加密算法。
- 从客户端提供的选项中选出的压缩方法。
Certificate:
服务器发送自己的证书(包括证书链和可选的服务器密钥交换信息(服务器公钥))。
客户端验证证书的有效性,包括验证证书是否由可信的证书颁发机构(CA)签发、证书是否在有效期内、以及证书的域名是否与当前访问的站点一致。
ServerKeyExchange(可选):
- 如果服务器选择的密钥交换算法需要额外的服务器参数(例如使用DHE或ECDHE),则服务器会发送ServerKeyExchange消息,包含所需的参数。通常用于非RSA算法的密钥交换过程中。
ServerHelloDone:
结束Server Hello信息发送,表明服务器的握手消息已完成,等待客户端的响应。
ClientKeyExchange:
客户端生成一个随机数预主密钥(PreMaster Secret),使用服务器的公钥加密后发送给服务器。服务器将使用对应的私钥解密这个随机数。
现在,客户端和服务端都已经得到客户端随机数、服务器随机数、预主密钥。
客户端和服务端都可以基于这三个参数和对应加密算法,计算出对称密钥。
Change Cipher Spec:
客户端发送这个消息告诉服务器,后续的通信将使用协商好的对称密钥和算法进行加密和解密。
Finished (Encrypted Handshake Message):
客户端发送一个包含之前所有握手消息的Hash值的消息,用检查握手过程中是否有任何改变。
Change Cipher Spec:
服务器同样发送这个消息,告知客户端已切换到新的加密算法。
Finished (Encrypted Handshake Message):
服务器同样发送这个消息,确认之前的握手消息,测试密钥的有效性。
数据传输:
此时,握手过程完成,双方可以使用相同的密钥进行对称加密,开始交换应用数据。
记录协议
TLS记录协议(TLS Record Protocol)是TLS协议的一个关键组件,负责在客户端和服务器之间安全地传输应用数据。它的主要任务是确保数据的机密性和完整性,并且可以为数据提供可靠的传输。TLS记录协议的工作流程如下:
- 分段:TLS记录协议将来自上层应用的数据分割成较小的片段,以便于处理和传输。每个片段的大小通常受限于TLS协议的最大片段大小,这通常是16KB。
- 压缩(可选):如果双方协商同意使用压缩,则对每个片段进行压缩。然而,由于压缩可能会引入安全漏洞(如CRIME和BREACH攻击),TLS 1.3已经废弃了对压缩的支持。
- 加密:使用握手过程中协商的加密算法和密钥对每个片段进行加密。加密可以是对称加密,如AES或ChaCha20,这取决于双方协商的加密套件。
- 计算MAC:为了确保数据的完整性,对每个加密后的片段计算消息认证码(MAC)。MAC是一个哈希值,用于验证数据在传输过程中未被篡改。TLS 1.2及更早版本使用HMAC(基于哈希的消息认证码),而TLS 1.3使用AEAD(Authenticated Encryption with Associated Data)模式,它结合了加密和完整性验证。
- 添加记录头:在加密和计算MAC之后,为每个片段添加一个记录头。记录头包含以下信息:
- 内容类型:指示记录内容类型(如应用数据、握手、警告等)。
- 协议版本:TLS的版本号。
- 长度:记录的长度。
- 传输:将处理后的记录发送到传输层,由传输层负责将其传送到对端。
- 接收和解密:接收方接收到数据后,首先去除记录头,然后使用相应的解密算法和密钥对数据进行解密。
- 验证MAC:解密后的数据需要验证MAC,以确保数据的完整性。如果MAC验证失败,表明数据可能在传输过程中被篡改。
- 解压缩(如果使用了压缩):对解密后的数据进行解压缩,恢复原始的应用数据。
- 重组:将解压缩后的片段重新组合成原始的应用数据,并将其传递给上层应用。
TLS记录协议通过这些步骤确保了数据的机密性和完整性,同时提供了对传输错误的检测。它是TLS协议中处理数据传输的核心机制,对于建立安全的网络通信至关重要。
警报协议
警报协议(Alert Protocol)是TLS协议中的一个组件,用于在TLS握手过程或数据传输过程中发送警报消息。这些警报消息用于通知对方出现的问题或错误条件。每个警报消息由一个警告级别和一个警告代码组成。
警报级别
- 警告(Warning):表示出现了一个非致命的问题,连接可以继续,但可能会受到影响。
- 致命(Fatal):表示出现了一个致命的错误,连接必须立即终止。
警报代码
警报代码定义了具体的警告或错误类型。一些常见的警报代码包括:
- Close Notify:用于优雅地关闭连接。
- Unexpected Message:接收到了一个在当前状态下不期望的消息。
- Bad Record MAC:记录中的MAC验证失败,表明数据可能在传输过程中被篡改。
- Decryption Failed:解密过程中出现错误,通常是由于密钥不匹配或加密算法不支持。
- Record Overflow:记录的长度超过了最大允许值。
- Handshake Failure:握手过程中出现错误,可能是由于不支持的加密套件或证书问题。
- Bad Certificate:收到的证书链有问题,如证书过期、签名无效或不受信任。
- Unsupported Certificate:证书类型不受支持。
- Certificate Revoked:证书已被撤销。
- Certificate Expired:证书已过期。
- Unknown CA:证书链中的CA不受信任。
警报协议的使用
当一端检测到问题时,它会发送一个警报消息给另一端。接收方根据警报级别和代码做出相应的反应。如果是一个警告级别的警报,接收方可能会采取一些措施来处理问题,但连接可以继续。如果是一个致命级别的警报,接收方会立即终止连接。
数字证书
数字证书,也称为公钥证书,是一种用于在互联网上验证通信实体身份的电子文档。它通过使用公钥加密技术来确保信息的安全性。
![]() | ![]() |
---|
数字证书的组成部分
- 证书所有者的公钥:这是证书的主要部分,它允许其他人使用该公钥来加密发送给证书持有者的信息。
- 证书所有者的标识信息:这包括证书持有者的名称或其他标识符,比如组织的名称、个人姓名或域名。
- 证书颁发者的数字签名:证书由一个可信的第三方机构(称为证书颁发机构或CA)颁发。CA用自己的私钥对证书进行数字签名,以证明证书的有效性。
- 有效期:证书只在特定的时间段内有效。
- 证书的使用条件:这定义了证书可以用于哪些目的,例如网站身份验证、安全电子邮件或代码签名。
数字证书的类型
根据用途和信任级别,数字证书可以分为以下几种类型:
- 域名验证(DV)证书:只验证域名的所有权,通常用于个人网站或小型企业。
- 组织验证(OV)证书:验证申请者的组织身份,适用于企业级应用。
- 扩展验证(EV)证书:提供最高级别的验证,浏览器会在地址栏显示公司的名称,适用于电子商务和在线银行等需要高度信任的场合。
自签名证书
自签名证书是一种SSL/TLS证书,它是由创建者自己签名的,而不是由公认的证书颁发机构(CA)签发的。由于没有第三方权威机构的验证,大多数浏览器和操作系统默认不信任自签名证书,并会在用户访问时显示安全警告。
尽管没有第三方验证,自签名证书仍然可以为HTTPS、SFTP等协议提供加密通道,确保客户端与服务器之间的数据传输安全。使用自签名证书不需要支付给商业CA费用,因此对于一些非公开的服务或内部系统来说是一个经济的选择。在内部系统或私有网络中,使用自签名证书可以满足加密需求,减少与外部CA的依赖。
可以使用OpenSSL生成自签名证书。
中间人攻击
HTTPS 中间人攻击(Man-in-the-Middle Attack, MITM)是指攻击者在客户端与服务器之间建立一个假冒的传输层安全(TLS)连接,从而能够截取、篡改和重新发送 HTTPS 通信数据。这类攻击依赖于攻击者能够插入到客户端和服务器之间的网络路径中,并且通常需要伪造或拦截SSL/TLS证书以欺骗客户端相信它正在直接与合法服务器通信。
以下是详细的 HTTPS 中间人攻击流程:
请求拦截:当客户端尝试发起 HTTPS 请求时,攻击者在网络中拦截该请求。这可以通过多种方式实现,例如通过恶意Wi-Fi接入点、DNS劫持、ARP欺骗等技术。
伪造证书:为了使客户端相信自己是在与真正的服务器通信,攻击者需要创建一个看起来合法但实际上是伪造的数字证书。这个伪造的证书可能包含一个看似真实的域名,并且攻击者可能会试图让客户端信任这个伪造的证书,比如通过诱导用户接受不受信的证书警告,或者预先在用户的设备上安装攻击者的根证书。
证书交换:攻击者将伪造的证书发送给客户端,而客户端由于某种原因接受了这个证书(可能是用户忽略了浏览器的安全警告)。此时,客户端认为它是与预期的服务端建立了加密连接。
密钥协商:客户端使用伪造证书中的公钥加密会话密钥,并将其发送给“服务器”(实际上是攻击者)。攻击者用其私钥解密获得会话密钥。
双重通信:攻击者现在可以分别与客户端和服务端建立两个独立的加密通道。对于服务端来说,攻击者扮演客户端的角色;对于客户端来说,攻击者扮演服务端的角色。这样,攻击者就可以监视并潜在地修改双方之间的所有通信内容。
数据篡改:一旦成功设置了上述双重通信机制,攻击者可以在转发之前修改来自任一方的数据包。这可能包括注入恶意脚本、更改交易细节等。
维持连接:在整个会话期间,只要没有检测到异常,攻击者就可以持续保持这种中间人的位置,直到会话结束。
为了防止 HTTPS 中间人攻击,以下是一些有效的防御措施:
严格验证证书:确保应用程序和浏览器正确地检查服务器提供的 SSL/TLS 证书的有效性,包括检查证书链、有效期以及是否被吊销。
使用HSTS (HTTP Strict Transport Security):这是一种安全策略,它告诉浏览器只应通过 HTTPS 访问特定网站,并且自动将 HTTP 请求升级为 HTTPS。
公共密钥固定(Public Key Pinning):允许网站指定哪些 CA 或具体的公钥应该用于它们的 TLS 连接,从而防止某些类型的中间人攻击。
教育用户不要忽略证书错误:提醒用户不要轻易忽略浏览器显示的安全警告,尤其是关于不受信任的证书的提示。
定期更新软件和操作系统:及时修补已知漏洞,减少遭受攻击的风险。
参考链接:
https://juejin.cn/post/6847902219745181709
https://www.51cto.com/article/698090.html