前段时间又遇到了一个奇奇怪怪的需求, 就是在程序中获取物理网卡的MAC地址, 之所以强调是物理网卡, 是因为不想要虚拟机和VPN的虚拟网卡的MAC地址. 当然了, 这个需求还是有其实际意义的, 就是做软件的反盗版功能. 看似简单的功能, 其实花费了好长时间, 而且还没写出来, 就把写的部分代码和找的资料贴在这里吧.
其实思路很简单, 就是通过接口名, MAC地址前缀和注册表过滤掉虚拟网卡, 我用JavaScript写的代码如下(没写完):
const os = require('os'); const regedit = require('regedit').promisified; const VIRTUAL_IF_PREFIX = [ "00:00:00:00:00:00", // 空地址 "00:05:69", // VMware1 "00:0c:29", // VMware2 "00:50:56", // VMware3 "00:1c:14", // VMware4 "08:00:27", // VirtualBox1 "0a:00:27", // VirtualBox2 "00:03:ff", // Microsoft Virtual PC "00:15:5d", // Hyper-V "00:1c:42", // parallels1 "00:0f:4b", // virtual iron 4 "00:16:3e", // red hat xen, oracle vm, xen source, novell xen ]; const NCF = { NCF_VIRTUAL: 0x1, // 虚拟适配器 NCF_SOFTWARE_ENUMERATED: 0x2, // 软件模拟的适配器 NCF_PHYSICAL: 0x4, // 物理适配器 NCF_HIDDEN: 0x8, // 不显示用户接口 NCF_NO_SERVICE: 0x10, // 没有相关的服务(设备驱动程序) NCF_NOT_USER_REMOVABLE: 0x20, // 不能被用户删除(通过控制面板或设备管理器) NCF_MULTIPORT_INSTANCED_ADAPTER: 0x40, // 有多个端口, 每个端口作为单独的设备安装 NCF_HAS_UI: 0x80, // 支持用户接口(例如Advanced Page或Customer Properties Sheet) NCF_FILTER: 0x400, // 过滤器 }; function readRegistry() { try { let registry = cp.execSync("REG QUERY HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}", { encoding: "utf-8" }); console.log(registry); } catch (err) { console.error(err); } return null; } function getPhysicsIf() { const ifaces = os.networkInterfaces(); return Object.entries(ifaces) .filter(([dev, iface]) => { // 过滤掉名称中有virtual的网卡 if (dev.toLowerCase().includes("virtual")) { return false; } for (let item of iface) { // 过滤掉127.0.0.1和::1 if (item.ernal) { return false; } // 通过前缀过滤掉虚拟网卡 if (VIRTUAL_IF_PREFIX.some(value => item.mac.startsWith(value))) { return false; } // TODO 通过注册表过滤掉虚拟网卡 } return true; }) .map(([dev, iface]) => { return iface[0].mac; }); } function getMac() { const ifaces = getPhysicsIf(); return ifaces[0]; } console.log(`本机物理网卡的MAC地址为: ${getMac()}`);
这还只考虑了Windows上, 还没考虑跨平台, 不想玩了…接下来就贴点我找到的资料吧