longjing 2020-08-07
MAC 地址(Media access control address)是分配给网络接口控制器(Network interface controller, NIC)的唯一标识符,它会在网络段中充当网络地址使用1,所有具有网卡的主机都有单独的 MAC 地址,该地址总共包含 48 位,占 6 字节的空间,可以表示 281,474,976,710,656 个网络设备,一个正常的 MAC 地址如下所示的格式表示,每个字节都会使用两位 16 进制的数字:
6e:77:0f:b8:8b:6b
因为 MAC 地址需要保证唯一,所以 IEEE 会根据设备的制造商分配地址段,48 位 MAC 地址的前 24 位是设备制造商的标识符2,也就是组织唯一标识符(Organizationally Unique Identifier,OUI),后面的 24 位是序列号;如果每个设备制造商都能保证在同一个命名空间中的全部 MAC 地址唯一,那么全世界所有的 MAC 地址就可以保证唯一。
图 1 - MAC 地址
MAC 地址可以使用两种不同的格式表示,分别是 48 位的 EUI-48 和 64 位的 EUI-643,本文会使用 EUI-48 格式的 MAC 地址,EUI-64 主要用于 IPv6 协议,我们在这篇文章就不展开讨论了。在通常情况下,MAC 地址会使用 24 位表示组织的序列号,但是因为很多组织不会生产这么多的设备,所以在实际操作中会划分出三种不同大小的地址块4:
图 2 - MA-L, MA-M, MA-S
这三种不同大小的地址块价格也完全不同,MA-L 的注册价格为 2995 美金,而 MA-S 的注册价格为 755 美金,感兴趣并且有需要的读者可以在 IEEE 的官方购买5,在理想情况下,所有的地址加起来价值大概在 52 万亿美金左右,果然定义和掌握了标准就可以躺着等别人注册来赚钱。
这种由机构分发 MAC 地址段并由设备商保证地址唯一的方式就是为了保证全世界所有硬件的网络地址唯一,但是在实际操作中,全球唯一是无法保证的而且我们也并不需要地址的全球唯一,这主要因为以下两个原因:
无论是在 Linux 上还是在 macOS 上,修改网络设备的 MAC 地址都是非常简单的。在 Linux 操作系统中我们可以使用命令 ifconfig 修改设备上的 MAC 地址:
$ ifconfig eth0 | grep ether ether 6e:77:0f:b8:8b:6b txqueuelen 1000 (Ethernet) $ ifconfig eth0 down $ ifconfig eth0 hw ether 6e:77:0f:b8:8b:6a $ ifconfig eth0 up $ ifconfig eth0 | grep ether ether 6e:77:0f:b8:8b:6a txqueuelen 1000 (Ethernet)
只要我们使用上述的命令就可以轻松地修改当前网卡的 MAC 地址,不过建议不要在远程的 Linux 机器上使用,最好在本地的 Linux 上测试相关的命令,在修改测试完成之后也最好使用命令将 MAC 地址改回去;在 macOS 上修改 MAC 地址也可以使用 ifconfig 命令,使用的方式与 Linux 几乎完全相同。
因为 MAC 地址是与硬件绑定的,所以这种修改 MAC 地址的方式其实都是临时的,一旦操作系统重启,这些变更就会被系统撤销,想要让类似的变更永久生效需要在系统重启时执行相应的命令或者修改对应的网卡配置文件6。
所有的计算机和终端设备都需要通过网络适配器连接到局域网中,每一个适配器都有唯一的链路层地址,也被叫做 LAN 地址或者 MAC 地址,MAC 地址被设计成了扁平结构,它们不会随着所处网络的不同而发生改变。
当设备的网络适配器想要向其他的适配器发送数据帧时,它会将目的适配器的 MAC 地址插入到如下所示的以太网帧中,每个以太网帧都与 IP 数据报类似,包含源地址和目标地址,只是以太网帧中的地址是 MAC 地址,而 IP 数据报中的地址是 IP 地址:
图 3 - 以太网帧
局域网中的数据传输不是通过网络层的 IP 地址进行路由和转发的,然而 IP 地址一般都是发送数据主机知道的唯一信息,想要在局域网中发送数据,还是需要知道它们的 MAC 地址。当我们的设备想要向其他的设备发送数据时,它会先通过 ARP(Address Resolution Protocol,地址解析协议) 在局域网中获取目的 IP 地址对应的 MAC 地址:
图 4 - 地址解析协议
在局域网中我们一般会使用集线器(Hub)或者交换机(Switch)来连接不同的网络设备。因为在集线器连接的局域网中,所有的数据帧都会被广播给局域网内的全部主机,所以使用相同的 MAC 地址一般也不会出现太多的问题;但是交换机会学习局域网中不同设备的 MAC 地址并将数据帧转发给特定主机,所以如果局域网是由交换机构成的,就会影响网络的通信。
图 5 - 集线器和交换机
假设局域网中的具有两台 MAC 地址完全相同的网络设备 A 和 B,即 6e:77:0f:b8:8b:6b,当设备 A 想要向设备 B 发送以太网帧时会遇到如下所示的情况:
因为交换机的 MAC 地址学习策略,所以我们不能在同一个局域网中使用相同的 MAC 地址,但是因为 MAC 地址是链路层网络中的概念,跨局域网的网络传输需要通过网络层的 IP 协议,所以在不同的局域网中使用相同的 MAC 地址就不存在类似的问题了。
MAC 地址是链路层网络中的重要概念,在局域网中会通过 MAC 地址转发以太网数据帧,全球唯一的 MAC 地址是非常理想的情况,然而在实际的网络场景中,我们不需要保证如此强的限制:
上述的结论不是说全球唯一的 MAC 地址没有意义,与此相反,我们应该尽可能保证 MAC 地址的唯一,这样在组建局域网时才不需要手动确认所有设备的 MAC 地址,减少网络工程师的工作量。到最后,我们还是来看一些比较开放的相关问题,有兴趣的读者可以仔细思考一下下面的问题:
如果对文章中的内容有疑问或者想要了解更多软件工程上一些设计决策背后的原因,可以在博客下面留言,作者会及时回复本文相关的疑问并选择其中合适的主题作为后续的内容。
Wikipedia: Mac Address https://en.wikipedia.org/wiki/MAC_address ??
Organizationally Unique Identifier Vendor List http://standards-oui.ieee.org/oui.txt ??
Creating EUI-64 based Interface Identifiers https://tools.ietf.org/html/rfc2373#page-19 ??
What is a MA-L, MA-M, MA-S assignment? https://macaddress.io/faq/what-is-a-ma-l-ma-m-ma-s-assignment ??
MAC Address Block Large (MA-L) https://standards.ieee.org/products-services/regauth/oui/index.html ??