Nmap vs Masscan vs RustScan: Know Your Tools | by Roshan Rajbanshi | Jul, 2026
Tool 3 — RustScan
RustScan takes a different approach. Instead of replacing Nmap, it acts as a fast front-end for it. RustScan opens connections to all 65,535 ports simultaneously using async I/O, collects the ones that respond, then passes only those ports to Nmap. The result: Nmap never wastes time on closed ports.
Install — not available via apt on current Kali:
wget https://github.com/bee-san/RustScan/releases/download/2.4.1/rustscan_2.4.1_amd64.deb
sudo dpkg -i rustscan_2.4.1_amd64.deb
rustscan --version
rustscan 2.4.1
Full port discovery — timed:
# time rustscan -a 10.38.1.119 --ulimit 5000
.----. .-. .-. .----..---. .----. .---. .--. .-. .-.
| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| |
| .-. \| {_} |.-._} } | | .-._} }\ }/ /\ \| |\ |
`-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: :
: :
--------------------------------------
RustScan: Where scanning meets swagging.
[~] The config file is expected to be at "/home/kali/.rustscan.toml"
[~] Automatically increasing ulimit value to 5000.
Open 10.38.1.119:21
Open 10.38.1.119:22
Open 10.38.1.119:23
Open 10.38.1.119:25
Open 10.38.1.119:53
Open 10.38.1.119:80
Open 10.38.1.119:111
Open 10.38.1.119:139
Open 10.38.1.119:445
Open 10.38.1.119:512
Open 10.38.1.119:513
Open 10.38.1.119:514
Open 10.38.1.119:1099
Open 10.38.1.119:1524
Open 10.38.1.119:2049
Open 10.38.1.119:2121
Open 10.38.1.119:3306
Open 10.38.1.119:3632
Open 10.38.1.119:5432
Open 10.38.1.119:5900
Open 10.38.1.119:6000
Open 10.38.1.119:6667
Open 10.38.1.119:6697
Open 10.38.1.119:8009
Open 10.38.1.119:8180
Open 10.38.1.119:8787
Open 10.38.1.119:50325
Open 10.38.1.119:56025
[~] Starting Script(s)
[~] Starting Nmap 7.98 ( ) at 2026-05-18 08:08 -0400PORT STATE SERVICE REASON
21/tcp open ftp syn-ack ttl 64
22/tcp open ssh syn-ack ttl 64
23/tcp open telnet syn-ack ttl 64
25/tcp open smtp syn-ack ttl 64
53/tcp open domain syn-ack ttl 64
80/tcp open http syn-ack ttl 64
111/tcp open rpcbind syn-ack ttl 64
139/tcp open netbios-ssn syn-ack ttl 64
445/tcp open microsoft-ds syn-ack ttl 64
512/tcp open exec syn-ack ttl 64
513/tcp open login syn-ack ttl 64
514/tcp open shell syn-ack ttl 64
1099/tcp open rmiregistry syn-ack ttl 64
1524/tcp open ingreslock syn-ack ttl 64
2049/tcp open nfs syn-ack ttl 64
2121/tcp open ccproxy-ftp syn-ack ttl 64
3306/tcp open mysql syn-ack ttl 64
3632/tcp open distccd syn-ack ttl 64
5432/tcp open postgresql syn-ack ttl 64
5900/tcp open vnc syn-ack ttl 64
6000/tcp open X11 syn-ack ttl 64
6667/tcp open irc syn-ack ttl 64
6697/tcp open ircs-u syn-ack ttl 64
8009/tcp open ajp13 syn-ack ttl 64
8180/tcp open unknown syn-ack ttl 64
8787/tcp open msgsrvr syn-ack ttl 64
50325/tcp open unknown syn-ack ttl 64
56025/tcp open unknown syn-ack ttl 64Nmap done: 1 IP address (1 host up) scanned in 1.46 secondsreal 141.25s
user 0.67s
sys 72.75s
cpu 51%
The real 141.25s includes both the RustScan async discovery phase and the Nmap scan. The Nmap portion itself finished in 1.46 seconds because RustScan passed it only the 28 confirmed open ports — Nmap had no closed ports to test.
A note on --ulimit. On many systems, the default open file descriptor limit will throttle RustScan’s async connections and slow it significantly. Passing --ulimit 5000 raises that limit for the session — RustScan applies it automatically when you include the flag, so no separate ulimit command is needed. It’s a common tuning step rather than a strict requirement, but it’s worth including on most scans.
Now pipe directly into Nmap with service detection:
rustscan -a 10.38.1.119 --ulimit 5000 -- -sV
RustScan discovers the ports, then Nmap runs -sV against only those ports:
PORT STATE SERVICE REASON VERSION
21/tcp open ftp syn-ack ttl 64 vsftpd 2.3.4
22/tcp open ssh syn-ack ttl 64 OpenSSH 4.7p1 Debian 8ubuntu1 (protocol 2.0)
23/tcp open telnet syn-ack ttl 64 Linux telnetd
25/tcp open smtp syn-ack ttl 64 Postfix smtpd
53/tcp open domain syn-ack ttl 64 ISC BIND 9.4.2
80/tcp open http syn-ack ttl 64 Apache httpd 2.2.8 ((Ubuntu) DAV/2)
111/tcp open rpcbind syn-ack ttl 64 2 (RPC #100000)
139/tcp open netbios-ssn syn-ack ttl 64 Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
445/tcp open netbios-ssn syn-ack ttl 64 Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
512/tcp open exec syn-ack ttl 64 netkit-rsh rexecd
514/tcp open shell syn-ack ttl 64 Netkit rshd
1099/tcp open java-rmi syn-ack ttl 64 GNU Classpath grmiregistry
1524/tcp open bindshell syn-ack ttl 64 Metasploitable root shell
2121/tcp open ftp syn-ack ttl 64 ProFTPD 1.3.1
3306/tcp open mysql syn-ack ttl 64 MySQL 5.0.51a-3ubuntu5
3632/tcp open distccd syn-ack ttl 64 distccd v1 ((GNU) 4.2.4 (Ubuntu 4.2.4-1ubuntu4))
5900/tcp open vnc syn-ack ttl 64 VNC (protocol 3.3)
6000/tcp open X11 syn-ack ttl 64 (access denied)
6667/tcp open irc syn-ack ttl 64 UnrealIRCd
6697/tcp open irc syn-ack ttl 64 UnrealIRCd
8009/tcp open ajp13 syn-ack ttl 64 Apache Jserv (Protocol v1.3)
8180/tcp open http syn-ack ttl 64 Apache Tomcat/Coyote JSP engine 1.1
8787/tcp open drb syn-ack ttl 64 Ruby DRb RMI (Ruby 1.8; path /usr/lib/ruby/1.8/drb)
37689/tcp open mountd syn-ack ttl 64 1-3 (RPC #100005)
45139/tcp open nlockmgr syn-ack ttl 64 1-4 (RPC #100021)
50325/tcp open status syn-ack ttl 64 1 (RPC #100024)
Nmap done: 1 IP address (1 host up) scanned in 14.14 seconds
Nmap portion: 14 seconds. Full-service detection on 26 ports.
You can pass targeted NSE scripts through RustScan the same way, without the noise -sC adds:
rustscan -a 10.38.1.119 --ulimit 5000 -- -sV \
--script "banner,ftp-anon,ssh-hostkey,smtp-commands,http-title,smb-os-discovery,mysql-info,vnc-info,irc-info"
This gives you meaningful per-service enumeration — FTP anonymous login check, SSH host keys, SMTP commands, HTTP titles, SMB OS info, MySQL details, VNC version, IRC banners — targeted rather than broad.
What RustScan cannot do:
- Standalone service detection without Nmap
- Replace Nmap’s output formats
- Work without Nmap installed
- Consistently outperforms Nmap on single-port targeted scans