一、网络层划分
1. OSI七层模型(理论模型)
7. 应用层 - HTTP、FTP、SMTP(用户接口)
6. 表示层 - 数据加密、压缩(数据表示)
5. 会话层 - 建立和管理会话(对话控制)
4. 传输层 - TCP、UDP(端到端连接)
3. 网络层 - IP、路由器(寻址和路由)
2. 数据链路层 - 交换机、MAC(帧传输)
1. 物理层 - 网线、光纤(比特流传输)
2. TCP/IP四层模型(实际应用)
4. 应用层 - HTTP、FTP、DNS、SMTP
3. 传输层 - TCP、UDP
2. 网络层 - IP、ICMP
1. 网络接口层 - Ethernet、WiFi
3. 五层模型(教学常用)
5. 应用层 - HTTP、WebSocket、MQTT
4. 传输层 - TCP、UDP
3. 网络层 - IP
2. 数据链路层 - MAC
1. 物理层 - 物理介质
二、TCP三次握手(建立连接)
握手过程:
客户端 → 服务器:SYN=1, seq=x(我要连接)
客户端 ← 服务器:SYN=1, ACK=1, seq=y, ack=x+1(我准备好了)
客户端 → 服务器:ACK=1, seq=x+1, ack=y+1(开始通信)
Swift伪代码理解:
class TCPThreeWayHandshake {
func connect() {
// 第一次握手:客户端发送SYN
print("1. 客户端 → 服务器: SYN=1, seq=100")
// 含义:我想连接,我的初始序列号是100
// 第二次握手:服务器回应SYN-ACK
print("2. 客户端 ← 服务器: SYN=1, ACK=1, seq=300, ack=101")
// 含义:我同意连接,我的序列号是300,确认收到你的100(期待101)
// 第三次握手:客户端发送ACK
print("3. 客户端 → 服务器: ACK=1, seq=101, ack=301")
// 含义:确认收到你的300(期待301),可以开始传输了
}
}
为什么需要三次?
- 第一次:客户端证明自己能发送
- 第二次:服务器证明自己能收发
- 第三次:客户端证明自己能接收
- 防止旧的重复连接:确保双方都具备收发能力
三、TCP四次挥手(断开连接)
挥手过程:
客户端 → 服务器:FIN=1, seq=u(我要断开)
客户端 ← 服务器:ACK=1, seq=v, ack=u+1(知道了)
客户端 ← 服务器:FIN=1, ACK=1, seq=w, ack=u+1(我也要断开)
客户端 → 服务器:ACK=1, seq=u+1, ack=w+1(好的,断开)
Swift伪代码理解:
class TCPFourWayWave {
func disconnect() {
// 第一次挥手:主动方发送FIN
print("1. 客户端 → 服务器: FIN=1, seq=500")
// 含义:我没有数据要发送了,想断开连接
// 第二次挥手:被动方发送ACK
print("2. 客户端 ← 服务器: ACK=1, seq=700, ack=501")
// 含义:我知道你要断开了,但我可能还有数据要发送
// 第三次挥手:被动方发送FIN
print("3. 客户端 ← 服务器: FIN=1, ACK=1, seq=700, ack=501")
// 含义:我也没有数据要发送了,同意断开
// 第四次挥手:主动方发送ACK
print("4. 客户端 → 服务器: ACK=1, seq=501, ack=701")
// 含义:我知道你也要断开了,确认断开
}
}
为什么需要四次?
- TCP是全双工的,每个方向需要单独关闭
- 第二次和第三次挥手不能合并:服务器可能还有数据要发送
- 确保数据完整传输,避免数据丢失
四、状态变化
三次握手状态:
客户端:CLOSED → SYN-SENT → ESTABLISHED
服务器:CLOSED → LISTEN → SYN-RECEIVED → ESTABLISHED
四次挥手状态:
主动方:ESTABLISHED → FIN-WAIT-1 → FIN-WAIT-2 → TIME-WAIT → CLOSED
被动方:ESTABLISHED → CLOSE-WAIT → LAST-ACK → CLOSED
五、实际应用示例
iOS中的体现:
// URLSession底层使用TCP
let task = URLSession.shared.dataTask(with: url) { data, response, error in
// 在发起请求时:三次握手建立连接
// 在收到响应后:四次挥手断开连接(HTTP/1.1 Keep-Alive可能复用)
}
// WebSocket连接
let webSocket = WebSocket(request: request)
webSocket.connect() // 触发三次握手
webSocket.disconnect() // 触发四次挥手
六、关键要点总结
三次握手核心:
- ✅ 确认双方的发送和接收能力
- ✅ 协商初始序列号
- ✅ 防止历史连接混淆
四次挥手核心:
- ✅ 全双工通信需要双向关闭
- ✅ 确保数据完全传输
- ✅ TIME-WAIT状态防止旧包混淆
网络层核心:
- 传输层:负责端到端通信(TCP/UDP)
- 网络层:负责主机到主机通信(IP)
- 应用层:面向用户的具体协议(HTTP/WebSocket等)
好的,这是一个非常基础的网络面试题,但回答时如果能深入一些底层原理,会大大加分。以下是 HTTP 和 HTTPS 的区别,从浅到深的解释。
一句话总结
HTTP 是明文传输的,如同寄送明信片,路上谁都能看。HTTPS 是加密传输的,如同寄送密封的信件,只有收件人能打开。
核心区别对比表
| 特性 | HTTP | HTTPS |
|---|---|---|
| 全称 | HyperText Transfer Protocol | HyperText Transfer Protocol Secure |
| 默认端口 | 80 | 443 |
| 协议层次 | 应用层协议 | HTTP + SSL/TLS 加密层 |
| 数据传输 | 明文,未加密 | 加密,密文传输 |
| 安全性 | 低,易被窃听、篡改、冒充 | 高,能有效防止上述攻击 |
| 证书 | 不需要 | 需要由权威机构颁发的 SSL 证书 |
| SEO | 搜索引擎排名不利 | 搜索引擎(如Google)给予排名优先 |
| 性能 | 较快,无加密开销 | 稍慢,有加密解密的计算开销 |
| 数据完整性 | 无法保证数据未被篡改 | 可验证数据在传输过程中是否被篡改 |
HTTP 和 HTTPS 的区别
1. 安全性:明文 vs 加密
这是最根本的区别。
-
HTTP:所有数据(包括用户名、密码、信用卡号、聊天内容)都以明文形式在网络中传输。任何一个在传输路径上的中间节点(路由器、交换机)或攻击者(通过ARP欺骗、Wi-Fi嗅探)都可以轻松截获并查看这些数据。
- 风险:窃听、数据泄露。
-
HTTPS:在 HTTP 和 TCP 之间加入了一个 SSL/TLS 加密层。所有数据在发送前都会加密,接收方再解密。即使数据被截获,攻击者看到的也是一堆无规律的乱码。
- 优势:保密性。
2. 身份认证:如何证明你是你?
-
HTTP:无法确认你正在通信的服务器就是你以为的那个服务器。攻击者可以架设一个假的网站来冒充你的银行官网,这就是 “中间人攻击”。
- 风险:冒充、网络钓鱼。
-
HTTPS:服务器必须向客户端(浏览器)提供一个 SSL 证书。这个证书由受信任的证书颁发机构 签发,类似于一个由政府颁发的护照。浏览器会验证这个证书:
- 是否由可信的CA签发?
- 是否在有效期内?
- 证书中的域名是否与正在访问的域名一致? 如果验证失败,浏览器会给出明显的安全警告。
- 优势:身份认证,确保你连接的是正确的服务器。
3. 数据完整性:数据是否被篡改?
-
HTTP:无法保证数据在传输过程中没有被恶意篡改。攻击者可以修改传输中的内容,比如将“向A账户转账100元”改成“向B账户转账10000元”。
- 风险:篡改。
-
HTTPS:利用加密和摘要算法,能够检测出数据是否在传输过程中被修改。如果接收方解密后验证失败,则会丢弃该数据包。
- 优势:完整性校验。
HTTPS 的工作原理(SSL/TLS 握手简化版)
理解这个流程能让你在面试中脱颖而出。它主要解决了如何安全地协商出同一个加密密钥的问题。
- Client Hello:客户端(浏览器)向服务器发送请求,包含支持的 SSL/TLS 版本、加密算法列表和一个随机数。
- Server Hello:服务器回应,确认使用的 SSL/TLS 版本、加密算法,并发送自己的SSL证书和另一个随机数。
- 验证证书:客户端验证服务器的证书是否合法、可信。
- 生成预主密钥:客户端验证通过后,会生成第三个随机数,称为“预主密钥”,并用证书中的公钥加密后发送给服务器。
- 生成会话密钥:服务器用自己的私钥解密,得到预主密钥。此时,客户端和服务器都拥有了三个随机数,双方使用相同的算法生成本次会话的对称加密密钥。
- 安全通信:握手完成,双方使用这个对称密钥进行快速的加密和解密通信。
为什么用非对称加密传递对称密钥?
- 非对称加密(公钥/私钥)计算复杂,速度慢,但适合安全地交换密钥。
- 对称加密(共享密钥)计算简单,速度快,适合加密大量数据。
- HTTPS 结合了两者优点:用非对称加密来安全地协商对称密钥,然后用对称密钥来加密实际传输的数据。
“HTTP 和 HTTPS 最核心的区别在于安全性。
-
HTTP 是明文传输的,像寄明信片,存在窃听、篡改和冒充三大风险。而 HTTPS 在 HTTP 下层加入了 SSL/TLS 协议,通过加密、身份认证和完整性校验解决了这三大问题。
-
具体来说,加密是通过混合加密机制实现的,即用非对称加密来安全交换对称加密的密钥,再用对称密钥加密数据,兼顾了安全性和性能。
-
身份认证是通过 SSL 证书实现的,确保我连接的是真正的服务器,而不是钓鱼网站。
这是一个非常好的问题,它触及了网络安全实践中的一个核心概念。你能抓到包,恰恰证明了你对工具的使用,而理解其原理则更加重要。
简单直接的答案是:当你用 Charles 成功抓到 HTTPS 的明文数据时,并不是 HTTPS 被破解了,而是你主动地、有意地在自己控制的设备上安装了一个“受信任的”中间人,从而“绕过”了 HTTPS 的证书验证机制。
这个过程就是经典的 中间人攻击,而 Charles 正是在你的授权下扮演了这个“中间人”。
Charles 的工作原理(中间人攻击流程)
让我们通过对比正常流程和 Charles 介入的流程来理解。
场景1:正常的 HTTPS 通信(无 Charles)
sequenceDiagram
participant C as 客户端(App/浏览器)
participant S as 服务器(比如 api.example.com)
Note over C, S: TLS 握手
C->>S: Client Hello
S->>C: Server Hello + 服务器的真实证书
Note right of C: 客户端验证证书:<br>1. 是否可信?<br>2. 域名是否匹配?
Note right of C: 验证成功!
C->>S: 用服务器公钥加密“预主密钥”
S->>C: 握手完成,开始加密通信
Note over C, S: 加密通信
C->>S: 加密后的请求
S->>C: 加密后的响应
- 客户端向服务器发起 HTTPS 连接。
- 服务器返回其真实的、由公共可信 CA(如 DigiCert, Let's Encrypt)签发的 SSL 证书。
- 客户端验证证书:客户端(操作系统或浏览器内的根证书库)检查这张证书是否由它信任的机构签发,并且证书中的域名是否与正在访问的域名匹配。验证通过。
- 生成加密密钥:双方基于 TLS 协议安全地协商出后续通信的对称加密密钥。
- 安全通信:此后所有的数据传输都使用这个密钥进行加密,第三方无法解密。
场景2:Charles 抓包时的 HTTPS 通信(中间人模式)
sequenceDiagram
participant C as 客户端(App/浏览器)
participant M as 中间人(Charles)
participant S as 服务器(比如 api.example.com)
Note over C, S: Charles 设置代理,所有流量先经过 Charles
C->>M: 想要连接 api.example.com
M->>S: 转发客户端的连接请求
S->>M: 返回服务器的真实证书
M->>C: 拦截服务器的证书,返回Charles自己生成的证书(伪造成api.example.com)
Note right of C: 客户端验证证书:<br>1. 是否可信? -> 失败!<br>(除非你安装了Charles的根证书)
Note right of C: 用户手动信任了Charles的根证书,所以验证“通过”。
C->>M: 用Charles的公钥加密“预主密钥”
M->>C: 握手完成(与客户端)
M->>S: 用服务器的公钥加密“预主密钥”
S->>M: 握手完成(与服务器)
Note over C, M: 加密通信 (密钥K1)
Note over M, S: 加密通信 (密钥K2)
C->>M: 用密钥K1加密的请求
M->>C: 用密钥K1加密的响应
Note over M: 关键一步:Charles用密钥K1解密,<br>得到明文,展示给你看,<br>然后用密钥K2重新加密,发给服务器。
M->>S: 用密钥K2加密的请求
S->>M: 用密钥K2加密的响应
- 设置代理:你将设备的网络代理设置为 Charles 的电脑。此时,设备的所有网络请求都会先发给 Charles。
- 客户端发起连接:客户端(你的 App)想要连接
api.example.com。 - Charles 拦截并“冒充”服务器:
- Charles 接收到客户端的请求后,会以自己的名义向真正的
api.example.com建立一个新的 HTTPS 连接。 - 当服务器将其真实证书发给 Charles 时,Charles 不会把这个证书原样传给客户端。相反,它会动态生成一个伪造的证书,这个证书的域名是
api.example.com,但签发者却是 Charles 自己的根证书。
- Charles 接收到客户端的请求后,会以自己的名义向真正的
- 客户端的验证(关键步骤!):
- 客户端收到了这张伪造的证书。它进行验证:“这张证书的签发者(Charles)是我信任的吗?”
- 默认情况下,答案是否定的,连接会中断,你会在客户端看到 SSL 错误警告。
- 但是,你手动在设备的信任证书库中安装了 Charles 的根证书。这意味着你明确地告诉设备:“我信任 Charles 这个证书颁发机构”。
- 因此,客户端验证“通过”了。它以为自己在和
api.example.com通信,而实际上是在和 Charles 通信。
- 建立两条加密连接:
- 连接 A:客户端 ⇄ Charles (使用密钥 K1 加密)
- 连接 B:Charles ⇄ 真实服务器 (使用密钥 K2 加密)
- Charles 的解密与展示:
- Charles 坐在中间,对客户端来说它是“服务器”,对服务器来说它是“客户端”。
- 当客户端发送用 K1 加密的请求时,Charles 用自己的私钥解密,得到明文,并将其展示在界面上给你看。
- 然后,Charles 再将这个明文请求用 K2 加密,转发给真实的服务器。
- 服务器的响应也经历同样的过程:Charles 用 K2 解密,得到明文,展示给你,再用 K1 加密返回给客户端。
这对 App 安全开发的启示
正因为有 Charles 这样的工具,所以 App 的安全不能仅仅依赖于标准的 HTTPS。必须采取额外措施:
1. SSL Pinning(证书绑定)
这是最有效的防御中间人攻击的手段。
- 原理:App 不信任操作系统内置的根证书列表,而是只信任它自己“认识”的特定证书或公钥。具体做法是,将服务器证书(或公钥)内置到 App 的代码或资源文件中。
- 流程:当建立 HTTPS 连接时,App 会将服务器返回的证书与本地内置的证书进行比较。如果一致,则通过;如果不一致(比如是 Charles 签发的伪造证书),则立即终止连接。
- 效果:即使手机上安装了 Charles 的根证书,SSL Pinning 也会使连接失败,从而无法解密流量。
2. 防止代理设置
App 可以检测当前网络是否设置了代理,如果检测到代理,可以拒绝发送敏感数据或直接退出。
“Charles 能抓到 HTTPS 明文,并不是因为 HTTPS 不安全,而是因为它实施了一次受用户授权的中间人攻击。关键步骤在于:
- 我在设备上安装了 Charles 的根证书,相当于单方面授权它成为我信任的证书颁发机构。
- 当 App 发起请求时,Charles 会拦截并返回一个它自己签发的、伪造成目标域名的证书。
- 由于我的设备信任 Charles 的根证书,所以它错误地‘验证通过’了这张伪造证书。
- 这样,Charles 就成功地介入了 App 与服务器之间,建立了两条独立的 HTTPS 连接,并在中间进行实时解密和加密,从而让我看到了明文。
这也解释了为什么像证券、银行这类高安全要求的 App 会采用 SSL Pinning(证书绑定) 技术,它将服务器证书直接内置在 App 里,完全绕过了系统的证书链验证,从而有效防御了这类工具抓包。”