How to Make the Fastest Port Scanner With Python in an Easy Way

In the realm of computer networking, a port serves as a crucial gateway for communication between devices and applications. Think of it as a designated door through which data enters or exits a system. Each port is identified by a numerical value and is associated with a particular service or protocol.

Well-known ports, ranging from 0 to 1023, are standardized and allocated to specific services by authorities like the Internet Assigned Numbers Authority (IANA). For instance, port 80 typically handles web traffic, while port 22 facilitates secure shell connections. On the other hand, dynamic or private ports, falling between 1024 and 49151, are available for general use by applications.

When data is transmitted over a network, it’s directed to a specific port on the receiving end, ensuring that it reaches the intended destination. Ports thus play a pivotal role in enabling seamless communication across diverse devices and services within a network infrastructure.

Getting Started

Today, we’re delving into an exhilarating tutorial, where we’ll delve deep into crafting an advanced port scanner using Python. Join me as we embark on this journey together, uncovering the mysteries of network exploration. Together, we’ll dissect the code into distinct blocks, offering detailed explanations for each step along the way.

Step1: Setting Up Virtual Environment and Installing Dependencies

Before we dive into coding, let’s establish a virtual environment and activate it. Next, we’ll install the argparse module, essential for parsing command-line arguments within our script.

# Create a virtual environment (replace 'env_name' with your preferred name)
$ python3 -m venv env_name

# Activate the virtual environment 
  # On Unix/Linux
$ source env_name/bin/activate 
  # On Windows 
$ env_name\Scripts\activate.bat

# Install necessary dependencies
$ pip install argparse

Step2: Importing Libraries

import socket
import threading
import concurrent.futures
from datetime import datetime
import argparse
import re

This section initiates the inclusion of critical libraries and modules essential for our port scanning application. We import socket to enable socket programming functionalities, threading for concurrent execution, concurrent.futures for efficient management of concurrent tasks, datetime for timestamping purposes, argparse for seamless parsing of command-line arguments, and re for regular expression support, enhancing our code’s flexibility and functionality.

Step3: Writing the Port Scanning Function

def scan_port(target, port):
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # Create socket object
        s.settimeout(1)  # Set timeout to 1 second
        result = s.connect_ex((target, port))  # Attempt connection
        if result == 0:  # Check if port is open
            print(f'[+] Port {port} is open')
            try:
                service = socket.getservbyport(port)  # Try to get service name
                print(f'    Service: {service}')
            except OSError:
                pass
        s.close()  # Close socket
    except KeyboardInterrupt:  # Handle keyboard interrupt
        exit()
    except Exception as e:  # Handle other exceptions
        print(f'Error: {e}')

This section encapsulates the definition of the scan_port function, tasked with scanning an individual port on a designated target. It endeavors to establish a connection to the specified port on the target IP address. Upon success, it signals that the port is open and endeavors to retrieve the associated service name. Subsequently, it gracefully closes the socket. The function adeptly manages keyboard interrupts and other exceptions, ensuring smooth operation even in unforeseen circumstances.

Step4: Port Scan Function

def port_scan(target, ports, num_threads):
    try:
        target_ip = socket.gethostbyname(target)  # Resolve target IP
    except socket.gaierror as e:  # Handle DNS resolution errors
        print(f'Error: {e}')
        return

    print(f'Starting port scan on {target} ({target_ip}) at {datetime.now()}')

    with concurrent.futures.ThreadPoolExecutor(max_workers=num_threads) as executor:
        future_to_port = {executor.submit(scan_port, target_ip, port): port for port in ports}
        for future in concurrent.futures.as_completed(future_to_port):
            port = future_to_port[future]
            try:
                future.result()
            except Exception as exc:
                print(f'Port {port} scan failed: {exc}')

This block defines the main function port_scan responsible for coordinating the port scanning process. It resolves the target’s IP address from its domain name, prints a start message with timestamp, and then scans ports concurrently using a thread pool. It submits the scan_port function for each port to the thread pool and handles the results or exceptions.

Step5: Main Function

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Advanced Port Scanner")
    parser.add_argument("target", help="Target IP address or domain name")
    parser.add_argument("-p", "--ports", help="Port range to scan (e.g., 1-1000)", default="1-1024")
    parser.add_argument("-t", "--threads", help="Number of threads (default: 10)", type=int, default=10)
    args = parser.parse_args()

    ports = []
    port_range = re.match(r'(\d+)-(\d+)', args.ports)
    if port_range:
        start_port = int(port_range.group(1))
        end_port = int(port_range.group(2))
        ports = range(start_port, end_port + 1)

    port_scan(args.target, ports, args.threads)

This segment serves as the script’s entry point. It employs argparse to parse command-line arguments, extracting the port range from the provided input. Subsequently, it kicks off the port scanning procedure by invoking the port_scan function with the specified target, port range, and the designated number of threads.


Bringing together all the code segments, let’s compile them into a single file named port_scanner.py. This consolidated file will contain the entirety of our port scanning application, ready to be executed and explored.

import socket
import threading
import concurrent.futures
from datetime import datetime
import argparse
import re

def scan_port(target, port):
    try:
        # Create socket object
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # Set timeout to 1 second
        s.settimeout(1)
        # Attempt connection
        result = s.connect_ex((target, port))
        # Check if port is open
        if result == 0:
            print(f'[+] Port {port} is open')
            try:
                # Try to get service name
                service = socket.getservbyport(port)
                print(f'    Service: {service}')
            except OSError:
                pass
        # Close socket
        s.close()
    except KeyboardInterrupt:
        exit()
    except Exception as e:
        print(f'Error: {e}')

def port_scan(target, ports, num_threads):
    try:
        # Resolve target IP
        target_ip = socket.gethostbyname(target)
    except socket.gaierror as e:
        print(f'Error: {e}')
        return

    print(f'Starting port scan on {target} ({target_ip}) at {datetime.now()}')

    # Scan ports concurrently using thread pool
    with concurrent.futures.ThreadPoolExecutor(max_workers=num_threads) as executor:
        # Submit scan_port function for each port
        future_to_port = {executor.submit(scan_port, target_ip, port): port for port in ports}

        # Wait for all threads to complete
        for future in concurrent.futures.as_completed(future_to_port):
            port = future_to_port[future]
            try:
                future.result()
            except Exception as exc:
                print(f'Port {port} scan failed: {exc}')

if __name__ == "__main__":
    # Argument parser
    parser = argparse.ArgumentParser(description="Advanced Port Scanner")
    parser.add_argument("target", help="Target IP address or domain name")
    parser.add_argument("-p", "--ports", help="Port range to scan (e.g., 1-1000)", default="1-1024")
    parser.add_argument("-t", "--threads", help="Number of threads (default: 10)", type=int, default=10)
    args = parser.parse_args()

    # Extract ports from port range
    ports = []
    port_range = re.match(r'(\d+)-(\d+)', args.ports)
    if port_range:
        start_port = int(port_range.group(1))
        end_port = int(port_range.group(2))
        ports = range(start_port, end_port + 1)

    # Perform port scan
    port_scan(args.target, ports, args.threads)

After amalgamating all the code blocks into a single Python file, let’s proceed to execute the script.

To execute the Python script, first, ensure your virtual environment is activated. Then, navigate to the directory housing your port_scanner.py script. Finally, run the script by executing the following command.

$ python port_scanner.py example.com -p 1-1000 -t 20

Arguments:

  1. example.com:
    • Description: Target IP address or domain name.
    • Example: google.com
  2. -p 1-1000 or --ports 1-1000:
    • Description: Port range to scan.
    • Example: 1-1000
  3. -t 20 or --threads 20:
    • Description: Number of threads for concurrent scanning.
    • Example: 20


Leave a Reply

Your email address will not be published. Required fields are marked *

DarkLight
×