📚 第三章 数据链路
📄 一句话概括

MAC 地址 48 位:前 24 位是厂商标识,后 24 位是厂商自己编的序号。 第一个字节的最低两位还藏着两个开关:单播/组播、全球/本地。

📝 本节和前面几节的关系

3.1 说这一层要「寻址」,这一节看这个地址长什么样、怎么读。 本机六张网卡的 MAC 都能直接读出来,比看教材上的例子直观。

一、48 位怎么切

三段,各有各的归属:

部分 位数 谁分配 含义
OUI(前 3 字节) 24 IEEE 统一分配 厂商标识
序号(后 3 字节) 24 厂商自己编 这块网卡的编号
第一个字节的位 0 1 — 0 单播/1 组播
第一个字节的位 1 1 — 0 全球/1 本地

第一行那个 OUI 是要花钱买的:一个 OUI 大约几千美元,买了才有资格给网卡烧 MAC。 所以「查 MAC 前三位就知道是哪家厂商」是可靠的——这也成了「识别设备品牌」的常用手段。 第三、四行那两个位挤在同一个字节里:所以「第一个字节」既有厂商信息、又有类型信息。 这就是为什么 01-00-5e-… 一定是组播——01 的最低位是 1。 而 ff-ff-ff-ff-ff-ff 全 1,是广播(组播的特例)。

二、本机的六张网卡

读出来的表里有三张是「虚拟」的:

网卡 MAC 类型
WLAN 9C-B6-D0-0D-D5-0F 物理网卡,全球唯一
以太网 28-F1-0E-18-FA-25 物理网卡,全球唯一
本地连接* 1 9E-B6-D0-0D-D5-0F 虚拟,本地管理
本地连接* 2 AE-B6-D0-0D-D5-0F 虚拟,本地管理
蓝牙网络连接 9C-B6-D0-0D-D5-10 物理,全球唯一

第三、四行那两个 MAC 和 WLAN 只差一个字节:9C 变成 9E、AE,动的正是第一个字节。 这不是巧合,是 Windows 的「托管网络」虚拟适配器—— 它在物理网卡上挂一张软网卡,MAC 就近取一个不冲突的。 注意 9E 和 AE 的次低位都是 1:所以它们属于「本地管理」这一档, 意思是「不需要向 IEEE 申请,自己编的」。 虚拟机、软 AP、容器网桥都用这一档。 这个设计有个副作用:「本地管理」的 MAC 不能保证唯一, 两台机器只要用了同一个软件、同一套默认值,就可能撞号。 所以「靠 MAC 绑定做认证」在虚拟化环境里很容易被绕开。

三、这个空间够用多久

48 位是很大的数,但分下去就不大了:

范围 数量 说明
全部 48 位 约 281 万亿 2 的 48 次方
一个 OUI 可用 约 1677 万 2 的 24 次方
一个 OUI 的组播部分 约 838 万 最高位被借走了

第二行说明「每个厂商能造 1677 万块网卡」: 听起来不多,但一家厂商卖到这个量级就已经是全球前几名了。 所以 MAC 地址池至今没有耗尽——和 IPv4 的 43 亿个比,它的余量大得多。 第三行那个「最高位被借走」要说清:OUI 里有一个位固定是 0(表示单播厂商), 所以真正能用的 OUI 只有 2 的 23 次方、约 838 万个。 这也是为什么「MAC 地址有一半留给组播」这个说法会出现。 最后一件必须说清的事:MAC 地址可以改。 它烧在网卡的 EEPROM 里,但操作系统允许软件覆盖, 这个动作叫「MAC 地址克隆」,路由器里就有这个功能。 所以「MAC 唯一」是「厂商承诺」,不是「技术保证」——这也是为什么「靠 MAC 做门禁」并不安全。

四、动手 Demo:MAC 地址里藏着的三条信息

把本机每张网卡的 MAC 拆成 OUI、序号,再读出那两个标志位。 重点看虚拟网卡那两行:它们的类型位和物理网卡不一样。

import psutil

def mac_bytes(s):
    h = s.replace('-', '').replace(':', '')
    return [int(h[i:i + 2], 16) for i in range(0, 12, 2)]

for name, addrs in sorted(psutil.net_if_addrs().items()):
    for a in addrs:
        if a.family != psutil.AF_LINK or not a.address:
            continue
        b = mac_bytes(a.address)
        print('%-12s %s OUI=%02X-%02X-%02X 单播=%s 全球=%s'
              % (name, a.address, b[0], b[1], b[2],
                 (b[0] & 0x01) == 0, (b[0] & 0x02) == 0))

实跑输出:

--------------------------------------------------------------------
MAC 地址里藏着的三条信息
--------------------------------------------------------------------
**MAC 地址是 48 位,写成 6 组十六进制。**这 48 位不是流水号,前 3 字节是厂商标识、
后 3 字节是厂商自己编的序号;第一个字节的最低两位还有两个含义。

  网卡             MAC                   厂商标识     序号         单播/组播     全球/本地
  -------------------------------------------------------------------------------------------
  WLAN             9C-B6-D0-0D-D5-0F     9C-B6-D0     0D-D5-0F     单播           全球唯一
  以太网           28-F1-0E-18-FA-25     28-F1-0E     18-FA-25     单播           全球唯一
  本地连接* 1      9E-B6-D0-0D-D5-0F     9E-B6-D0     0D-D5-0F     单播           本地管理
  本地连接* 2      AE-B6-D0-0D-D5-0F     AE-B6-D0     0D-D5-0F     单播           本地管理
  蓝牙网络连接     9C-B6-D0-0D-D5-10     9C-B6-D0     0D-D5-10     单播           全球唯一

**第一字节最低位是 0 就是单播、是 1 就是组播**:
**所以 `01-00-5e-…` 一定是组播**(01 的最低位是 1),**`ff-ff-ff-ff-ff-ff` 是广播**(全 1,
也算组播的一种特例)。
**第一字节次低位是 0 表示「全球唯一」(跟厂商要的),是 1 表示「本地管理」(自己编的)**:
**上面表里 `9E` 和 `AE` 开头的那两个,次低位都是 1**——
**它们是虚拟网卡,不需要向 IEEE 申请,直接用「本地管理」这一档。**
**注意这两张虚拟网卡的 MAC 只跟 WLAN 差一个字节**:
**`9C-B6-D0-0D-D5-0F` 变成 `9E-B6-D0-0D-D5-0F`,只把第一个字节的次低位翻了一下。**
**这是 Windows 的「托管网络」虚拟适配器的做法**:
**在同一块物理网卡上挂一张软网卡,MAC 就近取一个不冲突的号。**
**48 位能编多少个地址**:
**2 的 48 次方 = 281474976710656 个,约 281.47 万亿个。**
**而前 24 位已经分给了厂商(约 1.6 万个 OUI)。**
**所以每个厂商手里只有 2 的 24 次方、约 1677 万个地址**——
这个量级决定了「一块网卡一个 MAC」是可以撑很久的。
**顺带一个常被问的问题**:**MAC 地址能改吗?能。**
**它烧在网卡里,但操作系统允许软件覆盖(叫「MAC 地址克隆」)**,
**所以「MAC 地址唯一」是「厂商承诺」,不是「技术保证」**——
**这也是为什么「靠 MAC 做认证」并不可靠。**

五张网卡全是单播(最低位都是 0): 因为网卡自己的地址不能是组播——组播地址是「一群设备共用」的,不能烧在单块网卡上。 虚拟网卡那两行「全球 = False」:9E 是 1001 1110、AE 是 1010 1110, 次低位都是 1,所以是「本地管理」。 物理网卡的 9C 是 1001 1100、28 是 0010 1000,次低位都是 0,所以是「全球唯一」。 这两组地址只差一个字节这件事,本身就是线索: 虚拟适配器不是「凭空造一个地址」,而是「在物理网卡地址上改一位」。 好处是不用去 IEEE 申请,也不会和真正的厂商地址撞车—— 因为次低位是 1 的那一半地址空间,IEEE 根本不会分出去。

30 秒实验

  1. 把 0x01 换成 0x02,看输出变成什么(那是「组播」判断)。
  2. 找一台安卓手机连上同一个 WiFi,看路由器的 ARP 表里它的 MAC 属于哪个 OUI。
  3. 算一下:2 的 48 次方除以全球人口,平均每人能分几个 MAC?

常见误区

  1. 以为 MAC 地址不能改。 操作系统允许软件覆盖,「克隆 MAC」是路由器的常见功能。
  2. 以为 MAC 全球唯一是技术保证。 它是厂商承诺,而且虚拟网卡本来就可能撞号。
  3. 以为 MAC 的每一位都归厂商用。 第一个字节有两位被借走,一位表单播/组播, 一位表全球/本地。
自测三问(点开对答案) 1. MAC 地址的三段各是什么? —— **前 3 字节是 OUI(IEEE 分给厂商),后 3 字节是厂商自己编的序号。** 第一个字节的位 0 表单播/组播,位 1 表全球/本地。 2. `01-00-5e-00-00-fb` 是单播还是组播?为什么? —— **组播。** 第一字节 `01` 的最低位是 1,所以是组播地址。 3. 为什么虚拟网卡的 MAC 常常是「本地管理」这一档? —— **因为它不需要向 IEEE 申请。**自己编一个、把次位置 1,就不会和真正的厂商地址冲突。

下一节看:一根线上接了很多设备时,它们怎么排队说话。

相关笔记