模块一:网络理论基础——从一条网线到全球互联网的逐层解构
本模块不追求“背完七层模型去面试”,而是试图回答一个更本质的问题:当我在浏览器里按下回车,数据究竟经历了怎样的旅程? 为此,我们会从 OSI/TCP-IP 的分层思想出发,逐层拆解二层交换、三层路由、Overlay 隧道、TCP/UDP 传输,以及现代交换机的硬件转发流水线。每一部分都会给出报文字节结构、数据流示意图(Mermaid)、可运行的命令或代码示例,并保留原模块的核心知识点,但在深度、广度和工程联系上做了大幅扩展。
学习目标
完成本模块后,你应该能够:
- 准确描述 OSI 七层模型、TCP/IP 四层模型与五层教学模型之间的对应关系,并说明它们各自的使用场景。
- 逐字节解释 Ethernet II、802.1Q VLAN、ARP、IPv4、TCP/UDP 等关键报文格式。
- 用流程图和命令还原一次“主机 A ping 主机 B”的完整数据流,包括 ARP 解析、二层交换、三层路由、VLAN 标签、MTU 分片等细节。
- 清晰解释 VLAN、VxLAN、OSPF、BGP、ECMP 等技术的工作过程、报文交互和典型应用场景。
- 识别并纠正常见面试误区:ARP 的分层归属、OSI 七层与五层混淆、VLAN 与 IP 的关系、TLS 的层级位置等。
- 在 Linux 环境下独立完成 ARP 抓包、VLAN/VxLAN 接口配置、TCP 套接字实验。
1.1 网络为什么要分层?——从“邮递系统”到“协议栈”
计算机网络面对的是异构硬件、不同操作系统、跨越国家甚至大洲的传输介质。如果不做分层,每一次新增一种传输介质或应用协议,都需要重写整个网络系统。分层的核心思想是:每一层只关心自己的输入和输出,向上层提供稳定的服务,把复杂度封装在层内。
用邮递系统做类比:
- 应用层相当于信的内容和格式(情书、账单、合同)。
- 表示层相当于翻译成对方能看懂的语言、装进统一信封。
- 会话层相当于约定是否挂号、是否需要回执。
- 传输层相当于快递公司负责把完整信件送达,丢了补发、乱了排序。
- 网络层相当于邮局分拣,根据收件地址决定信件该走哪条路线。
- 数据链路层相当于同城配送员,根据门牌号把信件送到小区。
- 物理层相当于公路、铁路、飞机航线,只负责运输比特或货车。
当上层数据交给下层时,下层会加上自己的“信封头部”,这就是封装(Encapsulation);到达对端后,从下往上逐层拆掉信封,这就是解封装(Decapsulation)。
1.1.1 OSI 七层模型
OSI(Open Systems Interconnection)七层模型由 ISO 提出,是理论框架,常用于教学和故障分层定位。
| 层级 | 名称 | PDU(协议数据单元) | 核心功能 | 典型协议 / 设备 |
|---|---|---|---|---|
| 7 | 应用层(Application) | 数据(Data) | 为应用程序提供网络服务接口 | HTTP、FTP、SMTP、DNS、SSH |
| 6 | 表示层(Presentation) | 数据(Data) | 数据格式转换、加密解密、压缩编码 | TLS/SSL、JPEG、ASCII、ASN.1 |
| 5 | 会话层(Session) | 数据(Data) | 建立、管理、终止会话,断点续传 | NetBIOS、RPC、SIP |
| 4 | 传输层(Transport) | 段(Segment)/ 报文(Datagram) | 端到端连接、可靠性、流量控制、端口复用 | TCP、UDP、SCTP |
| 3 | 网络层(Network) | 包(Packet) | 逻辑寻址、路由选择、分组转发、差错报告 | IP、ICMP、OSPF、BGP |
| 2 | 数据链路层(Data Link) | 帧(Frame) | 物理寻址(MAC)、帧封装、差错检测、介质访问控制 | Ethernet、ARP、VLAN、交换机 |
| 1 | 物理层(Physical) | 比特(Bit) | 比特流传输、电气/光学/机械特性、编码方式 | 光纤、双绞线、集线器、PHY 芯片 |
关键理解:OSI 七层更多用于教学。真正在互联网上跑的是 TCP/IP 协议族,其层级划分与 OSI 并不严格一一对应,例如 ARP 就“跨”在二、三层之间。
1.1.2 TCP/IP 四层模型
TCP/IP 模型更贴近工程实现,是互联网的事实标准。
| TCP/IP 层级 | 对应 OSI 层级 | 核心协议 | 备注 |
|---|---|---|---|
| 应用层 | 5-7 层 | HTTP、FTP、DNS、SSH、TLS | 将 OSI 的应用、表示、会话合并,强调“端到端应用进程通信” |
| 传输层 | 4 层 | TCP、UDP、SCTP | 提供进程到进程的通信 |
| 网络层 | 3 层 | IP、ICMP、OSPF、BGP | 提供主机到主机的寻址与路由 |
| 网络接口层 | 1-2 层 | Ethernet、ARP、VLAN、Wi-Fi、PPP | 依赖具体链路技术 |
为什么实际工程爱用四层? 因为表示层和会话层在很多协议里并没有独立的协议实现,TLS 虽然承担“表示层”的加密职能,但通常被视为在 TCP 之上、HTTP 之下;SIP/WebSocket 的会话管理也被纳入应用层内部。合并后更简洁。
1.1.3 五层教学模型与七层的关系
国内教材常见的五层模型是 OSI 七层的简化版:
OSI 七层:物理层 → 数据链路层 → 网络层 → 传输层 → 会话层 → 表示层 → 应用层
五层模型:物理层 → 数据链路层 → 网络层 → 传输层 → 应用层五层模型把 OSI 的会话层、表示层、应用层合并为应用层,方便初学者抓重点。但面试中如果明确问“OSI 有几层”,必须回答七层,并逐层背出名称。
1.1.4 一次 HTTP 请求的封装与解封装数据流
假设主机 A 通过 HTTP 访问主机 B,整个过程可以用 Mermaid 表示:
sequenceDiagram
participant App as 浏览器 (应用层)
participant Pres as TLS/HTTP (表示/会话层)
participant Trans as TCP (传输层)
participant Net as IP (网络层)
participant Link as Ethernet (数据链路层)
participant Phy as 物理层
Note over App,Phy: 发送端:逐层封装
App->>Pres: HTTP 请求体
Pres->>Trans: 添加 TLS 记录 / HTTP 头
Trans->>Net: 添加 TCP 头(源/目的端口、序号、标志位)
Net->>Link: 添加 IP 头(源/目的 IP、TTL、协议号)
Link->>Phy: 添加 Ethernet 头(源/目的 MAC、类型) + FCS
Note over Phy,App: 接收端:逐层解封装
Phy->>Link: 校验 FCS,提取 Ethernet 帧
Link->>Net: 根据 Type=0x0800 交给 IPv4
Net->>Trans: 根据 Protocol=6 交给 TCP
Trans->>Pres: 根据端口号 443 交给 TLS/HTTP
Pres->>App: 解密后交给浏览器渲染每一层都会把上一层的数据视为不透明载荷(Payload),只关心自己的头部字段。这种“层间透明”是协议栈能够模块化扩展的关键。
1.1.5 可运行:查看本机协议栈与 MTU
在 Linux 上,可以用以下命令观察链路层和网络层的关键参数:
# 查看接口列表、MTU、MAC 地址、IP 地址
ip addr show
ip link show
# 查看本机路由表(网络层决策结果)
ip route show
# 查看 ARP 缓存(二层地址解析结果)
ip neigh show
# 或者传统命令
arp -a
# 查看监听端口与对应的进程(传输层)
ss -tlnp
# 或者
netstat -tlnp思考题:为什么 ip addr 既能显示 MAC 地址又能显示 IP 地址?因为 MAC 属于数据链路层,IP 属于网络层,Linux 内核在接口结构里同时维护这两类地址。1.2 二层协议详解:从一根网线到交换机的智慧
数据链路层要解决的核心问题是:在同一个广播域内,如何把数据从一台主机的网卡送到另一台主机的网卡? 它不关心 IP 地址,只认 MAC 地址;它还要处理冲突检测、帧边界、差错校验、虚拟局域网隔离等问题。
1.2.1 Ethernet II 帧结构逐字节拆解
Ethernet II(DIX Ethernet)是当今局域网最常见的帧格式。一个标准帧的字节布局如下:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination MAC Address (6 bytes) |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | Source MAC Address (6 bytes) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| EtherType (2 bytes) | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
| Payload (46 - 1500 bytes) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Frame Check Sequence (FCS, 4 bytes) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+字段说明:
| 字段 | 长度 | 含义 |
|---|---|---|
| 目的 MAC | 6 B | 下一跳设备的物理地址,广播为 FF:FF:FF:FF:FF:FF |
| 源 MAC | 6 B | 发送设备的物理地址 |
| EtherType | 2 B | 标识上层协议,例如 0x0800=IPv4、0x0806=ARP、0x86DD=IPv6、0x8100=802.1Q VLAN |
| Payload | 46-1500 B | 上层数据;不足 46 B 时填充(Padding) |
| FCS | 4 B | CRC32 校验序列,覆盖目的 MAC、源 MAC、EtherType、Payload、Padding |
MTU 与帧大小:标准以太网 MTU 为 1500 字节,加上 14 字节头部和 4 字节 FCS,物理线路上最大帧为 1518 字节。如果使用 802.1Q VLAN Tag,头部再增加 4 字节,MTU 仍是 1500,但线路上最大帧变成 1522 字节。
面试常问:MTU 1500 指的是哪一层?答:通常指 IP 层能封装的最大载荷,也就是 Ethernet 帧里 Payload 部分的上限。在 Linux 中 ip link show 看到的 MTU 一般指网络层 MTU。1.2.2 VLAN:把一台交换机逻辑切成多台
VLAN(Virtual LAN,虚拟局域网)通过 802.1Q 标签把物理局域网在二层上划分成多个广播域。没有 VLAN 时,交换机所有端口处于同一个广播域,ARP 广播、DHCP 发现等会泛滥到整网;引入 VLAN 后,不同 VLAN 的流量在二层完全隔离。
802.1Q 标签结构
带 VLAN Tag 的帧会在源 MAC 之后插入 4 字节:
| 目的 MAC (6B) | 源 MAC (6B) | TPID (2B) | TCI (2B) | 类型 (2B) | 数据 | FCS |- TPID(Tag Protocol Identifier):固定
0x8100,表明这是 802.1Q 标签。 TCI(Tag Control Information) 16 位,又分为:
- PCP(Priority Code Point):3 位,802.1p 优先级,用于 QoS。
- DEI(Drop Eligible Indicator):1 位, formerly CFI,用于拥塞时优先丢弃标记。
- VID(VLAN Identifier):12 位,范围
0-4095。0为空标签,1为默认 VLAN,4095保留,可用 VLAN ID 为1-4094。
端口类型:Access、Trunk、Hybrid
| 端口类型 | 发送帧 | 接收未标记帧 | 接收已标记帧 | 典型用途 |
|---|---|---|---|---|
| Access | 剥离 Tag 后发出 | 加入本端口 PVID 的 VLAN | 仅允许与 PVID 相同的 Tag | 连接终端主机 |
| Trunk | 保留 Tag 发出(PVID 对应的 VLAN 可剥离) | 加入 PVID VLAN | 允许指定 VLAN 列表通过 | 交换机之间互联 |
| Hybrid | 可配置哪些 VLAN 带 Tag、哪些剥离 | 加入 PVID VLAN | 允许指定 VLAN 列表通过 | 灵活接入 AP、IP 电话等 |
VLAN 间通信数据流
不同 VLAN 处于不同子网,二层无法直接互通,必须经过三层设备(路由器或三层交换机)。下图展示 PC-A(VLAN10,192.168.10.0/24)访问 PC-B(VLAN20,192.168.20.0/24)的完整流程:
sequenceDiagram
participant PCA as PC-A (VLAN10)
participant SW as L3 Switch
participant PCB as PC-B (VLAN20)
Note over PCA,PCB: 第一步:PCA 通过 ARP 获取网关 MAC
PCA->>SW: ARP Request 广播:谁是 192.168.10.1?
SW->>PCA: ARP Reply:网关 MAC 是 00:00:00:00:0a:01
Note over PCA,PCB: 第二步:PCA 把数据发给 VLAN10 的 SVI 网关
PCA->>SW: Ethernet 帧:目的 MAC=网关,Tag=10,Payload=IP 包(目的 IP=192.168.20.2)
SW->>SW: 解封装二层,查路由表,发现目的网段对应 VLAN20
Note over PCA,PCB: 第三步:三层交换机重新封装二层并转发
SW->>PCB: ARP 解析 PC-B MAC(若未知)<br>Ethernet 帧:目的 MAC=PC-B,Tag=20,Payload=IP 包1.2.3 ARP:IP 地址到 MAC 地址的翻译官
ARP(Address Resolution Protocol)是 IPv4 网络中不可或缺的协议。它的报文直接封装在 Ethernet 帧中,不经过 IP 层封装,但功能上为网络层提供服务。
ARP 报文格式
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Hardware Type (2) | Protocol Type (2) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| HLen (1) | PLen (1) | Operation (2) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sender Hardware Address (SHA, 6 bytes) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sender Protocol Address (SPA, 4 bytes) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Target Hardware Address (THA, 6 bytes) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Target Protocol Address (TPA, 4 bytes) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+字段说明:
| 字段 | 长度 | 含义 |
|---|---|---|
| Hardware Type | 2 B | 链路层类型,Ethernet 为 0x0001 |
| Protocol Type | 2 B | 网络层协议类型,IPv4 为 0x0800 |
| HLen | 1 B | 硬件地址长度,MAC 为 6 |
| PLen | 1 B | 协议地址长度,IPv4 为 4 |
| Operation | 2 B | 1=Request,2=Reply,3=RARP Request,4=RARP Reply |
| SHA | 6 B | 发送方 MAC |
| SPA | 4 B | 发送方 IP |
| THA | 6 B | 目标 MAC,Request 时填 00:00:00:00:00:00 |
| TPA | 4 B | 目标 IP |
ARP 工作过程
sequenceDiagram
participant A as 主机 A (10.0.0.2/24)
participant B as 主机 B (10.0.0.3/24)
A->>A: 发现目标 IP 10.0.0.3 在同一子网,但 ARP 缓存无对应 MAC
A->>B: 广播 ARP Request:谁有 10.0.0.3?
Note right of A: 目的 MAC=FF:FF:FF:FF:FF:FF<br>EtherType=0x0806
B->>B: 收到广播,TPA 匹配自身 IP,更新 ARP 缓存
B->>A: 单播 ARP Reply:10.0.0.3 的 MAC 是 xx:xx:xx:xx:xx:xx
A->>A: 将 10.0.0.3 -> MAC-B 写入 ARP 缓存ARP 的分层归属(面试重点)
- 功能上属于网络层:ARP 为 IP 地址解析 MAC 地址,是 IP 协议族的一部分,RFC 826 将其归为网络层。
- 承载方式上属于数据链路层:ARP 报文不封装在 IP 包中,而是直接放在 Ethernet 帧里,EtherType=
0x0806。 - 面试建议回答:“ARP 是网络层协议,但直接封装在二层帧中工作。”
常见 ARP 变体
| 类型 | 说明 |
|---|---|
| Gratuitous ARP | 主机主动发送 ARP Request,SPA 和 TPA 都是自己的 IP,用于 IP 冲突检测、更新他人 ARP 缓存、VRRP/Keepalived 主备切换 |
| Proxy ARP | 路由器代替目标主机回复 ARP,常用于 NAT、VPN 或某些三层转发场景 |
| RARP | 已淘汰,由 BOOTP/DHCP 替代,用于无盘工作站根据 MAC 获取 IP |
可运行:用 Python + Scapy 发送 ARP 请求
#!/usr/bin/env python3
# 运行前安装:pip install scapy
from scapy.all import ARP, Ether, srp
# 构造 ARP 请求:询问 192.168.1.1 的 MAC
packet = Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(pdst="192.168.1.1")
# 发送并接收应答,超时 2 秒
answered, unanswered = srp(packet, timeout=2, verbose=False)
for sent, received in answered:
print(f"IP: {received.psrc} -> MAC: {received.hwsrc}")如果你不想安装 Scapy,也可以直接用 Linux 命令观察 ARP 过程:
# 清空 ARP 缓存(需要 root)
ip neigh flush all
# 监听 ARP 报文
sudo tcpdump -i any -nn -e arp
# 触发 ARP 请求
ping -c 1 192.168.1.1
# 查看学习到的 ARP 表
ip neigh show1.2.4 NDP:IPv6 世界里的 ARP 替代者
IPv6 不再使用 ARP,而是用 NDP(Neighbor Discovery Protocol,邻居发现协议),它基于 ICMPv6。NDP 不仅负责地址解析,还承担路由器发现、前缀发现、重复地址检测(DAD)等功能。
主要报文类型:
| ICMPv6 类型 | 名称 | 作用 |
|---|---|---|
| 135 | Neighbor Solicitation(NS) | 类似 ARP Request,询问某 IPv6 地址对应的 MAC |
| 136 | Neighbor Advertisement(NA) | 类似 ARP Reply |
| 133 | Router Solicitation(RS) | 主机请求路由器发送前缀信息 |
| 134 | Router Advertisement(RA) | 路由器通告前缀、默认网关、MTU 等 |
| 137 | Redirect | 路由器告诉主机更优下一跳 |
# 查看 IPv6 邻居表(类似 ARP 表)
ip -6 neigh show
# 监听 NDP 报文
sudo tcpdump -i any -nn icmp61.2.5 STP/RSTP:防止二层环路
二层交换机一旦存在物理环路,广播帧会在环路中无限循环,造成广播风暴、MAC 地址表抖动、CPU 飙升。STP(Spanning Tree Protocol,IEEE 802.1D)通过逻辑阻塞冗余端口,保留无环树状拓扑。
STP 关键概念
- BID(Bridge ID):由 2 字节优先级 + 6 字节 MAC 组成,数值最小者当选为根桥(Root Bridge)。
- Root Port:非根桥上到达根桥开销最小的端口。
- Designated Port:每个网段上负责转发流量的端口。
- Blocked Port:被逻辑阻塞的冗余端口,只接收 BPDU,不转发用户流量。
STP 收敛过程
graph TD
A[启动 STP] --> B[选举根桥]
B --> C[非根桥选举 Root Port]
C --> D[每个网段选举 Designated Port]
D --> E[剩余端口进入 Blocking 状态]
E --> F[网络进入无环转发状态]传统 STP 收敛时间长达 30-50 秒(Listening 15s + Learning 15s),对于现代数据中心不可接受。RSTP(Rapid STP,IEEE 802.1w)引入 Alternate/Backup 端口角色和 Proposal/Agreement 机制,收敛时间可缩短到 1 秒以内。
# 在 Linux 网桥上启用 STP/RSTP
sudo brctl stp br0 on
# 或使用 iproute2 管理的 bridge
sudo bridge link set dev eth0 stp_state 1
# 查看网桥 STP 状态
sudo bridge stp show面试延伸
- MSTP(Multiple STP):802.1s,将多个 VLAN 映射到不同生成树实例,实现流量负载分担。
- 环路常见原因:误将交换机两个端口用网线直连、堆叠/链路聚合配置错误、接入小路由器/集线器。
1.3 三层协议详解:从子网到互联网的寻址与路由
网络层的核心使命是:把数据包从源主机经过若干跳路由器送到目的主机。 它不保证可靠性,只负责“尽力而为”的寻址、路由和转发。
1.3.1 IPv4 报文头逐字段解析
IPv4 报文头长度可变,最短 20 字节,最长 60 字节(带选项)。
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| IHL |Type of Service| Total Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identification |Flags| Fragment Offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Time to Live | Protocol | Header Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| 字段 | 长度 | 说明 |
|---|---|---|
| Version | 4 bits | IP 版本,IPv4 为 4 |
| IHL(Header Length) | 4 bits | 头部长度,单位为 4 字节。最小值 5,即 20 字节 |
| TOS / DSCP+ECN | 1 B | 服务类型,前 6 位 DSCP 用于 QoS,后 2 位 ECN 用于显式拥塞通知 |
| Total Length | 2 B | 整个 IP 包(头部 + 数据)的总长度,最大 65535 字节 |
| Identification | 2 B | 分片标识,同一原始包的分片 ID 相同 |
| Flags | 3 bits | DF=Don't Fragment,MF=More Fragments |
| Fragment Offset | 13 bits | 分片在原始数据中的位置,单位 8 字节 |
| TTL | 1 B | 生存时间,每经过一个路由器减 1,到 0 丢弃,防环 |
| Protocol | 1 B | 上层协议,6=TCP,17=UDP,1=ICMP,89=OSPF |
| Header Checksum | 2 B | 只校验 IP 头部,每跳路由器都会重新计算 |
| Source Address | 4 B | 源 IP |
| Destination Address | 4 B | 目的 IP |
IP 分片数据流
当 IP 包大小超过出接口 MTU 且 DF=0 时,路由器会进行分片:
graph LR
A[原始 IP 包 4000B] -->|MTU=1500| R[路由器]
R --> F1[分片1 1480B 数据 Offset=0 MF=1]
R --> F2[分片2 1480B 数据 Offset=185 MF=1]
R --> F3[分片3 1020B 数据 Offset=370 MF=0]分片会增加网络开销和重组复杂度,现代网络通常使用 Path MTU Discovery(PMTUD),发送方设置 DF=1,利用 ICMP "Fragmentation Needed" 探测整条路径的最小 MTU,从而避免中途分片。
1.3.2 IPv6:更大的地址与更简洁的头部
IPv6 头部固定 40 字节,取消了 IHL、Checksum、Identifier/Flags/Fragment Offset(分片由扩展头部或主机完成)。
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| Traffic Class | Flow Label |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Payload Length | Next Header | Hop Limit |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ +
| Source Address |
+ +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ +
| Destination Address |
+ +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| 字段 | 说明 |
|---|---|
| Version | 6 |
| Traffic Class | 类似 IPv4 的 TOS,用于 QoS |
| Flow Label | 20 位,标识同一流,便于路由器做流级别处理 |
| Payload Length | 载荷长度(不含 40 字节基本头部) |
| Next Header | 类似 IPv4 的 Protocol,可以是 TCP/UDP,也可以是扩展头部 |
| Hop Limit | 类似 TTL |
IPv6 不兼容 IPv4,过渡技术包括 双栈(Dual Stack)、隧道(6in4、GRE)、NAT64/DNS64 等。
1.3.3 ICMP:网络的“诊断报告”
ICMP(Internet Control Message Protocol)不是传输层协议,而是网络层的控制与差错报告协议,封装在 IP 包中(Protocol=1)。
常见类型与代码:
| Type | Code | 含义 | 典型场景 |
|---|---|---|---|
| 8 | 0 | Echo Request | ping 请求 |
| 0 | 0 | Echo Reply | ping 应答 |
| 3 | 0 | Network Unreachable | 网络不可达 |
| 3 | 1 | Host Unreachable | 主机不可达 |
| 3 | 3 | Port Unreachable | 端口不可达(Traceroute UDP 模式) |
| 11 | 0 | TTL exceeded in transit | Traceroute 利用此消息识别中间跳 |
| 5 | - | Redirect | 路由器告诉主机更优路由 |
ping 与 traceroute 原理
- ping:发送 ICMP Echo Request,等待 Echo Reply,计算 RTT 和丢包率。
traceroute:
- UDP 模式:发送目的端口递增的 UDP 到高端口,TTL 从 1 开始递增,每跳路由器返回 ICMP Time Exceeded,最终目的主机返回 Port Unreachable。
- ICMP 模式:发送 ICMP Echo Request,同样通过 TTL 递增探测路径。
可运行:用 Python 实现简单 traceroute
#!/usr/bin/env python3
# 需要 root 权限运行,因为使用了原始套接字
import socket
import struct
import sys
def traceroute(dest, max_hops=30, timeout=2):
try:
dest_ip = socket.getaddrinfo(dest, None, socket.AF_INET)[0][4][0]
except socket.gaierror:
print(f"无法解析 {dest}")
return
print(f"traceroute to {dest} ({dest_ip}), {max_hops} hops max")
for ttl in range(1, max_hops + 1):
# 创建原始 ICMP 套接字
recv_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
recv_socket.settimeout(timeout)
recv_socket.bind(("", 0))
send_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
send_socket.setsockopt(socket.SOL_IP, socket.IP_TTL, ttl)
# 构造 ICMP Echo Request:类型 8,代码 0,校验和先填 0
icmp_header = struct.pack("!BBHHH", 8, 0, 0, 12345, ttl)
# 简单校验和
def checksum(data):
if len(data) % 2:
data += b'\x00'
s = sum(struct.unpack("!" + "H" * (len(data) // 2), data))
s = (s & 0xFFFF) + (s >> 16)
s = ~s & 0xFFFF
return s
icmp_checksum = checksum(icmp_header + b'pingdata')
icmp_header = struct.pack("!BBHHH", 8, 0, icmp_checksum, 12345, ttl)
send_socket.sendto(icmp_header + b'pingdata', (dest_ip, 0))
try:
_, addr = recv_socket.recvfrom(512)
print(f"{ttl:2d} {addr[0]}")
if addr[0] == dest_ip:
print("到达目标")
break
except socket.timeout:
print(f"{ttl:2d} *")
finally:
send_socket.close()
recv_socket.close()
if __name__ == "__main__":
traceroute(sys.argv[1] if len(sys.argv) > 1 else "8.8.8.8")运行方式:
sudo python3 traceroute.py baidu.com1.3.4 OSPF:链路状态型 IGP
OSPF(Open Shortest Path First)是大型企业网和数据中心常用的内部网关协议(IGP)。它基于 Dijkstra SPF 算法,每台路由器维护一张完整的链路状态数据库(LSDB),计算以自己为根的最短路径树。
OSPF 核心概念
| 概念 | 说明 |
|---|---|
| Area | 区域,用于减少 LSA 泛洪范围,降低设备负担。Area 0 为骨干区域,所有区域必须直接连接到骨干。 |
| Router ID | 32 位无符号整数,通常取最大 Loopback IP 或最大接口 IP,用于唯一标识路由器。 |
| 邻居(Neighbor) | 通过 Hello 包发现的直连路由器。 |
| 邻接(Adjacency) | 邻居之间完成 LSDB 同步后进入 Full 状态。 |
| DR/BDR | 广播/NBMA 网络中选举指定路由器 / 备份指定路由器,减少邻接关系数量。 |
| LSA | 链路状态通告,描述链路或前缀状态。 |
| Cost | 开销,通常与接口带宽成反比:Cost = 参考带宽 / 接口带宽。 |
OSPF 路由器类型
- Internal Router(IR):所有接口都在同一个 Area。
- ABR(Area Border Router):连接骨干区域和其他区域,负责在区域之间汇总路由。
- ASBR(Autonomous System Boundary Router):将外部路由(如 BGP、静态路由、RIP)引入 OSPF。
OSPF 邻居状态机
stateDiagram-v2
[*] --> Down: 接口启动
Down --> Init: 收到 Hello,但自己的 Router ID 不在对方 Hello 中
Init --> TwoWay: 收到 Hello,且自己的 Router ID 在对方 Hello 中
TwoWay --> ExStart: 选举主从关系,准备交换 DD 报文
ExStart --> Exchange: 交换 DD(Database Description)报文摘要
Exchange --> Loading: 请求特定 LSA
Loading --> Full: 完成 LSU/LSAck 同步
Full --> [*]: LSDB 一致,开始 SPF 计算OSPF 报文类型
| 类型 | 名称 | 作用 |
|---|---|---|
| 1 | Hello | 发现和维护邻居关系(10 秒/次,Dead 40 秒) |
| 2 | DD(Database Description) | 描述本地 LSDB 摘要信息 |
| 3 | LSR(Link-State Request) | 请求特定 LSA |
| 4 | LSU(Link-State Update) | 发送完整 LSA 信息 |
| 5 | LSAck(Link-State Ack) | 确认收到 LSA |
OSPF 区域拓扑示例
graph LR
subgraph Area0 [骨干区域 Area 0]
R1[Router R1 ABR]
R2[Router R2 ABR]
end
subgraph Area1 [非骨干区域 Area 1]
R1 --- R3[Router R3]
R3 --- R4[Router R4]
end
subgraph Area2 [非骨干区域 Area 2]
R2 --- R5[Router R5]
R5 --- R6[Router R6 ASBR]
end
R6 -.->|引入外部路由| Ext[Internet / BGP]可运行:FRRouting OSPF 配置片段
FRR 是 Linux 上常用的开源路由套件。下面给出三台路由器组成 OSPF 的极简配置:
# /etc/frr/frr.conf(仅示意,需根据实际接口名修改)
!
hostname r1
!
interface eth0
ip ospf area 0
ip ospf cost 10
!
interface eth1
ip ospf area 1
ip ospf cost 20
!
router ospf
ospf router-id 1.1.1.1
network 10.0.0.0/8 area 0
!查看命令:
# 查看 OSPF 邻居
vtysh -c "show ip ospf neighbor"
# 查看 LSDB
vtysh -c "show ip ospf database"
# 查看路由表
vtysh -c "show ip route ospf"1.3.5 BGP:互联网的“路由外交协议”
BGP(Border Gateway Protocol)是自治系统(AS)之间的路径向量协议,也是事实上的外部网关协议(EGP)。与 OSPF 不同,BGP 不追求“最短路径”,而是追求策略可控。
核心概念
| 概念 | 说明 |
|---|---|
| AS(Autonomous System) | 自治系统,一个由单一管理机构控制的路由域,分配 16/32 位 AS 号。 |
| AS Path | BGP 路由属性之一,记录路由经过的 AS 序列,用于防环和选路。 |
| iBGP / eBGP | 同一 AS 内运行的 BGP 称为 iBGP;不同 AS 之间称为 eBGP。 |
| Route Reflector(RR) | 解决 iBGP 全互联问题,允许 RR 客户端之间不建立直接 BGP 会话。 |
| BGP 属性 | Origin、AS_Path、Next_Hop、Local_Pref、MED、Community、Atomic_Aggregate 等。 |
BGP 路由选择原则(Cisco 风格简化版)
- 最高 Weight(Cisco 私有,本地有效)
- 最高 Local Preference(本 AS 出口选择)
- 本地起源:本地生成 > IGP > EGP > Incomplete
- 最短 AS Path
- 最低 Origin 类型(IGP < EGP < Incomplete)
- 最低 MED(影响相邻 AS 如何进入本 AS)
- eBGP 优于 iBGP
- 最近的 IGP 下一跳
- 最老的路由(BGP 会话建立时间)
- 最低 Router ID
面试常考:Local_Pref 和 MED 的区别?Local_Pref 控制出向流量走哪个出口,MED 影响入向流量从哪个入口进来。
BGP 报文类型
| 类型 | 名称 | 作用 |
|---|---|---|
| Open | 建立 BGP 会话,协商 AS 号、Hold Time、BGP ID、可选能力 | |
| Update | 通告或撤销路由 | |
| Notification | 检测到错误时发送,随后关闭连接 | |
| Keepalive | 维持会话,默认 60 秒发送一次 | |
| Route-Refresh | 请求对方重新发送指定地址族的路由 |
eBGP 会话建立数据流
sequenceDiagram
participant R1 as AS100 Router
participant R2 as AS200 Router
R1->>R2: TCP SYN 到端口 179
R2->>R1: TCP SYN-ACK
R1->>R2: TCP ACK
Note over R1,R2: BGP 基于 TCP/179
R1->>R2: BGP Open (AS=100, Router-ID=1.1.1.1)
R2->>R1: BGP Open (AS=200, Router-ID=2.2.2.2)
R1->>R2: BGP Keepalive
R2->>R1: BGP Keepalive
R1->>R2: BGP Update (通告 10.0.0.0/8, AS Path=[100])
R2->>R1: BGP Update (通告 20.0.0.0/8, AS Path=[200])可运行:BIRD BGP 配置片段
BIRD 是 Linux 上另一款优秀的路由守护进程:
# /etc/bird/bird.conf
router id 1.1.1.1;
protocol device {
scan time 10;
}
protocol direct {
ipv4;
interface "eth*";
}
protocol bgp neighbor_as200 {
local 10.0.0.1 as 100;
neighbor 10.0.0.2 as 200;
ipv4 {
import all;
export all;
};
}1.3.6 ECMP:等价多路径负载分担
ECMP(Equal-Cost Multi-Path)允许路由器把去往同一目的地的流量分散到多条开销相等的路径上,提升带宽利用率和可靠性。
ECMP 的两种典型实现
| 实现方式 | 说明 |
|---|---|
| 逐包(Per-Packet) | 每个包轮询走不同路径,容易乱序,现代网络很少用 |
| 逐流(Per-Flow) | 根据五元组(源 IP、目的 IP、源端口、目的端口、协议号)做 Hash,同一流固定走同一条路径 |
对称哈希的重要性
对于需要保持会话状态的网络设备(如防火墙、IPS、NAT 设备、负载均衡器),如果同一个 TCP 连接的两个方向走了不同路径,设备可能只看到单向流量,导致状态表无法建立。因此数据中心通常启用 对称哈希(Symmetric Hash),保证同一五元组的流量无论从哪个方向进入都命中同一条链路。
# Linux 查看路由表中的 ECMP 条目示例
ip route show
# 输出示例:
# 10.0.0.0/24 nhid 10 via 192.168.1.2 dev eth0 weight 1
# via 192.168.1.3 dev eth1 weight 1
# 查看内核是否启用了 ECMP
sysctl net.ipv4.fib_multipath_hash_policy
# 0 = L3(仅 IP) 1 = L4(IP + 端口)graph LR
A[源主机] --> R[路由器]
R -->|Flow Hash A| P1[路径1]
R -->|Flow Hash B| P2[路径2]
P1 --> D[目的主机]
P2 --> D硬件快切
在数据中心交换机中,当某条 ECMP 成员链路失效时,ASIC 会在毫秒级将受影响的流重新 Hash 到其余链路,称为 Fast Reroute / Hardware Fast Convergence。这通常依赖 BFD 快速检测 + 路由收敛 + 硬件表项更新协同完成。
1.4 Overlay 与 VPN:跨越三层网络构建大二层
当虚拟机需要在不同机房或不同机架之间迁移,而底层网络已经是三层 IP 网络时,传统 VLAN 无法跨越三层。于是出现了 Overlay 网络:在现有 IP 网络之上再封装一层,把二层帧放进 UDP/IP 包中传输,从而在逻辑上构建一个“大二层”。
1.4.1 VxLAN:数据中心的多租户利器
VxLAN(Virtual Extensible LAN,RFC 7348)是最主流的 Overlay 技术之一,它把原始 Ethernet 帧封装在 UDP 报文中,UDP 目的端口为 4789。
VxLAN 封装结构
| Outer Ethernet | Outer IP | Outer UDP (Dst 4789) | VxLAN Header | Inner Ethernet | Inner IP | Payload |各部分说明:
| 层次 | 头部 | 关键字段 |
|---|---|---|
| Outer L2 | Ethernet | 源 MAC = 本端 VTEP MAC,目的 MAC = 对端 VTEP MAC(或下一跳网关) |
| Outer L3 | IP | 源 IP = 本端 VTEP IP,目的 IP = 对端 VTEP IP |
| Outer L4 | UDP | 源端口随机,目的端口 4789 |
| VxLAN Header | 8 B | VNI(24 bit)、I/ P 标志位 |
| Inner Frame | Ethernet | 原始 VM 的二层帧,含源/目的 VM MAC、可能带 VLAN Tag |
VxLAN Header 格式
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|R|R|R|R|I|P|R|R| Reserved | VNI |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| VNI | Reserved |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- I 位(Instance):必须为 1,表示这是有效的 VxLAN 帧。
- P 位:保留。
- VNI:24 位,支持约 1600 万个隔离网络,远超 VLAN 的 4094。
VxLAN 数据流:跨机架 VM 通信
sequenceDiagram
participant VM1 as VM-A (10.0.0.2/24, VNI 100)
participant VTEP1 as VTEP-1 (192.168.1.10)
participant IPNet as 三层 IP 网络
participant VTEP2 as VTEP-2 (192.168.2.10)
participant VM2 as VM-B (10.0.0.3/24, VNI 100)
VM1->>VTEP1: ARP Request 广播:谁是 10.0.0.3?
VTEP1->>VTEP2: VxLAN 封装 ARP 广播,目的 UDP=4789,VNI=100
VTEP2->>VM2: 解封装,转发原始 Ethernet 帧
VM2->>VTEP2: ARP Reply 单播
VTEP2->>VTEP1: VxLAN 封装 ARP Reply,VNI=100
VTEP1->>VM1: 解封装后交给 VM-A
VM1->>VTEP1: ICMP Echo Request (Ping)
VTEP1->>VTEP2: VxLAN 封装 ICMP,Outer IP 192.168.1.10 -> 192.168.2.10
VTEP2->>VM2: 解封装,目的 MAC 为 VM-B
VM2->>VTEP2: ICMP Echo Reply
VTEP2->>VTEP1: VxLAN 封装回复
VTEP1->>VM1: 解封装后返回可运行:在 Linux 上手工配置 VxLAN
下面的命令在两台 Linux 主机之间建立 VxLAN 隧道,实现跨三层的大二层互通。
主机 A(VTEP-1,底层 IP 192.168.1.10):
# 创建 VxLAN 接口,VNI=100,组播或单播学习
sudo ip link add vxlan100 type vxlan id 100 \
local 192.168.1.10 remote 192.168.2.10 dstport 4789 dev eth0
# 配置桥接,让物理/虚拟网卡加入该 VxLAN
sudo ip link set vxlan100 up
sudo ip link add br100 type bridge
sudo ip link set vxlan100 master br100
sudo ip link set eth1 master br100 # eth1 连接需要互通的虚拟机或测试网卡
sudo ip link set br100 up主机 B(VTEP-2,底层 IP 192.168.2.10):
sudo ip link add vxlan100 type vxlan id 100 \
local 192.168.2.10 remote 192.168.1.10 dstport 4789 dev eth0
sudo ip link set vxlan100 up
sudo ip link add br100 type bridge
sudo ip link set vxlan100 master br100
sudo ip link set eth1 master br100
sudo ip link set br100 up测试时,给 eth1 两端的测试接口配置同一子网 IP(如 10.0.0.2/24 和 10.0.0.3/24),即可直接 ping 通。抓包可见外层 UDP/4789:
sudo tcpdump -i eth0 -nn -s0 "udp port 4789"1.4.2 EVPN:用 BGP 控制 VxLAN
VxLAN 本身只定义了数据平面封装,控制平面(如何知道哪个 MAC/IP 在哪个 VTEP 后面)早期依赖 泛洪与学习(类似传统交换机)。这种方式在大规模数据中心会导致大量广播泛洪。
EVPN(Ethernet VPN,RFC 7432)使用 MP-BGP 作为控制平面,把主机的 MAC、IP、VNI、VTEP 位置信息以路由的形式分发,实现:
- 抑制广播:ARP/ND 请求可以通过控制平面直接回答,减少 BUM(Broadcast/Unknown Unicast/Multicast)流量。
- 主机移动性:当 VM 从一个 VTEP 迁移到另一个 VTEP 时,EVPN 可以快速更新路由。
- 多宿主冗余:支持双归接入(Multi-homing),实现链路冗余和负载分担。
EVPN 常见路由类型:
| 类型 | 名称 | 用途 |
|---|---|---|
| Type 1 | Ethernet Auto-Discovery | 多宿主冗余、快速收敛 |
| Type 2 | MAC/IP Advertisement | 通告主机 MAC 和 IP |
| Type 3 | Inclusive Multicast Ethernet Tag | 广播、未知单播、组播(BUM)转发 |
| Type 4 | Ethernet Segment Route | 多宿主选举 Designated Forwarder |
| Type 5 | IP Prefix Route | 通告外部 IP 前缀 |
graph LR
VM1[VM-A] -->|MAC/IP| VTEP1[VTEP-1]
VM2[VM-B] -->|MAC/IP| VTEP2[VTEP-2]
VTEP1 <-->|MP-BGP EVPN| VTEP2
VTEP1 -.->|Type 2 路由| VTEP2
VTEP2 -.->|Type 2 路由| VTEP11.4.3 Overlay 与 Underlay 的关系
| 术语 | 含义 | 类比 |
|---|---|---|
| Underlay | 底层承载网络,负责 VTEP 之间的 IP 可达性 | 高速公路 |
| Overlay | 叠加在 Underlay 之上的虚拟网络,面向租户/业务 | 高速公路上的物流集装箱 |
Underlay 通常跑 eBGP/IS-IS/OSPF + ECMP,提供高带宽、低延迟、快速收敛;Overlay 则跑 VxLAN/EVPN,提供多租户隔离、灵活的二层扩展。
1.5 传输层与应用层:端到端的可靠与高效
网络层负责把包送到主机,但一台主机上可能同时运行浏览器、SSH、数据库等多个进程。传输层通过端口号区分进程,并在需要时提供可靠传输。
1.5.1 TCP:可靠的字节流管道
TCP(Transmission Control Protocol)提供面向连接、可靠、按序、基于字节流的传输服务。它在 IP 的“尽力而为”之上,通过序列号、确认应答、重传、窗口、拥塞控制等机制实现可靠性。
TCP 头部结构
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |U|A|P|R|S|F| |
| Offset| Reserved |R|C|S|S|Y|I| Window |
| | |G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | Urgent Pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| 字段 | 说明 |
|---|---|
| Source/Destination Port | 源/目的端口,各 16 位 |
| Sequence Number | 本报文段发送数据的第一个字节序号 |
| Acknowledgment Number | 期望收到的下一个字节序号(只有 ACK=1 时有效) |
| Data Offset | TCP 头部长度,单位 4 字节,最小 5(20 字节) |
| Flags | URG、ACK、PSH、RST、SYN、FIN |
| Window | 接收窗口大小,用于流量控制 |
| Checksum | 覆盖头部、数据和伪头部 |
| Options | 常见 MSS、SACK、Timestamps、Window Scale |
三次握手与四次挥手
三次握手(建立连接):
sequenceDiagram
participant C as 客户端
participant S as 服务器
C->>S: SYN=1, seq=x
Note right of C: 客户端进入 SYN_SENT
S->>C: SYN=1, ACK=1, seq=y, ack=x+1
Note left of S: 服务器进入 SYN_RCVD
C->>S: ACK=1, seq=x+1, ack=y+1
Note right of C: 双方进入 ESTABLISHED为什么不是两次?因为双方都需要确认对方的接收和发送能力,并且同步初始序列号(ISN)。两次握手无法避免历史重复连接请求被服务器误接受。
四次挥手(释放连接):
sequenceDiagram
participant C as 客户端
participant S as 服务器
C->>S: FIN=1, seq=u
S->>C: ACK=1, ack=u+1
Note over C,S: 服务器可能还有数据要发
S->>C: FIN=1, seq=w
C->>S: ACK=1, ack=w+1
Note over C,S: 进入 TIME_WAIT,等待 2MSL 后关闭TIME_WAIT 存在的意义:
- 保证最后一个 ACK 能被服务器收到,若丢失可重传。
- 让网络中残留的报文消散,避免影响下一个使用相同四元组的连接。
滑动窗口与流量控制
TCP 使用滑动窗口实现流量控制:接收方在 ACK 中通告自己的接收窗口(Window),发送方据此控制未确认数据量。窗口大小受限于接收方缓存,而不是网络带宽。
拥塞控制
拥塞控制防止发送方把网络“撑爆”,主要算法包括:
| 阶段/算法 | 行为 |
|---|---|
| 慢启动(Slow Start) | 拥塞窗口 cwnd 从 1 MSS 开始,每收到一个 ACK 增加 1 MSS,指数增长 |
| 拥塞避免(Congestion Avoidance) | cwnd 超过慢启动阈值 ssthresh 后,每 RTT 增加 1 MSS,线性增长 |
| 快重传(Fast Retransmit) | 收到 3 个重复 ACK 立即重传,不必等待超时 |
| 快恢复(Fast Recovery) | 快重传后 ssthresh 减半,cwnd 设为 ssthresh + 3 MSS,避免直接回到慢启动 |
graph LR
A[连接建立] -->|cwnd < ssthresh| B[慢启动 指数增长]
B -->|cwnd >= ssthresh| C[拥塞避免 线性增长]
C -->|超时| D[ssthresh=cwnd/2, cwnd=1]
C -->|3 个重复 ACK| E[快重传 + 快恢复]
D --> B
E --> C可运行:Python TCP Echo Server / Client
server.py:
#!/usr/bin/env python3
import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('0.0.0.0', 9000))
s.listen(5)
print("TCP echo server listening on 9000...")
while True:
conn, addr = s.accept()
with conn:
print(f"Connected by {addr}")
while True:
data = conn.recv(1024)
if not data:
break
conn.sendall(b"Echo: " + data)client.py:
#!/usr/bin/env python3
import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect(('127.0.0.1', 9000))
s.sendall(b'Hello TCP')
data = s.recv(1024)
print(data.decode())运行:
python3 server.py &
python3 client.py1.5.2 UDP:简单快速的“明信片”
UDP(User Datagram Protocol)无连接、不保证可靠性,但头部极小、延迟低,适合实时性要求高的场景。
UDP 头部
0 7 8 15 16 23 24 31
+--------+--------+--------+--------+
| Source Port | Dest Port |
+--------+--------+--------+--------+
| Length | Checksum |
+--------+--------+--------+--------+| 字段 | 说明 |
|---|---|
| Source Port / Dest Port | 源/目的端口 |
| Length | UDP 头 + 数据的总长度 |
| Checksum | 可选(IPv4)/ 强制(IPv6),覆盖伪头部、UDP 头和数据 |
常见应用层协议端口
| 协议 | 端口 | 说明 |
|---|---|---|
| HTTP | 80 | 超文本传输 |
| HTTPS | 443 | HTTP over TLS |
| SSH | 22 | 安全 Shell |
| DNS | 53 | 域名解析(同时用 UDP 和 TCP) |
| DHCP | 67/68 | 动态主机配置(服务器/客户端) |
| BGP | 179 | 边界网关协议 |
| SMTP | 25/587 | 邮件发送 |
| FTP | 20/21 | 文件传输(数据/控制) |
为什么 DNS 既用 UDP 又用 TCP? 普通查询响应较小,用 UDP 速度快;当响应超过 512 字节(如 DNSSEC、大记录集)或区域传输(AXFR/IXFR)时使用 TCP。
可运行:Python UDP Echo
#!/usr/bin/env python3
import socket
# 服务端
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
s.bind(('0.0.0.0', 9001))
print("UDP echo server on 9001...")
while True:
data, addr = s.recvfrom(1024)
s.sendto(b"Echo: " + data, addr)#!/usr/bin/env python3
import socket
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
s.sendto(b'Hello UDP', ('127.0.0.1', 9001))
data, _ = s.recvfrom(1024)
print(data.decode())1.5.3 TLS:到底算哪一层?
TLS(Transport Layer Security)位于 TCP 之上、应用层协议之下,为 HTTP、SMTP、MQTT 等提供加密、身份认证和完整性保护。从 OSI 角度看,TLS 承担的是表示层的加密解密和格式转换功能;但从 TCP/IP 工程实现看,它通常被归入应用层协议栈的一部分(HTTPS = HTTP + TLS)。
面试回答策略:
- 如果面试官按 OSI 七层严格问:TLS 属于表示层。
- 如果面试官按 TCP/IP 四层或工程实践问:TLS 运行在传输层之上、应用层之内,常与 HTTP 一起称为 HTTPS。
1.6 交换机转发原理:从学习到转发的硬件流水线
交换机是二层网络的核心设备。理解它的转发流程,能帮助我们解释为什么 ping 第一次慢、为什么广播会泛洪、为什么三层交换比路由器快。
1.6.1 二层交换机转发流程
- 接收帧:物理层收到比特流,PHY 芯片完成编码解码,交给 MAC 层。
- FCS 校验:如果 FCS 错误,丢弃帧。
- 学习源 MAC:把“源 MAC → 入端口”写入 CAM 表(MAC 地址表),并更新老化计时器。
查目的 MAC:
- 如果表中有匹配项,单播转发到对应端口(同一 VLAN 内)。
- 如果表中没有匹配项,或目的 MAC 为广播/组播,则向同一 VLAN 的所有其他端口泛洪(Flooding)。
graph TD
A[收到 Ethernet 帧] --> B{FCS 校验}
B -->|失败| Z[丢弃]
B -->|通过| C[学习源 MAC -> 入端口]
C --> D{查目的 MAC}
D -->|命中| E[单播转发到对应端口]
D -->|未命中/广播| F[泛洪到同 VLAN 其他端口]1.6.2 三层交换机转发流程
三层交换机同时具备二层交换和三层路由能力。当收到一个目的 MAC 是交换机自己 SVI(Switched Virtual Interface)的帧时,进入三层转发:
- 解封装 Ethernet 头部,提取目的 IP。
- 查询 FIB(Forwarding Information Base)/ 路由表,决定下一跳 IP 和出接口。
- 如果下一跳 MAC 未知,触发 ARP 解析(或查 ARP 表)。
- 重新封装二层头部:源 MAC 改为出接口 MAC,目的 MAC 改为下一跳 MAC,VLAN Tag 改为出接口 VLAN。
- 发送帧。
sequenceDiagram
participant H as 主机 A (VLAN10)
participant L3 as 三层交换机
participant G as 网关 SVI (VLAN20)
participant B as 主机 B (VLAN20)
H->>L3: 帧:目的 MAC=SVI-VLAN10,Tag=10,IP 包目的 IP=B
L3->>L3: 解封装,发现目的 MAC 是自己,进入三层
L3->>L3: 查路由表:目的网段 -> VLAN20
L3->>L3: 查 ARP 表获取 B 的 MAC(或发 ARP 请求)
L3->>B: 新帧:目的 MAC=B,Tag=20,TTL-11.6.3 现代交换机的硬件转发流水线
高端交换机将转发逻辑固化在 ASIC 中,常见流水线如下:
graph LR
A[入端口] -->|Parser| B[提取 L2/L3/L4 字段]
B --> C{ACL/ QoS TCAM}
C --> D[MAC 表 / LPM 路由查找]
D --> E[ECMP Hash]
E --> F[重写二层头部]
F --> G[出端口队列]
G --> H[发送]| 组件 | 作用 |
|---|---|
| TCAM(Ternary Content Addressable Memory) | 三态内容寻址存储器,用于 ACL、QoS、路由最长前缀匹配,支持通配符匹配 |
| CAM / HASH 表 | 用于 MAC 地址表、ECMP 组成员、ARP 表等精确匹配 |
| LPM(Longest Prefix Match) | 路由表查找,找到最长匹配前缀 |
| ACL | 访问控制列表,基于规则过滤或标记流量 |
| QoS | 基于优先级队列、整形、调度保证关键业务带宽 |
1.6.4 可运行:在 Linux 上观察交换与转发
Linux 网桥就是一个软件二层交换机:
# 创建网桥并加入接口
sudo ip link add br0 type bridge
sudo ip link set eth0 master br0
sudo ip link set eth1 master br0
sudo ip link set br0 up
# 查看 MAC 地址表(类似交换机 CAM 表)
sudo bridge fdb show
# 查看网桥 STP 状态
sudo bridge stp show
# 查看三层转发表
ip route show
ip neigh show1.6.5 综合案例:PC-A ping PC-B 的完整数据流
为了把前面所有知识点串起来,下面展示一个完整场景:
- PC-A:IP
192.168.10.2/24,MACAA,连接 Access 口 VLAN10。 - PC-B:IP
192.168.20.2/24,MACBB,连接 Access 口 VLAN20。 - 三层交换机:VLAN10 SVI
192.168.10.1/24,VLAN20 SVI192.168.20.1/24。
sequenceDiagram
participant A as PC-A
participant SW as 三层交换机
participant B as PC-B
Note over A,B: 阶段一:ARP 请求网关
A->>SW: 广播 ARP Request:谁是 192.168.10.1?(Tag=10)
SW->>A: 单播 ARP Reply:网关 MAC=GW10(Tag=10)
Note over A,B: 阶段二:发送 ICMP Echo Request
A->>SW: 帧:目的 MAC=GW10,Tag=10,IP src=A dst=B,ICMP Echo
SW->>SW: 解封装,TTL-1,查路由表到 VLAN20
SW->>B: ARP Request:谁是 192.168.20.2?(Tag=20)
B->>SW: ARP Reply:MAC=BB(Tag=20)
SW->>B: 帧:目的 MAC=BB,Tag=20,IP src=A dst=B,ICMP Echo
Note over A,B: 阶段三:PC-B 回复
B->>SW: 帧:目的 MAC=GW20,Tag=20,IP src=B dst=A,ICMP Reply
SW->>SW: 解封装,TTL-1,查路由表到 VLAN10
SW->>A: 帧:目的 MAC=AA,Tag=10,IP src=B dst=A,ICMP Reply这个例子同时覆盖了:VLAN 标签、Access 端口、三层路由、ARP 解析、MAC 学习、TTL 递减、ICMP 封装。
1.7 面试常见错误与纠正
网络基础面试中,很多错误不是“不会”,而是“概念边界模糊”。下面列出几个高频误区。
错误一:OSI 答成五层
问题:面试官问“OSI 七层模型是什么”,候选人只答出五层。
纠正:OSI 严格是七层。五层是国内部分教材为了简化教学把会话、表示、应用合并后的说法。面试时如果问 OSI,必须逐层说出:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。同时可以补充 TCP/IP 四层模型以展示深度。
错误二:ARP 分层模糊
问题:“ARP 是二层还是三层?”回答含糊。
纠正:ARP 的功能属于网络层(为 IP 解析 MAC),但报文直接封装在 Ethernet 帧中(EtherType=0x0806),不经过 IP 封装。因此准确说法是:ARP 是网络层协议,承载在二层帧中。
错误三:数据加密解密归属层
问题:“TLS 属于哪一层?”简单回答传输层或应用层。
纠正:OSI 严格分层中,加密解密属于表示层。TLS 位于 TCP 之上,功能上承担表示层的加密、压缩、格式转换;在 TCP/IP 工程语境中,TLS 通常被视为应用层协议栈的一部分(HTTPS = HTTP over TLS)。回答时说明分层视角差异,是加分项。
错误四:认为 VLAN 划分取决于是否配置 IP
问题:“VLAN 是二层还是三层?”“配了 IP 才算一个 VLAN?”
纠正:VLAN 是纯二层概念,与 IP 无关。Access/Trunk 端口的划分、VLAN Tag 的处理完全不依赖 IP。一个 VLAN 可以没有三层网关(纯二层隔离),也可以配置 SVI 接口实现 VLAN 间路由。IP 是三层属性。
错误五:认为交换机不会修改帧
问题:“交换机转发帧时,源/目的 MAC 会不会变?”
纠正:
- 二层交换机:不修改帧的源/目的 MAC,只根据 MAC 表选择出端口,可能改变 VLAN Tag(Trunk/Access 处理)。
- 三层交换机/路由器:会解封装二层头部,重新封装新的二层头部,因此源/目的 MAC 都会改变,TTL 也会减 1。
错误六:混淆 IGP 与 EGP
问题:“OSPF 和 BGP 有什么本质区别?”只回答“一个是内部、一个是外部”。
纠正:
- OSPF 是链路状态型 IGP,基于带宽计算最短路径,强调域内快速收敛。
- BGP 是路径向量型 EGP,基于策略和 AS Path 选路,强调跨自治系统的可控性和稳定性。
- 两者使用的算法、报文封装、邻居关系、路由属性完全不同。
1.8 实验建议:把理论落地
动手实验是巩固网络基础最有效的方式。以下实验按难度递增排列,全部可以在 Linux 单机上用 network namespace + veth pair 完成,也可以使用 EVE-NG/GNS3 搭建虚拟网络。
实验 1:Wireshark/tcpdump 抓包分析 ARP
# 清空 ARP 缓存
sudo ip neigh flush all
# 在一个终端抓 ARP
sudo tcpdump -i any -nn -e arp
# 在另一个终端触发 ARP
ping -c 1 192.168.1.1
# 观察:先出现 ARP Request(广播),后出现 ARP Reply(单播)实验 2:Linux network namespace 模拟 VLAN 间路由
# 创建两个 namespace 分别代表两个 VLAN 的主机
sudo ip netns add ns10
sudo ip netns add ns20
# 创建 veth pair 连接 namespace 和 root
sudo ip link add veth10 type veth peer name veth10-br
sudo ip link add veth20 type veth peer name veth20-br
sudo ip link set veth10 netns ns10
sudo ip link set veth20 netns ns20
# 配置 IP
sudo ip netns exec ns10 ip addr add 192.168.10.2/24 dev veth10
sudo ip netns exec ns20 ip addr add 192.168.20.2/24 dev veth20
sudo ip netns exec ns10 ip link set veth10 up
sudo ip netns exec ns20 ip link set veth20 up
# root 命名空间创建 VLAN 子接口并配置 SVI
sudo ip link add link eth0 name eth0.10 type vlan id 10
sudo ip link add link eth0 name eth0.20 type vlan id 20
sudo ip addr add 192.168.10.1/24 dev eth0.10
sudo ip addr add 192.168.20.1/24 dev eth0.20
sudo ip link set eth0.10 up
sudo ip link set eth0.20 up
# 开启 IP 转发
sudo sysctl -w net.ipv4.ip_forward=1
# 测试
sudo ip netns exec ns10 ping 192.168.20.2实验 3:用 Python Scapy 构造并发送 ARP 包
from scapy.all import ARP, Ether, sendp
# 构造 Gratuitous ARP:主动宣告自己的 IP-MAC 映射
pkt = Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(
op=1, # request
psrc="192.168.1.100", # 自己的 IP
hwsrc="00:11:22:33:44:55", # 自己的 MAC
pdst="192.168.1.100" # TPA 也填自己
)
sendp(pkt, iface="eth0", count=5)实验 4:EVE-NG 搭建 OSPF/BGP 拓扑
- 三台路由器组成三角形拓扑。
- 两台跑 OSPF,划分 Area 0 和 Area 1,观察 DR/BDR 选举、LSDB 同步。
- 一台作为 ASBR 引入 BGP 路由,观察 AS Path 和 Local_Pref 对选路的影响。
实验 5:Linux 手工 VxLAN
参考 1.4.1 节的命令,在两台 Linux 主机或两个 network namespace 中创建 VxLAN 接口,跨三层网络实现大二层互通,并用 tcpdump 观察外层 UDP/4789 报文。
实验 6:用 socket 实现 TCP/UDP Echo
参考 1.5.1 和 1.5.2 节的 Python 代码,分别实现 TCP 和 UDP 的 echo server/client,并用 ss -tan / ss -uan 观察连接状态。
1.9 推荐资料
书籍:
- 《计算机网络:自顶向下方法》(James F. Kurose & Keith W. Ross)第 1-5 章
- 《TCP/IP 详解 卷 1:协议》(Kevin R. Fall & W. Richard Stevens)
- 《CCNA 学习指南》或 Cisco 官方文档(二层/三层基础)
RFC(进阶):
- RFC 826:ARP
- RFC 791:IPv4
- RFC 2460/8200:IPv6
- RFC 2328:OSPFv2
- RFC 4271:BGP-4
- RFC 7348:VxLAN
- RFC 7432:EVPN
视频:
- 哔哩哔哩“湖科大教书匠”计算机网络视频
- Cisco Networking Academy 官方课程
开源工具:
- Wireshark / tcpdump:协议分析
- FRRouting / BIRD:开源路由套件
- EVE-NG / GNS3:网络虚拟化实验平台
1.10 模块验收标准
完成本模块后,请对照以下清单自我检验:
- [ ] 能不看资料说出 OSI 七层和 TCP/IP 四层的对应关系,并解释为什么实际工程常用四层。
- [ ] 能逐字节解释 Ethernet II、802.1Q VLAN Tag、ARP、IPv4、TCP/UDP 头部关键字段。
- [ ] 能解释 VLAN、VxLAN、OSPF、BGP、ECMP 的工作原理,并画出它们的数据流或状态机。
- [ ] 能区分 ARP 的协议分层归属和报文承载分层,并正确回答 NDP 与 ARP 的关系。
- [ ] 能独立用 Wireshark/tcpdump 完成 ARP、ICMP、TCP 三次握手的抓包分析。
- [ ] 能在 Linux 环境下配置 VLAN 子接口、VxLAN 接口、网桥,并验证二层/三层转发。
- [ ] 能用 Python socket 或 Scapy 编写简单的网络程序或报文构造脚本。
网络基础不是背下来的,而是一次次抓包、一次次配置、一次次排错中沉淀的直觉。希望这篇深度博客能成为你面试和工作中的可靠参考。
评论 (0)