Nhận địa chỉ MAC


111

Tôi cần một phương pháp đa nền tảng để xác định địa chỉ MAC của máy tính tại thời điểm chạy. Đối với cửa sổ, mô-đun 'wmi' có thể được sử dụng và phương pháp duy nhất trong Linux mà tôi có thể tìm thấy là chạy ifconfig và chạy regex trên đầu ra của nó. Tôi không thích sử dụng một gói chỉ hoạt động trên một hệ điều hành và việc phân tích cú pháp đầu ra của một chương trình khác có vẻ không được thanh lịch cho lắm, chưa kể dễ xảy ra lỗi.

Có ai biết phương pháp đa nền tảng (windows và linux) phương pháp để lấy địa chỉ MAC không? Nếu không, có ai biết bất kỳ phương pháp thanh lịch hơn sau đó những người tôi liệt kê ở trên?


Có rất nhiều câu trả lời có thể hữu ích ở đây! Làm cách nào để lấy địa chỉ IP của eth0 trong Python?
uhoh

Câu trả lời:


160

Python 2.5 bao gồm một triển khai uuid (trong ít nhất một phiên bản) cần địa chỉ mac. Bạn có thể nhập chức năng tìm mac vào mã của riêng mình một cách dễ dàng:

from uuid import getnode as get_mac
mac = get_mac()

Giá trị trả về là địa chỉ mac dưới dạng số nguyên 48 bit.


25
Tôi vừa thử điều này trên hộp Windows và nó hoạt động tốt ... ngoại trừ việc máy tính xách tay tôi đã thử có 2 NIC (một không dây) và không có cách nào để xác định MAC nó trả về. Chỉ là một lời cảnh báo nếu bạn muốn sử dụng mã này.
technomalogical

24
Chỉ là một cảnh báo: Nếu bạn xem getnodetài liệu, nó nói rằng nó sẽ trả về một khoảng thời gian dài ngẫu nhiên nếu nó không phát hiện ra mac: "Nếu tất cả các nỗ lực lấy địa chỉ phần cứng đều thất bại, chúng tôi chọn một số 48 bit ngẫu nhiên với bit thứ tám của nó được đặt thành 1 như được đề xuất trong RFC 4122. " Vì vậy, hãy kiểm tra bit thứ tám!
deinonychusaur

27
hex(mac)để có được định dạng hex quen thuộc của mac
ảnh chụp màn

43
Hoặc ':'.join(("%012X" % mac)[i:i+2] for i in range(0, 12, 2))đối với MAC viết hoa với mỗi byte được phân tách bằng dấu hai chấm.
tomlogic

5
getnode () trả về một cái gì đó khác nhau mỗi khi tôi khởi động lại máy tính xách tay windows 7 của mình.
nu everest

80

Giải pháp python thuần túy cho vấn đề này trong Linux để lấy MAC cho giao diện cục bộ cụ thể, ban đầu được đăng dưới dạng nhận xét bởi vishnubob và được cải thiện bởi Ben Mackey trong công thức kích hoạt này

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

Đây là mã tương thích với 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 là một mô-đun tốt để sử dụng để lấy địa chỉ mac (và các địa chỉ khác). Nó có dạng crossplatform và có ý nghĩa hơn một chút so với việc sử dụng socket hoặc 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'}]


Đã sử dụng nó cá nhân, yêu cầu cài đặt / biên dịch cụ thể trên từng hệ thống nhưng hoạt động tốt.
Bắt đầu

22

Một điều khác mà bạn cần lưu ý là uuid.getnode()có thể giả mạo trình bổ sung MAC bằng cách trả về một số 48 bit ngẫu nhiên có thể không phải là những gì bạn mong đợi. Ngoài ra, không có dấu hiệu rõ ràng nào cho thấy địa chỉ MAC đã bị làm giả, nhưng bạn có thể phát hiện nó bằng cách gọi getnode()hai lần và xem kết quả có thay đổi hay không. Nếu cả hai lần gọi đều trả về cùng một giá trị thì bạn có địa chỉ MAC, nếu không thì bạn đang nhận được một địa chỉ giả.

>>> 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
Không phải giá trị của số 8 chính xác là 1 vì nó không thể được sử dụng bởi một card mạng. Chỉ cần kiểm tra bit này là đủ để phát hiện ra địa chỉ đó có bị làm giả hay không.
Frédéric Grosshans

15
Vui lòng cung chỉ được thực hiện với: if (mac >> 40)% 2: tăng OSError, "Hệ thống này dường như không có một MAC hợp lệ"
Frédéric Grosshans

17

Đôi khi chúng ta có nhiều hơn một giao diện mạng.

Một phương pháp đơn giản để tìm ra địa chỉ mac của một giao diện cụ thể, là:

def getmac(interface):

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

  return mac[0:17]

để gọi phương thức là đơn giản

myMAC = getmac("wlan0")

2
Không quá hữu ích cho OS X hoặc Windows. : |
RandomInsano

1
Hoàn hảo cho Pis!
MikeT

8

Sử dụng câu trả lời của tôi từ đây: https://stackoverflow.com/a/18031868/2362361

Điều quan trọng là phải biết bạn muốn MAC cho iface nào vì nhiều loại có thể tồn tại (bluetooth, vài nics, v.v.).

Điều này thực hiện công việc khi bạn biết IP của iface mà bạn cần MAC, sử dụng netifaces(có sẵn trong 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

Thử nghiệm:

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

6

Bạn có thể làm điều này với psutil đa nền tảng:

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 socketsau đó [addr.address for n in nics for addr in nics[n] if n == 'enp4s0' and addr.family == socket.AF_PACKET]kết quả là['ab:cd:ef:01:02:03']
Donn Lee

3

Lưu ý rằng bạn có thể xây dựng thư viện đa nền tảng của riêng mình trong python bằng cách sử dụng nhập có điều kiện. ví dụ

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

Điều này sẽ cho phép bạn sử dụng các cuộc gọi hệ thống hoặc các thư viện dành riêng cho nền tảng.


2
đó không thực sự là một câu trả lời - chỉ là một nhận xét
Stefano

1

Gói getmac đa nền tảng sẽ hoạt động cho điều này, nếu bạn không ngại việc phụ thuộc. Nó hoạt động với Python 2.7+ và 3.4+. Nó sẽ thử nhiều phương pháp khác nhau cho đến khi nhận được địa chỉ hoặc trả về Không có.

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)

Tuyên bố từ chối trách nhiệm: Tôi là tác giả của gói.

Cập nhật (ngày 14 tháng 1 năm 2019): gói hiện chỉ hỗ trợ Python 2.7+ và 3.4+. Bạn vẫn có thể sử dụng phiên bản cũ hơn của gói nếu bạn cần làm việc với Python cũ hơn (2.5, 2.6, 3.2, 3.3).


1

Để lấy eth0địa chỉ MAC của giao diện,

import psutil

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

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

0

Tôi không biết về một cách thống nhất, nhưng có một số điều mà bạn có thể thấy hữu ích:

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

Những gì tôi sẽ làm trong trường hợp này là gói chúng thành một hàm và dựa trên hệ điều hành, nó sẽ chạy lệnh thích hợp, phân tích cú pháp theo yêu cầu và chỉ trả lại địa chỉ MAC được định dạng như bạn muốn. Tất nhiên, tất cả đều giống nhau, ngoại trừ việc bạn chỉ phải làm điều đó một lần và nó trông gọn gàng hơn so với mã chính.


0

Đối với Linux, hãy để tôi giới thiệu một tập lệnh shell sẽ hiển thị địa chỉ mac và cho phép thay đổi nó (đánh hơi MAC).

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

Các cuộc tranh luận cắt giảm có thể trở nên tồi tệ hơn (tôi không phải là chuyên gia) hãy thử:

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

Để thay đổi MAC, chúng tôi có thể làm:

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

sẽ thay đổi địa chỉ mac thành 00: 80: 48: BA: d1: 30 (tạm thời, sẽ khôi phục về địa chỉ thực khi khởi động lại).


6
Điều này có liên quan gì đến câu hỏi không?
bot47

-1

Ngoài ra,

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

-8

Đối với Linux, bạn có thể truy xuất địa chỉ MAC bằng 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 ...

Bạn đã gắn thẻ câu hỏi "python". Tôi không biết mô-đun Python hiện có để lấy thông tin này. Bạn có thể sử dụng ctypes để gọi ioctl trực tiếp.


8
-1 Anh ta muốn một giải pháp cho trăn, vì vậy bạn đi và đưa cho anh ta cùng một dung dịch C bị trào ngược được dán trên khắp trang web.
Bắt đầu
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.