Mac地址作为电脑唯一标识符-nodejs

205 阅读4分钟

一、MAC地址获取的可变因素

1、多样性

  1. 多网络接口:现代计算机和服务器通常配备有多个网络接口,包括物理网络接口和虚拟网络接口。每个接口都可能有自己的MAC地址,这增加了获取特定MAC地址的复杂性。
  2. 虚拟化环境:在虚拟化环境中,如VMware、KVM等,虚拟机会被分配虚拟网络接口和相应的MAC地址。这些MAC地址可能与宿主机的物理MAC地址不同,且可能随着虚拟机的迁移而发生变化。

2、可变性

  1. 硬件更换:更换网络接口卡(NIC)会直接导致MAC地址的更改。这是因为MAC地址是绑定在NIC上的,更换NIC后,新的NIC将具有不同的MAC地址。
  2. 操作系统和驱动程序:某些操作系统或驱动程序允许用户更改MAC地址,这称为MAC地址欺骗或克隆。虽然这种更改在大多数情况下是非法的,但在某些特定场景下(如测试或安全测试)可能会被使用。
  3. 网络管理策略:网络管理员可能会出于安全或管理目的更改MAC地址,例如,在部署新的网络设备或重新配置网络时。

3、人为因素

  1. 错误配置:网络管理员或用户在配置网络时可能会错误地输入MAC地址,导致无法正确识别设备。
  2. 恶意修改:恶意用户或软件可能会更改MAC地址以逃避检测或进行网络钓鱼攻击。

二、如何应对Mac地址可变性

虚拟化环境中MAC地址非唯一的情况:

  1. 检测虚拟化环境:首先确认系统是否运行在虚拟化环境中。
  2. 检查MAC地址唯一性:在虚拟化环境中,通过管理工具或脚本定期检查各虚拟机的MAC地址,确认其唯一性。
  3. MAC地址冲突检测:如果发现MAC地址冲突,应立即进行冲突检测,确定哪些虚拟机或设备使用了相同的MAC地址。
  4. 处理MAC地址冲突:
    • 更新MAC地址:对于冲突的虚拟机,可以手动或通过自动化脚本更新其MAC地址。
    • 更新映射表:确保网络设备的MAC地址表(如交换机的CAM表)得到更新,以反映最新的MAC地址与虚拟机/设备的映射关系。

处理Mac地址漂移情况:

  1. 监控MAC地址漂移:实施持续的监控机制,以检测网络中MAC地址的异常变化。
  2. 分析漂移原因:一旦检测到MAC地址漂移,立即分析其原因,可能包括配置错误、网络故障或安全事件等。
  3. 根据原因处理:
    • 配置错误:检查并修改虚拟化配置,确保MAC地址分配正确无误。
    • 网络故障:检查网络设备(如交换机、路由器)的运行状态,修复任何可能的故障。
    • 安全事件:实施安全措施,如隔离受影响的虚拟机/设备,调查并防止进一步的攻击。

三、实现代码

1、获取电脑上所有的Mac地址

方法1 使用第三方库, npm install systeminformation

const si = require('systeminformation');  
  
si.networkInterfaces().then(data => {  
    console.log(data); // 包含所有网络接口的详细信息,包括MAC地址  
    data.forEach(interface => {  
        console.log(`${interface.iface}: ${interface.mac}`);  
    });  
}).catch(error => {  
    console.error(error);  
});

方法二

/**
输出本机上所有的Mac地址
**/
const os = require('os');

function getPhysicalMacAddresses() {
  const interfaces = os.networkInterfaces();
  const macAddresses = { wired: [], wireless: [] };

  for (const [name, ifaceArray] of Object.entries(interfaces)) {
    ifaceArray.forEach(iface => {
    console.log("name=>"+name);
    console.log("ifaceArray=>"+ifaceArray);
    }
  }

2、思路以及实现

20240823完善代码


/**
1、检查并获取有线网卡的MAC地址(如果存在)。 如果没有有线网卡,则获取Wi-Fi接口的MAC地址。
2、最好用管理员打开。
3、如果系统上有多个网络接口(例如,多个有线网卡或多个Wi-Fi适配器),你需要确定选择哪个接口的MAC地址。通常,你会选择“主”接口,但这需要一种方法来识别它。
4、排除掉虚拟化的网络接口。
5、MAC地址可能被视为敏感信息,要告知用户。
6、MAC地址被篡改情况暂不考虑。
**/
const os = require('os');

function getPhysicalMacAddresses() {
  const interfaces = os.networkInterfaces();
  const macAddresses = { wired: [], wireless: [] };

  for (const [name, ifaceArray] of Object.entries(interfaces)) {
    ifaceArray.forEach(iface => {
      if (!iface.internal && iface.family === 'IPv4') {
        const isVirtual = name.toLowerCase().includes('vm') || name.toLowerCase().includes('vbox') || name.toLowerCase().includes('virtual');

        if (!isVirtual) {
          if (name.toLowerCase().includes('eth') || name.toLowerCase().includes('en')) {
            macAddresses.wired.push(iface.mac);
          } else if (name.toLowerCase().includes('wlan') || name.toLowerCase().includes('wi-fi') || name.toLowerCase().includes('wl')) {
            macAddresses.wireless.push(iface.mac);
          }
        }
      }
    });
  }

  console.log("Wired MAC Addresses (Physical):", macAddresses.wired);
  console.log("Wireless MAC Addresses:", macAddresses.wireless);
  return macAddresses.wireless;
}

20240827完善代码

/**
 * 1.优先尝试获取有线网卡的MAC地址。
   2.如果没有找到,则尝试获取无线网卡的MAC地址。
   3.如果仍然没有找到,最后获取虚拟网卡的MAC地址。
 */

const os = require('os');

function getPhysicalMacAddresses() {
  const interfaces = os.networkInterfaces();
  let macAddress = '';

  function findMacAddress(keywords, excludeKeywords = []) {
    // 对接口名称排序,保证每次处理的顺序一致
    const sortedNames = Object.keys(interfaces).sort(); 

    for (const name of sortedNames) {
      const ifaceArray = interfaces[name];
      const nameLower = name.toLowerCase();

      if (excludeKeywords.some(keyword => nameLower.includes(keyword))) {
        continue;
      }

      for (const iface of ifaceArray) {
        if (!iface.internal && iface.family === 'IPv4') {
          if (keywords.some(keyword => nameLower.includes(keyword))) {
            return iface.mac;
          }
        }
      }
    }
    return null;
  }

  // 优先顺序:有线 -> 无线 -> 虚拟
  macAddress = findMacAddress(['eth', 'en', '本地连接'], ['vm', 'vbox', 'virtual', 'wsl']) || 
               findMacAddress(['wlan', 'wi-fi', 'wl'], ['vm', 'vbox', 'virtual', 'wsl']) || 
               findMacAddress(['vm', 'vbox', 'virtual', 'wsl']);

  console.log("Selected MAC Address:", macAddress);
  return macAddress;
}

getPhysicalMacAddresses();