MAC-Adresse abrufen


111

Ich benötige eine plattformübergreifende Methode zum Ermitteln der MAC-Adresse eines Computers zur Laufzeit. Für Windows kann das 'wmi'-Modul verwendet werden, und die einzige Methode unter Linux, die ich finden konnte, bestand darin, ifconfig auszuführen und einen regulären Ausdruck für die Ausgabe auszuführen. Ich mag es nicht, ein Paket zu verwenden, das nur auf einem Betriebssystem funktioniert, und das Parsen der Ausgabe eines anderen Programms scheint nicht sehr elegant zu sein, ganz zu schweigen von der Fehleranfälligkeit.

Kennt jemand eine plattformübergreifende Methode (Windows und Linux), um die MAC-Adresse zu erhalten? Wenn nicht, kennt jemand elegantere Methoden als die oben aufgeführten?


Hier gibt es viele potenziell hilfreiche Antworten! Wie kann ich die IP-Adresse von eth0 in Python erhalten?
Uhoh

Antworten:


160

Python 2.5 enthält eine UUID-Implementierung, die (in mindestens einer Version) die Mac-Adresse benötigt. Sie können die Mac-Suchfunktion einfach in Ihren eigenen Code importieren:

from uuid import getnode as get_mac
mac = get_mac()

Der Rückgabewert ist die Mac-Adresse als 48-Bit-Ganzzahl.


25
Ich habe es gerade auf einer Windows-Box versucht und es funktioniert hervorragend ... außer dass der Laptop, auf dem ich es ausprobiert habe, 2 Netzwerkkarten (eine drahtlose) hat und es keine Möglichkeit gibt, festzustellen, welcher MAC zurückgegeben wurde. Nur ein Wort der Warnung, wenn Sie diesen Code verwenden möchten.
technomalogical

24
Nur eine Warnung: Wenn Sie sich die getnodeDokumentation ansehen , heißt es, dass ein zufälliger Long zurückgegeben wird, wenn der Mac nicht erkannt wird: "Wenn alle Versuche, die Hardwareadresse zu erhalten, fehlschlagen, wählen wir eine zufällige 48-Bit-Zahl mit ihrem achten Bit wie in RFC 4122 empfohlen auf 1 gesetzt. " Überprüfen Sie also das achte Bit!
Deinonychusaur

27
hex(mac)um das bekannte Hex-Format des Mac zu erhalten
Screenshot345

43
Oder ':'.join(("%012X" % mac)[i:i+2] for i in range(0, 12, 2))für einen MAC in Großbuchstaben, wobei jedes Byte durch einen Doppelpunkt getrennt ist.
Tomlogic

5
getnode () gibt bei jedem Neustart meines Windows 7-Laptops etwas anderes zurück.
Nu Everest

80

Die reine Python-Lösung für dieses Problem unter Linux, um den MAC für eine bestimmte lokale Schnittstelle zu erhalten, die ursprünglich als Kommentar von vishnubob veröffentlicht und von Ben Mackey in diesem Aktivierungsrezept verbessert wurde

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

Dies ist der Python 3-kompatible Code:

#!/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 ist ein gutes Modul zum Abrufen der Mac-Adresse (und anderer Adressen). Es ist plattformübergreifend und etwas sinnvoller als die Verwendung von Socket oder 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'}]


Wird es persönlich verwendet, erfordert eine spezifische Installation / Kompilierung auf jedem System, funktioniert aber gut.
Aatch

22

Eine andere Sache, die Sie beachten sollten, ist, dass uuid.getnode()die MAC-Adresse gefälscht werden kann, indem eine zufällige 48-Bit-Zahl zurückgegeben wird, die möglicherweise nicht Ihren Erwartungen entspricht. Es gibt auch keinen expliziten Hinweis darauf, dass die MAC-Adresse gefälscht wurde. Sie können sie jedoch erkennen, indem Sie getnode()zweimal anrufen und prüfen, ob das Ergebnis variiert. Wenn bei beiden Aufrufen der gleiche Wert zurückgegeben wird, haben Sie die MAC-Adresse, andernfalls erhalten Sie eine gefälschte Adresse.

>>> 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
Nicht dass der Wert des 8. 1 ist, gerade weil er nicht von einer Netzwerkkarte verwendet werden kann. Das Überprüfen dieses Bits reicht aus, um festzustellen, ob die Adresse gefälscht ist oder nicht.
Frédéric Grosshans

15
Die Überprüfung erfolgt nur mit: if (mac >> 40)% 2: OSError auslösen, "Das System scheint keinen gültigen MAC zu haben"
Frédéric Grosshans

17

Manchmal haben wir mehr als eine Netzschnittstelle.

Eine einfache Methode, um die Mac-Adresse einer bestimmten Schnittstelle herauszufinden, ist:

def getmac(interface):

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

  return mac[0:17]

Die Methode aufzurufen ist einfach

myMAC = getmac("wlan0")

2
Nicht besonders nützlich für OS X oder Windows. : |
RandomInsano

1
Perfekt für Pis!
MikeT

8

Verwenden Sie meine Antwort von hier: https://stackoverflow.com/a/18031868/2362361

Es wäre wichtig zu wissen, für welches iface Sie den MAC möchten, da viele existieren können (Bluetooth, mehrere Nics usw.).

Dies erledigt die Aufgabe, wenn Sie die IP des iface kennen, für das Sie den MAC benötigen, und zwar mithilfe netifaces(verfügbar in 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

Testen:

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

6

Sie können dies mit plattformübergreifendem psutil tun:

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 socketdann [addr.address for n in nics for addr in nics[n] if n == 'enp4s0' and addr.family == socket.AF_PACKET]ergibt sich['ab:cd:ef:01:02:03']
Donn Lee

3

Beachten Sie, dass Sie mithilfe von bedingten Importen Ihre eigene plattformübergreifende Bibliothek in Python erstellen können. z.B

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

Auf diese Weise können Sie os.system-Aufrufe oder plattformspezifische Bibliotheken verwenden.


2
Das ist nicht wirklich eine Antwort - nur ein Kommentar
Stefano

1

Das plattformübergreifende getmac- Paket funktioniert hierfür, wenn es Ihnen nichts ausmacht, eine Abhängigkeit zu übernehmen. Es funktioniert mit Python 2.7+ und 3.4+. Es werden viele verschiedene Methoden ausprobiert, bis entweder eine Adresse abgerufen oder None zurückgegeben wird.

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)

Haftungsausschluss: Ich bin der Autor des Pakets.

Update (14. Januar 2019): Das Paket unterstützt jetzt nur Python 2.7+ und 3.4+. Sie können weiterhin eine ältere Version des Pakets verwenden, wenn Sie mit einem älteren Python (2.5, 2.6, 3.2, 3.3) arbeiten müssen.


1

Um die eth0MAC-Adresse der Schnittstelle zu erhalten ,

import psutil

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

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

0

Ich kenne keinen einheitlichen Weg, aber hier ist etwas, das Sie vielleicht nützlich finden:

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

In diesem Fall würde ich diese in eine Funktion einbinden und basierend auf dem Betriebssystem den richtigen Befehl ausführen, nach Bedarf analysieren und nur die nach Ihren Wünschen formatierte MAC-Adresse zurückgeben. Es ist natürlich egal, außer dass Sie es nur einmal tun müssen, und es sieht sauberer aus als der Hauptcode.


0

Für Linux möchte ich ein Shell-Skript einführen, das die Mac-Adresse anzeigt und deren Änderung ermöglicht (MAC-Sniffing).

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

Schnittargumente können dffer (ich bin kein Experte) versuchen:

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

Um den MAC zu ändern, können wir:

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

ändert die Mac-Adresse in 00: 80: 48: BA: d1: 30 (wird vorübergehend beim Neustart auf die tatsächliche wiederhergestellt).


6
Hat das etwas mit der Frage zu tun?
Bot47

-1

Alternative,

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

-8

Unter Linux können Sie die MAC-Adresse mit einem SIOCGIFHWADDR ioctl abrufen.

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

Sie haben die Frage "Python" markiert. Ich kenne kein vorhandenes Python-Modul, um diese Informationen zu erhalten. Sie können ctypes verwenden , um das ioctl direkt aufzurufen.


8
-1 Er möchte eine Python-Lösung, also geben Sie ihm dieselbe C-Lösung, die im gesamten Web verputzt ist.
Aatch
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.