IP 包是怎么一跳一跳转发的:路由表、ARP、MAC、交换机与路由器

前言

学到网络层和数据链路层时,最容易混在一起的几个问题是:

  • 客户端怎么知道下一跳是谁?
  • ARP 到底在查什么?
  • 源 MAC 是谁决定的?
  • 交换机和路由器分别看什么?
  • IP 包里的源 IP、目标 IP 会不会变?
  • 每一跳到底是不是都重新封装?

这篇文章只讲一件事:

一个 HTTP 请求封装成 IP 包后,是如何被 MAC 帧一跳一跳送到目标服务器的。


动画先看一遍

下面这张动画图展示了完整主线:客户端封装完整协议栈,中间交换机按 MAC 转发,路由器拆帧看 IP,再为下一跳重新封装 MAC 帧。

IP 包与 MAC 帧的一跳一跳转发过程

先记住一句话:

IP 负责最终目标,MAC 负责当前这一跳。


1. 从 HTTP 到 TCP,再到 IP

浏览器发请求时,最开始是应用层数据:

1
2
GET /api/user HTTP/1.1
Host: example.com

传输层会把 HTTP 数据交给 TCP,TCP 加上:

1
2
3
4
5
源端口
目标端口
序号
确认号
控制位

网络层再把 TCP 段封装成 IP 包,IP 头里有:

1
2
3
4
源 IP
目标 IP
TTL
协议类型

比如:

1
2
源 IP = 192.168.1.10
目标 IP = 93.184.216.34

到这里,数据还不能直接发到网线上。IP 包必须继续交给数据链路层,封装成当前链路能发送的帧。


2. 客户端怎么知道下一跳是谁

客户端不是先问路由器“下一跳是谁”。

它会先查自己的本机路由表。

电脑联网时,通常会通过 DHCP 拿到这些配置:

1
2
3
4
本机 IP:192.168.1.10
子网掩码:255.255.255.0
默认网关:192.168.1.1
DNS 服务器:192.168.1.1

操作系统会据此生成路由表,简化后类似:

1
2
3
目标网段            下一跳
192.168.1.0/24 直接发送
0.0.0.0/0 默认网关 192.168.1.1

如果目标 IP 是:

1
192.168.1.20

系统发现它在本地网段,就直接发给这台机器。

如果目标 IP 是:

1
93.184.216.34

系统发现它不在本地网段,于是命中默认路由:

1
下一跳 = 192.168.1.1

所以:

路由表决定下一跳 IP。


3. ARP 查的是下一跳 MAC

知道下一跳 IP 还不够。

在以太网 / Wi-Fi 这样的二层网络里,真正发送帧时需要目标 MAC。

于是客户端会查 ARP 缓存:

1
192.168.1.1 -> AA:BB:CC:DD:EE:FF

如果缓存里没有,就发 ARP 广播:

1
2
目标 MAC:FF:FF:FF:FF:FF:FF
内容:谁是 192.168.1.1?请告诉我你的 MAC。

同一个广播域里的设备都会收到这个问题,但只有 192.168.1.1 会回复:

1
我是 192.168.1.1,我的 MAC 是 AA:BB:CC:DD:EE:FF。

客户端拿到结果后写入 ARP 缓存,后续一段时间可以直接使用。

所以:

ARP 不是查最终服务器的 MAC,而是查当前下一跳 IP 对应的 MAC。

只有当目标 IP 本来就在本地网段时,ARP 才会直接查询目标主机的 MAC。


4. 源 MAC 是怎么确定的

源 MAC 来自当前要发出去的网络接口。

你的电脑可能有多个网卡:

1
2
3
Wi-Fi 网卡
有线网卡
虚拟网卡

操作系统先查路由表,决定这个 IP 包从哪个接口出去。

如果走 Wi-Fi:

1
源 MAC = Wi-Fi 网卡 MAC

如果走有线:

1
源 MAC = 有线网卡 MAC

路由器也是一样。路由器有多个接口:

1
2
3
LAN 口
WAN 口
其他出口

路由器决定从哪个出口转发,就用哪个出口接口的 MAC 作为源 MAC。


5. 数据链路帧里装着 IP 包

以太网帧和 IP 包是嵌套关系。

不是“数据链路层同时带源 MAC、目标 MAC、源 IP、目标 IP”。

更准确是:

1
2
3
4
5
6
7
8
9
10
11
12
13
以太网帧 {
源 MAC
目标 MAC
IP 包 {
源 IP
目标 IP
TCP 段 {
源端口
目标端口
HTTP 数据
}
}
}

比如客户端发给家用路由器时:

1
2
3
4
5
6
7
帧头:
源 MAC = 客户端网卡 MAC
目标 MAC = 家用路由器 LAN 口 MAC

IP 包:
源 IP = 192.168.1.10
目标 IP = 93.184.216.34

这就是:

1
2
目标 MAC = 当前这一跳
目标 IP = 最终目的地

6. 交换机做什么

交换机主要工作在数据链路层。

它收到以太网帧后,看帧头里的目标 MAC:

1
目标 MAC = 家用路由器 MAC

然后查自己的 MAC 地址表:

1
2
3
MAC 地址                  端口
客户端 MAC 1 号端口
家用路由器 MAC 5 号端口

如果知道目标 MAC 在哪个端口,就把整个帧转发到对应端口。

注意:

交换机通常不拆 IP 包,也不理解 HTTP,它只是按 MAC 转发帧。

所以不要说“交换机把 IP 包发给目标 MAC”,更准确是:

交换机把整个数据链路帧转发到目标 MAC 所在端口。


7. 路由器做什么

路由器收到帧后,先看目标 MAC。

如果目标 MAC 是自己的某个接口 MAC,就收下这一帧:

1
目标 MAC = 家用路由器 LAN 口 MAC

然后路由器拆掉数据链路层帧,取出里面的 IP 包。

接着看 IP 包里的目标 IP:

1
目标 IP = 93.184.216.34

路由器查自己的路由表,决定下一跳和出口接口。

例如:

1
2
目标网段              下一跳
0.0.0.0/0 运营商下一跳

查到下一跳后,路由器同样需要知道下一跳 MAC。

如果 ARP 缓存里没有,就在出口所在链路上发 ARP:

1
谁是下一跳 IP?告诉我你的 MAC。

拿到下一跳 MAC 后,路由器重新封装新的二层帧:

1
2
源 MAC = 路由器出口接口 MAC
目标 MAC = 下一跳设备 MAC

里面仍然装着那个 IP 包。

所以:

路由器重新封装的是二层 MAC 帧,不是每一跳都重新造一个全新的 IP 包。


8. 路由器会不会修改 IP 包

通常情况下,IP 包里的目标 IP 保持不变。

1
目标 IP = 93.184.216.34

路由器每转发一次,通常会修改:

1
2
TTL 减 1
IP 头校验和更新

如果经过 NAT,还可能修改:

1
2
3
源 IP
源端口
相关校验和

比如你家里设备访问公网:

1
内网源 IP = 192.168.1.10

经过家用路由器 NAT 后,出公网时可能变成:

1
2
公网源 IP = 运营商分配的公网 IP
源端口 = 路由器分配的新端口

注意:

跨网段不等于一定 NAT。

跨网段一定需要路由,但 NAT 通常发生在私网访问公网,或者某些网络边界需要地址转换的场景。


9. 是不是所有网络传输都要 MAC

在以太网和 Wi-Fi 里,通常要用 MAC 地址。

但更准确地说:

IP 包必须被某种链路层协议承载,不能直接在物理网络里裸传。

日常局域网里,这个链路层协议通常是:

1
以太网帧 / Wi-Fi 帧

它们使用 MAC 地址。

但某些点对点链路、隧道或其他链路层技术,不一定使用传统以太网 MAC 转发。

所以可以这样区分:

1
2
IP 可以不经过 TCP / UDP,比如 ICMP ping。
IP 不能脱离链路层封装直接传输。

例如:

1
2
3
HTTP -> TCP -> IP -> 以太网/Wi-Fi
DNS -> UDP -> IP -> 以太网/Wi-Fi
ICMP -> IP -> 以太网/Wi-Fi

ICMP 没有 TCP/UDP,但仍然需要链路层承载。


10. 不同网络包分别怎么走

前面一直拿 HTTP 请求举例,但要注意:

不是只有 HTTP 数据才走这套链路,只要数据要发到网络上,就必须被底层协议承载。

区别只在于:它从哪一层开始,经过哪些协议。

DNS 查询

DNS 是应用层协议,用来查询域名对应的 IP。

比如:

1
example.com 的 A 记录是什么?

它通常这样封装:

1
2
3
4
5
6
7
8
9
DNS 查询
↓
UDP 53,少数情况走 TCP 53
↓
IP
↓
以太网帧 / Wi-Fi 帧
↓
物理层信号

所以:

1
DNS -> UDP/TCP -> IP -> MAC -> 物理层

DNS 查询本身不是 HTTP 请求,它只是为了帮后面的 HTTP 请求找到目标服务器 IP。

TCP 三次握手

TCP 三次握手时,通常还没有 HTTP 请求。

三次握手传的是 TCP 控制报文:

1
2
3
SYN
SYN + ACK
ACK

每一个握手包也要往下封装:

1
2
3
4
5
6
7
TCP SYN
↓
IP
↓
MAC 帧
↓
物理层信号

所以:

1
TCP 握手包 -> IP -> MAC -> 物理层

HTTP 请求是在 TCP 连接建立之后才发送的。

HTTPS 请求

如果访问的是 HTTPS,通常会经历:

1
2
3
4
5
TCP 三次握手
↓
TLS 握手
↓
加密后的 HTTP 请求

TLS 握手数据本身也要通过 TCP 传输:

1
2
3
4
5
6
7
8
9
TLS 握手数据
↓
TCP
↓
IP
↓
MAC
↓
物理层

HTTP 数据在 TLS 加密后,也继续走:

1
2
3
4
5
6
7
8
9
10
11
HTTP
↓
TLS
↓
TCP
↓
IP
↓
MAC
↓
物理层

ICMP ping

ping 常用 ICMP。

ICMP 不走 TCP,也不走 UDP,它直接由 IP 承载:

1
2
3
4
5
6
7
ICMP Echo Request
↓
IP
↓
MAC
↓
物理层

所以:

1
IP 可以不经过 TCP / UDP。

但 ICMP 仍然要经过数据链路层和物理层。

ARP 查询

ARP 更特殊。

ARP 的目的就是在局域网里查询:

1
这个 IP 对应哪个 MAC?

它不走 IP,因为它本来就是为 IP 层准备下一跳 MAC 的。

ARP 通常直接封装在二层帧里:

1
2
3
4
5
ARP Request
↓
以太网广播帧
↓
物理层信号

所以:

1
ARP -> MAC -> 物理层

这也是为什么 ARP 广播只能在同一个广播域里工作,不能跨路由器到远方网络里广播。

小结

把它们放在一起看:

1
2
3
4
5
6
HTTP/1.1      -> TCP -> IP -> MAC -> 物理层
HTTPS -> TLS -> TCP -> IP -> MAC -> 物理层
DNS -> UDP/TCP -> IP -> MAC -> 物理层
TCP 三次握手 -> IP -> MAC -> 物理层
ICMP ping -> IP -> MAC -> 物理层
ARP -> MAC -> 物理层

这就是为什么不能把网络理解成“只有 HTTP 请求才走完整链路”。

真正的规则是:

每一种网络数据都有自己的起点层,但只要要离开本机,就必须继续交给下面的层来承载。


11. 整个链路总结

把完整过程压缩一下:

1
2
3
4
5
6
7
8
9
10
1. HTTP 数据生成
2. TCP 加源端口、目标端口
3. IP 加源 IP、目标 IP
4. 客户端查路由表,决定下一跳
5. ARP 查下一跳 MAC
6. 封装当前这一跳的 MAC 帧
7. 交换机按目标 MAC 转发帧
8. 路由器拆帧,看目标 IP,查路由表
9. 路由器为下一跳重新封装 MAC 帧
10. 一跳一跳重复,直到目标服务器

最关键的几句话:

1
2
3
4
5
6
客户端和每个路由器都会查路由表决定下一跳。
ARP 查的是当前链路上的下一跳 MAC。
源 MAC 来自当前发送设备的出口网卡。
交换机看 MAC,路由器看 IP。
IP 目标通常跨全程不变,MAC 每一跳都会变化。
NAT 时源 IP / 源端口可能被修改。

一句话:

IP 包负责“最终去哪”,MAC 帧负责“这一跳交给谁”;路由器决定下一跳,交换机把帧送到这一跳的目标 MAC。