Blog 12: Building a Simple Port Scanner in Python

Building a Simple Port Scanner in Python

Building a Simple Port Scanner in Python

This blog post is written for students new to ethical hacking and Python programming. We’ll walk you through a real Python tool you can build: a simple port scanner. Don’t worry — everything will be explained in plain language.

๐Ÿ“ฆ What is a Port?

Think of a port like a door into your computer. Each service (like a website or email server) uses a specific door number (port) to talk to other devices.

๐Ÿ” What is a Port Scanner?

A port scanner is a tool that checks which doors (ports) are open on a machine. Ethical hackers use it to find services that may need to be secured or tested.

๐Ÿ› ️ The Full Python Script: [Click Here for Github Repo]

import socket
import sys
import time
import concurrent.futures

if len(sys.argv) != 2:
    print("Usage: script.py [HOST]")
    sys.exit()

def scan_port(ip, port):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(3)
    conn = s.connect_ex((ip, port))
    if conn == 0:
        try:
            service = socket.getservbyport(port)
        except Exception:
            service = "unknown service"
        return (port, service)
    else:
        return None

def Scanner():
    host = sys.argv[1]
    ports = (20, 21, 22, 23, 25, 53, 69, 80, 139, 137, 443, 445, 1433, 1434, 3306, 3389, 8000, 8080, 8443)
    ip = socket.gethostbyname(host)

    print(f"Starting scan on host {host} ({ip})")
    start_time = time.time()

    open_ports = []

    with concurrent.futures.ThreadPoolExecutor(max_workers=100) as executor:
        futures = {executor.submit(scan_port, ip, port) for port in ports}
        for future in concurrent.futures.as_completed(futures):
            result = future.result()
            if result is not None:
                open_ports.append(result)

    print("PORT\tSTATE\tSERVICE")
    for port, service in open_ports:
        print(f"{port}/tcp\topen\t{service}")

    end_time = time.time()
    print(f"\nScan completed in {end_time - start_time:.2f} seconds")

Scanner()

๐Ÿ” What Does This Script Do?

This is a Python port scanner. It checks if certain ports on a target IP address are open. This is useful for ethical hackers and cybersecurity students to understand what services a server or computer is running.

๐Ÿ”ข Let's Break It Down Line by Line:

import socket
import sys
import time
import concurrent.futures
  • import socket – Allows Python to use network connections.
  • import sys – Used to take input from the command line (like the target website/IP).
  • import time – To measure how long the scan takes.
  • import concurrent.futures – Helps us scan multiple ports at the same time (makes it faster).


if len(sys.argv) != 2:
    print("Usage: script.py [HOST]")
    sys.exit()
  • This checks if the user gave exactly one argument (the host/IP).
  • If not, it tells them how to use the script and stops running.


๐Ÿ”ง scan_port() function – checks if a single port is open:

def scan_port(ip, port):
  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  s.settimeout(3)
  conn = s.connect_ex((ip, port))
  • socket.socket(...): Creates a socket (like a phone line to connect).
  • AF_INET: Use IPv4.
  • SOCK_STREAM: Use TCP (reliable connection).
  • settimeout(3): Wait 3 seconds max; don’t hang forever.
  • connect_ex(...): Tries to connect to a port.
  • Returns 0 if success (port is open), else error code.


if conn == 0:
    try:
        service = socket.getservbyport(port)
    except Exception:
        service = "unknown service"
    return (port, service)
else:
    return None
  • If connection succeeded (conn == 0), it means the port is open.
  • getservbyport(port) tries to find the service name (like http, ftp, ssh).
  • If that fails, we just say "unknown service".
  • Returns a tuple like (80, 'http').
  • If the port is closed, it returns None.


๐Ÿ” Scanner() – the main scanner function:

def Scanner():
    host = sys.argv[1]
    ports = (20, 21, 22, ..., 8080, 8443)
    ip = socket.gethostbyname(host)
  • Takes the host (like example.com) from command line.
  • Converts it to an IP address using gethostbyname().
  • ports is a list of common ports hackers check.


print(f"Starting scan on host {host} ({ip})")
    start_time = time.time()
  • Just tells the user that the scan has started.
  • Starts a timer to measure how long the scan takes.


    open_ports = []
  • This list will store the ports that are open.


๐Ÿงต Run multiple scans at the same time using threads:

with concurrent.futures.ThreadPoolExecutor(max_workers=100) as executor:
    futures = {executor.submit(scan_port, ip, port) for port in ports}
    for future in concurrent.futures.as_completed(futures):
        result = future.result()
        if result is not None:
            open_ports.append(result)
  • ThreadPoolExecutor: Runs multiple scans in parallel (faster than doing one-by-one).
  • It scans all the ports at the same time (up to 100 at once).
  • If a port is open (result is not None), we save it.


๐Ÿ“‹ After scanning, show the result:

print("PORT\tSTATE\tSERVICE")
    for port, service in open_ports:
        print(f"{port}/tcp\topen\t{service}")
  • This prints a neat table of open ports and their services.


    end_time = time.time()
    total_time = end_time - start_time
    print(f"\nScan completed in {total_time:.2f} seconds")
  • Shows how long the scan took to finish.


Scanner()
  • This runs the scanner when the script starts.


๐Ÿ’ป Example Output

Starting scan on host scanme.nmap.org (45.33.32.156)
PORT	STATE	SERVICE
22/tcp	open	ssh
80/tcp	open	http
443/tcp	open	https

Scan completed in 2.53 seconds

๐Ÿงฐ Summary:

Term Meaning
socket Connects to other machines via network
port A door to a service (like web server, SSH, FTP)
connect_ex() Tries to open a connection to that door
ThreadPoolExecutor Runs many scans at once
sys.argv Gets the target host from the command line
getservbyport() Tries to guess which service runs on the port

Comments