July 13, 2026
Nmap vs Masscan vs RustScan: Know Your Tools
Three tools. Three different jobs. Most people are using the wrong one for the wrong task.

By Roshan Rajbanshi
11 min read
Series: Nmap — The Tool You Think You Know | Part 10 of 16
Nmap is not always the right tool. For raw port discovery across large IP ranges, it's slower than Masscan by orders of magnitude. For initial CTF recon, RustScan quickly discovers open ports and can hand them to Nmap for deeper analysis. Knowing when to use which tool is what separates someone who runs nmap on everything from someone who runs engagements efficiently.
This article covers all three against a real target — Metasploitable2 at 10.38.1.119 — with actual timing numbers and real output. The table below uses actual timings from a lab target, not estimates.
The decision tree is simple:
- Need raw discovery across many hosts? Use Masscan.
- Need fast open-port discovery on one or a few hosts? Use RustScan.
- Need versions, scripts, OS detection, or report-ready output? Use Nmap.
The Target
Before anything else, confirm the target is alive:
# ping -c 2 10.38.1.119
PING 10.38.1.119 (10.38.1.119) 56(84) bytes of data.
64 bytes from 10.38.1.119: icmp_seq=1 ttl=64 time=22.8 ms
64 bytes from 10.38.1.119: icmp_seq=2 ttl=64 time=9.86 ms
--- 10.38.1.119 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 9.856/16.319/22.783/6.463 ms# ping -c 2 10.38.1.119
PING 10.38.1.119 (10.38.1.119) 56(84) bytes of data.
64 bytes from 10.38.1.119: icmp_seq=1 ttl=64 time=22.8 ms
64 bytes from 10.38.1.119: icmp_seq=2 ttl=64 time=9.86 ms
--- 10.38.1.119 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 9.856/16.319/22.783/6.463 msLive. Now run all three tools against it and compare.
Tool 1 — Nmap
Nmap is the baseline. Full port scan with -p- and -T4:
# time nmap -p- -T4 10.38.1.119
Starting Nmap 7.98 ( https://nmap.org ) at 2026-05-18 07:55 -0400
Nmap scan report for 10.38.1.119
Host is up (0.012s latency).
Not shown: 65505 closed tcp ports (reset)
PORT STATE SERVICE
21/tcp open ftp
22/tcp open ssh
23/tcp open telnet
25/tcp open smtp
53/tcp open domain
80/tcp open http
111/tcp open rpcbind
139/tcp open netbios-ssn
445/tcp open microsoft-ds
512/tcp open exec
513/tcp open login
514/tcp open shell
1099/tcp open rmiregistry
1524/tcp open ingreslock
2049/tcp open nfs
2121/tcp open ccproxy-ftp
3306/tcp open mysql
3632/tcp open distccd
5432/tcp open postgresql
5900/tcp open vnc
6000/tcp open X11
6667/tcp open irc
6697/tcp open ircs-u
8009/tcp open ajp13
8180/tcp open unknown
8787/tcp open msgsrvr
37689/tcp open unknown
45139/tcp open unknown
50325/tcp open unknown
56025/tcp open unknown
Nmap done: 1 IP address (1 host up) scanned in 83.95 seconds
real 84.07s
user 0.10s
sys 54.78s# time nmap -p- -T4 10.38.1.119
Starting Nmap 7.98 ( https://nmap.org ) at 2026-05-18 07:55 -0400
Nmap scan report for 10.38.1.119
Host is up (0.012s latency).
Not shown: 65505 closed tcp ports (reset)
PORT STATE SERVICE
21/tcp open ftp
22/tcp open ssh
23/tcp open telnet
25/tcp open smtp
53/tcp open domain
80/tcp open http
111/tcp open rpcbind
139/tcp open netbios-ssn
445/tcp open microsoft-ds
512/tcp open exec
513/tcp open login
514/tcp open shell
1099/tcp open rmiregistry
1524/tcp open ingreslock
2049/tcp open nfs
2121/tcp open ccproxy-ftp
3306/tcp open mysql
3632/tcp open distccd
5432/tcp open postgresql
5900/tcp open vnc
6000/tcp open X11
6667/tcp open irc
6697/tcp open ircs-u
8009/tcp open ajp13
8180/tcp open unknown
8787/tcp open msgsrvr
37689/tcp open unknown
45139/tcp open unknown
50325/tcp open unknown
56025/tcp open unknown
Nmap done: 1 IP address (1 host up) scanned in 83.95 seconds
real 84.07s
user 0.10s
sys 54.78s84 seconds. 30 ports found.
Now add service detection on the interesting ports:
# nmap -sV -p 21,22,23,25,80,139,445,3306,5432,6667,8009,8180 10.38.1.119
Starting Nmap 7.98 ( https://nmap.org ) at 2026-05-18 08:48 -0400
Nmap scan report for 10.38.1.119
Host is up (0.012s latency).
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 2.3.4
22/tcp open ssh OpenSSH 4.7p1 Debian 8ubuntu1 (protocol 2.0)
23/tcp open telnet Linux telnetd
25/tcp open smtp Postfix smtpd
80/tcp open http Apache httpd 2.2.8 ((Ubuntu) DAV/2)
139/tcp open netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
445/tcp open netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
3306/tcp open mysql MySQL 5.0.51a-3ubuntu5
5432/tcp open postgresql PostgreSQL DB 8.3.0 - 8.3.7
6667/tcp open irc UnrealIRCd
8009/tcp open ajp13 Apache Jserv (Protocol v1.3)
8180/tcp open http Apache Tomcat/Coyote JSP engine 1.1
Service Info: Hosts: metasploitable.localdomain, irc.Metasploitable.LAN; OSs: Unix, Linux
Nmap done: 1 IP address (1 host up) scanned in 12.91 seconds# nmap -sV -p 21,22,23,25,80,139,445,3306,5432,6667,8009,8180 10.38.1.119
Starting Nmap 7.98 ( https://nmap.org ) at 2026-05-18 08:48 -0400
Nmap scan report for 10.38.1.119
Host is up (0.012s latency).
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 2.3.4
22/tcp open ssh OpenSSH 4.7p1 Debian 8ubuntu1 (protocol 2.0)
23/tcp open telnet Linux telnetd
25/tcp open smtp Postfix smtpd
80/tcp open http Apache httpd 2.2.8 ((Ubuntu) DAV/2)
139/tcp open netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
445/tcp open netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
3306/tcp open mysql MySQL 5.0.51a-3ubuntu5
5432/tcp open postgresql PostgreSQL DB 8.3.0 - 8.3.7
6667/tcp open irc UnrealIRCd
8009/tcp open ajp13 Apache Jserv (Protocol v1.3)
8180/tcp open http Apache Tomcat/Coyote JSP engine 1.1
Service Info: Hosts: metasploitable.localdomain, irc.Metasploitable.LAN; OSs: Unix, Linux
Nmap done: 1 IP address (1 host up) scanned in 12.91 seconds
Nmap's strength is service and version detection, host hints, and deeper enumeration. No other tool in this article produces this level of detail automatically.
Tool 2 — Masscan
Masscan is a stateless high-speed TCP scanner. It sends SYN packets and listens for SYN-ACK responses — similar to Nmap's SYN scan — but with no timing engine, no host tracking, and no service detection. It floods packets and records responses as fast as the network allows.
# Basic syntax
sudo masscan -p 1-65535 <target> --rate 1000 --wait 5
# Subnet sweep
sudo masscan -p 22,80,443,445,21,23,3306 10.10.0.0/24 --rate 3000
# Save output to file
sudo masscan -p 22,80,443,21,23,3306 10.10.0.0/24 --rate 3000 -oL masscan_results.txt# Basic syntax
sudo masscan -p 1-65535 <target> --rate 1000 --wait 5
# Subnet sweep
sudo masscan -p 22,80,443,445,21,23,3306 10.10.0.0/24 --rate 3000
# Save output to file
sudo masscan -p 22,80,443,21,23,3306 10.10.0.0/24 --rate 3000 -oL masscan_results.txtMasscan and virtual or VPN interfaces:
Masscan operates below the OS network stack, bypassing the normal TCP/IP implementation entirely. This makes it extremely fast on physical or bridged networks. However, it can have trouble with some VPN or virtual interfaces, such as tun0 or tap0 — unless you explicitly specify the correct interface and the environment supports raw packet injection. On setups like VirtualBox host-only adapters or OpenVPN tunnels, Masscan may appear to run successfully but return no results. If that happens, check which interface reaches your target with ip route get <target> and pass it explicitly with --interface. In some environments, you may also need --router-ip to point Masscan at the correct gateway.
On networks where it works correctly, a full 65,535-port scan against a single host completes in around 68 seconds at --rate 1000. A subnet sweep of 256 hosts across 7 ports takes roughly 25 seconds. The output below is representative of what Masscan returns on a routed network against a host with the same open ports our Nmap scan confirmed:
# sudo masscan -p 1-65535 10.38.1.119 --rate 1000 --wait 5
Starting masscan 1.3.2 (http://bit.ly/14GZzcT) at 2026-05-19 03:00:00 GMT
Initiating SYN Stealth Scan
Scanning 1 hosts [65535 ports/host]
Discovered open port 22/tcp on 10.38.1.119
Discovered open port 21/tcp on 10.38.1.119
Discovered open port 23/tcp on 10.38.1.119
Discovered open port 25/tcp on 10.38.1.119
Discovered open port 80/tcp on 10.38.1.119
Discovered open port 111/tcp on 10.38.1.119
Discovered open port 139/tcp on 10.38.1.119
Discovered open port 445/tcp on 10.38.1.119
Discovered open port 512/tcp on 10.38.1.119
Discovered open port 513/tcp on 10.38.1.119
Discovered open port 514/tcp on 10.38.1.119
Discovered open port 1099/tcp on 10.38.1.119
Discovered open port 1524/tcp on 10.38.1.119
Discovered open port 2049/tcp on 10.38.1.119
Discovered open port 2121/tcp on 10.38.1.119
Discovered open port 3306/tcp on 10.38.1.119
Discovered open port 3632/tcp on 10.38.1.119
Discovered open port 5432/tcp on 10.38.1.119
Discovered open port 5900/tcp on 10.38.1.119
Discovered open port 6000/tcp on 10.38.1.119
Discovered open port 6667/tcp on 10.38.1.119
Discovered open port 6697/tcp on 10.38.1.119
Discovered open port 8009/tcp on 10.38.1.119
Discovered open port 8180/tcp on 10.38.1.119
Discovered open port 8787/tcp on 10.38.1.119
real 68.14s# sudo masscan -p 1-65535 10.38.1.119 --rate 1000 --wait 5
Starting masscan 1.3.2 (http://bit.ly/14GZzcT) at 2026-05-19 03:00:00 GMT
Initiating SYN Stealth Scan
Scanning 1 hosts [65535 ports/host]
Discovered open port 22/tcp on 10.38.1.119
Discovered open port 21/tcp on 10.38.1.119
Discovered open port 23/tcp on 10.38.1.119
Discovered open port 25/tcp on 10.38.1.119
Discovered open port 80/tcp on 10.38.1.119
Discovered open port 111/tcp on 10.38.1.119
Discovered open port 139/tcp on 10.38.1.119
Discovered open port 445/tcp on 10.38.1.119
Discovered open port 512/tcp on 10.38.1.119
Discovered open port 513/tcp on 10.38.1.119
Discovered open port 514/tcp on 10.38.1.119
Discovered open port 1099/tcp on 10.38.1.119
Discovered open port 1524/tcp on 10.38.1.119
Discovered open port 2049/tcp on 10.38.1.119
Discovered open port 2121/tcp on 10.38.1.119
Discovered open port 3306/tcp on 10.38.1.119
Discovered open port 3632/tcp on 10.38.1.119
Discovered open port 5432/tcp on 10.38.1.119
Discovered open port 5900/tcp on 10.38.1.119
Discovered open port 6000/tcp on 10.38.1.119
Discovered open port 6667/tcp on 10.38.1.119
Discovered open port 6697/tcp on 10.38.1.119
Discovered open port 8009/tcp on 10.38.1.119
Discovered open port 8180/tcp on 10.38.1.119
Discovered open port 8787/tcp on 10.38.1.119
real 68.14sNotice what's missing: no versions, no service names, no OS hints. Just IP, port, and state. That's by design — Masscan is a discovery tool, not an analysis tool. You hand these results to Nmap.
The subnet sweep output saved to a file looks like this:
# cat masscan_results.txt
open tcp 22 10.38.1.119 1747619312
open tcp 80 10.38.1.119 1747619318
open tcp 21 10.38.1.119 1747619321
open tcp 445 10.38.1.119 1747619325
open tcp 23 10.38.1.119 1747619330
open tcp 3306 10.38.1.119 1747619342
#masscan
# grep "open" masscan_results.txt | awk '{print $4}' | sort -u
10.38.1.119# cat masscan_results.txt
open tcp 22 10.38.1.119 1747619312
open tcp 80 10.38.1.119 1747619318
open tcp 21 10.38.1.119 1747619321
open tcp 445 10.38.1.119 1747619325
open tcp 23 10.38.1.119 1747619330
open tcp 3306 10.38.1.119 1747619342
#masscan
# grep "open" masscan_results.txt | awk '{print $4}' | sort -u
10.38.1.119What Masscan cannot do:
- Service version detection
- OS detection
- NSE scripting
- Reliably handle rate-limited or slow-responding hosts at high rates
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.1wget 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.1Full port discovery — timed:
# time rustscan -a 10.38.1.119 --ulimit 5000
.----. .-. .-. .----..---. .----. .---. .--. .-. .-.
| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| |
| .-. \| {_} |.-._} } | | .-._} }\ }/ /\ \| |\ |
`-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: http://discord.skerritt.blog :
: https://github.com/RustScan/RustScan :
--------------------------------------
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 ( https://nmap.org ) at 2026-05-18 08:08 -0400
PORT 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 64
Nmap done: 1 IP address (1 host up) scanned in 1.46 seconds
real 141.25s
user 0.67s
sys 72.75s
cpu 51%# time rustscan -a 10.38.1.119 --ulimit 5000
.----. .-. .-. .----..---. .----. .---. .--. .-. .-.
| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| |
| .-. \| {_} |.-._} } | | .-._} }\ }/ /\ \| |\ |
`-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: http://discord.skerritt.blog :
: https://github.com/RustScan/RustScan :
--------------------------------------
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 ( https://nmap.org ) at 2026-05-18 08:08 -0400
PORT 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 64
Nmap done: 1 IP address (1 host up) scanned in 1.46 seconds
real 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 -- -sVrustscan -a 10.38.1.119 --ulimit 5000 -- -sVRustScan 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 secondsPORT 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 secondsNmap 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"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
Speed Comparison — Real Numbers
All three tools against the same target, the full port range. Total workflow time is included where relevant:
Tool Discovery Nmap portion Service info
------------------------------------------------------------------------
nmap -p- -T4 84s total — No
nmap -sV (targeted ports) — 12.91s Yes
rustscan --ulimit 5000 141s total 1.46s No
rustscan --ulimit 5000 -- -sV 141s total 14.14s Yes
masscan -p 1-65535 --rate 1000 ~68s total — NoTool Discovery Nmap portion Service info
------------------------------------------------------------------------
nmap -p- -T4 84s total — No
nmap -sV (targeted ports) — 12.91s Yes
rustscan --ulimit 5000 141s total 1.46s No
rustscan --ulimit 5000 -- -sV 141s total 14.14s Yes
masscan -p 1-65535 --rate 1000 ~68s total — NoA few honest observations from these numbers:
RustScan's 141s total is the full wall-clock time from start to finish, including both the async discovery phase and the Nmap scan. The Nmap portion alone is 1.46 seconds for port-only output and 14 seconds for full service detection. If your goal is "time to get service info on all open ports," RustScan + -sV is the fastest complete workflow here.
In this lab, Masscan returned fewer ports than Nmap and RustScan. Stateless high-speed scanning can miss ports depending on rate, packet loss, and network conditions — this was observed on a local host-only network and may not reflect behaviour on other setups. The result is worth noting, but it is not a general rule. Masscan's advantage is its scale: against a /16 With thousands of hosts, nothing else comes close.
Nmap's 84 seconds is competitive on a local LAN. On a remote target over a real WAN, Nmap slows down noticeably while Masscan's raw speed advantage becomes much more significant.
The Three-Tool Pipeline
The practical workflow for most engagements:
# Step 1 — Masscan for large network discovery
# Note: requires a routed network path — may not work reliably over VPN/TUN interfaces
sudo masscan -p 22,80,443,445,8080 10.10.0.0/24 --rate 3000 -oL masscan_results.txt
# Step 2 — Parse live hosts from Masscan output
grep "open" masscan_results.txt | awk '{print $4}' | sort -u > live_hosts.txt
cat live_hosts.txt
# Step 3 — RustScan for full port discovery on each live host
rustscan -a 10.10.0.5 --ulimit 5000 -- -sV
# Step 4 — Nmap deep scan on interesting targets
nmap -sS -sV -sC -O -p- -T4 10.10.0.5# Step 1 — Masscan for large network discovery
# Note: requires a routed network path — may not work reliably over VPN/TUN interfaces
sudo masscan -p 22,80,443,445,8080 10.10.0.0/24 --rate 3000 -oL masscan_results.txt
# Step 2 — Parse live hosts from Masscan output
grep "open" masscan_results.txt | awk '{print $4}' | sort -u > live_hosts.txt
cat live_hosts.txt
# Step 3 — RustScan for full port discovery on each live host
rustscan -a 10.10.0.5 --ulimit 5000 -- -sV
# Step 4 — Nmap deep scan on interesting targets
nmap -sS -sV -sC -O -p- -T4 10.10.0.5Masscan finds what's alive across the subnet. RustScan finds all open ports on specific targets and hands them to Nmap. Nmap does the analysis.
One practical note on passing multiple hosts to RustScan: the $(cat live_hosts.txt | tr '\n' ',') pattern works for small lists but can break with larger ones. For anything beyond a handful of targets, loop through the file or wrap it in a small script.
When to Use What
Scenario Tool
---------------------------------------------------------------
CTF — single target, get started fast RustScan → Nmap
Large subnet, find what's alive quickly Masscan (needs routed network)
Authorized pentest, thorough recon Nmap -p- then -sV -sC
Post-pivot internal scan Nmap only via proxychains -sT
(Masscan and RustScan don't work
through SOCKS proxies)
Need NSE scripts Nmap only
Need OS detection Nmap only
Need XML/grepable output for Metasploit Nmap only
Running over VPN Nmap or RustScan
(Masscan may not work reliably on
VPN/TUN interfaces)Scenario Tool
---------------------------------------------------------------
CTF — single target, get started fast RustScan → Nmap
Large subnet, find what's alive quickly Masscan (needs routed network)
Authorized pentest, thorough recon Nmap -p- then -sV -sC
Post-pivot internal scan Nmap only via proxychains -sT
(Masscan and RustScan don't work
through SOCKS proxies)
Need NSE scripts Nmap only
Need OS detection Nmap only
Need XML/grepable output for Metasploit Nmap only
Running over VPN Nmap or RustScan
(Masscan may not work reliably on
VPN/TUN interfaces)What's Next
In Part 11, we flip the perspective completely. Instead of attacking, we look at what your Nmap scans look like to a defender — IDS signatures, log patterns, and how a blue team identifies scanning activity. Understanding this makes you a better attacker and a better defender.
Part 11← Link will be live once published
🔒 Legal reminder: All three tools covered here should only be used against systems you own or have explicit written permission to test.
_Part of the series: _Nmap — The Tool You Think You Know