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)