[python]Capture live hosts with scapy using threading

This script borrows the code from Python Code by far I felt this code is the best in terms of structure, the author structured blocks of code with explanation, although oddly Pycharm fails to resolve Ether and ARP functions from scapy.all
py1

Pycharm also fails to resolve the arguments of SRP method, such as the verbose and timeout arguments. Nevertheless the Python code’s code works.

This is a basic network discovery script that discovers network with specified subnet, MAC addresses and IP addresses will be captured in a list of dictionary if the hosts are alive.

Without threading
The network is 192.168.1.0/24 which is 254 hosts, time taken is approximately 13 minutes to finish.
withoutthreading1

from scapy.all import srp, Ether, ARP
from ipaddress import IPv4Network
from pprint import pprint
from time import time



clients = list()
if __name__ == "__main__":
    start = time()
    for ip in IPv4Network('192.168.1.0/24').hosts():
        packet = Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(pdst=str(ip))
        result = srp(packet, timeout=3, verbose=1)[0]
        for _, received in result:
            clients.append(
                {
                    "ip": received.psrc,
                    "mac": received.hwsrc
                }
            )
    pprint(clients)
    print(f"Executed in {time() - start} seconds.")

With threading
With threading acquiring live hosts took 9 seconds.
thread1

from scapy.all import srp, Ether, ARP
from threading import Thread
from ipaddress import IPv4Network
from pprint import pprint
from time import sleep, time

threads = []

clients = list()
class Scanner(Thread):
    def __init__(self, ip):
        super().__init__()
        self.ip = ip

    def run(self):
        # The below code from https://www.thepythoncode.com/article/building-network-scanner-using-scapy
        packet = Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(pdst=self.ip)
        # this is a tuple, which index 0 is host that answers arp request.
        # while index 1 is unanswered when no host answers arp request.
        result = srp(packet, timeout=3, verbose=0)[0]
        # the result is a tuple with index 0 as sent, and 1 as received.
        for _, received in result:
            # psrc is the arp responder's ip address
            # hwsrc is the arp responder's mac address
            clients.append(
                {
                    "ip": received.psrc,
                    "mac": received.hwsrc
                }
            )
        # maintain consistency by forcing this method to sleep for 1 second
        # before beginning the next host.
        sleep(1)


if __name__ == "__main__":
    start = time()
    for ip in IPv4Network('192.168.1.0/24').hosts():
        t = Scanner(str(ip))
        threads.append(t)
        t.start()

    for t in threads:
        t.join()

    pprint(clients)
    print(f"Executed in {time() - start} seconds.")

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s