59 lines
2.6 KiB
Python
59 lines
2.6 KiB
Python
from scapy.layers.l2 import ARP, Ether
|
|
from scapy.sendrecv import srp
|
|
import netifaces
|
|
from netaddr import IPNetwork
|
|
|
|
class NetworkScanner:
|
|
"""Иницилазицая сетевого сканера"""
|
|
def __init__(self, interface=None):
|
|
"""Инициализация параметров интерфейсов """
|
|
self.interface = interface or netifaces.gateways()['default'][netifaces.AF_INET][1]
|
|
self.ip_info = netifaces.ifaddresses(self.interface).get(netifaces.AF_INET, [])
|
|
self.networks = [IPNetwork(f"{ip['addr']}/{ip['netmask']}") for ip in self.ip_info]
|
|
self.local_mac = netifaces.ifaddresses(self.interface)[netifaces.AF_LINK][0]['addr']
|
|
|
|
def _create_arp_packet(self, target_ip):
|
|
"""Создание пакета ARP для отправки"""
|
|
arp = ARP(pdst=target_ip)
|
|
ether = Ether(dst="ff:ff:ff:ff:ff:ff")
|
|
return ether/arp
|
|
|
|
def scan_network(self, attempts=3, timeout=2):
|
|
"""Подготовка к сканированию сети"""
|
|
all_clients = []
|
|
|
|
for network in self.networks:
|
|
target_ip = f"{network.network}/{network.prefixlen}"
|
|
packet = self._create_arp_packet(target_ip)
|
|
clients = []
|
|
|
|
for _ in range(attempts):
|
|
result = srp(packet, timeout=timeout, iface=self.interface, verbose=0)[0]
|
|
for _, received in result:
|
|
client = {'ip': received.psrc, 'mac': received.hwsrc}
|
|
if client not in clients: # Избегаем дублирования клиентов
|
|
clients.append(client)
|
|
|
|
all_clients.extend(clients)
|
|
|
|
# Добавляет все локальные IP-адреса интерфейса как клиенты
|
|
for ip_info in self.ip_info:
|
|
local_client = {'ip': ip_info['addr'], 'mac': self.local_mac}
|
|
if local_client not in all_clients:
|
|
all_clients.append(local_client)
|
|
|
|
# Удаление дубликатов
|
|
unique_clients = {tuple(client.items()) for client in all_clients}
|
|
return [dict(client) for client in unique_clients]
|
|
|
|
def print_clients(self, clients):
|
|
"""Лист адресов клиентов"""
|
|
print("Доступные устройства в сети:")
|
|
print("IP" + " "*18+"MAC")
|
|
for client in sorted(clients, key=lambda x: x['ip']):
|
|
print(f"{client['ip']:<16} {client['mac']}")
|
|
|
|
if __name__ == "__main__":
|
|
scanner = NetworkScanner()
|
|
clients = scanner.scan_network()
|
|
scanner.print_clients(clients)
|