网络基础

153 阅读21分钟

一、网络层划分

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-2TIME-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 是加密传输的,如同寄送密封的信件,只有收件人能打开。


核心区别对比表

特性HTTPHTTPS
全称HyperText Transfer ProtocolHyperText Transfer Protocol Secure
默认端口80443
协议层次应用层协议HTTP + SSL/TLS 加密层
数据传输明文,未加密加密,密文传输
安全性低,易被窃听、篡改、冒充高,能有效防止上述攻击
证书不需要需要由权威机构颁发的 SSL 证书
SEO搜索引擎排名不利搜索引擎(如Google)给予排名优先
性能较快,无加密开销稍慢,有加密解密的计算开销
数据完整性无法保证数据未被篡改可验证数据在传输过程中是否被篡改

HTTP 和 HTTPS 的区别

1. 安全性:明文 vs 加密

这是最根本的区别。

  • HTTP:所有数据(包括用户名、密码、信用卡号、聊天内容)都以明文形式在网络中传输。任何一个在传输路径上的中间节点(路由器、交换机)或攻击者(通过ARP欺骗、Wi-Fi嗅探)都可以轻松截获并查看这些数据。

    • 风险窃听数据泄露
  • HTTPS:在 HTTP 和 TCP 之间加入了一个 SSL/TLS 加密层。所有数据在发送前都会加密,接收方再解密。即使数据被截获,攻击者看到的也是一堆无规律的乱码。

    • 优势保密性

2. 身份认证:如何证明你是你?

  • HTTP:无法确认你正在通信的服务器就是你以为的那个服务器。攻击者可以架设一个假的网站来冒充你的银行官网,这就是 “中间人攻击”

    • 风险冒充网络钓鱼
  • HTTPS:服务器必须向客户端(浏览器)提供一个 SSL 证书。这个证书由受信任的证书颁发机构 签发,类似于一个由政府颁发的护照。浏览器会验证这个证书:

    1. 是否由可信的CA签发?
    2. 是否在有效期内?
    3. 证书中的域名是否与正在访问的域名一致? 如果验证失败,浏览器会给出明显的安全警告。
    • 优势身份认证,确保你连接的是正确的服务器。

3. 数据完整性:数据是否被篡改?

  • HTTP:无法保证数据在传输过程中没有被恶意篡改。攻击者可以修改传输中的内容,比如将“向A账户转账100元”改成“向B账户转账10000元”。

    • 风险篡改
  • HTTPS:利用加密和摘要算法,能够检测出数据是否在传输过程中被修改。如果接收方解密后验证失败,则会丢弃该数据包。

    • 优势完整性校验

HTTPS 的工作原理(SSL/TLS 握手简化版)

理解这个流程能让你在面试中脱颖而出。它主要解决了如何安全地协商出同一个加密密钥的问题。

  1. Client Hello:客户端(浏览器)向服务器发送请求,包含支持的 SSL/TLS 版本、加密算法列表和一个随机数。
  2. Server Hello:服务器回应,确认使用的 SSL/TLS 版本、加密算法,并发送自己的SSL证书和另一个随机数。
  3. 验证证书:客户端验证服务器的证书是否合法、可信。
  4. 生成预主密钥:客户端验证通过后,会生成第三个随机数,称为“预主密钥”,并用证书中的公钥加密后发送给服务器。
  5. 生成会话密钥:服务器用自己的私钥解密,得到预主密钥。此时,客户端和服务器都拥有了三个随机数,双方使用相同的算法生成本次会话的对称加密密钥
  6. 安全通信:握手完成,双方使用这个对称密钥进行快速的加密和解密通信。

为什么用非对称加密传递对称密钥?

  • 非对称加密(公钥/私钥)计算复杂,速度慢,但适合安全地交换密钥。
  • 对称加密(共享密钥)计算简单,速度快,适合加密大量数据。
  • HTTPS 结合了两者优点:用非对称加密来安全地协商对称密钥,然后用对称密钥来加密实际传输的数据。

“HTTP 和 HTTPS 最核心的区别在于安全性

  1. HTTP 是明文传输的,像寄明信片,存在窃听、篡改和冒充三大风险。而 HTTPS 在 HTTP 下层加入了 SSL/TLS 协议,通过加密、身份认证和完整性校验解决了这三大问题。

  2. 具体来说,加密是通过混合加密机制实现的,即用非对称加密来安全交换对称加密的密钥,再用对称密钥加密数据,兼顾了安全性和性能。

  3. 身份认证是通过 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: 加密后的响应
  1. 客户端向服务器发起 HTTPS 连接
  2. 服务器返回其真实的、由公共可信 CA(如 DigiCert, Let's Encrypt)签发的 SSL 证书
  3. 客户端验证证书:客户端(操作系统或浏览器内的根证书库)检查这张证书是否由它信任的机构签发,并且证书中的域名是否与正在访问的域名匹配。验证通过
  4. 生成加密密钥:双方基于 TLS 协议安全地协商出后续通信的对称加密密钥。
  5. 安全通信:此后所有的数据传输都使用这个密钥进行加密,第三方无法解密。

场景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加密的响应
  1. 设置代理:你将设备的网络代理设置为 Charles 的电脑。此时,设备的所有网络请求都会先发给 Charles。
  2. 客户端发起连接:客户端(你的 App)想要连接 api.example.com
  3. Charles 拦截并“冒充”服务器
    • Charles 接收到客户端的请求后,会以自己的名义向真正的 api.example.com 建立一个新的 HTTPS 连接。
    • 当服务器将其真实证书发给 Charles 时,Charles 不会把这个证书原样传给客户端。相反,它会动态生成一个伪造的证书,这个证书的域名是 api.example.com,但签发者却是 Charles 自己的根证书
  4. 客户端的验证(关键步骤!)
    • 客户端收到了这张伪造的证书。它进行验证:“这张证书的签发者(Charles)是我信任的吗?”
    • 默认情况下,答案是否定的,连接会中断,你会在客户端看到 SSL 错误警告。
    • 但是,你手动在设备的信任证书库中安装了 Charles 的根证书。这意味着你明确地告诉设备:“我信任 Charles 这个证书颁发机构”。
    • 因此,客户端验证“通过”了。它以为自己在和 api.example.com 通信,而实际上是在和 Charles 通信。
  5. 建立两条加密连接
    • 连接 A:客户端 ⇄ Charles (使用密钥 K1 加密)
    • 连接 B:Charles ⇄ 真实服务器 (使用密钥 K2 加密)
  6. 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 不安全,而是因为它实施了一次受用户授权的中间人攻击。关键步骤在于:

  1. 我在设备上安装了 Charles 的根证书,相当于单方面授权它成为我信任的证书颁发机构。
  2. 当 App 发起请求时,Charles 会拦截并返回一个它自己签发的、伪造成目标域名的证书。
  3. 由于我的设备信任 Charles 的根证书,所以它错误地‘验证通过’了这张伪造证书。
  4. 这样,Charles 就成功地介入了 App 与服务器之间,建立了两条独立的 HTTPS 连接,并在中间进行实时解密和加密,从而让我看到了明文。

这也解释了为什么像证券、银行这类高安全要求的 App 会采用 SSL Pinning(证书绑定) 技术,它将服务器证书直接内置在 App 里,完全绕过了系统的证书链验证,从而有效防御了这类工具抓包。”