获取 MAC 地址

Posted

技术标签:

【中文标题】获取 MAC 地址【英文标题】:Getting MAC Address 【发布时间】:2010-09-14 14:53:27 【问题描述】:

我需要一种在运行时确定计算机 MAC 地址的跨平台方法。对于 Windows,可以使用“wmi”模块,在 Linux 下我能找到的唯一方法是运行 ifconfig 并在其输出中运行正则表达式。我不喜欢使用只能在一个操作系统上运行的包,并且解析另一个程序的输出似乎不是很优雅,更不用说容易出错了。

有谁知道的跨平台方法(windows 和 linux)方法吗?如果没有,有没有人知道比我上面列出的更优雅的方法?

【问题讨论】:

这里有很多可能有用的答案! How can I get the IP address of eth0 in Python? 【参考方案1】:

netifaces 是一个很好的模块,用于获取 mac 地址(和其他地址)。它是跨平台的,比使用 socket 或 uuid 更有意义。

>>> import netifaces
>>> netifaces.interfaces()
['lo', 'eth0', 'tun2']

>>> netifaces.ifaddresses('eth0')[netifaces.AF_LINK]
['addr': '08:00:27:50:f2:51', 'broadcast': 'ff:ff:ff:ff:ff:ff']

pypi location

Good Intro to netifaces

【讨论】:

个人使用,需要在每个系统上进行特定的安装/编译,但效果很好。【参考方案2】:

我不知道统一的方式,但这里有一些你可能会觉得有用的东西:

http://www.codeguru.com/Cpp/I-N/network/networkinformation/article.php/c5451

在这种情况下,我要做的是将它们包装成一个函数,并根据操作系统运行正确的命令,根据需要进行解析并仅返回您想要格式化的 MAC 地址。当然都是一样的,除了你只需要做一次,而且从主代码看起来更干净。

【讨论】:

【参考方案3】:

Python 2.5 包含一个 uuid 实现,它(至少在一个版本中)需要 mac 地址。您可以轻松地将mac查找功能导入自己的代码中:

from uuid import getnode as get_mac
mac = get_mac()

返回值为48位整数的mac地址。

【讨论】:

我刚刚在 Windows 机器上尝试过,效果很好……除了我尝试过的笔记本电脑有 2 个 NIC(一个无线)并且无法确定它返回的是哪个 MAC。如果您想使用此代码,请注意。 只是一个警告:如果您查看getnode 文档,它说如果它无法检测到mac,它将返回一个随机长:“如果所有获取硬件地址的尝试都失败,我们按照 RFC 4122 的建议,选择一个随机的 48 位数字,并将其第八位设置为 1。”所以检查第八位! hex(mac)获取mac熟悉的十六进制格式 ':'.join(("%012X" % mac)[i:i+2] for i in range(0, 12, 2)) 表示大写 MAC,每个字节用冒号分隔。 getnode() 每次重新启动 Windows 7 笔记本电脑时都会返回不同的内容。【参考方案4】:

对于 Linux,您可以使用 SIOCGIFHWADDR ioctl 检索 MAC 地址。

struct ifreq    ifr;
uint8_t         macaddr[6];

if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0)
    return -1;

strcpy(ifr.ifr_name, "eth0");

if (ioctl(s, SIOCGIFHWADDR, (void *)&ifr) == 0) 
    if (ifr.ifr_hwaddr.sa_family == ARPHRD_ETHER) 
        memcpy(macaddr, ifr.ifr_hwaddr.sa_data, 6);
        return 0;
... etc ...

您已将问题标记为“python”。我不知道现有的 Python 模块可以获取此信息。您可以使用ctypes 直接调用ioctl。

【讨论】:

-1 他想要一个 python 解决方案,所以你去给他提供与整个网络相同的反刍 C 解决方案。【参考方案5】:

请注意,您可以使用条件导入在 python 中构建自己的跨平台库。例如

import platform
if platform.system() == 'Linux':
  import LinuxMac
  mac_address = LinuxMac.get_mac_address()
elif platform.system() == 'Windows':
  # etc

这将允许您使用 os.system 调用或特定于平台的库。

【讨论】:

这不是一个真正的答案 - 只是一个评论【参考方案6】:

您应该注意的另一件事是uuid.getnode() 可以通过返回一个可能不是您所期望的随机 48 位数字来伪造 MAC 地址。此外,没有明确的迹象表明 MAC 地址已被伪造,但您可以通过调用 getnode() 两次并查看结果是否变化来检测它。如果两个调用都返回相同的值,则您拥有 MAC 地址,否则您将获得伪造的地址。

>>> print uuid.getnode.__doc__
Get the hardware address as a 48-bit positive integer.

    The first time this runs, it may launch a separate program, which could
    be quite slow.  If all attempts to obtain the hardware address fail, we
    choose a random 48-bit number with its eighth bit set to 1 as recommended
    in RFC 4122.

【讨论】:

并不是说第8个的值为1正是因为它不能被网卡使用。只需检查该位就足以检测地址是否是伪造的。 检查刚刚完成: if (mac >> 40)%2 : raise OSError, "The system does not seem to have a valid MAC"【参考方案7】:

Linux 下该问题的纯 python 解决方案,用于获取特定本地接口的 MAC,最初由 vishnubob 作为评论发布,并由 this activestate recipeBen Mackey 改进

#!/usr/bin/python

import fcntl, socket, struct

def getHwAddr(ifname):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    info = fcntl.ioctl(s.fileno(), 0x8927,  struct.pack('256s', ifname[:15]))
    return ':'.join(['%02x' % ord(char) for char in info[18:24]])

print getHwAddr('eth0')

这是兼容 Python 3 的代码:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import fcntl
import socket
import struct


def getHwAddr(ifname):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    info = fcntl.ioctl(s.fileno(), 0x8927,  struct.pack('256s', bytes(ifname, 'utf-8')[:15]))
    return ':'.join('%02x' % b for b in info[18:24])


def main():
    print(getHwAddr('enp0s8'))


if __name__ == "__main__":
    main()

【讨论】:

【参考方案8】:

对于 Linux,让我介绍一个 shell 脚本,它会显示 mac 地址并允许更改它(MAC 嗅探)。

 ifconfig eth0 | grep HWaddr |cut -dH -f2|cut -d\  -f2
 00:26:6c:df:c3:95

减少争论可能会有所不同(我不是专家)尝试:

ifconfig etho | grep HWaddr
eth0      Link encap:Ethernet  HWaddr 00:26:6c:df:c3:95  

要更改 MAC,我们可以这样做:

ifconfig eth0 down
ifconfig eth0 hw ether 00:80:48:BA:d1:30
ifconfig eth0 up

将mac地址改为00:80:48:BA:d1:30(暂时重启后恢复为实际)。

【讨论】:

这和这个问题有关系吗?【参考方案9】:

使用我的回答:https://***.com/a/18031868/2362361

了解您希望 MAC 用于哪个接口很重要,因为可以存在许多接口(蓝牙、多个网卡等)。

当您知道需要 MAC 的 iface 的 IP 时,这可以完成工作,使用 netifaces(在 PyPI 中可用):

import netifaces as nif
def mac_for_ip(ip):
    'Returns a list of MACs for interfaces that have given IP, returns None if not found'
    for i in nif.interfaces():
        addrs = nif.ifaddresses(i)
        try:
            if_mac = addrs[nif.AF_LINK][0]['addr']
            if_ip = addrs[nif.AF_INET][0]['addr']
        except IndexError, KeyError: #ignore ifaces that dont have MAC or IP
            if_mac = if_ip = None
        if if_ip == ip:
            return if_mac
    return None

测试:

>>> mac_for_ip('169.254.90.191')
'2c:41:38:0a:94:8b'

【讨论】:

【参考方案10】:

有时我们有不止一个网络接口。

查找特定接口的mac地址的简单方法是:

def getmac(interface):

  try:
    mac = open('/sys/class/net/'+interface+'/address').readline()
  except:
    mac = "00:00:00:00:00:00"

  return mac[0:17]

调用方法很简单

myMAC = getmac("wlan0")

【讨论】:

对于 OS X 或 Windows 不是超级有用。 :| 完美的小便士!【参考方案11】:

您可以使用跨平台的 psutil 来做到这一点:

import psutil
nics = psutil.net_if_addrs()
print [j.address for j in nics[i] for i in nics if i!="lo" and j.family==17]

【讨论】:

import socket 然后[addr.address for n in nics for addr in nics[n] if n == 'enp4s0' and addr.family == socket.AF_PACKET] 导致['ab:cd:ef:01:02:03']【参考方案12】:

跨平台的getmac 包可以解决这个问题,如果你不介意承担依赖的话。它适用于 Python 2.7+ 和 3.4+。它将尝试许多不同的方法,直到获得地址或返回 None。

from getmac import get_mac_address
eth_mac = get_mac_address(interface="eth0")
win_mac = get_mac_address(interface="Ethernet 3")
ip_mac = get_mac_address(ip="192.168.0.1")
ip6_mac = get_mac_address(ip6="::1")
host_mac = get_mac_address(hostname="localhost")
updated_mac = get_mac_address(ip="10.0.0.1", network_request=True)

免责声明:我是包的作者。

更新(2019 年 1 月 14 日):该软件包现在仅支持 Python 2.7+ 和 3.4+。如果您需要使用较旧的 Python(2.5、2.6、3.2、3.3),您仍然可以使用较旧版本的包。

【讨论】:

上述变量的标准输出:无 无 无 无 00:00:00:00:00:00 无 这些只是使用示例。您需要将参数替换为适用于您的系统的值,这很可能是您得到空结果的原因。例如,“eth0”不适用于 Windows 系统,“Ethernet 3”不适用于 Linux 系统,但两者都作为示例包含在上面,因此您知道如何在两个平台上使用该库。注意:“localhost”将始终返回“00:00:00:00:00:00”。【参考方案13】:

或者,

import uuid
mac_id=(':'.join([':02x'.format((uuid.getnode() >> ele) & 0xff)

【讨论】:

【参考方案14】:

要获取eth0接口MAC地址,

import psutil

nics = psutil.net_if_addrs()['eth0']

for interface in nics:
   if interface.family == 17:
      print(interface.address)

【讨论】:

以上是关于获取 MAC 地址的主要内容,如果未能解决你的问题,请参考以下文章

如何根据网卡MAC地址获取手机品牌

CentOS7获取网卡Mac地址

C# 获取MAC地址

如何通过IP获取MAC地址?如何通过mac来获取IP地址?

如何从网卡中获取MAC地址?

在linux里面怎么获取mac地址