DEV Community

Cover image for Basic Port Scanner using Python
Bharath Kumar
Bharath Kumar

Posted on

Basic Port Scanner using Python

Source code click here

This is basic Port Scanner tool that allows users to scan host to find open ports and which service running on the port...

First let's take look at the code and then, break it down into pieces to analysis it...

import socket
from datetime import datetime
import sys
import os 

def usage():
    """Prints the usage information for this script."""
    usage_info = """
    Tool Name: SimplePortScanner 

    Developed by : Bharath Kumar

    Usage:
        python3 port_scanner.py [options]

    Options:
        -h, --help           Show this help message and exit.
        -t, --target <ip>    Specify the target hostname or IP address (required).
        -p, --port <port>    Specify a port (or) range of ports to scan (e.g. -p 80 (or) -p 1-1024).

    Description:
        This script performs a port scan on a specified hostname or IP address
        for a specific port or a range of ports, checking which ports are open. 

    Examples:
        python3 port_scanner.py -t example.com (or) 192.0.0.1 
        python3 port_scanner.py -t example.com (or) 192.168.1.1 -p 80
        python3 port_scanner.py -t example.com (or) 192.168.1.1 --ports 1-1024
    """
    print(usage_info)

start_time = datetime.now()

def scan_port(ip, port):

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(1)
    try:
        result = s.connect_ex((ip, port))
        service = socket.getservbyport(int(port))
    except:
        service = "None"
    if result == 0:
        print(" Port: {}\t State: Open\t Service: {}".format(port, service))

    else:
        pass

    s.close()


def host(target):
    try:
        ip = socket.gethostbyname(target)
        print('_'*51)
        print("[#] Resolved {} to {}".format(target,ip))
        return ip
    except:
        print('_'*51)
        print("[#] Error: Unable to resolve hostname {}".format(target))
        sys.exit(1)

def check_host_up(ip):

    ping = os.system("ping {} -c 1 > /dev/null".format(ip))

    if ping == 0:
       print("[#] {} host is up and running".format(ip))
       return True
    else:
        print("[#] {} host is down".format(ip))
        print("Exiting...")
        exit()
        return False





if __name__ == "__main__":

    target_ip = None
    start_port = 1
    end_port = 65535

    try:
        for i, arg in enumerate(sys.argv):
            if arg in ("-t", "--target"):
                target_ip = sys.argv[i + 1]
            elif arg in ("-p", "--ports"):
                port_range = sys.argv[i + 1]
                if "-" in port_range:
                    start_port, end_port = map(int, port_range.split('-'))
                else:
                    start_port = end_port = int(port_range)

        if target_ip is None:
            print("[#] Error: Target hostname or IP address is required.")
            usage()
            sys.exit(1)

        if start_port is None or end_port is None:
            print("[#] Error: Port range is required.")
            usage()
            sys.exit(1)

        target_ip = host(target_ip)

        if not check_host_up(target_ip):
            sys.exit(1)

        print(f"[#] Scanning {target_ip} from port {start_port} to {end_port}...")
        print("[#] Scanning started at: {}".format(start_time))
        print('_'*51)

        for port in range(start_port, end_port + 1):
            scan_port(target_ip, port)

    except (IndexError, ValueError):
        print("[#] Error: Invalid arguments provided.")
        usage()
        sys.exit(1)

start_time = start_time.now() - start_time
print('_'*51)
print("Scanning is completed in ",start_time)

Enter fullscreen mode Exit fullscreen mode

Import socket: A way of two nodes(server,client) to talk to each other.

from datetime import datetime: Is used compute time spent on scanning.

Import sys: is access to system-specific parameters(argv).

Import os: is used for executing the command ping.

def_usage(): Prints the usage information for this script.

start_time = datetime.now(): is used to get current time and date to calculate time spent on scanning.

def scan_port(ip, port):

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(1)
    try:
        result = s.connect_ex((ip, port))
        service = socket.getservbyport(int(port))
    except:
        service = "None"
    if result == 0:
        print(" Port: {}\t State: Open\t Service: {}".format(port, service))

    else:
        pass

    s.close()


Enter fullscreen mode Exit fullscreen mode

This block of code define function scan_port(ip, port) that checks if specific port on a given ip addr is open using socket.

Socket creation: socket.socket(socket.AF_INET, socket.SOCK_STREAM) Create new socket for IPv4 using TCP.

Timeout: s.settimeout(1) set socket time to 1 sec, if the connection isn't successful within that time, it will stop trying.

Connection test:s.connect_ex((ip, port))it try to connect the specific ip and port. if it successful,result will be 0; otherwise, it will be a different value.

Service detection: socket.getservbyport(int(port))try to detect services running on the specified port.like HTTP for port 80.

Error Handling: In case of an error (e.g., no service on the port), the except block sets service to "None".

Output: If the port is open (result == 0), it prints the port number, state ("Open"), and the service name.

Connection Closure: s.close() closes the socket to free up resources.

def host(target):
    try:
        ip = socket.gethostbyname(target)
        print('_'*51)
        print("[#] Resolved {} to {}".format(target,ip))
        return ip
    except:
        print('_'*51)
        print("[#] Error: Unable to resolve hostname {}".format(target))
        sys.exit(1)
Enter fullscreen mode Exit fullscreen mode

This block of code define function host(target) that resolve a given target(a hostname) to its corresponding ip address using socket.gethostname()

def check_host_up(ip):

    ping = os.system("ping {} -c 1 > /dev/null".format(ip))

    if ping == 0:
       print("[#] {} host is up and running".format(ip))
       return True
    else:
        print("[#] {} host is down".format(ip))
        print("Exiting...")
        exit()
        return False
Enter fullscreen mode Exit fullscreen mode

This function check_host_up(ip) that checks if specific port on a given target ip is up or down using os.system() ping method to identify .

if __name__ == "__main__":

    target_ip = None
    start_port = 1
    end_port = 65535

    try:
        for i, arg in enumerate(sys.argv):
            if arg in ("-t", "--target"):
                target_ip = sys.argv[i + 1]
            elif arg in ("-p", "--ports"):
                port_range = sys.argv[i + 1]
                if "-" in port_range:
                    start_port, end_port = map(int, port_range.split('-'))
                else:
                    start_port = end_port = int(port_range)


Enter fullscreen mode Exit fullscreen mode

Command-line Argument Parsing

The sys.argv array contains the list of arguments passed to the script. We loop through these arguments to check for the target IP (-t or --target) and port range (-p or --ports).

The target IP/hostname is stored in target_ip.
The port range is parsed and split into start_port and end_port. If no range is specified, it defaults to scanning all ports from 1 to 65535.

target_ip = host(target_ip)

        if not check_host_up(target_ip):
            sys.exit(1)


Enter fullscreen mode Exit fullscreen mode

Host Resolution and Reachability

Once we have a valid IP address, we need to check if the host is reachable. The function host(target_ip) resolves a hostname to its IP address, and check_host_up(target_ip) verifies whether the host is online.

for port in range(start_port, end_port + 1):
            scan_port(target_ip, port)

Enter fullscreen mode Exit fullscreen mode

Port scanning

The core of the port scanning functionality happens inside the loop:

This loop iterates through the specified port range, and for each port, the function scan_port(target_ip, port) probes the port to check whether it is open or closed.

Conclusion

By following this guide, you’ve learned how to build a simple Python port scanner that accepts command-line arguments, validates inputs, and scans a range of ports on a given target. While this is a basic implementation, it lays the groundwork for more advanced features like threading or service detection.

Feel free to adapt and expand this script to suit your specific needs. Happy scanning!

Top comments (0)