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), elseerror
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
Post a Comment