物理层与数据链路层:以太网帧结构、MAC地址、ARP协议的工作原理与抓包分析
好,我们正式开始第二讲。上一章聊了TCP/IP协议栈的整体轮廓,这一章我们要往下沉一层,看看数据在物理介质上到底是怎么跑的。说白了,就是网线里的电信号、光纤里的光信号,怎么变成你能理解的“数据包”。
我个人习惯把物理层和数据链路层放在一起讲,因为这两层在实际硬件里是高度耦合的。你拆开一台交换机,看到的PHY芯片和MAC芯片,就是这两层的物理化身。嗯,咱们先从最基础的以太网帧结构说起。
以太网帧结构:数据在线上长什么样
你想想看,两台电脑用网线直连,数据从网卡发出去,总得有个格式吧?不然接收方怎么知道哪一段是目标地址、哪一段是数据本身?以太网帧就是干这个的。
标准的Ethernet II帧结构如下:
| 字段 | 长度(字节) | 说明 |
|---|---|---|
| 前导码(Preamble) | 7 | 同步时钟,10101010... 交替 |
| 帧起始定界符(SFD) | 1 | 10101011,标志帧开始 |
| 目标MAC地址 | 6 | 接收方网卡地址 |
| 源MAC地址 | 6 | 发送方网卡地址 |
| 类型/长度(EtherType) | 2 | 0x0800=IPv4,0x0806=ARP |
| 载荷(Payload) | 46~1500 | 上层协议数据(IP包) |
| 帧校验序列(FCS) | 4 | CRC32校验,检测传输错误 |
这里有个细节我当年踩过坑——前导码和SFD。很多教材说以太网帧从目标MAC开始,其实那是给上层软件看的。物理层真正在线路上跑的时候,前面还有8个字节的同步信号。我曾经在调试FPGA网卡时,忘了把前导码算进帧间隔,结果交换机死活不认我的数据,折腾了两天才发现是同步头没给够。
核心要点:以太网帧的最小载荷是46字节,最大是1500字节(MTU)。如果上层数据不足46字节,网卡会自动填充到46字节。这个填充在抓包时能看到,叫"Padding"。
MAC地址:网卡的身份证
MAC地址,全称Media Access Control Address,是网卡出厂时烧录的全球唯一标识。48位,前24位是OUI(厂商代码),后24位是厂商分配的序列号。
举个例子:00:1A:2B:3C:4D:5E,前三个字节00:1A:2B代表某厂商,后三个字节是流水号。你可以在命令行用ipconfig /all(Windows)或ifconfig(Linux)看到自己的MAC地址。
这里有个常见的误解——很多人以为MAC地址是绝对唯一的。其实不然。虚拟机的MAC地址经常冲突,有些廉价网卡厂商会重复使用OUI内的序列号。我在数据中心遇到过一台交换机上两个网口MAC地址一模一样,查了半天发现是某品牌服务器批量采购时烧录错了。所以,不要完全依赖MAC地址做安全认证。
避坑指南:我曾经在写网络驱动时,以为MAC地址前三位固定是厂商代码,结果遇到一个自定义协议栈,源MAC地址被改成了全0。网卡直接丢弃了这些帧,因为全0是非法地址。记住:MAC地址全0、全1(广播)、以及组播地址(第40位为1)都有特殊含义,不能随便用。
ARP协议:IP地址到MAC地址的翻译官
现在问题来了:你的电脑知道目标IP(比如192.168.1.1),但以太网帧里填的是MAC地址。怎么把IP变成MAC?ARP(Address Resolution Protocol)就是干这个的。
ARP的工作原理其实很简单,就四个字:问一圈。
- 主机A想发数据给192.168.1.1,但不知道它的MAC地址。
- 主机A在局域网内广播一个ARP请求:"谁是192.168.1.1?请告诉我你的MAC地址。"
- 所有主机都收到这个广播,但只有192.168.1.1回应:"我是,我的MAC是00:1A:2B:3C:4D:5E。"
- 主机A收到回应,把IP-MAC映射写入ARP缓存,然后发送数据。
你想想看,这个过程是不是很像你在小区里喊一嗓子找人?效率其实不高,所以ARP缓存很重要。默认缓存时间一般是2分钟,但不同操作系统有差异。
安全警告:ARP协议没有任何认证机制。任何人都可以伪造ARP回应,这就是ARP欺骗攻击的原理。我曾经在渗透测试中,用工具发送伪造的ARP包,让目标主机的流量全部经过我的机器,轻松抓到了明文密码。生产环境中,建议使用静态ARP表或DAI(Dynamic ARP Inspection)来防御。
抓包分析:用Wireshark看真实数据
光说不练假把式。咱们用Wireshark抓一个真实的ARP包看看。
假设你在Windows上打开Wireshark,选择网卡,然后执行ping 192.168.1.1。你会看到类似这样的输出:
No. Time Source Destination Protocol Length Info
1 0.000 00:0c:29:ab:cd:ef Broadcast ARP 42 Who has 192.168.1.1? Tell 192.168.1.100
2 0.002 00:1a:2b:3c:4d:5e 00:0c:29:ab:cd:ef ARP 60 192.168.1.1 is at 00:1a:2b:3c:4d:5e
展开第一个包,你会看到:
- 硬件类型:1(以太网)
- 协议类型:0x0800(IPv4)
- 硬件地址长度:6
- 协议地址长度:4
- 操作码:1(请求)
- 发送方MAC:00:0c:29:ab:cd:ef
- 发送方IP:192.168.1.100
- 目标MAC:00:00:00:00:00:00(未知,填0)
- 目标IP:192.168.1.1
第二个包是回应,操作码变成2,目标MAC填上了真实地址。注意看长度:请求包42字节,回应包60字节。为什么?因为回应包的数据链路层做了填充,凑够了以太网帧的最小长度64字节(包括FCS)。
实操建议:我建议你亲自抓一次ARP包。在Wireshark里设置过滤条件arp,然后清空ARP缓存(Windows用arp -d,Linux用ip neigh flush all),再ping一个局域网内的IP。你会看到完整的请求-回应过程。这个实验5分钟就能做完,但对理解ARP帮助极大。
ARP协议的工作流程与状态机
ARP不是简单的请求-回应就完了。它有一个完整的状态机,处理超时、重试、缓存更新等场景。我画了一张流程图,帮你理清逻辑:
这张图里有个关键点:ARP缓存不是永久的。每次成功收到回应,缓存条目会被更新并重置计时器。如果一段时间没用到,条目会过期被删除。这样做是为了应对网络拓扑变化——比如你换了网卡,IP没变但MAC变了,旧的缓存条目就会导致通信失败。
我记得有一次帮客户排查一个间歇性断网的问题,现象是每过几分钟就会丢几个包。抓包发现,ARP缓存过期后重新请求时,交换机没有及时转发广播包,导致超时。最后把ARP缓存超时时间从默认的120秒改到300秒,问题就解决了。嗯,有时候问题不在协议本身,而在参数调优。
物理层:信号是怎么在线路上跑的
数据链路层之上是帧,之下就是物理层。物理层负责把帧里的0和1变成电信号、光信号或无线电波。这里我不展开讲调制方式,但有几个关键概念你得知道:
- 编码方式:比如曼彻斯特编码、4B/5B编码、8B/10B编码。目的是保证信号中有足够的跳变,方便接收方恢复时钟。
- 传输介质:双绞线(Cat5e/Cat6)、光纤(单模/多模)、同轴电缆。不同介质支持的速率和距离不同。
- 速率与双工:10M/100M/1G/10G/25G/40G/100G... 全双工 vs 半双工。现在基本全是全双工了,半双工时代的CSMA/CD已经很少见。
个人经验:我曾经在调试一个10G光纤链路时,发现链路能起来但丢包率高达5%。用光功率计一测,接收光功率只有-18dBm,而规范要求至少-14dBm。换了一根尾纤后,光功率恢复到-10dBm,丢包瞬间消失。物理层的问题,很多时候就是信号质量的问题,别总往上层找原因。
数据链路层的核心功能:封装、寻址、差错检测
总结一下,数据链路层做了三件事:
- 封装成帧:把上层IP包加上MAC头尾,变成以太网帧。
- MAC寻址:用MAC地址标识源和目标网卡。
- 差错检测:FCS字段用CRC32校验,检测传输中的比特错误。注意,它只能检错,不能纠错。发现错误就直接丢弃帧,由上层协议(TCP)负责重传。
这里有个容易混淆的点:数据链路层不保证可靠传输。它只保证帧结构正确、地址正确、校验通过。至于帧丢了怎么办、乱序怎么办,那是上层的事。所以以太网被称为"尽力而为"的网络。
一句话总结:物理层负责把比特变成信号,数据链路层负责把信号变成帧,并用MAC地址和CRC保证帧能正确到达相邻节点。ARP是连接IP层和MAC层的桥梁,它让IP地址能映射到MAC地址,从而完成帧的封装。