在您控制硬件配置并确定所有具有相同硬件模型的设备确实具有其网络接口的唯一 MAC 地址的情况下,编写使用该假设的代码有什么缺点吗?(根据一些回复的说明:我不会使用这个假设编写网络代码。它只是一种低接触的方式,让每个设备都有一个 uuid,而无需在部署到现场之前手动生成并使用 id 更新设备 HDD)
这件事的背景是,我正在研究为客户实现私有硬件 IOT 类型的实现。我们将提供一组具有网络功能的硬件设备,以安装在远程位置。然后,这些设备将通过发送消息与 API 进行通信。为了降低设置的复杂性,我希望在消息中发送设备上网络接口的 MAC 地址,以便将这些消息绑定回 API 端的“device_id”。我的想法是,通过使其成为在使用前无需在设备上设置的东西,只需在正常运行期间查询即可。我可以放心地假设,我们可以确定每个设备的 MAC 地址实际上是唯一的,并且我们可以控制何时/是否更换设备,以知道该 device_id 的消息现在将具有不同的 MAC 地址。
答案1
根据您的陈述,您可以在配置期间确认制造商 MAC 在您正在创建的设备网络中实际上是唯一的(这本身并不是确定的,即使它应该是),您可能可以继续进行,但请考虑以下问题:
您是否使用 MAC 进行安全检查(身份验证、授权)?如果是,MAC 是不够的。不要考虑它。使用加密结构,并安全地传输任何身份验证请求。
48 位宽度够用吗?可能够用,但值得一问。
您是否需要通过更换网卡来修复设备?
如果您确实更换了整个设备或更换了其网卡,您是否需要将新地址与数据库中的现有密钥关联起来,以确保部署位置的数据收集连续性?
是否有任何维护接口可供用户(无论是否授权)在 ROM、驱动程序或操作系统级别更改网卡?如果攻击者修改 MAC,他们可能会在您的数据中引入漏洞。
您的数据是否会使用 MAC 作为密钥与其他数据源连接?
除了简单地导航设备所连接的第 2 层 LAN(有线或无线)之外,您是否还会将 MAC 用于其他网络目的?
您的设备所连接的局域网是专用网络,还是大量临时客户端(如员工手机)所连接的网络?
如果你的答案是
NO, yes, no, no, no, no, no, private
那么我想不出你的计划有什么真正的缺陷。
请记住,您不需要全局唯一的 MAC 来实现这一点;您只需要确保调用 API 的 Internet 设备子集是唯一的。就像在两个不同城市分配的重复网卡不会发生冲突(因为它们位于不同的 LAN 上)一样,如果 MAC 从未调用过您的 API,则不会在 MAC 上发生数据库密钥冲突。
答案2
MAC 地址不是唯一的
MAC 可能会重复,而且会重复。原因有很多,其中之一是不必(全球)独一无二。
MAC 在本地网络上必须是唯一的,这样 ARP/NDP 才能发挥作用,交换机也知道将传入的数据报发送到哪里。通常(不一定)这个先决条件得到满足,一切工作正常,因为在同一个 LAN 上有两个相同 MAC(即使它们不是唯一的)的可能性很低。
另一个原因是设备数量比地址数量多。虽然 48 位地址听起来足够所有人使用,但事实并非如此。
地址空间分为两个 24 位部分(这稍微复杂一些,但我们先忽略这些琐碎的细节)。其中一个部分是 OUI,您可以向 IEEE 注册并分配给您的公司,费用约为 2000 美元。剩下的 24 位,您可以随意使用。当然,您可以注册多个 OUI,这是大公司的做法。
以英特尔为例。他们一共注册了 7 个 OUI,总共有 1.16 亿个地址。
我的电脑主板(使用 X99 芯片组)以及我的笔记本电脑主板以及每一个我过去 10-15 年拥有的 x86 计算机的芯片组中包含英特尔网卡。世界上基于英特尔的计算机数量肯定远不止 1.16 亿台。因此,它们的 MAC不可能是独一无二的(从全球独一无二的意义上来说)。
此外,据报道,呃……更便宜的……制造商只是从其他人的 OUI“窃取”地址。换句话说,他们只是使用了一些随机地址。我也听说过制造商对整个产品系列使用相同的地址。这两种情况都不符合要求,也没有什么意义,但你能做些什么呢?这些网卡确实存在。再次:它成为实际的如果地址用于其预期用途,问题仍然很低,你需要有两个在同一个局域网上甚至注意到。
现在,该如何解决你的问题呢?
解决方案可能比您想象的要简单。您的 IoT 设备很可能需要一些时间概念,通常时间是通过 NTP 自动获取的。NTP 的典型精度在微秒范围内(是的,是微秒,而不是毫秒)。我刚跑去ntpq -c rl
确认了一下,被告知是 2 -20。
您的两台设备在同一微秒内首次开机的可能性非常低。当然,这种情况通常有可能发生(特别是如果您在很短的时间内销售了数百万台,恭喜您成功了!)。但可能性不大——实际上不会发生。因此,请节省首次启动永久存储后的时间。
您的 IoT 设备在每个设备上的启动时间都是相同的。但事实并非如此。
给定一个高分辨率计时器,即使在同一台设备上,每次启动时间也存在明显差异。可能只有几个时钟滴答声不同(或者几十万个,如果你读过类似 CPU 的时间戳计数器),所以总体上不是非常独特,但它肯定会增加一些熵。
同样,启动所需的时间connect
首次访问 API 站点时返回的值每次都会略有不同,但可以测量。同样,getaddrinfo
首次查找 Web API 的主机名时,每个设备所花的时间也会略有不同,但可以测量。
将这三四个熵源(MAC 地址、首次开机时间、首次启动时间、连接时间)连接起来,然后计算哈希值。MD5 就足以满足这一目的。这样,您就是独一无二的。
虽然这并不确实保证唯一性,它“几乎”保证了这一点,失败的可能性微乎其微。您必须拥有两台具有相同 MAC 的设备,它们在同一微秒内首次打开,并且启动和连接到您的站点所花的时间完全相同。这不会发生。如果确实发生了,您应该立即开始玩彩票,因为从各方面来看,您肯定会赢。
但是,如果“不会发生”还不足以保证,只需在设备首次访问您的 Web API 时向每个设备传递一个按顺序递增的数字(在服务器上生成)。让设备存储该数字,就大功告成了。
答案3
由于这里的问题实际上是一个 XY 问题,我将着手解决这个问题:如何在第一次启动时获取硬件的唯一标识符,而无需在其上预加载标识符。所有好的方法实际上都归结为一件事:拥有一个熵源。
如果你的硬件有专门设计为硬件熵源的东西(注意:这基本上是任何适当的物联网设备实现的要求,因为它是 TLS 所必需的,所以你的硬件应该考虑到这一点,只需使用它即可。如果没有,你必须发挥创造力。
幸运的是,几乎每一台计算机都有一个极好的熵源:晶体振荡器(时钟)。给定晶体的速率不仅取决于细微的温度变化,而且甚至受温度的影响滞后以非线性方式。但是,要测量熵,您需要第二个时钟来计时第一个时钟。这意味着,只要您的计算机至少有两个时钟可供采样,您就可以使用其中一个时钟测量另一个时钟的速率作为非常高质量的熵源。
答案4
我不喜欢假设 XY 问题,因为 OP 这样做事通常有一个很好的虽然很复杂的理由,但你可能需要研究其他方法来为每个设备生成唯一的标识符,就像 MAC 地址一样,它是“内置”在设备中的,不需要生成你自己的标识符。
如果所有设备都来自同一制造商(或者更好的是,同一型号),则可以使用序列号生成标识符。但是,即使您将它与制造商名称和型号结合起来,这种方法在不同制造商的设备之间也不太有效,因为对于嵌入式/专有设备,序列号格式不同,获取序列号的 API 也不同。设备序列号的替代方法可能是主板、CPU 或硬盘的序列号(我相信 Windows 许可使用这些的组合)。
还值得记住的是,文件系统格式化程序通常会为每个文件系统生成一个唯一的 ID。除非您从同一个映像准备所有设备(出于不相关的原因,我建议这样做),否则每个硬盘都会有一个存储在文件系统中的唯一 ID,您可以使用它。
话虽如此,但确实没有理由不是使用 MAC 地址,特别是如果您在配置过程中可以确定它们实际上是唯一的(尽管这甚至不是必需的,假设我们讨论的设备不超过几千台)。当然,请记住,您使用的任何东西都可能被设备欺骗,因此不要依赖它在不受信任的环境中进行身份验证(您说这是一个私人设置,所以大概这是一个“受信任”的环境,您不关心您的客户端欺骗他们自己的设备对抗他们自己的服务器,但如果设备的管理权移交给第三方或最终用户,他们显然应该记住这一点)。