A multithreaded TCP/SSH/RDP port scanner
Protocol fingerprinting · CIDR support · JSON/CSV/TXT output
Rashnu is a multithreaded port scanner for TCP, SSH, and RDP services. It performs protocol fingerprinting to accurately identify SSH and RDP services, supports CIDR notation and hostname resolution, and provides flexible output formats including text, JSON, and CSV.
Additional features include retry mechanisms, rate limiting, customizable alerts, and a live progress display. The scanner follows a classic build workflow for easy installation on Linux systems.
Author: Abolfazl Hosseini
- Pure C++17, POSIX sockets.
- Multithreaded connect-scan engine (non-blocking
connect()+poll()). - Real protocol fingerprinting for SSH (banner) and RDP (X.224 handshake) — not just a raw connect.
- CIDR expansion, hostname resolution, and
--excludelists. - Retries with configurable delay, global rate limiting, randomized scan order.
- Output as
txt,json, orcsv;--appendand--resumesupport. - File logging (
--no-loggingto disable). --alert=CMD— run any shell command when a port is found open, with{ip},{port},{proto}placeholders.- Live progress line (Tested/Open/speed/ETA), clean Ctrl+C handling that still saves partial results.
- Classic autotools-style build:
./configure && make && sudo make install.
rashnu/
├── configure # hand-written POSIX sh configure script
├── Makefile.in # Makefile template (processed by configure)
├── LICENSE
├── README.md
├── logo.png # Project logo
├── man/
│ └── rashnu.1 # man page (installed by 'make install')
└── src/
├── main.cpp # entry point / orchestration
├── common.hpp/.cpp # shared types, globals
├── options.hpp/.cpp # argument parsing (getopt_long)
├── target_loader.hpp/.cpp # CIDR/hostname expansion, exclude, resume
├── logger.hpp/.cpp # thread-safe file logger
├── rate_limiter.hpp # token-bucket rate limiter
├── alerter.hpp/.cpp # --alert command execution
├── protocol_probe.hpp/.cpp # SSH/RDP fingerprinting
├── scanner_engine.hpp/.cpp # core scan/connect logic + worker threads
└── output_writer.hpp/.cpp # txt/json/csv output
Requirements: a C++17 compiler (g++ ≥ 7 or clang++ ≥ 5), make, and a
Linux system. Nothing else — no package manager dependencies.
./configure # checks compiler/pthreads, generates Makefile
make # builds ./rashnu
sudo make install # installs to /usr/local/bin (+ man page)Custom install prefix:
./configure --prefix=$HOME/.local
make
make install # no sudo needed for a user prefixUninstall:
sudo make uninstallDebug build:
./configure --enable-debug
makerashnu -p PORTS (-i FILE | -T LIST) [OPTIONS]
Run rashnu --help for the full option list, or man rashnu after
installing.
Scan a subnet for SSH with 300 threads, JSON output:
rashnu -T 10.0.0.0/24 -p 22 -P ssh -c 300 -o found.json --format jsonScan a target list for RDP, fire a shell command on every hit:
rashnu -i targets.txt -p 3389 -P rdp \
--alert="echo '[ALERT] RDP open on {ip}:{port}' >> rdp_hits.log"Resume an interrupted scan, keeping a persistent log file:
rashnu -i targets.txt -p 1-1000 -P tcp --resume -o open.csv --format csvSkip the authorization prompt (e.g. in automated pipelines you already control) and disable file logging:
rashnu -T 192.168.1.0/24 -p 80,443 -y --no-logging| Option | Description |
|---|---|
-i, --input FILE |
File with IPs/CIDR/hostnames, one per line |
-T, --targets LIST |
Comma separated IPs/CIDR/hostnames |
-x, --exclude FILE |
File with IPs/CIDR to exclude |
-p, --ports SPEC |
Ports: 22, 80,443, 1-1000 (required) |
-P, --protocol PROTO |
tcp | ssh | rdp |
--no-banner |
Disable protocol fingerprinting |
-c, --concurrency N |
Worker threads (default 200) |
--timeout MS |
Per-connection timeout (default 2000) |
--retries N |
Attempts per target (default 1) |
--retry-delay MS |
Delay between retries (default 300) |
--rate-limit N |
Max attempts/sec, 0=unlimited |
--randomize |
Shuffle target order |
-o, --output FILE |
Output file (default open.txt) |
--format FMT |
txt | json | csv |
--append |
Append instead of overwrite |
--resume |
Skip already-scanned pairs in --output |
--no-logging |
Disable logging to a file |
--log-file FILE |
Log file path (default rashnu.log) |
--alert=CMD |
Run shell command on open port ({ip}/{port}/{proto}) |
-v, --verbose |
Also print closed/filtered/error results |
-q, --quiet |
Suppress the live progress line |
-h, --help |
Show usage |
-V, --version |
Show version |
Each worker thread pulls target indices from a shared atomic counter
(lock-free fan-out), performs a non-blocking connect(), then
poll()s for writability up to --timeout. SO_ERROR is inspected to
classify the result precisely:
open— connection succeededclosed—ECONNREFUSEDfiltered— timed out (no response — typically firewalled)unreachable—EHOSTUNREACH/ENETUNREACH/ENETDOWNerror— anything else
When a port is open and -P ssh/-P rdp is set, the socket is briefly
switched to blocking mode with SO_RCVTIMEO/SO_SNDTIMEO for a minimal,
non-intrusive protocol probe (SSH banner read, or an RDP X.224
Connection Request/response check) before being closed.
- IPv4 only (CIDR expansion and hostname resolution both target
AF_INET). - Expanding a network larger than a
/8in one entry is refused to avoid runaway memory usage — split large ranges into smaller CIDR blocks. --alertruns your command through/bin/sh -c; you are responsible for anything that command does.- This is a connect-scanner, not an exploitation tool: SSH/RDP fingerprinting only performs the protocols' normal opening handshake to confirm what's listening, nothing more.
MIT — see LICENSE.
