Recupero dell'indirizzo MAC


111

Ho bisogno di un metodo multipiattaforma per determinare l'indirizzo MAC di un computer in fase di esecuzione. Per Windows è possibile utilizzare il modulo "wmi" e l'unico metodo in Linux che ho trovato è stato eseguire ifconfig ed eseguire un'espressione regolare sull'output. Non mi piace usare un pacchetto che funziona solo su un sistema operativo e analizzare l'output di un altro programma non sembra molto elegante per non parlare della possibilità di errori.

Qualcuno conosce un metodo multipiattaforma (Windows e Linux) per ottenere l'indirizzo MAC? In caso contrario, qualcuno conosce metodi più eleganti di quelli che ho elencato sopra?


Ci sono molte risposte potenzialmente utili qui! Come posso ottenere l'indirizzo IP di eth0 in Python?
uhoh

Risposte:


160

Python 2.5 include un'implementazione uuid che (in almeno una versione) necessita dell'indirizzo mac. Puoi importare facilmente la funzione di ricerca del Mac nel tuo codice:

from uuid import getnode as get_mac
mac = get_mac()

Il valore restituito è l'indirizzo MAC come intero a 48 bit.


25
L'ho appena provato su una scatola Windows e funziona alla grande ... tranne per il fatto che il laptop su cui l'ho provato ha 2 NIC (uno wireless) e non c'è modo di determinare quale MAC ha restituito. Solo un avvertimento se desideri utilizzare questo codice.
tecnomalogico

24
Solo un avvertimento: se guardi la getnodedocumentazione dice che restituirà un long casuale se non riesce a rilevare il mac: "Se tutti i tentativi di ottenere l'indirizzo hardware falliscono, scegliamo un numero casuale di 48 bit con il suo ottavo bit impostato su 1 come consigliato in RFC 4122. " Quindi controlla quell'ottavo bit!
deinonychusaur

27
hex(mac)per ottenere il familiare formato esadecimale del mac
screenshot345

43
O ':'.join(("%012X" % mac)[i:i+2] for i in range(0, 12, 2))per un MAC maiuscolo con ogni byte separato da due punti.
tomlogic

5
getnode () restituisce qualcosa di diverso ogni volta che riavvio il mio laptop Windows 7.
nu everest

80

La pura soluzione python per questo problema sotto Linux per ottenere il MAC per una specifica interfaccia locale, originariamente pubblicata come commento da vishnubob e migliorata da Ben Mackey in questa ricetta di 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')

Questo è il codice compatibile con 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 è un buon modulo da usare per ottenere l'indirizzo mac (e altri indirizzi). È multipiattaforma e ha un po 'più senso rispetto all'utilizzo di socket o 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'}]


Usato personalmente, richiede una specifica installazione / compilazione su ogni sistema ma funziona bene.
Partita il

22

Un'altra cosa che dovresti notare è che uuid.getnode()può falsificare l'indirizzo MAC restituendo un numero casuale a 48 bit che potrebbe non essere quello che ti aspetti. Inoltre, non vi è alcuna indicazione esplicita che l'indirizzo MAC sia stato falsificato, ma è possibile rilevarlo chiamando getnode()due volte e vedendo se il risultato varia. Se lo stesso valore viene restituito da entrambe le chiamate, hai l'indirizzo MAC, altrimenti ottieni un indirizzo falso.

>>> 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
Non che il valore dell'8 ° sia 1 proprio perché non può essere utilizzato da una scheda di rete. Basta controllare questo bit per rilevare se l'indirizzo è falsificato o meno.
Frédéric Grosshans

15
Il controllo è appena fatto con: if (mac >> 40)% 2: raise OSError, "Il sistema non sembra avere un MAC valido"
Frédéric Grosshans

17

A volte abbiamo più di un'interfaccia di rete.

Un metodo semplice per scoprire l'indirizzo MAC di una specifica interfaccia è:

def getmac(interface):

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

  return mac[0:17]

chiamare il metodo è semplice

myMAC = getmac("wlan0")

2
Non molto utile per OS X o Windows. : |
RandomInsano

1
Perfetto per Pis!
MikeT

8

Usando la mia risposta da qui: https://stackoverflow.com/a/18031868/2362361

Sarebbe importante sapere a quale iface vuoi il MAC visto che possono esistere molti (bluetooth, diversi nics, ecc.).

Questo fa il lavoro quando conosci l'IP dell'iface per cui hai bisogno del MAC, utilizzando netifaces(disponibile 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

test:

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

6

Puoi farlo con psutil che è multipiattaforma:

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

3

Tieni presente che puoi creare la tua libreria multipiattaforma in Python utilizzando le importazioni condizionali. per esempio

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

Ciò ti consentirà di utilizzare le chiamate os.system o le librerie specifiche della piattaforma.


2
non è proprio una risposta - solo un commento
Stefano

1

Il pacchetto getmac multipiattaforma funzionerà per questo, se non ti dispiace prendere una dipendenza. Funziona con Python 2.7+ e 3.4+. Proverà molti metodi diversi fino a ottenere un indirizzo o restituire Nessuno.

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)

Disclaimer: sono l'autore del pacchetto.

Aggiornamento (14 gennaio 2019): il pacchetto ora supporta solo Python 2.7+ e 3.4+. È comunque possibile utilizzare una versione precedente del pacchetto se è necessario lavorare con un Python precedente (2.5, 2.6, 3.2, 3.3).


1

Per ottenere l' eth0indirizzo MAC dell'interfaccia,

import psutil

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

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

0

Non conosco un modo unificato, ma ecco qualcosa che potresti trovare utile:

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

Quello che farei in questo caso sarebbe racchiuderli in una funzione e, in base al sistema operativo, eseguire il comando corretto, analizzare come richiesto e restituire solo l'indirizzo MAC formattato come desiderato. Ovviamente è lo stesso, tranne per il fatto che devi farlo solo una volta, e sembra più pulito dal codice principale.


0

Per Linux lasciatemi introdurre uno script di shell che mostrerà l'indirizzo mac e permetterà di modificarlo (sniffing MAC).

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

Gli argomenti tagliati possono dffer (non sono un esperto) prova:

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

Per cambiare MAC possiamo fare:

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

cambierà l'indirizzo mac in 00: 80: 48: BA: d1: 30 (temporaneamente, ripristinerà quello effettivo al riavvio).


6
Questo ha a che fare con la domanda?
bot47

-1

In alternativa,

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

-8

Per Linux puoi recuperare l'indirizzo MAC usando un 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 ...

Hai taggato la domanda "pitone". Non conosco un modulo Python esistente per ottenere queste informazioni. È possibile utilizzare ctypes per chiamare direttamente ioctl.


8
-1 Vuole una soluzione Python, quindi vai a dargli la stessa soluzione C rigurgitata intonacata in tutto il web.
Partita il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.