获取MAC地址


111

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

有谁知道跨平台方法(Windows和Linux)方法来获取MAC地址?如果没有,还有谁比我上面列出的方法更优雅?


这里有许多潜在的有用答案!如何在Python中获取eth0的IP地址?
uhoh 18-4-11

Answers:


160

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

from uuid import getnode as get_mac
mac = get_mac()

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


25
我只是在Windows机顶盒上尝试过,它工作得很好...除了我尝试过的笔记本电脑上有2个NIC(一个无线),而且无法确定它返回的MAC。如果您想使用此代码,只需警告一下。
技术论

24
只是警告:如果您查看getnode文档说它无法检测到mac,它将返回一个随机的long:按照RFC 4122中的建议设置为1。” 因此,请检查第八位!
deinonychusaur 2013年

27
hex(mac)获得熟悉的mac十六进制格式
屏幕快照

43
要么 ':'.join(("%012X" % mac)[i:i+2] for i in range(0, 12, 2))对于大写MAC,每个字节之间用冒号分隔。
tomlogic 2014年

5
每当我重新启动Windows 7笔记本电脑时,getnode()都会返回不同的内容。
nu everest 2014年

80

在Linux下针对此问题的纯python解决方案,用于获取特定本地接口的MAC,最初由vishnubob作为注释发布,并在本activestate食谱中由Ben 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()

35

netifaces是一个很好的模块,可用于获取mac地址(和其他地址)。它是跨平台的,比使用套接字或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'}]


亲自使用它,需要在每个系统上进行特定的安装/编译,但效果很好。
2011年

22

您应该注意的另一件事是,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
并不是因为第8位的值为1就是因为它不能被网卡使用。仅检查此位就足以检测该地址是否为伪造。
弗雷德里克·格罗斯汉斯

15
检查是在与完成的:如果(MAC >> 40)%2:提高OSERROR,“系统似乎不具备有效的MAC”
弗雷德里克Grosshans

17

有时我们有多个网络接口。

找出特定接口的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")

2
对于OS X或Windows并非超级有用。:|
RandomInsano

1
非常适合Pis!
MikeT

8

从这里使用我的答案:https : //stackoverflow.com/a/18031868/2362361

重要的是要知道您想要MAC到哪个iface,因为可能存在很多(蓝牙,几个nic等)。

当您知道需要使用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'

6

您可以使用跨平台的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']
Donn Lee

3

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

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

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


2
那不是真正的答案-只是评论
Stefano

1

如果您不介意依赖,则跨平台的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),则仍可以使用该软件包的旧版本。




0

对于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(临时,重新启动后将还原为实际地址)。


6
这与问题有关系吗?
bot47 '16

-1

或者,

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

-8

For Linux you can retrieve the MAC address using a SIOCGIFHWADDR ioctl.

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 ...

You've tagged the question "python". I don't know of an existing Python module to get this information. You could use ctypes to call the ioctl directly.


8
-1 He wants a python solution, so you go and give him the same regurgitated C solution plastered throughout the web.
Aatch
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.