Writing a Basic Port Scanner in Python

By Guy Nguyen-Phuoc on October 15, 2020

(By: Guy Nguyen-Phuoc on October 16, 2020)

INTRODUCTION

Port Scanning is the art of looking for open ports on a host or system. When you visit a website, you are allowing information to traverse through a port. In this case port 80 (http) or 443 (https). In addition to the above case, we have SSH (port 22), FTP (port 21), DNS (port 53), POP3 (port 110) and thousands of others. Ports or sockets allow the flow of information via a network [1]. However, not all ports are open. In fact, most ports are closed off outside the most popular ports, port 80 for example. This is where a port scanner comes in handy, it allows pentesters to see which ports are open to the internet and sniffing out the types of services on these ports.

For this paper we will be building a basic port scanner in python, add multi-threading techniques and set up a basic command line interface.

Part 1 (Writing a out basic port scanner)

ATTENTION: This paper uses Visual Studio Code for all coding examples. Feel free to use your favorite text editor/IDE to follow along.

First, we set up our basic framework to work from where we can easily expand our program later on.

python framework outline
We are going to be using our scanner a lot, so it warrants a function call. It [tcp_scanner] will take one parameter, the port number being scanned. Our libraries “socket” and “sys” will help us write our scanner. If you are new to python and do not understand the “if __name__” stuff, here is a great post on stack overflow to help out:
 
Now we will add our scanner with this piece of code.
tcp_scanner function()

“sock” is the name of our socket object we will use to connect to ports. “connect_ex” returns “0” if our connection goes through and “errno” if not. We then use this value from the “result” variable to determine if a port is open.

We now have our basic port scanner. We need to add a bit of code so we can resolve the IP address from the host name (if applicable). It looks like this:

code asking for host to scan

Awesome, now we have a fully operational port scanner! Just one minor problem, when we scan a domain, “scanme.nmap.org” it takes almost four minutes to scan 100 ports.

time it takes to complete a port scan without threading

If this was a full vertical scan (scanning all 65535 ports) it would take ages. Thankfully, we can speed this up tremendously by using threads or multi-threading.

PART 2 (adding multi-threading)

Multi-threading is the idea of using more than one thread to work on a problem in parallel. A thread is a single process being executed on a system. A key part in threading that is different from multiple core processes is a thread will wait for a response and work on another thread that has been queued up until it receives the response from the first thread. So if I have one thread currently running waiting for a response with three more processes waiting to be runned the one thread will start working on the other processes. This is perfect for processes that work over the internet because we have to wait for the server to respond to our requests, which can take several seconds.

Now that we have a basic understanding of threads we can move onto implementing it into our scanner.
First we need to lock threads that are being runned. We do this to avoid having two threads accessing the same resources at the same time. If we don’t do this it can lead to crashes and incorrect calculations. Additionally we can set up a queue for the work not currently being processed. It looks something like this:

setting up threading

Once we do that we can add the “threader” function to the program.

threader function
The first for loop creates the amount of threads to use, typically more is faster, with the second for loop controls what ports to scan that is then put into a queue called “q”. The threader() takes an unprocessed port number and assigns it to a thread created under main(). q.task_done() will remove it from the queue list.
 

Now that is done, let us test how fast it is by scanning 1,000 ports.

time it takes to finish program with threading

Six seconds! Almost 40 times as fast as the single threaded version of the port scanner we wrote!

Conclusion

We successfully created a simple port scanner with multi-threading. Now when we use more robust programs like nmap we know a little bit of how the system works internally and its underlying mechanism. For further improvements of this program, we can try to sort the information of the threads (the ports are not done in order) and add some form of command line interface.

REFERENCES

https://tools.ietf.org/html/rfc147
https://www.paloaltonetworks.com/cyberpedia/what-is-a-port-scan
https://smb.avast.com/answers/port-scanning-techniques-and-explanations