Build A Simple Port Scanner in Python


Introduction:

A port scanner is a program that is used to scan a target machine for open ports. Port scanners are often used by ethical hackers to identify potential vulnerabilities in a target system. In this blog post, we'll take a look at a simple Python script that can be used to scan a target machine for open ports.


The Script

The Python script we'll be discussing is a simple port scanner that takes an IP address or hostname as a command-line argument and attempts to connect to each port in a specified range to determine if it is open. Here's the script:


*************************************************

import sys, socket

from datetime import datetime


# Define our target using command line arguments

if len(sys.argv) == 2:

    target = socket.gethostbyname(sys.argv[1])  # Translate a hostname to IPv4

else:

    print("Invalid amount of arguments")

    print("Syntax: python3 <ip>")


# Print a banner with information on the target and time of scan

print("*" * 50)

print("Scanning target: " + target)

print("Time: " + str(datetime.now()))

print("*" * 50)


# Try to connect to each port on the target within a specified range

try:

    for port in range(1, 85):

        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        socket.setdefaulttimeout(1)

        result = s.connect_ex((target, port))  # Returns an error indicator

        if result == 0:

            print("Port {} is open.".format(port))

        s.close()   # To close the connection


# Catch any exceptions that occur during the scan and exit gracefully

except KeyboardInterrupt:

    print("\nExiting program.")

    sys.exit()

except socket.gaierror:

    print("\nHostname could not be resolved.")

    sys.exit()

except socket.error:

    print("\nCould not connect to server.")

    sys.exit()


****************************



How it Works

Let's break down the code to understand how it works.


****************************************************

import sys, socket

from datetime import datetime

****************************************************


The script begins with importing the necessary modules for working with command-line arguments and sockets.


******************************************************

if len(sys.argv) == 2:

    target = socket.gethostbyname(sys.argv[1])

else:

    print("Invalid amount of arguments")

    print("Syntax: python3 <ip>")

Next, the script checks if the user has provided exactly one command-line argument (in addition to the script name itself) which is the target IP address or hostname. If the user provided a hostname, the script translates it to an IP address using the socket.gethostbyname() function. If the user did not provide the correct number of arguments, the script prints an error message and exits.


******************************************

print("*" * 50)

print("Scanning target: " + target)

print("Time: " + str(datetime.now()))

print("*" * 50)

The script prints a banner of asterisks to separate the output from the rest of the command-line interface, followed by the target IP address or hostname and the current time.


*****************************************

for port in range(1, 85):

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    socket.setdefaulttimeout(1)

    result = s.connect_ex((target, port))

    if result == 0:

        print("Port {} is open.".format(port))

    s.close()



The for loop iterates through each port in the specified range and attempts to connect to it using a socket. The socket.socket() function is used to create a new socket object. socket.AF_INET is used to indicate that we're working with IPv4 addresses, and socket.SOCK_STREAM specifies that we're working with TCP connections.


socket.setdefaulttimeout() sets a timeout period for the socket connection attempt. This ensures that if the connection attempt takes longer than the specified timeout period (in this case, 1 second), the socket will close and move on to the next port.


The s.connect_ex() function attempts to connect to the target IP address and port number specified in the function arguments. If the connection is successful, it returns a value of 0. If the connection attempt fails, it returns an error code instead.


If the connection attempt was successful, the script prints a message indicating that the port is open. Finally, the script closes the socket connection using s.close().


# Catch any exceptions that occur during the scan and exit gracefully

except KeyboardInterrupt:

    print("\nExiting program.")

    sys.exit()

except socket.gaierror:

    print("\nHostname could not be resolved.")

    sys.exit()

except socket.error:

    print("\nCould not connect to server.")

    sys.exit()

Finally, the script includes a few exception handlers to catch any errors that might occur during the port scan. The KeyboardInterrupt exception is used to catch the user pressing Ctrl + C to interrupt the scan. If this happens, the script prints a message and exits.


The socket.gaierror exception is used to catch errors that occur when the socket.gethostbyname() function is unable to translate the user-provided hostname to an IP address.


The socket.error exception is used to catch any other errors that might occur during the port scan, such as a failure to connect to the target server.


Conclusion

In this blog post, we've explored a simple Python script for port scanning. This script can be used to identify potential vulnerabilities in a target system by checking for open ports. By understanding how the script works, you can begin to build your own port scanner or modify this one to suit your needs.


Keep in mind, however, that port scanning can be illegal in some jurisdictions if done without proper authorization. Be sure to always obtain proper authorization and follow ethical hacking practices.