Obtenir l'adresse MAC

111

J'ai besoin d'une méthode multiplateforme pour déterminer l'adresse MAC d'un ordinateur au moment de l'exécution. Pour Windows, le module 'wmi' peut être utilisé et la seule méthode sous Linux que j'ai pu trouver était d'exécuter ifconfig et d'exécuter une expression régulière sur sa sortie. Je n'aime pas utiliser un package qui ne fonctionne que sur un seul système d'exploitation, et l'analyse de la sortie d'un autre programme ne semble pas très élégante, sans parler des erreurs.

Est-ce que quelqu'un connaît une méthode multiplateforme (Windows et Linux) pour obtenir l'adresse MAC? Sinon, est-ce que quelqu'un connaît des méthodes plus élégantes que celles que j'ai énumérées ci-dessus?

Mark Roddy
la source
Il existe de nombreuses réponses potentiellement utiles ici! Comment puis-je obtenir l'adresse IP de eth0 en Python?
uhoh

Réponses:

160

Python 2.5 inclut une implémentation uuid qui (dans au moins une version) a besoin de l'adresse mac. Vous pouvez facilement importer la fonction de recherche Mac dans votre propre code:

from uuid import getnode as get_mac
mac = get_mac()

La valeur de retour est l'adresse mac sous forme d'entier 48 bits.

Armin Ronacher
la source
25
Je viens de l'essayer sur une boîte Windows et cela fonctionne très bien ... sauf que l'ordinateur portable sur lequel je l'ai essayé a 2 cartes réseau (une sans fil) et qu'il n'y a aucun moyen de déterminer quel MAC il a renvoyé. Juste un mot d'avertissement si vous souhaitez utiliser ce code.
technomalogical
24
Juste un avertissement: si vous regardez la getnodedocumentation, elle indique qu'elle renverra un long aléatoire s'il ne parvient pas à détecter le mac: "Si toutes les tentatives pour obtenir l'adresse matérielle échouent, nous choisissons un nombre aléatoire de 48 bits avec son huitième bit mis à 1 comme recommandé dans la RFC 4122. " Alors vérifiez ce huitième bit!
deinonychusaur
27
hex(mac)pour obtenir le format hexadécimal familier du mac
capture d'
43
Ou ':'.join(("%012X" % mac)[i:i+2] for i in range(0, 12, 2))pour un MAC en majuscule avec chaque octet séparé par un deux-points.
tomlogic
5
getnode () renvoie quelque chose de différent chaque fois que je redémarre mon ordinateur portable Windows 7.
nu everest
80

La solution pure python pour ce problème sous Linux pour obtenir le MAC pour une interface locale spécifique, initialement publiée en tant que commentaire par vishnubob et améliorée par sur Ben Mackey dans cette recette d'activation

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

Voici le code compatible 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()
synthétiseurpatel
la source
35

netifaces est un bon module à utiliser pour obtenir l'adresse mac (et d'autres adresses). C'est crossplatform et cela a un peu plus de sens que d'utiliser socket ou 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'}]

camflan
la source
Utilisé personnellement, nécessite une installation / compilation spécifique sur chaque système mais fonctionne bien.
Aatch le
22

Une autre chose que vous devez noter est que vous uuid.getnode()pouvez simuler l'adresse MAC en renvoyant un nombre aléatoire de 48 bits qui peut ne pas être ce que vous attendez. De plus, il n'y a aucune indication explicite que l'adresse MAC a été falsifiée, mais vous pouvez la détecter en appelant getnode()deux fois et en voyant si le résultat varie. Si la même valeur est renvoyée par les deux appels, vous avez l'adresse MAC, sinon vous obtenez une fausse 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.
mhawke
la source
8
Non pas que la valeur du 8e soit 1 précisément parce qu'il ne peut pas être utilisé par une carte réseau. Il suffit de vérifier ce bit pour détecter si l'adresse est fausse ou non.
Frédéric Grosshans
15
La vérification est juste faite avec: if (mac >> 40)% 2: lever OSError, "Le système ne semble pas avoir de MAC valide"
Frédéric Grosshans
17

Parfois, nous avons plus d'une interface réseau.

Une méthode simple pour connaître l'adresse mac d'une interface spécifique est:

def getmac(interface):

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

  return mac[0:17]

appeler la méthode est simple

myMAC = getmac("wlan0")
Julio Schurt
la source
2
Pas super utile pour OS X ou Windows. : |
RandomInsano
1
Parfait pour les Pis!
MikeT
8

En utilisant ma réponse d'ici: https://stackoverflow.com/a/18031868/2362361

Il serait important de savoir pour quelle iface vous voulez le MAC car beaucoup peuvent exister (bluetooth, plusieurs nics, etc.).

Cela fait le travail lorsque vous connaissez l'adresse IP de l'iface pour laquelle vous avez besoin du MAC, en utilisant netifaces(disponible dans 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

Essai:

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

Vous pouvez le faire avec psutil qui est multiplateforme:

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]
Novice Python
la source
import socketpuis [addr.address for n in nics for addr in nics[n] if n == 'enp4s0' and addr.family == socket.AF_PACKET]résultats['ab:cd:ef:01:02:03']
Donn Lee
3

Notez que vous pouvez créer votre propre bibliothèque multiplateforme en python à l'aide d'importations conditionnelles. par exemple

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

Cela vous permettra d'utiliser des appels os.system ou des bibliothèques spécifiques à la plateforme.

John Fouhy
la source
2
ce n'est pas vraiment une réponse - juste un commentaire
Stefano
1

Le package getmac multiplateforme fonctionnera pour cela, si cela ne vous dérange pas de prendre une dépendance. Il fonctionne avec Python 2.7+ et 3.4+. Il essaiera de nombreuses méthodes différentes jusqu'à obtenir une adresse ou renvoyer Aucune.

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)

Avertissement: Je suis l'auteur du package.

Mise à jour (14 janvier 2019): le package ne prend désormais en charge que Python 2.7+ et 3.4+. Vous pouvez toujours utiliser une ancienne version du package si vous devez travailler avec un ancien Python (2.5, 2.6, 3.2, 3.3).

Fantôme de Goes
la source
1

Pour obtenir l' eth0adresse MAC de l' interface,

import psutil

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

for interface in nics:
   if interface.family == 17:
      print(interface.address)
Balaji Reddy
la source
0

Je ne connais pas de manière unifiée, mais voici quelque chose que vous pourriez trouver utile:

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

Ce que je ferais dans ce cas serait de les envelopper dans une fonction, et en fonction du système d'exploitation, il exécuterait la commande appropriée, analyserait si nécessaire et ne renverrait que l'adresse MAC formatée comme vous le souhaitez. C'est bien sûr tout de même, sauf que vous ne devez le faire qu'une seule fois, et cela semble plus propre du code principal.

La plupart du temps inoffensifs
la source
0

Pour Linux, permettez-moi d'introduire un script shell qui affichera l'adresse mac et permet de la changer (reniflage MAC).

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

Les arguments de coupe peuvent différer (je ne suis pas un expert) essayer:

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

Pour changer de MAC, nous pouvons faire:

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

changera l'adresse mac à 00: 80: 48: BA: d1: 30 (temporairement, restaure à l'adresse réelle au redémarrage).

Sarath Sadasivan Pillai
la source
6
Cela a-t-il quelque chose à voir avec la question?
bot47
-1

Alternativement,

import uuid
mac_id=(':'.join(['{:02x}'.format((uuid.getnode() >> ele) & 0xff)
Ajay Kumar KK
la source
-8

Pour Linux, vous pouvez récupérer l'adresse MAC à l'aide d'un ioctl SIOCGIFHWADDR.

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

Vous avez tagué la question "python". Je ne connais pas de module Python existant pour obtenir ces informations. Vous pouvez utiliser ctypes pour appeler l'ioctl directement.

DGentry
la source
8
-1 Il veut une solution python, alors vous allez lui donner la même solution C régurgitée plâtrée dans tout le web.
Aatch le