← Back to projects

Personal project
Port Scanner — async TCP scanner & detection lab
Zero-dependency asyncio port scanner, secure by default, that explains the risk of every open service — and the Blue Team side: how to detect that very scan with Wireshark, Suricata and Sigma
Context
I rebuilt this project from scratch with a defender's mindset. A port scanner is usually shown from the attacker's side; I wanted the opposite: a tool that is safe to run on a home or company network, tells you why an open port matters and what to do about it, and then teaches how a SOC detects the scan it just performed (MITRE ATT&CK T1046 — Network Service Discovery).
What I built
- An asynchronous TCP connect scanner (asyncio, standard library only): open / closed / filtered states, latency, bounded concurrency and memory
- Target and port parsing (IP, CIDR, hostnames; 22, 20-25, top100, all) with strict validation
- About 50 service profiles: risk level from info to critical and a defensive recommendation for each open port
- Optional passive banner grabbing, with every non-printable character escaped
- Text, JSON and CSV outputs, stable exit codes and --fail-on high for CI pipelines
- A bilingual local web UI (port-scanner-web) driving the same engine
Security choices
- Secure by default: only private networks (RFC 1918, IPv6 ULA) and loopback; IPv4-mapped IPv6, every DNS answer and ambiguous shorthand IPs (127.1, 0x7f.1) are checked
- Hard caps checked before any packet is sent: 1,024 addresses, 262,144 probes, 500 concurrent connections, 30 s timeout
- Banners treated as hostile input: terminal escape sequences and invisible bidirectional characters (Trojan Source) neutralised
- CSV formula injection prevented (OWASP); reports never overwrite an existing file without --force
- Local web server protected like an exposed service: loopback only, random 256-bit token in the URL fragment, Host check against DNS rebinding, Origin check against CSRF, strict CSP, textContent-only rendering
- Repository hardening: protected main branch, secret scanning with push protection, Dependabot, Ruff with Bandit rules, private vulnerability reporting
Detection side (Blue Team)
- Lab captures of a real scan, normal traffic and a very busy legitimate client
- Step-by-step Wireshark and tshark guide: the filters that reveal a scan
- Two Suricata rules (SYN burst, RST burst) and a Sigma value_count correlation (distinct ports per source)
- A CI job replays the captures through Suricata and checks the expected alerts — including no alert on normal traffic and a documented false positive
Engineering quality
250+
Automated tests
real sockets on loopback, network simulated otherwise
6
CI jobs
Windows + Linux, Python 3.11/3.14, Ruff, Suricata + Sigma
0
Runtime dependencies
v1.0.0 → v1.1.0
Releases
How it works
- 1ValidateTargets and ports are parsed and checked against the private-network guard and the size caps before anything is sent.
- 2ScanA fixed pool of asyncio workers opens and immediately closes one TCP connection per (address, port).
- 3ExplainEach open port gets its probable service, a risk level and a defensive recommendation; banners are read and sanitised on request.
- 4DetectThe same scan is captured and caught by Suricata and Sigma rules, verified automatically in CI.
Screenshots
