最可靠方式是遍历NetworkInterface.GetAllNetworkInterfaces()并过滤:OperationalStatus.Up、非Loopback/Tunnel、MAC非全0;避免按IP反查,因其逻辑错误且多场景失效;注意跨平台兼容性与MAC不可靠性。

用 NetworkInterface.GetAllNetworkInterfaces() 获取所有网卡的 MAC 地址
这是最常用、最可靠的方式,能拿到系统中所有启用/禁用网卡的物理地址(包括虚拟网卡、回环、隧道等),但需要自己过滤出「真实可用」的网卡。
关键点在于:不是所有网卡都返回有效 PhysicalAddress,有些返回全 0(00-00-00-00-00-00)或长度不对(比如 IPv6 隧道接口可能返回空)。
- 必须检查
networkInterface.OperationalStatus == OperationalStatus.Up才代表网卡已启用 - 必须检查
networkInterface.NetworkInterfaceType != NetworkInterfaceType.Loopback排除回环 - 必须检查
networkInterface.GetPhysicalAddress().ToString() != "000000000000"(注意无分隔符格式) - 推荐额外过滤掉
NetworkInterfaceType.Tunnel和NetworkInterfaceType.Unknown
示例片段:
foreach (var ni in NetworkInterface.GetAllNetworkInterfaces())
{
if (ni.OperationalStatus != OperationalStatus.Up ||
ni.NetworkInterfaceType == NetworkInterfaceType.Loopback ||
ni.NetworkInterfaceType == NetworkInterfaceType.Tunnel)
continue;
var mac = ni.GetPhysicalAddress();
if (mac.ToString() == "000000000000") continue;
Console.WriteLine($"{ni.Name}: {mac.ToString()}"); // 输出如 "Ethernet: 1A-2B-3C-4D-5E-6F"
}
为什么 GetMacAddressByIP() 这类“按 IP 查 MAC”的方法不推荐
这类写法常见于网上搜到的“通过本机 IPv4 地址反查 MAC”,本质是调用 System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties() + 遍历 UnicastAddresses,再匹配网卡 —— 逻辑绕、易出错,且不能解决多网卡同网段或 DHCP 地址未分配等边界情况。
更严重的问题是:它隐含一个错误假设——「本机某个 IPv4 地址一定对应唯一一块物理网卡」。而现实中,一块网卡可配多个 IP,一个 IP 也可能被多个网卡(如绑定多个 NIC 的负载均衡场景)共享。
- 实际获取的是「绑定该 IP 的网卡」的 MAC,而非「本机主网卡」的 MAC
- 若本机只有 IPv6 地址(如纯 IPv6 环境),该逻辑直接失效
- 若使用了容器、WSL2 或 Hyper-V 虚拟交换机,
UnicastAddresses列表里会出现大量非物理网卡的地址
在 .NET Core / .NET 5+ 中要注意 NetworkInterface 的兼容性差异
Windows 上行为一致;但在 Linux/macOS 上,GetPhysicalAddress() 对某些虚拟接口(如 veth、docker0)可能抛 NotSupportedException,或返回空字符串。这不是 bug,而是底层 OS 限制 —— 某些虚拟设备根本不暴露 MAC 给用户态。
- 务必用
try/catch包裹GetPhysicalAddress()调用 - Linux 下建议额外检查
ni.Id.StartsWith("en") || ni.Id.StartsWith("eth")(常见物理网卡前缀),比依赖NetworkInterfaceType更靠谱 - .NET 6+ 引入了
ni.GetIPv4Statistics()等新 API,但对 MAC 获取无帮助,别误以为能替代
别把 MAC 当唯一标识来用:隐私与稳定性双坑
MAC 地址看似稳定,但实际在现代系统中极不可靠:
- Windows 10/11 默认启用「随机硬件地址」(Wi-Fi 网络下每次连接生成新 MAC),
NetworkInterface返回的就是这个随机值,不是物理 ROM 地址 - 管理员可通过组策略或 PowerShell(
Set-NetAdapterAdvancedProperty)禁用该功能,但无法在运行时检测是否启用 - Linux 上
macchanger、Windows 上第三方工具均可随时修改 MAC,应用层完全无法感知 - 云服务器(如 Azure VM、AWS EC2)的网卡 MAC 是平台分配的虚拟地址,重启可能变更(取决于实例类型和网络模式)
如果真要唯一标识设备,优先考虑 WindowsIdentity.GetCurrent().User.Value(域环境)、MachineGuid 注册表项(仅 Windows)、或应用层生成并持久化 UUID。


















