Сканирование IP устройств в локальной сети. Часть 2.

Продолжим мучать наш сканер локальной сети. В прошлой статье мы реализовали пинг. Давайте теперь добавим отображение MAC адреса.

Что такое вообще MAC и зачем он ? Допустим у нас есть устройство А которое хочет отправит данные устройству Б. Для этого на нужно IP адрес устройства и обязательно его физический адрес. Так вот сложилось.

MAC-адрес (Media Access Control — управление доступом к среде, также Hardware Address, также физический адрес) — уникальный идентификатор, присваиваемый каждой единице активного оборудования или некоторым их интерфейсам в компьютерных сетях Ethernet.

ru.wikipedia.org

Что бы его узнать есть специальный протокол ARP . То есть устройство A кричит в сеть всем (бруткастит) : Алеее, устройство Б с IP 10.10.10.10 какой у тебя MAC ?

ARP (.Address Resolution Protocol — протокол определения адреса) — протокол в компьютерных сетях, предназначенный для определения MAC-адреса по IP-адресу другого компьютера.

ru.wikipedia.org

Что бы не засорять эфир, ответы кэшируются в таблицу ARP ( в Windows это по моему 4 минуты). Вот от туда мы и будем брать MAC после пинга IP адреса. Для этого есть специальная утилита в операционной системе — ARP ))))

Парсим таблицу :

response_arp = os.popen('arp -a -N '+ net)
data_arp = response_arp.readlines()
     for line_arp in data_arp:
         flag = line_arp.split()
         if len(flag) > 0 and flag[0] == addr:
            print(addr, "--> Ping Ok", ' МАС:', flag[1])

Ну и модифицированная функция сканирования :

def scan_Ip(ip):
    addr = net + str(ip)
    comm = ping_com + addr
    response = os.popen(comm)
    data = response.readlines()
    for line in data:
        if 'TTL' in line:
            response_art = os.popen('arp -a')
            data_arp = response_art.readlines()
            for line_arp in data_arp:
                flag = line_arp.split()
                    
                if len(flag) > 0 and flag[0] == addr:
                    print(addr, "--> Ping Ok", ' МАС:', flag[1])

            break

Еще немного красоты и доделки.

Ну и последним штрихом захотелось добавить доменные имена компов если они есть. В Windows это может быть имена компов по протоколу NetBIOC если включено сетевое обнаружение. Для этого добавим всего лишь параметр -a в команду ping.

Весь код целиком:

import os
import platform
import threading
import socket
from datetime import datetime
global strin
strin = []
def getMyIp():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #Создаем сокет (UDP)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) # Настраиваем сокет на BROADCAST вещание.
    s.connect(('<broadcast>', 0))
    return s.getsockname()[0]

def scan_Ip(ip):
    addr = net + str(ip)
    comm = ping_com + addr
    response = os.popen(comm)
    data = response.readlines()
    name = data[1].split(' ')
    for line in data:
        if 'TTL' in line:
            response_art = os.popen('arp -a')
            data_arp = response_art.readlines()
            for line_arp in data_arp:
                flag = line_arp.split()

                if len(flag) > 0 and flag[0] == addr:
                    tmp =(addr+"--> Ping Ok"+ '    '+ name[3]+'    '+flag[1])
                    strin.append(tmp)

            break

net = getMyIp()
print('You IP :',net)
net_split = net.split('.')
a = '.'
net = net_split[0] + a + net_split[1] + a + net_split[2] + a
start_point = int(input("Enter the Starting Number: "))
end_point = int(input("Enter the Last Number: "))

oс = platform.system()
if (oс == "Windows"):
    ping_com = "ping -n 1 -a "
else:
    ping_com = "ping -c 1 "

t1 = datetime.now()
print("Scanning in Progress:")
print('IP                 Status          Name            MAC')
for ip in range(start_point, end_point):
    if ip == int(net_split[3]):
        continue
    potoc = threading.Thread(target=scan_Ip, args=[ip])
    potoc.start()
    #potoc.join()
potoc.join()
t2 = datetime.now()
total = t2 - t1
for i in strin:
    print(i)
print ('Find ip :',len(strin))
print("Scanning completed in: ", total)

P.S Если у кого будут мысли по более интересной(практично) реализации пишите в комментариях ))))