What is a port scan?
Hackers use port scan technique to find out weak points in a network, for example, they can find any open ports in printers, computers or any other types of hosts, or whether firewalls are being used.
The cyber criminals send out requests to a port and analyze the responses for potential attack possibility.
Business and organizations also use port scan technique to locate any unnecessary open ports in their own network, they can then take appropriate actions to close the security gaps.
This project today is to use my own local host for practicing port scan technique with Python. To be clear, to practice port scanning on any networks without their permissions is an illegal conduct. This post is solely for learning Python threading and networking skills, please be advised not to do any illegal port scanning for exploitation purpose.
Internet service providers (ISP) use IP address in conjunction with port numbers to process requests from clients. Port numbers range from 0 to 65,536. Among those, from 0 to 1023 are 'well-known' ports assigned for specific TCP/IP applications.
How to determine if a port is open?
By using socket connection, we try to connect to a target server or IP address, the port is deemed open if the connection goes through, otherwise the port is closed.
Python modules used in this project:
So now, let's start to code.
We use socket to connect to a server, or any host, for doing so, we need IP address and a port number.
The first step of this project is to get the IP address. You can use the local host IP address, which is '127.0.0.1' ; or the IP address of the computer you are using. I wrote down how to retrieve the IP address through Python socket module. However, you can also use start menu of your computer, go to cmd (command prompt), then type ipconfig, it will list a series of networking-related data, including 'IPv4 Address', which is the IP address you are looking for.
From there, we'll create a method to connect to a port of an IP address, if succeeded, it is an open port, otherwise, the port is closed.
We create a worker() function, this function will continuously do the port scanning, till all the ports are scanned. In order to speed up the process, multithreading is used here. We can create as many thread as we like, such as 500, however, each thread can only keep on working on those ports that haven't been scanned yet. How to track what ports have been scanned by different threads? Here the 'queue' module comes to the rescue. Its Queue class is a FIFO Queue. We can put all ports into a Queue, then remove the scanned ports using get() method.
Let's see how to implement the above in the coding:
'''
Port scan local host ports using socket
'''
import socket, threading, queue
# get IP address of your computer
hostname = socket.gethostname()
ipaddress = socket.gethostbyname(hostname)
# or use the local host address
target = '127.0.0.1'
# a list to store all open ports
open_ports = []
# create a queue for store all ports
port_queue = queue.Queue()
# create a list for storing threads for join() later
thread_list=[]
# method for doing port scanning
def port_scan(port):
try:
# create a 'client socket' using connect()
# not a 'server socket' with 'bind' and 'listen'
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((ipaddress,port)) # connect to a tuple
print(f'{port} is connected')
open_ports.append(port)
except:
pass
# put all ports into a queue
def enqueue_ports():
for i in range(0, 1024):
port_queue.put(i)
# the task that needs to be done by each thread continuously
def worker():
# run continuously when queue is not empty
while not port_queue.empty():
# remove and get a port from the queue
port_number = port_queue.get()
# print(port_number)
port_scan(port_number)
#
def create_thread(num):
# create all threads
for _ in range(num):
# must use 'target='
thread = threading.Thread(target =worker)
thread_list.append(thread)
# start all threads
for thread in thread_list:
thread.start()
# wait till all threads to finish
for thread in thread_list:
thread.join()
print('All done!')
def run_port_scanning():
enqueue_ports()
create_thread(500)
print(open_ports)
run_port_scanning()
This project demonstrates how to use threading to speed up tasks, how to use socket to connect to a host or server, and the elegant role of queue for tracking and exchanging information safely among multiple threads
For source code, go to github.