关注

【Linux网络】深入理解数据链路层:从MAC帧到ARP协议的底层原理

在这里插入图片描述

🔥草莓熊Lotso:个人主页

❄️个人专栏: 《C++知识分享》 《Linux 入门到实践:零基础也能懂》

✨生活是默默的坚持,毅力是永久的享受!

🎬 博主简介:

在这里插入图片描述



前言

当你在浏览器输入网址按下回车,数据首先会被封装成 IP 数据报,但 IP 数据报并不能直接在物理网络上传输。它必须被进一步封装成以太网帧,通过 MAC 地址在局域网内找到下一跳设备。为什么我们的电脑能准确把数据发给路由器,而不是隔壁室友的电脑?为什么 IP 地址已经能标识全球主机,还需要 MAC 地址?这些问题的答案都藏在 TCP/IP 协议栈的数据链路层中。数据链路层负责解决 “怎么把数据从一个节点传到同一链路的另一个节点"的问题,是网络通信的” 最后一公里 "。本文将从以太网帧格式讲起,深入解析局域网通信原理、MTU 对上层协议的影响,最后拆解 ARP 协议的工作机制与安全问题,带你彻底搞懂数据链路层的核心逻辑。

在这里插入图片描述


一. 数据链路层基础与以太网

1.1 数据链路层的核心作用

对比理解网络层数据链路层

  • 网络层(IP):描述数据传输的全程起点和终点,解决 “去哪里” 的问题
  • 数据链路层(MAC):描述数据传输的每一个区间的起点和终点,解决 “怎么去下一跳” 的问题

经典类比(唐僧例子之白龙马):唐僧要去西天取经,IP 地址是 “长安→西天” 的全程路线,而 MAC 地址是每一段路的具体交通工具。白龙马负责把唐僧从长安送到两界山(第一跳),再由孙悟空负责从两界山送到高老庄(第二跳),每一段都只关心当前区间的起点和终点。

1.2 认识以太网

“以太网” 不是一种具体的网络,而是一套技术标准,同时定义了数据链路层和物理层的规范:

  • 物理层:规定使用双绞线作为传输介质,支持 10M/100M/1000M 等传输速率
  • 数据链路层:定义了以太网帧格式、访问控制方式(CSMA/CD)等

以太网是目前应用最广泛的局域网技术,与之并列的还有令牌环网、无线 LAN 等,但以太网凭借简单、高效的特点占据了绝对主导地位。

1.3 以太网帧格式详解(RFC 894)

以太网帧是数据链路层的基本传输单元,标准格式如下:

字段长度(字节)作用
目的 MAC 地址6接收方网卡的物理地址
源 MAC 地址6发送方网卡的物理地址
类型2标识上层协议类型:0x0800=IP,0x0806=ARP,0x8035=RARP
数据46~1500上层协议数据(IP 数据报、ARP 报文等)
CRC 校验4循环冗余校验,检测传输错误

关键细节:

  1. MAC 地址:48 位(6 字节)全球唯一的物理地址,网卡出厂时固化,格式为08:00:27:03:fb:19。虚拟机的 MAC 地址可能冲突,部分网卡支持手动修改。
  2. 数据长度限制
    1. 最大 1500 字节:即MTU(最大传输单元),超过则需要在网络层分片
    2. 最小 46 字节:不足时自动填充无用数据(PAD),接收方通过 IP 首部的总长度字段区分有效数据和填充

在这里插入图片描述

1.4 局域网通信的基本原理

局域网内的所有主机共享同一传输介质,通信采用广播 + 单播的方式:

  1. 主机 A 要给主机 E 发送数据,封装以太网帧,目的 MAC 填主机 E 的 MAC 地址
  2. 将帧发送到局域网中,所有主机都会收到这个帧
  3. 每台主机提取帧的目的 MAC 地址,与自己的 MAC 地址对比:
    1. 不匹配:直接在链路层丢弃,上层协议完全不知道
    2. 匹配:接收帧,剥离以太网首部,将数据部分交给上层协议处理

形象类比:在教室里老师喊 “张三”,所有人都听到了,但只有张三会站起来回应,其他人都会忽略这个喊话。

在这里插入图片描述
在这里插入图片描述

1.5 数据碰撞与 CSMA/CD

由于局域网是共享介质的,多台主机同时发送数据会产生数据碰撞,导致数据损坏。以太网采用 CSMA/CD(载波监听多路访问 / 碰撞检测) 机制解决这个问题:

  1. 载波监听:发送数据前先监听信道是否空闲
  2. 碰撞检测:发送数据时同时监听信道,如果检测到碰撞,立即停止发送
  3. 碰撞避免:等待一个随机时间后重新尝试发送

这就是为什么宿舍人多的时候网速会变慢:碰撞概率增加,单位时间内成功传输的数据量减少。

在这里插入图片描述

1.6 混杂模式与抓包原理

默认情况下,网卡只会接收目的 MAC 是自己的帧。但可以将网卡设置为混杂模式,此时网卡会接收所有经过的帧。

抓包软件(如 Wireshark)就是利用这个原理工作的。这也意味着:同一局域网内的任何主机都可以抓到你的数据,这也是为什么应用层加密(HTTPS)如此重要。

1.7 MTU 对上层协议的影响

MTU(最大传输单元)是数据链路层对上层数据的最大长度限制,以太网标准 MTU=1500 字节。

对 IP 协议的影响

  • 如果 IP 数据报长度超过 MTU,会在网络层分片
  • 每个分片都有相同的 16 位标识,不同的片偏移和 MF 标志
  • 任意一个分片丢失,整个 IP 数据报都会被丢弃,IP 层不负责重传

在这里插入图片描述
在这里插入图片描述

对 UDP 协议的影响

  • UDP 首部 8 字节,IP 首部 20 字节,因此 UDP 数据最大不能超过1500-20-8=1472字节
  • 超过 1472 字节会导致 IP 分片,丢包率大幅上升
  • UDP 本身不保证可靠性,因此使用 UDP 时应尽量控制报文大小

对 TCP 协议的影响

TCP 通过 MSS(最大段大小) 机制避免 IP 分片:

  • MSS = MTU - IP 首部长度 - TCP 首部长度
  • 标准以太网中 MSS=1460 字节(1500-20-20)
  • TCP 在三次握手时,双方会在 SYN 包的选项字段(kind=2)中交换自己支持的 MSS 值
  • 最终选择较小的 MSS 作为通信的最大段大小

这就是为什么 TCP 的滑动窗口是一段段发送的:每一段的大小都不超过 MSS,确保 IP 层不需要分片。

在这里插入图片描述

在这里插入图片描述

补充:逻辑闭环

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


二. ARP 协议:IP 地址到 MAC 地址的映射

2.1 ARP 协议的作用

我们知道 IP 地址可以标识全球主机,但数据链路层只能识别 MAC 地址。ARP(地址解析协议) 的作用就是:根据 IP 地址获取对应的 MAC 地址

ARP 是一个介于数据链路层和网络层之间的协议,它的报文需要封装在以太网帧中传输。
在这里插入图片描述
在这里插入图片描述

2.2 ARP 的工作原理

ARP 采用先广播请求,再单播应答的工作方式:

  1. 主机 A 要和主机 B 通信,知道主机 B 的 IP 地址但不知道 MAC 地址
  2. 主机 A 在局域网内广播ARP 请求包:“谁是 IP 地址 192.168.1.2?请告诉我你的 MAC 地址”
  3. 局域网内所有主机都会收到这个请求
  4. 只有主机 B 发现请求中的 IP 地址是自己的,于是单播ARP 应答包给主机 A:“我是 192.168.1.2,我的 MAC 地址是 08:00:27:03:fb:19”
  5. 主机 A 收到应答后,就可以用主机 B 的 MAC 地址封装以太网帧进行通信了

形象类比:在教室里你不知道张三的学号,于是大喊一声 “张三是谁?告诉我你的学号”,只有张三会回应你,告诉你他的学号。

2.3 ARP 报文格式详解

ARP 报文长度为 28 字节,封装在以太网帧的数据部分:

字段长度(字节)作用
硬件类型2链路层网络类型,1 = 以太网
协议类型2要映射的协议类型,0x0800=IP
硬件地址长度1MAC 地址长度,6 字节
协议地址长度1IP 地址长度,4 字节
操作码(op)21=ARP 请求,2=ARP 应答
发送端以太网地址6发送方 MAC 地址
发送端 IP 地址4发送方 IP 地址
目的以太网地址6接收方 MAC 地址(请求时填全 0)
目的 IP 地址4接收方 IP 地址

在这里插入图片描述

为什么 MAC 地址会出现两次?

细心的读者会发现,源 MAC 和目的 MAC 在以太网首部ARP 数据部分各出现了一次,这不是多余的吗?

这是严格的分层设计原则决定的:

  • 以太网首部的 MAC 地址是给网卡和交换机看的,决定帧在物理上要发给谁
  • ARP 数据部分的 MAC 地址是给操作系统的 ARP 协议看的,用于更新 ARP 缓存表

类比:你寄快递时,快递单(以太网首部)上写了收件人地址,包裹里的退款单(ARP 数据)上也写了收件人地址。快递员只看快递单,商家只看退款单,各司其职。

在这里插入图片描述
在这里插入图片描述

2.4 ARP 缓存机制

如果每次发送数据都要发 ARP 请求,效率会很低。因此每台主机都维护一个ARP 缓存表,记录 IP 地址到 MAC 地址的映射关系。

  • 查看 ARP 缓存表:arp -a(Windows/Linux 通用)
  • 缓存条目有过期时间:不同系统默认 15-45 秒,过期后会重新发送 ARP 请求
  • 为什么不能永久缓存?因为 IP 地址是动态分配的,主机可能更换网卡或下线

在这里插入图片描述

2.5 ARP 在跨网通信中的作用

ARP 不只是在目标子网才会发生,每一跳转发都需要 ARP

  1. 主机 A 要访问外网的百度服务器,首先查路由表,发现下一跳是网关 192.168.1.1
  2. 主机 A 发送 ARP 请求,获取网关的 MAC 地址
  3. 网关收到 IP 数据报后,查路由表发现下一跳是运营商路由器
  4. 网关发送 ARP 请求,获取运营商路由器的 MAC 地址
  5. 这个过程会一直重复,直到数据到达目标主机

结论:IP 地址是全程不变的,而 MAC 地址每经过一跳都会被重写。

2.6 实战:获取局域网内所有主机的 MAC 地址

我们可以通过ping 扫描 + ARP 缓存的方式获取局域网内所有在线主机的 MAC 地址:

# 1. 扫描局域网内所有IP(以192.168.1.0/24为例)
for i in {1..254}; do ping -c1 -W1 192.168.1.$i > /dev/null 2>&1 & done

# 2. 查看ARP缓存表,获取所有在线主机的MAC地址
arp -a

原理:ping 命令会触发 ARP 请求,对方主机回复后,MAC 地址就会被缓存到本地 ARP 表中。

2.7 RARP 协议(了解)

RARP(逆地址解析协议) 的作用与 ARP 相反:根据 MAC 地址获取 IP 地址。

  • 主要应用场景:早期的无盘工作站,启动时没有 IP 地址,通过 RARP 向服务器请求分配 IP
  • 现在已被 DHCP 协议取代,几乎不再使用

在这里插入图片描述

2.8 ARP 欺骗原理与安全问题

ARP 协议有一个致命的缺陷:它不验证 ARP 应答的合法性,只要收到 ARP 应答就会更新自己的缓存表。这就导致了ARP 欺骗攻击的可能。

中间人攻击原理:

  1. 攻击者主机 M 向主机 A 发送大量 ARP 应答:“我是网关 192.168.1.1,我的 MAC 地址是 macM”
  2. 同时向网关发送大量 ARP 应答:“我是主机 A 192.168.1.2,我的 MAC 地址是 macM”
  3. 主机 A 和网关的 ARP 缓存都会被更新,认为对方的 MAC 地址是攻击者的 MAC
  4. 所有主机 A 和网关之间的流量都会经过攻击者主机 M,攻击者可以窃听、篡改数据

断网攻击原理:

攻击者向目标主机发送 ARP 应答,将网关的 IP 地址映射到一个不存在的 MAC 地址,导致目标主机无法上网。

  • 下面的图中这个通过打开百度看透全栈可以关注一下
    在这里插入图片描述
    在这里插入图片描述

三. Linux 内核 ARP 源码解读

Linux 内核中 ARP 协议的实现位于net/ipv4/arp.c文件中,核心函数包括arp_rcv()(处理接收的 ARP 报文)和arp_send()(发送 ARP 请求 / 应答)。

3.1 ARP 报文接收函数:arp_rcv ()

int arp_rcv(struct sk_buff *skb, struct net_device *dev,
            struct packet_type *pt, struct net_device *orig_dev)
{
    struct arphdr *arp;
    struct net *net = dev_net(dev);

    // 检查报文长度是否合法
    if (skb->len < sizeof(struct arphdr))
        goto out_free;

    arp = arp_hdr(skb);

    // 只处理以太网和IP地址的ARP请求/应答
    if (arp->ar_hrd != htons(ARPHRD_ETHER) ||
        arp->ar_pro != htons(ETH_P_IP) ||
        arp->ar_hln != ETH_ALEN ||
        arp->ar_pln != 4)
        goto out_free;

    // 根据操作码处理请求或应答
    switch (ntohs(arp->ar_op)) {
    case ARPOP_REQUEST:
        arp_process(net, skb, arp);  // 处理ARP请求
        break;
    case ARPOP_REPLY:
        arp_process(net, skb, arp);  // 处理ARP应答
        break;
    default:
        goto out_free;
    }

    return 0;

out_free:
    kfree_skb(skb);
    return 0;
}

核心逻辑

  1. 检查报文长度和协议类型是否合法
  2. 根据操作码区分 ARP 请求和应答
  3. 调用arp_process()函数处理报文,更新 ARP 缓存表

3.2 ARP 报文处理函数:arp_process ()

static void arp_process(struct net *net, struct sk_buff *skb, struct arphdr *arp)
{
    __be32 sip, tip;
    unsigned char *sha, *tha;
    struct neighbour *n;

    // 提取发送端IP、MAC和目的IP
    sip = *(__be32 *)arp->ar_sip;
    tip = *(__be32 *)arp->ar_tip;
    sha = arp->ar_sha;
    tha = arp->ar_tha;

    // 更新ARP缓存表:无论请求还是应答,都更新发送端的IP-MAC映射
    n = neigh_lookup(&arp_tbl, &sip, dev);
    if (n) {
        neigh_update(n, sha, NUD_REACHABLE, 0, 0);
        neigh_release(n);
    }

    // 如果是ARP请求,且目的IP是自己,则发送ARP应答
    if (arp->ar_op == htons(ARPOP_REQUEST) &&
        inet_addr_type(net, tip) == RTN_LOCAL) {
        arp_send(ARPOP_REPLY, ETH_P_ARP, tip, dev, sip, sha, tha);
    }
}

核心逻辑

  1. 提取 ARP 报文中的发送端 IP、MAC 和目的 IP
  2. 无条件更新ARP 缓存表中发送端的 IP-MAC 映射(这就是 ARP 欺骗的根源)
  3. 如果是发给自己的 ARP 请求,则发送 ARP 应答

核心考点总结

  1. 以太网帧格式
    1. 目的 MAC (6B) + 源 MAC (6B) + 类型 (2B) + 数据 (46-1500B) + CRC (4B)
    2. MTU=1500 字节,最小帧长 64 字节(14+46+4)
  2. MAC 地址与 IP 地址的区别
    1. IP 地址:全程不变,标识主机的网络位置
    2. MAC 地址:每一跳都变,标识同一链路内的节点
  3. MTU 与 MSS
    1. MTU:数据链路层最大传输单元,以太网 = 1500 字节
    2. MSS:TCP 最大段大小,标准值 = 1460 字节
    3. TCP 在三次握手时协商 MSS,避免 IP 分片
  4. ARP 协议
    1. 作用:根据 IP 地址获取 MAC 地址
    2. 工作方式:广播请求,单播应答
    3. ARP 缓存:有过期时间,不验证应答合法性
    4. ARP 欺骗:利用 ARP 的无验证特性,实现中间人攻击或断网攻击

结尾:

🍓 我是草莓熊 Lotso!若这篇技术干货帮你打通了学习中的卡点:
👀 【关注】跟我一起深耕技术领域,从基础到进阶,见证每一次成长
❤️ 【点赞】让优质内容被更多人看见,让知识传递更有力量
⭐ 【收藏】把核心知识点、实战技巧存好,需要时直接查、随时用
💬 【评论】分享你的经验或疑问(比如曾踩过的技术坑?),一起交流避坑
🗳️ 【投票】用你的选择助力社区内容方向,告诉大家哪个技术点最该重点拆解
技术之路难免有困惑,但同行的人会让前进更有方向~愿我们都能在自己专注的领域里,一步步靠近心中的技术目标!

结语:数据链路层是整个 TCP/IP 协议栈的基础,它为上层网络层提供了可靠的链路传输服务。理解了数据链路层的工作原理,你就掌握了局域网通信的核心逻辑。虽然我们平时上网时几乎感觉不到数据链路层的存在,但它却是网络通信不可或缺的一部分。从以太网帧的封装到 ARP 地址解析,每一个细节都体现了计算机网络设计者的智慧。如果你觉得本文对你有帮助,欢迎点赞、收藏、关注,我会持续分享更多 Linux 底层和网络编程的技术干货。

✨把这些内容吃透超牛的!放松下吧✨
ʕ˘ᴥ˘ʔ
づきらど

在这里插入图片描述

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/2503_91389547/article/details/161764122

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--