รับที่อยู่ MAC


111

ฉันต้องการวิธีข้ามแพลตฟอร์มในการกำหนดที่อยู่ MAC ของคอมพิวเตอร์ในขณะทำงาน สำหรับ windows โมดูล 'wmi' สามารถใช้ได้และวิธีเดียวใน Linux ที่ฉันพบคือเรียกใช้ ifconfig และเรียกใช้ regex ในเอาต์พุต ฉันไม่ชอบใช้แพคเกจที่ใช้งานได้กับระบบปฏิบัติการเดียวเท่านั้นและการแยกวิเคราะห์ผลลัพธ์ของโปรแกรมอื่นดูไม่สวยงามมากนักหากไม่พูดถึงข้อผิดพลาดที่มีแนวโน้มที่จะเกิดข้อผิดพลาด

ไม่มีใครรู้วิธีข้ามแพลตฟอร์ม (windows และ linux) เพื่อรับที่อยู่ MAC? ถ้าไม่มีใครรู้วิธีการที่หรูหรากว่านี้จากที่ฉันระบุไว้ข้างต้นหรือไม่?


มีคำตอบที่เป็นประโยชน์มากมายที่นี่! ฉันจะรับที่อยู่ IP ของ eth0 ใน Python ได้อย่างไร
uhoh

คำตอบ:


160

Python 2.5 มีการใช้งาน uuid ซึ่ง (อย่างน้อยหนึ่งเวอร์ชัน) ต้องการที่อยู่ mac คุณสามารถนำเข้าฟังก์ชั่นการค้นหา mac ลงในโค้ดของคุณเองได้อย่างง่ายดาย:

from uuid import getnode as get_mac
mac = get_mac()

ค่าส่งคืนคือที่อยู่ mac เป็นจำนวนเต็ม 48 บิต


25
ฉันเพิ่งลองสิ่งนี้ในกล่อง Windows และใช้งานได้ดี ... ยกเว้นว่าแล็ปท็อปที่ฉันลองใช้นั้นมี 2 NIC (ไร้สายหนึ่งเครื่อง) และไม่มีทางระบุได้ว่า MAC ใดที่ส่งคืน เพียงคำเตือนหากคุณต้องการใช้รหัสนี้
technomalogical

24
คำเตือน: หากคุณดูgetnodeเอกสารที่ระบุว่าจะส่งคืนแบบสุ่มหากตรวจไม่พบ mac: "หากความพยายามทั้งหมดในการรับที่อยู่ฮาร์ดแวร์ล้มเหลวเราจะเลือกหมายเลข 48 บิตแบบสุ่มด้วยบิตที่แปด ตั้งค่าเป็น 1 ตามที่แนะนำใน RFC 4122 " ดังนั้นตรวจสอบที่แปดบิต!
deinonychusaur

27
hex(mac)เพื่อรับรูปแบบฐานสิบหกที่คุ้นเคยของ mac
screenshot345

43
หรือ':'.join(("%012X" % mac)[i:i+2] for i in range(0, 12, 2))สำหรับ MAC ตัวพิมพ์ใหญ่ที่มีแต่ละไบต์คั่นด้วยเครื่องหมายจุดคู่
tomlogic

5
getnode () ส่งคืนสิ่งที่แตกต่างทุกครั้งที่ฉันรีสตาร์ทแล็ปท็อป Windows 7
nu everest

81

โซลูชัน python ที่บริสุทธิ์สำหรับปัญหานี้ภายใต้ Linux เพื่อรับ MAC สำหรับอินเทอร์เฟซเฉพาะที่โพสต์เดิมเป็นความคิดเห็นโดย vishnubob และปรับปรุงโดย Ben Mackey ใน สูตร 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')

นี่คือรหัสที่เข้ากันได้กับ 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()

36

netifaces เป็นโมดูลที่ดีในการรับที่อยู่ mac (และที่อยู่อื่น ๆ ) มันข้ามแพลตฟอร์มและสมเหตุสมผลกว่าการใช้ซ็อกเก็ตหรือ 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'}]


ใช้เป็นการส่วนตัวต้องติดตั้ง / คอมไพล์เฉพาะในแต่ละระบบ แต่ทำงานได้ดี
Aatch

22

อีกสิ่งหนึ่งที่คุณควรทราบคือuuid.getnode()สามารถปลอม MAC addr ได้โดยส่งคืนหมายเลข 48 บิตแบบสุ่มซึ่งอาจไม่ใช่สิ่งที่คุณคาดหวัง นอกจากนี้ยังไม่มีข้อบ่งชี้ที่ชัดเจนว่าที่อยู่ MAC ถูกปลอม แต่คุณสามารถตรวจพบได้โดยการโทรgetnode()สองครั้งและดูว่าผลลัพธ์แตกต่างกันไปหรือไม่ หากทั้งสองสายส่งคืนค่าเดียวกันแสดงว่าคุณมีที่อยู่ MAC มิฉะนั้นคุณจะได้รับที่อยู่ปลอม

>>> 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
ไม่ใช่ว่าค่าของ 8 คือ 1 อย่างแม่นยำเพราะการ์ดเครือข่ายไม่สามารถใช้งานได้ เพียงตรวจสอบบิตนี้ก็เพียงพอที่จะตรวจสอบว่าที่อยู่นั้นถูกปลอมหรือไม่
Frédéric Grosshans

15
การตรวจสอบทำได้โดย: if (mac >> 40)% 2: เพิ่ม OSError, "ดูเหมือนว่าระบบจะไม่มี MAC ที่ถูกต้อง"
Frédéric Grosshans

17

บางครั้งเรามีอินเทอร์เฟซสุทธิมากกว่าหนึ่งรายการ

วิธีง่ายๆในการค้นหาที่อยู่ mac ของอินเทอร์เฟซเฉพาะคือ:

def getmac(interface):

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

  return mac[0:17]

การเรียกวิธีการนั้นง่ายมาก

myMAC = getmac("wlan0")

2
ไม่มีประโยชน์อย่างยิ่งสำหรับ OS X หรือ Windows : |
RandomInsano

1
เหมาะสำหรับพิส!
MikeT

8

ใช้คำตอบของฉันจากที่นี่: https://stackoverflow.com/a/18031868/2362361

สิ่งสำคัญคือต้องรู้ว่า iface ใดที่คุณต้องการ MAC เนื่องจากสามารถมีได้หลายตัว (บลูทู ธ นิคส์หลายตัว ฯลฯ )

สิ่งนี้จะได้ผลเมื่อคุณทราบ IP ของ iface ที่คุณต้องการ MAC โดยใช้netifaces(มีให้ใน 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

การทดสอบ:

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

6

คุณสามารถทำได้ด้วย psutil ซึ่งเป็นข้ามแพลตฟอร์ม:

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 socketแล้ว[addr.address for n in nics for addr in nics[n] if n == 'enp4s0' and addr.family == socket.AF_PACKET]ผลลัพธ์ใน['ab:cd:ef:01:02:03']
Donn Lee

3

โปรดทราบว่าคุณสามารถสร้างไลบรารีข้ามแพลตฟอร์มของคุณเองใน python โดยใช้การนำเข้าตามเงื่อนไข เช่น

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

สิ่งนี้จะช่วยให้คุณใช้การเรียกใช้ระบบปฏิบัติการหรือไลบรารีเฉพาะแพลตฟอร์ม


2
นั่นไม่ใช่คำตอบจริงๆ - เพียงความคิดเห็น
Stefano

1

แพคเกจgetmacข้ามแพลตฟอร์มจะใช้งานได้หากคุณไม่คิดจะพึ่งพา ทำงานร่วมกับ Python 2.7+ และ 3.4+ จะลองใช้วิธีการต่างๆมากมายจนกว่าจะได้รับที่อยู่หรือส่งคืน None

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)

คำเตือน: ฉันเป็นผู้เขียนแพ็คเกจ

อัปเดต (14 ม.ค. 2019): แพ็คเกจรองรับเฉพาะ Python 2.7+ และ 3.4+ เท่านั้น คุณยังสามารถใช้แพ็กเกจเวอร์ชันเก่าได้หากคุณต้องการทำงานกับ Python รุ่นเก่า (2.5, 2.6, 3.2, 3.3)



0

ฉันไม่รู้วิธีที่เป็นหนึ่งเดียว แต่นี่คือสิ่งที่คุณอาจพบว่ามีประโยชน์:

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

สิ่งที่ฉันจะทำในกรณีนี้คือการรวมสิ่งเหล่านี้ไว้ในฟังก์ชันและขึ้นอยู่กับระบบปฏิบัติการมันจะเรียกใช้คำสั่งที่เหมาะสมแยกวิเคราะห์ตามที่ต้องการและส่งคืนเฉพาะที่อยู่ MAC ที่จัดรูปแบบตามที่คุณต้องการ แน่นอนว่ามันเหมือนกันทั้งหมดยกเว้นว่าคุณต้องทำเพียงครั้งเดียวและมันดูสะอาดกว่าจากรหัสหลัก


0

สำหรับ Linux ให้ฉันแนะนำเชลล์สคริปต์ที่จะแสดงที่อยู่ mac และอนุญาตให้เปลี่ยนได้ (การดมกลิ่น MAC)

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

การตัดข้อโต้แย้งอาจไม่เหมาะสม (ฉันไม่ใช่ผู้เชี่ยวชาญ) ลอง:

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

ในการเปลี่ยน MAC เราสามารถทำได้:

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

จะเปลี่ยนที่อยู่ mac เป็น 00: 80: 48: BA: d1: 30 (ชั่วคราวจะคืนค่าเป็นจริงเมื่อรีบูต)


6
สิ่งนี้ต้องทำอะไรกับคำถามหรือไม่?
ธ ปท 47


-8

สำหรับ Linux คุณสามารถดึงข้อมูลที่อยู่ MAC โดยใช้ 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 ...

คุณได้ติดแท็กคำถาม "python" ฉันไม่รู้จักโมดูล Python ที่มีอยู่เพื่อรับข้อมูลนี้ คุณสามารถใช้ctypesเพื่อเรียก ioctl ได้โดยตรง


8
-1 เขาต้องการวิธีแก้ปัญหา python ดังนั้นคุณจึงไปหาวิธีแก้ปัญหา C แบบสำรอกให้เขาฉาบทั่วทั้งเว็บ
Aatch
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.