计算机网络
尽量保证描写的清楚,且简洁。
TCP/IP 模型
四层:
- 应用层:
- HTTP、FTP、Telnet、DNS、SMTP
- 应用层是工作在操作系统中的用户态,传输层及以下则工作在内核态。
- 传输层:加上 TCP 头部
- TCP(大部分) 和 UDP
- TCP: 流量控制、超时重传、拥塞控制(保证数据包能可靠地传输给对方),当数据非常大:数据包大小超过 MSS(TCP 最大报文段长度),需要将数据包分块(TCP 段),这样丢包损失较小
- UDP:不保证数据包是否能抵达对方,但它实时性相对更好,传输效率也高
- 当设备作为接收方时,传输层则要负责把数据包传给应用,需要用一个编号将应用区分开来,即端口
- TCP(大部分) 和 UDP
- 网络层:(传输功能)加上 IP 头部
- IP:网络号+主机号(哪个子网+子网下的哪个主机)
- 将主机和子网掩码进行与运算,得到网络号,将主机和子网掩码取反值进行与运算得到主机号
- IP 协议的寻址作用是告诉我们去往下一个目的地该朝哪个方向走,路由则是根据「下一个目的地」选择路径。寻址更像在导航,路由更像在操作方向盘。
- IP:网络号+主机号(哪个子网+子网下的哪个主机)
- 网络接口层:加上 MAC 头部,并封装成数据帧(Data frame)发送到网络上
- 网络接口层主要为网络层提供「链路级别」传输的服务,负责在以太网、WiFi 这样的底层网络上发送原始数据包,工作在网卡这个层次,使用 MAC 地址来标识网络上的设备。
网络解析网址的方式 :
URL:
协议+//+服务器名称+/.../(数据源的路径)
通俗版解析:从输入网址到网页显示的全过程
1. 第一步:浏览器解析网址(找地址)
• 比喻:就像你想去朋友家,但只知道小区名,不知道具体门牌号。
• 过程:
• 拆解 URL:浏览器把网址拆成「域名」(如 www.example.com
)和「路径」(如 /index.html``)。 • **检查缓存**:先翻自己的「小本本」(浏览器缓存)看有没有记录过这个域名的 IP 地址。 • **问操作系统**:如果小本本没记,就问电脑管家(操作系统):“你记得
www.example.com` 的地址吗?”
2. DNS 查询:全网找门牌号
• 比喻:打电话问 114 查号台,但需要层层转接。
• 过程:
- 本地 DNS 服务器(小区物业):
◦ 先查自己的记录,没有就联系上级。 - 根 DNS 服务器(全球总台):
◦ 回答:“.com
的顶级 DNS 服务器地址是X.X.X.X,你问它。” - 顶级域 DNS(.com 管理局):
◦ 回答:“example.com
的权威 DNS 服务器是Y.Y.Y.Y,你问它。” - 权威 DNS 服务器(朋友小区的物业):
◦ 最终给出 IP 地址:“门牌号是93.184.216.34
!”
• 结果:浏览器拿到 IP 地址,准备出发。
3. 建立 TCP 连接:确认对方在家
• 比喻:打电话给朋友,先确认他是否在线。
• 三次握手:
- 你(客户端):“喂,能听到吗?”(发送
SYN
包) - 朋友(服务器):“能听到,你说话吧!”(回复
SYN-ACK
包) - 你:“好的,我要说正事了!”(发送
ACK
包)
• 结果:连接建立,开始传输数据。
4. 发送 HTTP 请求:打包你的需求
• 比喻:写一封信,告诉朋友你要借哪本书。
• 内容:
• 请求行:“GET /index.html HTTP/1.1”(我要首页)
• 请求头:附加信息(浏览器类型、支持的语言等)。
• 请求体:如果是登录请求,会包含账号密码。
5. 数据包旅行:跨城快递
• 比喻:把信交给快递员,经过多个中转站。
• 过程:
- 封装成 TCP 包:信纸装进信封(TCP 头部),写上序号(防止丢件)。
- 封装成 IP 包:套上快递袋(IP 头部),写清发件人(你的 IP)和收件人(服务器 IP)。
- MAC 地址定位:快递员(交换机)根据门牌号(MAC 地址)送到小区门口。
- 路由器接力:
◦ 小区门口快递站(路由器)检查地址:“这封信要跨省,先送到省中心!”
◦ 省中心再转发到目标城市,直到抵达朋友家。
6. 服务器处理:拆信并回信
• 比喻:朋友收到信,找到书后回寄给你。
• 过程:
• 拆包:服务器一层层剥开 IP、TCP 头部,看到 HTTP 请求。
• 处理请求:读取 /index.html
,从硬盘找到文件。
• 生成响应:把 HTML 内容塞进 HTTP 响应包,反向封装(TCP→IP→MAC)。
• 回传:按原路返回,经过路由器、交换机,最终到你的电脑。
7. 浏览器渲染:拆包裹拼图
• 比喻:收到回信后,把碎片拼成完整的画。
• 过程:
• 接收数据包:按 TCP 序号重组文件。
• 解析 HTML:读取文本、图片、CSS 样式。
• 渲染页面:把代码变成你看到的按钮、文字、图片。
关键概念通俗解析
术语 | 通俗解释 | 类比 |
---|---|---|
DNS | 把网站名翻译成数字地址的电话簿 | 查号台(114) |
TCP | 确保数据完整送达的“快递保价服务” | 快递员打电话确认你收到包裹 |
IP 地址 | 设备的全球唯一“门牌号” | 家庭住址(XX 省 XX 市 XX 街道) |
MAC 地址 | 设备的“身份证号”,用于同一网络内精准定位 | 快递柜编号(A 区 3 号柜) |
路由器 | 跨网络转发数据的“中转站” | 跨省快递分拣中心 |
交换机 | 同一网络内转发数据的“快递柜” | 小区内的快递代收点 |
Linux 网络包收发机制
一、网络模型基础
-
OSI 七层模型(理论模型):
• 应用层(用户接口)
• 表示层(数据格式转换)
• 会话层(建立/管理连接)
• 传输层(端到端传输)
• 网络层(路由和寻址)
• 数据链路层(物理寻址)
• 物理层(比特流传输) -
TCP/IP 四层模型(实际实现):
• 应用层(HTTP/FTP/DNS 等)
• 传输层(TCP/UDP)
• 网络层(IP/ICMP)
• 网络接口层(以太网/WiFi)
关键区别:TCP/IP 模型将 OSI 的上三层合并为应用层,更注重实用性。Linux 系统采用 TCP/IP 模型实现。
二、数据封装过程(发送时)
以发送"Hello"字符串为例:
应用层:原始数据 "Hello"
↓ 添加TCP头(源/目标端口、序列号等)
传输层:[TCP头]+"Hello"
↓ 添加IP头(源/目标IP地址)
网络层:[IP头]+[TCP头]+"Hello"
↓ 添加帧头帧尾(MAC地址、CRC校验)
网络接口层:[帧头]+[IP头]+[TCP头]+"Hello"+[帧尾]
三、接收网络包流程
-
硬件接收阶段:
• 网卡通过 DMA 将数据包存入环形缓冲区(Ring Buffer)
• 触发硬件中断通知 CPU -
中断处理优化(NAPI 机制):
• 传统方式:每个包都触发中断 → 高负载时 CPU 被频繁打断
• NAPI 方案:
◦ 首次中断唤醒处理线程
◦ 后续采用轮询方式批量处理多个数据包
◦ 减少中断次数,提升吞吐量 -
协议栈处理:
graph TD A[网卡驱动] --> B[网络接口层] B --> C{校验检查} C -->|合法| D[剥离帧头帧尾] D --> E[网络层处理IP头] E --> F[传输层处理TCP/UDP头] F --> G[Socket接收缓冲区] G --> H[应用层read调用]
-
关键数据结构:
•sk_buff
:贯穿整个协议栈的核心数据结构
• 通过指针调整实现零拷贝:struct sk_buff { unsigned char *head; // 缓冲区起始 unsigned char *data; // 当前协议层起始 unsigned char *tail; // 数据结束 unsigned char *end; // 缓冲区结束 };
四、发送网络包流程
-
应用层发起:
send(socket_fd, buffer, len, 0); // 系统调用
-
内核处理过程:
• 创建sk_buff
并拷贝用户数据
• 逐层添加协议头:graph LR A[应用数据] --> B[添加TCP头] B --> C[添加IP头] C --> D[添加帧头帧尾]
-
TCP 重传机制:
• 克隆sk_buff
副本发送
• 原始包保留直到收到 ACK
• 实现可靠传输的核心机制 -
分片处理(MTU 限制):
• 当 IP 包超过 1500 字节时:def fragment(packet): chunks = [] while len(packet) > MTU: chunk = packet[:MTU-20] # 保留IP头空间 chunks.append(add_ip_header(chunk)) packet = packet[MTU-20:] chunks.append(add_ip_header(packet)) return chunks
五、关键性能优化点
-
零拷贝技术:
• sendfile 系统调用:文件→Socket 直接传输
• 减少用户态与内核态数据拷贝 -
多队列网卡:
• 每个 CPU 核心绑定独立队列
• 避免缓存行竞争 -
TSO/GSO:
• TCP Segmentation Offload:网卡硬件分片
• Generic Segmentation Offload:内核延迟分片
六、完整流程对比
接收流程 | 发送流程 |
---|---|
1. 网卡 DMA 到 Ring Buffer | 1. 应用调用 send() |
2. 触发硬中断 | 2. 创建 sk_buff 并拷贝数据 |
3. ksoftirqd 软中断处理 | 3. 协议栈逐层封装 |
4. 协议栈逐层解析 | 4. 分片处理(如果需要) |
5. 数据存入 Socket 缓冲区 | 5. ARP 查询下一跳 MAC |
6. 应用 read()读取 | 6. 网卡 DMA 发送 |
七、常见问题解答
Q:为什么需要三次内存拷贝?
A:发送时的三次拷贝:
- 用户空间→内核 sk_buff
- TCP 重传保留副本
- IP 分片时产生新副本
Q:MTU 设置 1500 字节的历史原因?
A:源自早期以太网的电气特性限制,现代网络可通过 Jumbo Frame(9000 字节)提升吞吐量。
Q:如何查看协议栈统计?
netstat -s # 统计摘要
ethtool -S eth0 # 网卡详细统计
cat /proc/net/softnet_stat # 软中断统计
HTTP
1xx 类状态码属于提示信息,是协议处理中的一种中间状态,实际用到的比较少。
2xx 类状态码表示服务器成功处理了客户端的请求,也是我们最愿意看到的状态。
-
「200 OK」是最常见的成功状态码,表示一切正常。如果是非 HEAD 请求,服务器返回的响应头都会有 body 数据。
-
「204 No Content」也是常见的成功状态码,与 200 OK 基本相同,但响应头没有 body 数据。
-
「206 Partial Content」是应用于 HTTP 分块下载或断点续传,表示响应返回的 body 数据并不是资源的全部,而是其中的一部分,也是服务器处理成功的状态。
3xx 类状态码表示客户端请求的资源发生了变动,需要客户端用新的 URL 重新发送请求获取资源,也就是重定向。
-
「301 Moved Permanently」表示永久重定向,说明请求的资源已经不存在了,需改用新的 URL 再次访问。
-
「302 Found」表示临时重定向,说明请求的资源还在,但暂时需要用另一个 URL 来访问。
301 和 302 都会在响应头里使用字段 Location,指明后续要跳转的 URL,浏览器会自动重定向新的 URL。
-
「304 Not Modified」不具有跳转的含义,表示资源未修改,重定向已存在的缓冲文件,也称缓存重定向,也就是告诉客户端可以继续使用缓存资源,用于缓存控制。
4xx 类状态码表示客户端发送的报文有误,服务器无法处理,也就是错误码的含义。 -
「400 Bad Request」表示客户端请求的报文有错误,但只是个笼统的错误。
-
「403 Forbidden」表示服务器禁止访问资源,并不是客户端的请求出错。
-
「404 Not Found」表示请求的资源在服务器上不存在或未找到,所以无法提供给客户端。
5xx 类状态码表示客户端请求报文正确,但是服务器处理时内部发生了错误,属于服务器端的错误码。
-
「500 Internal Server Error」与 400 类型,是个笼统通用的错误码,服务器发生了什么错误,我们并不知道。
-
「501 Not Implemented」表示客户端请求的功能还不支持,类似“即将开业,敬请期待”的意思。
-
「502 Bad Gateway」通常是服务器作为网关或代理时返回的错误码,表示服务器自身工作正常,访问后端服务器发生了错误。
-
「503 Service Unavailable」表示服务器当前很忙,暂时无法响应客户端,类似“网络服务正忙,请稍后重试”的意思。
常见字段:
- host:指定服务器的域名
- Content-Length:表明本次回应的数据长度
- Connection :(Keep-Alive)
- Content-Type:用于服务器回应时,告诉客户端,本次数据是什么格式
- Content-Encoding:数据的压缩方法
GET(从服务器获取指定的资源) 和 POST 请求(根据请求负荷(报文 body)对指定的资源做出处理)
HTTP 缓存
HTTP 缓存:
- 强制缓存:
- Cache-Control,是一个相对时间(建议), Expires,是一个绝对时间;
- 当浏览器第一次请求访问服务器资源时,服务器会在返回这个资源的同时,在 Response 头部加上 Cache-Control,Cache-Control 中设置了过期时间大小;
- 浏览器再次请求访问服务器中的该资源时,会先通过请求资源的时间与 Cache-Control 中设置的过期时间大小,来计算出该资源是否过期,如果没有,则使用该缓存,否则重新请求服务器;
- 服务器再次收到请求后,会再次更新 Response 头部的 Cache-Control。
- 同时有,则 Cache-Control 的优先级高于 Expires
- Cache-Control,是一个相对时间(建议), Expires,是一个绝对时间;
- 协商缓存:协商缓存就是与服务端协商之后,通过协商结果来判断是否使用本地缓存。
- 请求头部中的
If-Modified-Since
字段与响应头部中的Last-Modified
字段实现- 如果
Last-Modified
更新,则说明资源被修改过了,返回最新资源 - 否则说明没有修改,响应 HTTP 304 走缓存。
- 如果
- 请求头部中的
If-None-Match
字段与响应头部中的ETag
字段(唯一标识)- 当资源过期时,浏览器发现响应头里有 Etag,则再次向服务器发起请求时,会将请求头 If-None-Match 值设置为 Etag 的值。服务器收到请求后进行比对,如果资源没有变化返回 304,如果资源变化了返回 200。
- 请求头部中的
相对来说后者可以更加准确地判断文件内容是否被修改,避免由于时间篡改导致的不可靠问题。
HTTP 特性
HTTP 特性:( HTTP/1.1,HTTP/2.0,HTTP/3.0)
- HTTP/1.1
- 简单
- 灵活和易于扩展
- 应用广泛和跨平台
- 无状态双刃剑:
- 能减轻服务器的负担,能够把更多的 CPU 和内存用来对外提供服务
- 在完成有关联性的操作时会非常麻烦(购物时每次都会确认身份),使用 cookie 技术可以解决这个问题(即相当于,在客户端第一次请求后,服务器会下发一个装有客户信息的「小贴纸」,后续客户端请求服务器的时候,带上「小贴纸」,服务器就能认得了了)
- 明文传输双刃剑:明文意味着方便,但信息很容易被窃取
- 不安全:可以通过 https 来解决(引入 SSL/TLS 层)
- 性能:(一般般)
- 长连接:只要任意一端没有明确提出断开连接,则保持 TCP 连接状态。减少了 TCP 连接的重复建立和断开所造成的额外开销,减轻了服务器端的负载
- 管道网络传输:
- 可在同一个 TCP 连接里面,客户端可以发起多个请求
- 只要第一个请求发出去了,不必等其回来,就可以发第二个请求出去,可以减少整体的响应时间(),但服务器必须按照接收请求的顺序发送对这些管道化请求的响应。(即如果在处理某任务堵住了,则后面的都会被堵住【队头堵塞】)
- 管道化技术不是默认开启,而且浏览器基本都没有支持(知道有这个东西即可)
HTTP1.1 相比 HTTP1.0:
性能改进:
- 使用长连接的方式改善了 HTTP/1.0 短连接造成的性能开销。
- 支持管道(pipeline)网络传输,只要第一个请求发出去了,不必等其回来,就可以发第二个请求出去,可以减少整体的响应时间。
缺点:
- 请求 / 响应头部(Header)未经压缩就发送,首部信息越多延迟越大。只能压缩 Body 的部分;
- 发送冗长的首部。每次互相发送相同的首部造成的浪费较多;
- 服务器是按请求的顺序响应的,如果服务器响应慢,会招致客户端一直请求不到数据,也就是队头阻塞;
- 没有请求优先级控制;
- 请求只能从客户端开始,服务器只能被动响应。
HTTP2 相比 HTTP1.1
HTTP/2 协议是基于 HTTPS 的,所以 HTTP/2 的安全性也是有保障的。
性能改进:
- 头部压缩
- 如果你同时发出多个请求,他们的头是一样的或是相似的,那么,协议会帮你消除重复的部分。
- 二进制格式
- 全面采用了二进制格式,头信息和数据体都是二进制,并且统称为帧(frame):头信息帧(Headers Frame)和数据帧(Data Frame),这样计算机无需解析报文,增加传输效率
- 并发传输
- 引出了 Stream 概念,多个 Stream 复用在一条 TCP 连接。
- 针对不同的 HTTP 请求用独一无二的 Stream ID 来区分,接收端可以通过 Stream ID 有序组装成 HTTP 消息,不同 Stream 的帧是可以乱序发送的,因此可以并发不同的 Stream ,也就是 HTTP/2 可以并行交错地发送请求和响应。
- 服务器主动推送资源
- 服务端不再是被动地响应,可以主动向客户端发送消息。
HPACK 算法:在客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。
缺点:
- 虽然 HTTP/2 通过 Stream 的并发能力,解决了 HTTP/1 队头阻塞的问题,但是 HTTP/2 还是存在“队头阻塞”的问题,只不过问题不是在 HTTP 这一层面,而是在 TCP 这一层 。一旦发生了丢包现象,就会触发 TCP 的重传机制,这样在一个 TCP 连接中的所有的 HTTP 请求都必须等待这个丢了的包被重传回来。
HTTP3.0 的优化
特点:
- 无队头阻塞
- QUIC 有自己的一套机制可以保证传输的可靠性的。当某个流发生丢包时,只会阻塞这个流,其他流不会受到影响,因此不存在队头阻塞问题。
- 更快的连接建立
- HTTP/3 的 QUIC 协议并不是与 TLS 分层,而是 QUIC 内部包含了 TLS,它在自己的帧会携带 TLS 里的“记录”,再加上 QUIC 使用的是 TLS/1.3,因此仅需 1 个 RTT 就可以「同时」完成建立连接与密钥协商
- 连接迁移
- 通过连接 ID 来标记通信的两个端点,客户端和服务器可以各自选择一组 ID 来标记自己,因此即使移动设备的网络变化后,导致 IP 地址变化了,只要仍保有上下文信息(比如连接 ID、TLS 密钥等),就可以“无缝”地复用原连接,消除重连的成本,没有丝毫卡顿感
HTTP1.1 如何优化
提升性能的方式
- 尽量避免发送 HTTP 请求;
- 缓存,对于一些具有重复性的 HTTP 请求,可以把这对「请求-响应」的数据都缓存在本地,那么下次就直接读取本地的数据
- 如何缓存?
- 将请求的 URL 作为 key,而响应作为 value,两者形成映射关系。后续发起相同的请求时,通过 key 查找 value 即可
- 缓存一致性?
- 服务器在发送 HTTP 响应时,会估算一个过期的时间,一旦发现缓存的响应是过期的,则就会重新发送网络请求。
- 在请求的 Etag 头部带上第一次请求的响应头部中的摘要,这个摘要是唯一标识响应的资源,当服务器收到请求后,会将本地资源的摘要与请求中的摘要做个比较。
- 若相同,返回不含有包体的 304 Not Modified 响应,告诉客户端仍然有效
- 若不同,说明客户端的缓存已经没有价值,服务器在响应中带上最新的资源。
- 在需要发送 HTTP 请求时,考虑如何减少请求次数;
- 减少重定向请求次数;资源转移之后,可能需要多次发起 HTTP 请求
- 重定向的工作交由代理服务器完成,就能减少 HTTP 请求次数了
- 当代理服务器知晓了重定向规则后,可以进一步减少消息传递次数
- 合并请求:把多个访问小文件的请求合并成一个大的请求,虽然传输的总资源还是一样,但是减少请求,也就意味着减少了重复发送的 HTTP 头部
- 带来新的问题,当大资源中的某一个小资源发生变化后,客户端必须重新下载整个完整的大资源文件,带来了额外的开销
- 延迟发送请求:当前不需要的资源,我们没必要也获取过来,于是可以通过「按需获取」的方式,来减少第一时间的 HTTP 请求次数
- 减少重定向请求次数;资源转移之后,可能需要多次发起 HTTP 请求
- 减少服务器的 HTTP 响应的数据大小;
- 无损压缩;
- 有损压缩
HTTPS
与 HTTP 的区别:
- HTTPS 在 TCP 和 HTTP 网络层之间加入了 SSL/TLS 安全协议,使得报文能够加密传输。
- 对于连接的建立:HTTPS 在 TCP 三次握手之后,还需进行 SSL/TLS 的握手过程,才可进入加密报文传输。
- HTTP 默认端口号是 80,HTTPS 默认端口号是 443。
- HTTPS 协议需要向 CA(证书权威机构)申请数字证书,来保证服务器的身份是可信的。
解决"不安全"的方式:
- 混合加密:保证信息的机密性,解决了窃听的风险。
- 对称加密和非对称加密结合的「混合加密」方式
- 在通信建立前采用非对称加密的方式交换「会话秘钥」,后续就不再使用非对称加密。
- 在通信过程中全部使用对称加密的「会话秘钥」的方式加密明文数据。、
- 对称加密和非对称加密结合的「混合加密」方式
- 摘要算法 + 数字签名
- 为了确保传输内容不被篡改,发送方会计算内容的哈希值,作为内容的「指纹」并一同发送。接收方对内容再计算哈希值并与发送方的「指纹」进行比较,如果匹配则表明内容未被篡改。然而,这种方式无法保证「内容 + 哈希值」没有被中间人篡改,因此需要引入非对称加密算法以确认消息的真实来源。
- 非对称加密使用一对密钥:公钥(可公开)和私钥(由个人保管)。公钥用于加密内容,私钥用于解密,实现了内容的保密;反之,私钥加密后,用公钥解密,可以验证消息的来源,因为只有持有私钥的人能生成该签名。这种机制通常用于数字签名,其中私钥会对内容的哈希值进行加密,确认消息身份。
- 借助数字签名,父母可以用私钥「签名」请假条,老师用公钥验证签名,确保请假条的真实性,从而防止冒充。
- 数字证书:防止"我"请假偷偷伪造公钥
- 家长把他的公钥注册到警察局,警察局用他们自己的私钥对你父亲的公钥做了个数字签名,然后把你爸爸的「个人信息 + 公钥 + 数字签名」打包成一个数字证书。
- 老师拿到了数字证书后,首先会去警察局验证这个数字证书是否合法,因为数字证书里有警察局的数字签名,警察局要验证证书合法性的时候,用自己的公钥解密,如果能解密成功,就说明这个数字证书是在警察局注册过的,就认为该数字证书是合法的,然后就会把数字证书里头的公钥(你爸爸的)给到老师。
- 于是老师就可以安心的用这个公钥解密出请假条,如果能解密出,就证明是你爸爸写的请假条。
- 权威的机构即 CA(数字证书认证机构)
HTTPS 建立连接过程:
TLS 协议建立的详细流程如下:
-
ClientHello
- 客户端向服务器发起加密通信请求,发送 ClientHello 消息。
- 主要信息包括:
- 支持的 TLS 协议版本(如 TLS 1.2)。
- 客户端生成的随机数(Client Random),用于后续生成会话秘钥。
- 支持的密码套件列表(如 RSA 加密算法)。
-
ServerHello
- 服务器收到请求后,回应 ClientHello,发送 ServerHello 消息。
- 主要内容包括:
- 确认支持的 TLS 协议版本。
- 服务器生成的随机数(Server Random),也用于生成会话秘钥。
- 确认的密码套件列表。
- 服务器的数字证书。
-
客户端回应
- 客户端通过 CA 公钥验证服务器的数字证书。
- 如果证书有效,客户端提取服务器公钥,用其加密以下信息并发送给服务器
- 一个随机数(pre-master key)。
- 加密通信算法改变通知,表示后续信息将使用会话秘钥加密。
- 客户端握手结束通知,连同数据摘要供服务器校验。
- 三个随机数(Client Random、Server Random、pre-master key)用于生成会话秘钥。
-
服务器的最后回应
- 服务器用协商的加密算法计算会话秘钥。
- 向客户端发送最后的信息:
- 加密通信算法改变通知。
- 服务器握手结束通知,连同数据摘要供客户端校验。
整个 TLS 握手结束后,客户端与服务器开始使用会话秘钥进行加密通信,内容以普通 HTTP 协议方式传输。
数字证书签发和验证流程:
如何保证数据完整性?
分为握手协议和记录协议两层:
- TLS 握手协议就是我们前面说的 TLS 四次握手的过程,负责协商加密算法和生成对称密钥,后续用此密钥来保护应用程序数据(即 HTTP 数据);
- TLS 记录协议负责保护应用程序数据并验证其完整性和来源,所以对 HTTP 数据加密是使用记录协议;
具体过程如下:
- 首先,消息被分割成多个较短的片段,然后分别对每个片段进行压缩。
- 接下来,经过压缩的片段会被加上消息认证码(MAC 值,这个是通过哈希算法生成的),这是为了保证完整性,并进行数据的认证。通过附加消息认证码的 MAC 值,可以识别出篡改。与此同时,为了防止重放攻击,在计算消息认证码时,还加上了片段的编码。
- 再接下来,经过压缩的片段再加上消息认证码会一起通过对称密码进行加密。
- 最后,上述经过加密的数据再加上由数据类型、版本号、压缩后的长度组成的报头就是最终的报文数据。
记录协议完成后,最终的报文数据将传递到传输控制协议 (TCP) 层进行传输。
HTTPS 一定可靠吗?
HTTPS 协议本身到目前为止还是没有任何漏洞的,即使你成功进行中间人攻击,本质上是利用了客户端的漏洞(用户点击继续访问或者被恶意导入伪造的根证书),并不是 HTTPS 不够安全。
客户端通过浏览器向服务端发起 HTTPS 请求时,被「假基站」转发到了一个「中间人服务器」,于是客户端是和「中间人服务器」完成了 TLS 握手,然后这个「中间人服务器」再与真正的服务端完成 TLS 握手。
从客户端的角度看,其实并不知道网络中存在中间人服务器这个角色。那么中间人就可以解开浏览器发起的 HTTPS 请求里的数据,也可以解开服务端响应给浏览器的 HTTPS 响应数据。相当于,中间人能够 “偷看” 浏览器与服务端之间的 HTTPS 请求和响应的数据。
CA 被攻破或错误签发证书时(或电脑中病毒,被恶意导入了中间人的根证书),这种情况下,浏览器是不会弹出证书存在问题的风险提醒的。
抓包工具如何截取 Https 数据?
使用抓包工具进行 HTTPS 抓包的时候,需要在客户端安装 Fiddler 的根证书,这里实际上起认证中心(CA)的作用。
抓包工具能够抓包的关键是客户端会往系统受信任的根证书列表中导入抓包工具生成的证书,而这个证书会被浏览器信任,也就是抓包工具给自己创建了一个认证中心 CA,客户端拿着中间人签发的证书去中间人自己的 CA 去认证,当然认为这个证书是有效的。
如何避免被截取数据?
*不去点击非法网站即可*
通过 HTTPS 双向认证来避免这种问题.
一般我们的 HTTPS 是单向认证,客户端只会验证了服务端的身份,但是服务端并不会验证客户端的身份。
如果用了双向认证方式,不仅客户端会验证服务端的身份,而且服务端也会验证客户端的身份。服务端一旦验证到请求自己的客户端为不可信任的,服务端就拒绝继续通信,客户端如果发现服务端为不可信任的,那么也中止通信。