前段时间又遇到了一个奇奇怪怪的需求, 就是在程序中获取物理网卡的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上, 还没考虑跨平台, 不想玩了…接下来就贴点我找到的资料吧