
Why write one when Nmap exists?
Because using a tool and understanding a tool are different skills. When you write the scan loop yourself, you feel why a full connect scan is loud, why timeouts dominate your runtime, and why threading matters. That intuition transfers directly to reading Nmap output later.
The naive version
Start with the simplest thing that works: a socket, a connect call, and a loop.
import socket
def scan(host, ports):
for port in ports:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(0.5)
if s.connect_ex((host, port)) == 0:
print(f"[+] {port}/tcp open")
s.close()
scan("127.0.0.1", range(1, 1025))connect_ex is the key: it returns an error code instead of raising, so a closed port is just a non-zero return, not an exception to catch.
Why it’s painfully slow
Run it against 1024 ports and you’ll wait. Each closed port burns the full timeout serially. Scanning 1024 ports at 0.5s each is over eight minutes in the worst case — for one host.
Making it threaded
Network scanning is I/O bound, so threads help enormously here despite the GIL.
from concurrent.futures import ThreadPoolExecutor
def check(host, port):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(0.5)
if s.connect_ex((host, port)) == 0:
return port
def scan(host, ports, workers=200):
with ThreadPoolExecutor(max_workers=workers) as pool:
results = pool.map(lambda p: check(host, p), ports)
return [p for p in results if p]Suddenly 1024 ports finish in seconds.
Where to go next
Grab banners: after connecting, send a probe and read the first bytes to fingerprint the service.
Add a SYN scan with raw sockets (requires root) to avoid completing the handshake.
Rate-limit yourself so you don’t trip IDS on networks you’re allowed to test.
One rule before you run it
Only scan hosts you own or have written permission to test. A port scan against someone else’s infrastructure can be illegal in most jurisdictions, full stop.
If you want the finished version, my Portscanner repo is on GitHub.
Comments (0)
Join the discussion by logging into your account.