怎么利用Node獲取物理網卡mac地址

蝸牛 互聯網技術資訊 2022-10-16 18 0

本篇內容介紹了“怎么利用Node獲取物理網卡mac地址”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

在基于 Electron 的應用中,有一個業務需求是獲取物理網卡的 Mac 地址以用于客戶機唯一性識別。

剛接到需求時你可能會想,這還不簡單,調用 Node.js 的 os 模塊提供的 networkInterfaces API 就行了。

于是馬上開干:

import?{?networkInterfaces?}?from?'os';

?function?isZeroMac(mac)?{
??return?/^(0{1,2}[:-]){5}0{1,2}$/.test(mac);
}

function?getMac(family?=?'IPv4')?{
????const?nif?=?networkInterfaces();
????for?(const?list?of?Object.values(nif))?{
????????const?item?=?list.find(d?=>?!d.internal?&&?!isZeroMac(d.mac)?&&?(!d.family?||d.family?===?family));
????????if?(item)?return?item.mac;
???}

???return?'';
}

兩分鐘就寫完了,測試一下返回值也與 ipconfig/ifconfig 打印的信息一致,滿懷信心的提交代碼完工。

測試同學當天驗證了一下表示沒什么問題,然而第二天卻找上門了:同一臺電腦今昨兩天取到的值不一樣。經過各種排查分析,最后才發現原來這位測試妹妹因疫情管控居家了,用著 VPN 遠程接入辦公網絡干活呢。

原來開 VPN 的時候使用了虛擬網卡,此時你才發現事情并沒有那么簡單。實際上,在存在 VPN、虛擬機等場景下,都可能會使用到虛擬網卡。

1. 根據 networkInterfaces 返回值的字段值過濾

networkInterfaces 可以獲取到所有網卡的基本信息,可根據 internal、mac 等字段的值做一次過濾,得到有效的信息:

const?isValid?=?(item)?=>?item.internal?===?false?&&?!isZeroMac(item.mac);

但是對于 VPN、虛擬機等存在虛擬網卡的場景下,僅根據該信息無法進行有效區分。

2. 根據虛擬網卡 Mac 特征過濾

如果能夠得到虛擬網卡的特征,則可基于相關特征點進行識別與過濾。

基于某內部項目長達六年的實踐積累以及參考 vscode 中類似的實現,我們得到了一個常見虛擬網卡默認 Mac 地址特征的列表,參考如下:

//?see?https://standards-oui.ieee.org/oui/oui.txt
const?virtualMacPrefix?=?new?Set([
??'00:05:69',?//?vmware1
??'00:0c:29',?//?vmware2
??'00:50:56',?//?vmware3
??'00:1c:14',?//?vmware
??'00:1c:42',?//?parallels1
??'02:00:4c',?//?Microsoft?Loopback?Adapter?(微軟回環網卡)
??'00:03:ff',?//?microsoft?virtual?pc
??'00:0f:4b',?//?virtual?iron?4
??'00:16:3e',?//?red?hat?xen?,?oracle?vm?,?xen?source,?novell?xen
??'08:00:27',?//?virtualbox
]);

于是可以據此實現一個是否為虛擬網卡的判斷方法 isVirtualMac

export?function?isMac(mac:?string)?{
??return?/^([\da-f]{1,2}[:-]){5}([\da-f]{1,2})$/i.test(mac);
}

export?function?formatMac(mac:?string)?{
??return?String(mac).trim().toLowerCase().replace(/-/g,?':');
}

export?function?isVirtualMac(mac:?string)?{
??return?isMac(mac)?&&?virtualMacPrefix.has(formatMac(mac).slice(0,?8));
}

據此可對 getMac 方法改進如下:

function?getMac(family?=?'IPv4')?{
????const?nif?=?networkInterfaces();
????for?(const?list?of?Object.values(nif))?{
????????const?item?=?list.find(d?=>?!d.internal?&&?!isZeroMac(d.mac)?&&?(!d.family?||d.family?===?family)?&&?!isVirtualMac(d.mac));
????????if?(item)?return?item.mac;
???}

???return?'';
}

3. 根據描述關鍵字特征過濾

在 Windows 系統下,可以通過執行 ipconfig /allwmic nic get 命令得到所有網卡的詳情,其中包含了描述信息。

基于實踐經驗分析,我們總結了一個常見虛擬網卡描述關鍵字的特征列表,參考如下:

const?virtualDescList?=?['virtual',?'?vpn?',?'?ssl?',?'tap-windows',?'hyper-v',?'km-test',?'microsoft?loopback'];

若經過前述規則過濾之后仍然存在多個網卡信息,則可繼續獲取網卡詳情,并基于 virtualDescList 列表以嘗試進一步的過濾處理:

//?執行?wmic?nic?get?命令獲取所有網卡詳情
function?getNetworkIFacesInfoByWmic()?{
??//?略
}

if?(hasMutiMac(list))?{
??const?info?=?await?getNetworkIFacesInfoByWmic();

??list?=?list.filter(item?=>?{
????if?(!info.config[item.mac])?return?true;
????const?desc?=?String(info.config[item.mac].desc).toLowerCase();
????return?!virtualDescList.some(d?=>?desc.includes(d));
??});
}

4. 按優先級規則排序

過濾方式會將視為無效的項排除,但是可能會因規則的誤差而導致最后得到的列表為空。為了避免這種可能現象的出現,可以將過濾排除改為優先級排序方式,最后取列表第一項視為最優選項。

排序方法實現示例:

/**
?*?sort?by:?!internal?>?!zeroMac(mac)?>?visual?>?family=IPv4?
?*/
function?ifacesSort(list:?NetworkInterfaceInfo[])?{
??return?list.sort((a,?b)?=>?{
????if?(a.internal?!==?b.internal)?return?a.internal???1?:?-1;
????if?(isZeroMac(a.mac)?!==?isZeroMac(b.mac))?return?isZeroMac(a.mac)???1?:?-1;

????const?isVirtualA?=?isVirtualMac(a.mac);
????const?isVirtualB?=?isVirtualMac(b.mac);
????if?(isVirtualA?!==?isVirtualB)?return?isVirtualA???1?:?-1;

????if?(a.family?!==?b.family)?return?a.family?===?'IPv6'???1?:?-1;
??});
}

于是最終的邏輯大致如下:

  • 獲取全部網卡信息

  • 基于 iface 特征排序取得全部列表:en0 - mac, eth4 - linux, ethernet - windows 優先級更高

  • 基于 internal字段、虛擬網卡特征(mac)、family字段等進行排序

  • 對排序的結果進行基礎過濾:internal=true、isZeroMac

  • 若過濾后列表多于1個,則基于虛擬網卡特征繼續過濾

  • 若過濾結果仍多余1個,則基于描述特征繼續過濾

  • 取最終結果的第一項作為最優選擇

“怎么利用Node獲取物理網卡mac地址”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注蝸牛博客網站,小編將為大家輸出更多高質量的實用文章!

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:niceseo99@gmail.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

評論

日本韩欧美一级A片在线观看