I Wrote a Port Scanner to Feel Something

Apr 22, 2025 · 2 min · python , recon , asyncio , tooling

There is a specific kind of joy in writing the tool instead of running it. I have run nmap plenty. But I wrote my own scanner, pyscan, and although it is slower and dumber than nmap in every measurable way, it is mine, and I understand every line, which nmap has never once let me say about itself.

I started it synchronous, the obvious way: loop over the ports, try to connect to each, write down which ones answer. It works. It is also painfully slow, because most of the time it is just standing there waiting for a port to respond or time out, doing nothing, like me in a queue.

Then asyncio, which is the whole point. Scanning a port is almost entirely waiting, and waiting is exactly the thing you should never do one at a time. Fire off hundreds of connection attempts and let them all wait together, and a scan that took minutes takes seconds. Watching it tear through a /24 in under a minute still produces a noise I am not proud of.

It does banner grabbing too. Connect, stay quiet for a beat, and a lot of services will introduce themselves, version number and all. Services are so eager to tell you who they are. It is almost rude not to write it down.

I test it the responsible way: against 127.0.0.1 with nc listeners I spin up myself, then against Metasploitable 2 on its isolated network. Then nmap against the same box, diffed, partly to check my work, partly to stay honest about what mine misses.

I did not write pyscan to beat nmap. I wrote it to stop treating recon as magic. The map of a network is not handed to you. You build it, one open port at a time, and now I have the thing that builds the map.

Edit this page on GitHub Last updated: 5/29/2026, 3:36:43 PM