VPN によって作成された仮想ネットワーク インターフェイスではなく、実際の物理ネットワーク カードの MAC アドレスを確認する方法 (.NET C#)
-
21-09-2019 - |
質問
背景
コンピュータから一意の識別子を取得しようとしていますが、毎回確実に同じ MAC アドレスを返せるようにしたいと考えています。信じてください、私にはMACアドレスを使用する理由があり、代替の一意のID方法に関する多くの投稿を読みました(そして、はい、ネットワークカードがない場合も検討しました)。
問題
問題は .NET にあり、特定の NetworkInterface が、特定の VPN または WiFi ネットワークに接続するときに追加される「Nortel IPSECSHM アダプタ - パケット スケジューラ ミニポート」のような物理ハードウェア ネットワーク カードであるかどうかがわかりません。
次のようなコードを使用して Mac アドレスを取得する方法はわかっています。
foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
{
log.Debug("NIC " + nic.OperationalStatus + " " + nic.NetworkInterfaceType + " " + nic.Speed + " " + nic.GetPhysicalAddress() + " " + nic.Description);
}
当然のことながら、内部ネットワーク カードを確実に入手できることを 100% 確認する方法はありませんが、 特定のマシンに対して、変更される可能性が最も低い MAC アドレスを選択して返したいと考えています。. 。Wi-Fi に接続されているかどうかなどの要因に依存しません。何らかのテザー接続を介して接続されます...または、新しいインターフェイスを追加する新しい VPN ソフトウェアをインストールします。
検討された戦略
1) 「アップ」になっている最初のインターフェースを選択します。「パケット ミニポート」が常に稼働しているため、私のラップトップではこれが失敗します。さらに、携帯電話をラップトップにテザリングすると、これも最初のカードとして表示されます。
2) 最も適切なタイプを選択します...これは失敗します。基本的に、WiFi アダプターや iPhone のテザリング インターネット接続を含むすべてが「イーサネット」として表示されます。
3) IP アドレスを持つ NIC を選択します。いくつかの理由で失敗します。1) ネットワーク カードが LAN に接続されていない可能性があります。 2) IP アドレスを持つ可能性のある複数の NIC があります。
4) すべての MAC アドレスを送信するだけです...問題は、インストールされているソフトウェアに基づいてリストが変更されるため、比較が困難になることです。
5) 最も高速な MAC アドレスを選択します。おそらくこれが最善の策だと思います。通常、最速のインターフェイスが最も永続的になると言っても過言ではないと思います。
あるいは、.NET で物理カードを検出する他の方法があるかもしれません。または、別の情報を提供する API 呼び出しを推奨できる場合は、他の API 呼び出しを呼び出すことを検討します。
他に何かアイデアはありますか?
ここでデモンストレーションするために、iPhone をテザリングしたときの上記のサンプル コードの出力を示します。
DEBUG - NIC Down Ethernet 500000 0021E98BFBEF Apple Mobile Device Ethernet - Packet Scheduler Miniport
DEBUG - NIC Up Ethernet 10000000 444553544200 Nortel IPSECSHM Adapter - Packet Scheduler Miniport
DEBUG - NIC Down Ethernet 54000000 00166FAC94C7 Intel(R) PRO/Wireless 2200BG Network Connection - Packet Scheduler Miniport
DEBUG - NIC Down Ethernet 1000000000 0016D326E957 Broadcom NetXtreme Gigabit Ethernet - Packet Scheduler Miniport
DEBUG - NIC Up Loopback 10000000 MS TCP Loopback interface
iPhone が接続されていない場合:
DEBUG - NIC Up Ethernet 10000000 444553544200 Nortel IPSECSHM Adapter - Packet Scheduler Miniport
DEBUG - NIC Down Ethernet 54000000 00166FAC94C7 Intel(R) PRO/Wireless 2200BG Network Connection - Packet Scheduler Miniport
DEBUG - NIC Down Ethernet 1000000000 0016D326E957 Broadcom NetXtreme Gigabit Ethernet - Packet Scheduler Miniport
DEBUG - NIC Up Loopback 10000000 MS TCP Loopback interface
解決
これは私の方法です。 それは物理的なカードがPCIインターフェース
に接続されているという事実を使用していますManagementObjectSearcher searcher = new ManagementObjectSearcher
("Select MACAddress,PNPDeviceID FROM Win32_NetworkAdapter WHERE MACAddress IS NOT NULL AND PNPDeviceID IS NOT NULL");
ManagementObjectCollection mObject = searcher.Get();
foreach (ManagementObject obj in mObject)
{
string pnp = obj["PNPDeviceID"].ToString();
if (pnp.Contains("PCI\\"))
{
string mac = obj["MACAddress"].ToString();
mac = mac.Replace(":", string.Empty);
return mac;
}
}
他のヒント
MACアドレスの最初の3つのバイトは、製造業者のIDです。あなたの目的のために不適当であることが知られている特定のメーカーIDをブラックリスト、およびそれらのインターフェイスを無視することができます。
スピードに依存する可能性が高いVPNインターフェイスは、ギガビットスピードを持つものとして自分自身を報告できない理由はありませんので、良いアイデアされるものではない。
MACアドレスは、物理的なハードウェアアドレスです。私はこのPCでテストすることはできませんが、私はそれは、ハードウェアの実際の作品ではありませんので、仮想接続が追加された場合は、新しいMACアドレスを取得するとは思いません。それは別の接続ではなく、別のMACアドレスになります。
ですから、マシンに接続されているすべての時間は、ハードウェアの同じ部分に依存して、同じMACアドレスを取得することを保証し、そのハードウェアから選択するのと同じアルゴリズムを使用します。
私もこの問題を見て、そして永続的な状態ずに、安定したMACを維持することが困難になるだろうと信じてきました。
私はいじるよソリューションが取るで最初のNICは、アダプタの順序と使用することをのそれの保存で見つかりました。それがスタックしてもいない場合は最初にどこにも見つかった場合、その後のUUIDの世代に、保存されたMACを使用します。この方法で、アダプタの順序は動き回ることができ、我々は(そのようなライセンスモジュールとして)安定したMACに依存何でも爆破心配しないでください。
保存されたMACは、スタック内に見つからない場合は、は、それが破棄されていますし、私達はちょうど結合順序で最初のMACを使用して、最初からやり直します。
public static string GetMacAddressPhysicalNetworkInterface()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher
("Select MACAddress,PNPDeviceID FROM Win32_NetworkAdapter WHERE MACAddress IS NOT NULL AND" +
" PNPDeviceID IS NOT NULL AND" +
" PhysicalAdapter = true");
ManagementObjectCollection mObject = searcher.Get();
string macs = (from ManagementObject obj in mObject
let pnp = obj["PNPDeviceID"].ToString()
where !(pnp.Contains("ROOT\\"))
//where pnp.Contains("PCI\\") || pnp.Contains("USB\\")
select obj).Select(obj => obj["MACAddress"].ToString())
.Aggregate<string, string>(null, (mac, currentMac) => mac + currentMac.Replace(":", string.Empty) + ",");
return !string.IsNullOrEmpty(macs) ? macs.Substring(0, macs.Length - 1) : macs;
}
public static NetworkInterface GetPhysicalNetworkInterface(string macAddressPhysicalNetworkInterface)
{
return NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault(currentNetworkInterface => string.Equals(currentNetworkInterface.GetPhysicalAddress().ToString(), macAddressPhysicalNetworkInterface, StringComparison.CurrentCultureIgnoreCase));
}