How to determine MAC Address of the actual physical network card -- not virtual network interfaces created by VPN's (.NET C#)
Asked Answered
E

5

21

Background

I'm trying to get obtain a unique identifier out of a computer and want to be able to reliably return the same MAC address each time. Trust me I have my reasons for using MAC address and have read many posts about alternate unique id methods (and yes i've considered if they don't have any network cards).

Problem

The problem is in .NET i don't see anyway to tell whether a specific NetworkInterface is a physical hardware network card from something like a "Nortel IPSECSHM Adapter - Packet Scheduler Miniport" which get added when you connect to certain VPNs or WiFi networks.

I know how to get the Mac Addresses by using code similar to this:

    foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
    {
        log.Debug("NIC " + nic.OperationalStatus + " " + nic.NetworkInterfaceType + " " + nic.Speed + " " + nic.GetPhysicalAddress() + " " + nic.Description);
    }

Understandably there is no 100% way to make sure i'd be getting an internal network card but i'd like to pick the MAC address to return which for a given machine which is least likely to change. Independent of factors such as -- whether it's connected to wifi... gets connected via some type of tether connection... or they install some new vpn software which adds a new interface.

Strategies Considered

1) Choose the first interface that is "Up". This fails on my laptop because the "Packet Miniport" is always up. Additionally, if I tether my phone to my laptop this also shows up as the first card.

2) Choose the most appropriate type... This fails b/c basically everything shows up as "Ethernet" including WiFi Adapters and my iPHone tethering internet connection.

3) Pick the NIC which has an IP address. Fails for several reasons: 1) Network card might not be connected to LAN 2) There are multiple nics which might have IP Addresses.

4) Just send all MAC addresses... Problem is the list would change based on installed software and it'll be difficult to compare.

5) Pick the mac address with the fastest speed. I think this is probably my best bet. I think it's safe to say that the fastest interface is usually going to be the most permanent.

Alternatively, there may be some other way to detect physical cards in .NET or I'd consider invoking other API calls if you could recommend one that will provide different information.

Any other ideas?

To demonstrate here is the output of my sample code above when I have my iphone tethered:

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

Without Iphone Connected:

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
Equerry answered 14/10, 2009 at 16:13 Comment(4)
you should also consider computers with multiple NICs of the same type.Accuse
You can't depend on a MAC address as a unique identifier. If you want a unique identifier, generate a GUID, encrypt it and store it on the computer.Wirer
@John Saunders, I do use a GUID. MAC address is a backup in case the location where the GUID is stored is removed.Equerry
See my answer https://mcmap.net/q/87973/-c-finding-my-machine-39-s-local-ip-address-and-not-the-vm-39-s to check physical device.Joris
W
12

This is my method: it uses the fact that physical card is connected to PCI interface

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;
    }
}
Wednesday answered 20/8, 2010 at 11:23 Comment(6)
I don't think this'll cater for something like this: amazon.co.uk/Belkin-Ethernet-Adapter-Patch-Cable/dp/B0002AFKN0 - however they're not really that prevalent.Annadiana
yes, this is a problem. I do not have such device, it is interesting, what is written in "PNPDeviceID" in such cases. Second problem is when there are more than one card. Because i always take the "first" card, it may cause errors in the case when the order of cards in "select" operator is not determined. I have not found "order by" construction in this "SQL for WMI" dialect :)Wednesday
I have an adapter with caption "Broadcom BCM5709C NetXtreme II GigE (NDIS VBD Client)" and PNPDeviceID without "PCI\". It is physical.Limonite
How get IPv4 address for physical adapter ? (remote computer)Vitia
PhysicalAdapter ? Network adapter property name: NetEnabled - value: True Network adapter property name: PhysicalAdapter - value: True Network adapter property name: PNPDeviceID - value: PCI\VEN_15AD&DEVitia
Relations Win32_NetworkAdapterConfiguration and Win32_NetworkAdapter ? NetworkAdapterConfiguration give me 16 ítems, and Win32_NetworkAdapter give me 12 ítems.Vitia
C
2

The first three bytes of the MAC address are a manufacturer ID. You could blacklist certain manufacturer IDs known to be unsuitable for your purposes, and ignore those interfaces.

Relying on the speed is not likely to be a good idea, because there's no reason why a VPN interface couldn't report itself as having gigabit speed.

Congreve answered 14/10, 2009 at 22:31 Comment(1)
I considered a blacklist... I was thinking it'd probably be easier to do it based on strings that appear in the description (for example: " VPN ", " IPSECSHM "... but thought that'd be pretty hard to come up with. Alternatively, I suppose i could create a whitelist of the most popular network interface... " Realtek ", " Gigabit " - I really wanted to avoid the hassle of creating and maintaining a whitelist though.Equerry
H
0

MAC addresses are physical hardware addresses. I can't test on this pc, but I don't think you will get a new MAC address if a virtual connection is added because it's not an actual piece of hardware. It will be another connection, but not another MAC address.

So guaranteeing that you get the same MAC address every time depends on the same pieces of hardware being attached to the machine and you using the same algorithm to pick from that hardware.

Hark answered 14/10, 2009 at 18:43 Comment(1)
@Hark - MAC addresses are also used in virtual interfaces... in my case that Nortel Packet interface.Equerry
D
0

I've been looking at this problem as well, and believe that without persistent state it's going to be difficult to maintain a stable MAC.

The solution I'm toying with is take the first NIC found in the adapter order and use that and save it. Then on subsequent UUID generations, use the saved MAC if it's found anywhere in the stack even if not the first. This way the adapter order can move around and we don't worry about blowing up whatever depends on the stable MAC (such as a licensing module).

If the saved MAC is not found in the stack, it's discarded and we just use the first MAC in the binding order and start over.

Didymous answered 28/12, 2012 at 16:15 Comment(0)
M
0
 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));
    }
Melendez answered 23/8, 2017 at 7:6 Comment(3)
Some explanation / documentation links explaning why this answer is better than others would help. I do like the 'physicaladapter = true' check, but can it be relied upon?Paddy
Checking this property is also enoughMelendez
How get GetPhysicalNetworkInterface using scope = "\\\\" + ip + "\\root\\cimv2"; ?Vitia

© 2022 - 2024 — McMap. All rights reserved.