簡體   English   中英

獲取 MAC 地址

[英]Getting MAC Address

我需要一種在運行時確定計算機 MAC 地址的跨平台方法。 對於 windows,可以使用“wmi”模塊,在 Linux 下,我能找到的唯一方法是運行 ifconfig 並在其 output 上運行正則表達式。我不喜歡使用僅適用於一個操作系統的 package,並解析 output另一個程序似乎不太優雅,更不用說容易出錯了。

有誰知道獲取MAC地址的跨平台方法(windows和linux)方法? 如果沒有,有沒有人知道比我上面列出的方法更優雅的方法?

Python 2.5 包含一個 uuid 實現,它(至少在一個版本中)需要 mac 地址。 您可以輕松地將 mac 查找功能導入到您自己的代碼中:

from uuid import getnode as get_mac
mac = get_mac()

返回值為 48 位整數的 mac 地址。

Linux 下此問題的純 python 解決方案,用於獲取特定本地接口的 MAC,最初由 vishnubob 作為評論發布,並由 Ben Mackey 在此 activestate 配方中改進

#!/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()

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'}]

有時我們有不止一個網絡接口。

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

您應該注意的另一件事是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.

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

重要的是要知道您想要 MAC 用於哪個接口,因為可以存在許多接口(藍牙、多個 nic 等)。

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

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'

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

請注意,您可以使用條件導入在 python 中構建自己的跨平台庫。 例如

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

這將允許您使用 os.system 調用或特定於平台的庫。

如果您不介意依賴依賴,跨平台的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),您仍然可以使用較舊版本的包。

要獲取eth0接口 MAC 地址,

import psutil

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

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

nice實際上在字典中返回一個字典,它返回一個列表,在列表中,它返回一個訂書釘。 但是nics['Ethernet'][0].address迭代解決了這個問題。

import psutil

nics = psutil.net_if_addrs()

mac_address = nics['Ethernet'][0].address

print(mac_address)

我不知道統一的方式,但這里有一些你可能會覺得有用的東西:

http://www.codeguru.com/Cpp/IN/network/networkinformation/article.php/c5451

在這種情況下,我要做的是將它們包裝成一個函數,並根據操作系統運行正確的命令,根據需要進行解析並僅返回您想要格式化的 MAC 地址。 它當然都是一樣的,除了你只需要做一次,而且從主代碼看起來更干凈。

跨平台代碼並非 100% 適用於 Windows。這適用於 Windows:

import psutil
print([(k, addr.address) for k, v in psutil.net_if_addrs().items() for addr in v if addr.family == -1])

例子:

[
    ('Local Area Connection', '01-23-45-67-89-0A'), 
    ('Wireless Network Connection', '23-45-67-89-0A-BC'), 
    ('Bluetooth Network Connection', '45-67-89-0A-BC-DE'), 
    ('isatap.{01ABCDEF-0123-4567-890A-0123456789AB}', '00-00-00-00-00-00-00-01')
]

或者,

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

對於 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 (暫時,將在重新啟動時恢復為實際地址)。

對於 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。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM