Mendapatkan Alamat MAC

111

Saya memerlukan metode lintas platform untuk menentukan alamat MAC komputer pada saat dijalankan. Untuk windows, modul 'wmi' dapat digunakan dan satu-satunya metode di Linux yang dapat saya temukan adalah menjalankan ifconfig dan menjalankan regex di seluruh outputnya. Saya tidak suka menggunakan paket yang hanya bekerja pada satu OS, dan mengurai output dari program lain sepertinya tidak terlalu elegan apalagi rawan kesalahan.

Adakah yang tahu metode lintas platform (windows dan linux) metode untuk mendapatkan alamat MAC? Jika tidak, apakah ada yang tahu metode yang lebih elegan dari yang saya sebutkan di atas?

Mark Roddy
sumber
Ada banyak jawaban yang berpotensi membantu di sini! Bagaimana saya bisa mendapatkan alamat IP eth0 dengan Python?
uhoh

Jawaban:

160

Python 2.5 menyertakan implementasi uuid yang (setidaknya dalam satu versi) membutuhkan alamat mac. Anda dapat mengimpor fungsi pencarian mac ke dalam kode Anda sendiri dengan mudah:

from uuid import getnode as get_mac
mac = get_mac()

Nilai yang dikembalikan adalah alamat mac sebagai bilangan bulat 48 bit.

Armin Ronacher
sumber
25
Saya baru saja mencoba ini di kotak Windows dan berfungsi dengan baik ... kecuali bahwa laptop yang saya coba memiliki 2 NIC (satu nirkabel) dan tidak ada cara untuk menentukan MAC mana yang dikembalikan. Hanya satu kata peringatan jika Anda ingin menggunakan kode ini.
technomalogical
24
Hanya peringatan: Jika Anda melihat getnodedokumentasi, dikatakan bahwa ia akan mengembalikan panjang acak jika gagal mendeteksi mac: "Jika semua upaya untuk mendapatkan alamat perangkat keras gagal, kami memilih nomor 48-bit acak dengan bit kedelapan setel ke 1 seperti yang direkomendasikan di RFC 4122. " Jadi periksa bagian kedelapan itu!
deinonychusaur
27
hex(mac)untuk mendapatkan format hex familiar dari mac
screenshot345
43
Atau ':'.join(("%012X" % mac)[i:i+2] for i in range(0, 12, 2))untuk MAC huruf besar dengan setiap byte dipisahkan oleh titik dua.
tomlogic
5
getnode () mengembalikan sesuatu yang berbeda setiap kali saya me-restart laptop windows 7 saya.
nu everest
80

Solusi python murni untuk masalah ini di Linux untuk mendapatkan MAC untuk antarmuka lokal tertentu, awalnya diposting sebagai komentar oleh vishnubob dan ditingkatkan oleh Ben Mackey dalam resep aktivasi ini

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

Ini adalah kode yang kompatibel dengan 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()
synthesizerpatel
sumber
35

netifaces adalah modul yang bagus untuk digunakan untuk mendapatkan alamat mac (dan alamat lain). Ini lintas platform dan lebih masuk akal daripada menggunakan soket atau 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.dll
sumber
Digunakan secara pribadi, membutuhkan instalasi / kompilasi khusus pada setiap sistem tetapi berfungsi dengan baik.
Saksikan
22

Satu hal lain yang harus Anda perhatikan adalah bahwa uuid.getnode()dapat memalsukan alamat MAC dengan mengembalikan nomor 48-bit acak yang mungkin bukan yang Anda harapkan. Selain itu, tidak ada indikasi eksplisit bahwa alamat MAC telah dipalsukan, tetapi Anda dapat mendeteksinya dengan menelepon getnode()dua kali dan melihat apakah hasilnya bervariasi. Jika nilai yang sama dikembalikan oleh kedua panggilan, Anda memiliki alamat MAC, jika tidak, Anda akan mendapatkan alamat palsu.

>>> 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
sumber
8
Bukan berarti nilai yang ke-8 adalah 1 justru karena tidak bisa digunakan oleh kartu jaringan. Hanya memeriksa bit ini sudah cukup untuk mendeteksi apakah alamat tersebut palsu atau tidak.
Frédéric Grosshans
15
Pemeriksaan baru saja dilakukan dengan: if (mac >> 40)% 2: raise OSError, "Sistem tampaknya tidak memiliki MAC yang valid"
Frédéric Grosshans
17

Terkadang kami memiliki lebih dari satu antarmuka internet.

Metode sederhana untuk mengetahui alamat mac dari antarmuka tertentu, adalah:

def getmac(interface):

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

  return mac[0:17]

memanggil metode ini sederhana

myMAC = getmac("wlan0")
Julio Schurt
sumber
2
Tidak terlalu berguna untuk OS X atau Windows. : |
RandomInsano
1
Sempurna untuk Pis!
MikeT
8

Menggunakan jawaban saya dari sini: https://stackoverflow.com/a/18031868/2362361

Penting untuk mengetahui untuk iface mana Anda menginginkan MAC karena banyak yang bisa ada (bluetooth, beberapa nics, dll.).

Ini melakukan pekerjaan ketika Anda mengetahui IP iface yang Anda butuhkan MAC-nya, menggunakan netifaces(tersedia di 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

Pengujian:

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

Anda dapat melakukan ini dengan psutil yang bersifat lintas platform:

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 Novice
sumber
import socketkemudian [addr.address for n in nics for addr in nics[n] if n == 'enp4s0' and addr.family == socket.AF_PACKET]menghasilkan['ab:cd:ef:01:02:03']
Donn Lee
3

Perhatikan bahwa Anda dapat membuat pustaka lintas platform Anda sendiri dengan python menggunakan impor bersyarat. misalnya

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

Ini akan memungkinkan Anda untuk menggunakan panggilan os.system atau pustaka khusus platform.

John Fouhy
sumber
2
itu sebenarnya bukan jawaban - hanya komentar
Stefano
1

Paket getmac lintas platform akan berfungsi untuk ini, jika Anda tidak keberatan menggunakan ketergantungan. Ia bekerja dengan Python 2.7+ dan 3.4+. Ini akan mencoba berbagai metode sampai mendapatkan alamat atau mengembalikan Tidak Ada.

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)

Penafian: Saya adalah pembuat paket.

Pembaruan (14 Jan 2019): paket sekarang hanya mendukung Python 2.7+ dan 3.4+. Anda masih dapat menggunakan versi paket yang lebih lama jika Anda perlu bekerja dengan Python yang lebih lama (2.5, 2.6, 3.2, 3.3).

Ghost of Goes
sumber
1

Untuk mendapatkan eth0alamat MAC antarmuka,

import psutil

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

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

Saya tidak tahu cara bersatu, tetapi inilah sesuatu yang mungkin berguna bagi Anda:

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

Apa yang akan saya lakukan dalam kasus ini adalah membungkus ini menjadi sebuah fungsi, dan berdasarkan OS itu akan menjalankan perintah yang tepat, mengurai sesuai kebutuhan dan hanya mengembalikan alamat MAC yang diformat seperti yang Anda inginkan. Tentu saja semua sama, kecuali Anda hanya perlu melakukannya sekali, dan terlihat lebih bersih dari kode utama.

Sebagian besar tidak berbahaya
sumber
0

Untuk Linux izinkan saya memperkenalkan skrip shell yang akan menampilkan alamat mac dan memungkinkan untuk mengubahnya (mengendus MAC).

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

Perselisihan yang dipotong mungkin berbeda (saya bukan ahli) coba:

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

Untuk mengubah MAC kita dapat melakukan:

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

akan mengubah alamat mac menjadi 00: 80: 48: BA: d1: 30 (sementara, akan dikembalikan ke alamat sebenarnya saat reboot).

Sarath Sadasivan Pillai
sumber
6
Apakah ini ada hubungannya dengan pertanyaan?
bot47
-1

Kalau tidak,

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

Untuk Linux, Anda dapat mengambil alamat MAC menggunakan 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 ...

Anda telah menandai pertanyaan "python". Saya tidak tahu modul Python yang ada untuk mendapatkan informasi ini. Anda dapat menggunakan ctypes untuk memanggil ioctl secara langsung.

DGentry
sumber
8
-1 Dia menginginkan solusi python, jadi Anda pergi dan memberinya solusi C yang sama yang terpampang di seluruh web.
Aatch