Port Scanning with Nmap & Alternatives
#Overview
Port scanning is the foundational enumeration technique used to discover open TCP and UDP ports, identify running services, fingerprint operating systems, and detect service versions. Nmap is the industry-standard tool, complemented by faster alternatives like Masscan and RustScan for initial discovery. This technique covers scan recipes from quick initial sweeps through exhaustive full-port scans, NSE script usage, output parsing, and operational security considerations.
#Prerequisites
- Tools: nmap, masscan, rustscan, xsltproc (for HTML reports)
- Access Level: Network connectivity to target (same subnet or routable path)
- Recommended: sudo/root access for SYN scans (-sS), UDP scans (-sU), and OS detection (-O)
#Detection & Enumeration
#Quick Initial Scan (First Pass)
Start with a fast SYN scan of the top 1000 ports to quickly identify obvious services:
# Quick TCP scan (top 1000 ports, SYN stealth)
sudo nmap -sS -T4 --min-rate=1000 -Pn 10.10.10.161
# Even faster: top 100 ports only
sudo nmap -sS -T4 -F 10.10.10.161
# Quick scan with version detection on discovered ports
sudo nmap -sS -sV -T4 -F 10.10.10.161
Flag Explanations:
-sS: SYN stealth scan (half-open TCP, never completes handshake). Requires root.-T4: Timing template 4 (aggressive). Faster but noisier. Range is T0 (paranoid) through T5 (insane).--min-rate=1000: Send at least 1000 packets/sec. Prevents nmap from being too slow on responsive hosts.-Pn: Skip host discovery (ping). Treat all hosts as up. Use when ICMP is filtered.-F: Fast mode (top 100 ports instead of top 1000).-sV: Probe open ports to determine service/version info.
#Comprehensive Full-Port TCP Scan
The standard pattern used across nearly every HTB walkthrough:
# Phase 1: Discover all open TCP ports quickly
ports=$(nmap -p- --min-rate=1000 -T4 10.10.10.161 | grep '^[0-9]' | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)
# Phase 2: Deep scan only the open ports
nmap -p$ports -sC -sV 10.10.10.161
Flag Explanations:
-p-: Scan all 65535 TCP ports.grep '^[0-9]': Filter to lines starting with digits (port numbers).cut -d '/' -f 1: Extract just the port number from "PORT/STATE" lines.tr '\n' ',': Replace newlines with commas to create comma-separated port list.sed s/,$//: Remove trailing comma.-sC: Run default NSE scripts (equivalent to--script=default). Safe, useful collection.-sV: Version detection. Probes open ports to identify service name and version number.
#One-Liner Combined Scan
nmap -p- --min-rate=1000 -sC -sV -T4 -Pn -oA full_scan 10.10.10.161
Flag Explanations:
-oA full_scan: Output in all three formats (.nmapnormal,.gnmapgrepable,.xmlXML).
#UDP Scanning
UDP scanning is slow because UDP is connectionless and responses may not come. Always do UDP after TCP.
# Top 100 UDP ports (common services)
sudo nmap -sU -T4 --top-ports 100 -Pn 10.10.10.161
# Full UDP scan (can take hours - use with caution)
sudo nmap -sU -p- --min-rate=500 -T4 -Pn 10.10.10.161
# UDP with service detection on specific port
sudo nmap -sU -sV -p 161,500,4500 10.10.10.161
Flag Explanations:
-sU: UDP scan. Always requires root.--top-ports 100: Scan the 100 most common ports instead of all ports.- UDP scan speeds are inherently slower than TCP; expect 10-100x longer.
#Alternative Scanners
Masscan (Fastest Initial Discovery)
# Scan all TCP ports at high speed
sudo masscan -p1-65535 --rate=10000 10.10.10.161 -e tun0
# Scan specific ports, output to file
sudo masscan -p80,443,8080,8443 --rate=5000 10.10.10.0/24 -oJ masscan_output.json
Key Differences from Nmap:
- Masscan is designed for Internet-scale scanning. Can scan the entire IPv4 space.
--ratecontrols packets per second. Higher = faster but packet loss increases.- Does NOT do service/version detection. Use for port discovery, feed results to nmap.
- SYN scanning only. No TCP connect scan mode.
RustScan (Fast with Nmap Integration)
# Default scan (top 1000 ports, then feeds to nmap)
rustscan -a 10.10.10.161
# Custom port range with nmap args
rustscan -a 10.10.10.161 -p 1-65535 -- -sC -sV
# Ultra fast with batch size tuning
rustscan -a 10.10.10.161 --range 1-65535 -b 5000 -- -A
Key Features:
- Scans all 65535 ports in ~3 seconds using adaptive batch sizing.
- Automatically pipes discovered ports to nmap for service detection.
-b: Batch size (number of ports to scan simultaneously).
#OS Detection
# Full OS detection (requires at least one open and one closed TCP port)
sudo nmap -O 10.10.10.161
# Aggressive OS detection (combines -O, -sC, -sV, --traceroute)
sudo nmap -A 10.10.10.161
# OS detection with specific port requirements met
sudo nmap -O --osscan-guess 10.10.10.161
#Common NSE Script Categories
# Default scripts (safe, informative)
nmap -sC 10.10.10.161
# All scripts in a category
nmap --script=discovery 10.10.10.161
nmap --script=vuln 10.10.10.161
nmap --script=safe 10.10.10.161
# Multiple specific scripts
nmap --script=smb-os-discovery,smb-enum-shares,http-title,ssl-cert 10.10.10.161
# Vulnerability scanning (can be noisy/intrusive)
nmap --script=vuln -p- 10.10.10.161
Most Useful NSE Scripts for Pentesting:
| Script | Purpose | Ports |
|---|---|---|
smb-os-discovery | OS, computer name, domain, FQDN via SMB | 445 |
http-title | HTML title from web servers | 80,443,8080 |
ssl-cert | Extract SSL certificate details (CN, SANs, expiry) | 443,8443 |
http-enum | Directory enumeration via NSE | 80,443 |
ftp-anon | Check for anonymous FTP access | 21 |
ldap-rootdse | LDAP root DSE information | 389,3268 |
rdp-ntlm-info | NTLM info from RDP | 3389 |
dns-zone-transfer | Attempt DNS zone transfer | 53 |
snmp-info | SNMP system information extraction | 161 |
banner | Simple banner grab across all open ports | any |
#Output Formats and Parsing
# All output formats at once
nmap -p- -oA scan_results 10.10.10.161
# Grepable output for quick parsing
nmap -p- -oG scan.gnmap 10.10.10.161
grep "open" scan.gnmap | cut -d " " -f 2,5-
# Extract open ports from grepable output
grep -oP '\d+/open' scan.gnmap | cut -d '/' -f 1 | sort -n | uniq
# Generate HTML report from XML
xsltproc scan_results.xml -o scan_report.html
# Extract IP and open ports in concise format
cat scan.gnmap | grep "open" | awk '{print $2, $5}' | sed 's/Ports://'
#Execution
#Standard Two-Phase Workflow (Most Common)
This is the pattern used in virtually every HTB walkthrough:
# Step 1: Quick full-port discovery
ports=$(nmap -p- --min-rate=1000 -T4 10.10.10.161 | grep '^[0-9]' | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)
# Step 2: Targeted deep scan with scripts and version detection
nmap -p$ports -sC -sV -oA targeted_scan 10.10.10.161
#Firewall Evasion Scenarios
# Fragment packets (bypass simple firewalls)
sudo nmap -f 10.10.10.161
# Custom MTU (fragment to specific size, must be multiple of 8)
sudo nmap --mtu 24 10.10.10.161
# Decoy scan (mix traffic with decoy IPs - ethical engagements only)
sudo nmap -D RND:5 10.10.10.161
# Source port spoofing (common bypass: port 53 DNS, 80 HTTP)
sudo nmap --source-port 53 10.10.10.161
# Idle scan (stealthy, uses zombie host - needs a host with predictable IP ID)
sudo nmap -sI zombie_host 10.10.10.161
# Connect scan (no root required, completes TCP handshake - very noisy)
nmap -sT 10.10.10.161
#Scan Timing Templates Reference
| Template | Name | Min Delay | Max Delay | Use Case |
|---|---|---|---|---|
| T0 | Paranoid | 5 min | -- | IDS evasion, extreme stealth |
| T1 | Sneaky | 15 sec | -- | IDS evasion |
| T2 | Polite | 0.4 sec | -- | Slower, less bandwidth used |
| T3 | Normal | -- | -- | Default, balanced |
| T4 | Aggressive | -- | 1.25 sec | Fast LAN/internal scans |
| T5 | Insane | -- | 0.3 sec | Fastest, may miss ports, very noisy |
#Scanning All Hosts in a Subnet
# Ping sweep to find live hosts
nmap -sn 10.10.10.0/24
# Full port scan on a /24 subnet (use with care)
nmap -p 22,80,443,445,3389 10.10.10.0/24 -oA subnet_common
# From a file of targets
nmap -p- -iL targets.txt -oA full_scans
#Key NSE Vulnerability Scripts
| Script | Port | Purpose |
|---|---|---|
--script smb-vuln-ms17-010 | 445 | EternalBlue check |
--script smb-vuln-cve2009-3103 | 445 | Samba vulnerability |
--script ssl-heartbleed | 443 | Heartbleed check |
--script ssl-poodle | 443 | POODLE check |
--script ssl-ccs-injection | 443 | CCS injection check |
--script http-vuln* | 80,443 | All HTTP vulnerability scripts |
--script rdp-vuln-ms12-020 | 3389 | BlueKeep check |
--script dns-brute | 53 | DNS subdomain brute-force |
--script redis-info | 6379 | Redis server info |
--script ldap-rootdse | 389 | LDAP root DSE info |
--script ms-sql-info | 1433 | MSSQL server info |
--script dns-zone-transfer | 53 | DNS zone transfer attempt |
--script vulscan/vulscan.nse | Any | OS/Service version to CVE mapping |
Usage: nmap --script <script-name> -p <port> <target>
#Additional Nmap Features
# Update NSE scripts (important for new CVE coverage)
nmap --script-updatedb
# Version intensity (control how aggressive service detection is)
nmap -sV --version-intensity 5 <target> # 0=all, 9=only most reliable, 7=default
# Lower intensity = faster but less accurate service detection
# Pass arguments to NSE scripts
nmap --script smb-vuln-ms17-010 --script-args smbusername=user,smbpassword=pass -p 445 <target>
nmap --script http-enum --script-args http.useragent="Mozilla/5.0" -p 80 <target>
#Common Pitfalls
- Skipping host discovery when ICMP is blocked. Use
-Pnto skip ping check and treat host as up. - UDP scans timing out. UDP scans are inherently slow. Start with
--top-ports 100for UDP, and increase timeouts with--host-timeout. - Missing ports due to high packet loss at high rates. If
-T5or high--min-ratecauses drops, reduce to-T4or even-T3. - Forgetting that
-sCis NOT a full vulnerability scan. It runs only "default" scripts. Use--script vulnfor vulnerability checks (noisier). - Assuming a closed port means the service is absent. Firewall rules may drop or reject packets. A "filtered" state is ambiguous.
- Running
-Aon production without authorization.-Aincludes traceroute, OS detection, script scanning, and version detection -- very intrusive. - Forgetting to add discovered domain names to
/etc/hosts. Many services (Kerberos, IIS virtual hosts, SMB) require proper name resolution. - Using
-sT(TCP connect scan) when you have root. It is slower, completes the TCP handshake (creating full log entries), and offers no advantage over-sS.
#OPSEC Considerations
- SYN scans (
-sS) generate connection attempts to every port scanned. Rate and port count determine noise level. A full 65535-port scan will generate log entries on every open (and many closed) ports. - Default scripts (
-sC) may trigger IDS/IPS signatures. For example,http-sql-injectionand similar intrusive scripts in the default set can trigger WAF alerts. - Version detection (
-sV) sends probes that some services log. Database servers, SSH, and HTTP servers may log version probes as suspicious activity. - Nmap sends TCP SYN packets by default. These are logged by most firewalls and HIDS. Each SYN to an unfiltered closed port triggers a RST; each to an open port triggers a SYN-ACK. Firewalls may log every connection attempt.
- T4 timing is the standard in HTB/CTF environments but is noticeably aggressive on production networks. T3 or lower is recommended for stealth.
- OS detection (
-O) sends unusual packet sequences that are easily flagged by NIDS/NIPS systems. - UDP scans generate ICMP "port unreachable" responses which are logged by host-based firewalls and kernel audit systems.
- Consider timing your scans during business hours if blending in with normal traffic is possible. Off-hours scanning may stand out more.
- Nmap's default User-Agent and probe patterns are well-known and signatured by most security products. Customizing
--script-argscan help but does not fully anonymize. - Using
--source-port 53or--source-port 80may bypass poorly configured firewall rules but is still logged. - Masscan and RustScan are even noisier than Nmap due to their ultra-high packet rates. They should only be used on internal assessments or with explicit authorization.
- Scan results (especially XML/GNMAP outputs) contain sensitive network topology info. Encrypt or delete after reporting.
- OPSEC: -sC default scripts are "safe" category but some (http-sql-injection) are intrusive. T4/T5 timing templates create distinctive packet patterns fingerprinted by modern IDS. SYN scan (-sS) completion triggers kernel connection state logging on some systems.
--script vulnis very noisy -- runs dozens of exploit checks, triggers IDS/WAF alerts.
#Post-Exploitation Value
Port scanning provides the complete network surface map that guides all subsequent enumeration. Without a thorough port scan:
- Hidden services (high ports, UDP services) remain undiscovered.
- Service versions cannot be correlated with known vulnerabilities.
- The attack surface remains incompletely understood, increasing the chance of missing the intended exploitation path.
After obtaining a foothold, internal port scanning from the compromised host reveals services not exposed externally (e.g., MySQL on 127.0.0.1:3306, internal web apps on 8080, Redis on 6379).
#Cross-References
#Common Port/Service Reference Table
| Port | Protocol | Service | Enumeration Focus |
|---|---|---|---|
| 21 | TCP | FTP | Anonymous login, file download, version exploits |
| 22 | TCP | SSH | Banner, auth methods, user enumeration, weak keys |
| 23 | TCP | Telnet | Default credentials, cleartext capture |
| 25 | TCP | SMTP | User enumeration (VRFY/EXPN/RCPT TO) |
| 53 | TCP/UDP | DNS | Zone transfer, subdomain enumeration, DNSSEC |
| 80 | TCP | HTTP | Web enumeration, directory brute-force, CMS fingerprinting |
| 88 | TCP/UDP | Kerberos | AS-REP roasting, user enumeration, SPN discovery |
| 110 | TCP | POP3 | Credential capture, version exploits |
| 111 | TCP/UDP | RPC (Portmapper) | RPC service enumeration |
| 135 | TCP | MSRPC | DCOM, RPC endpoint enumeration |
| 139 | TCP | NetBIOS-SSN | NetBIOS name service, shares |
| 143 | TCP | IMAP | Credential capture, version exploits |
| 161 | UDP | SNMP | Community string brute-force, MIB enumeration |
| 389 | TCP/UDP | LDAP | Anonymous bind, user/group enumeration, domain info |
| 443 | TCP | HTTPS | Same as HTTP + SSL/TLS certificate inspection |
| 445 | TCP | SMB (Direct) | Share enumeration, null sessions, version detection |
| 464 | TCP/UDP | kpasswd5 | Kerberos password change |
| 514 | UDP | Syslog | Log capture, sensitive data |
| 636 | TCP | LDAPS | Same as LDAP, encrypted |
| 873 | TCP | Rsync | Module enumeration, anonymous access |
| 993 | TCP | IMAPS | Same as IMAP, encrypted |
| 995 | TCP | POP3S | Same as POP3, encrypted |
| 1433 | TCP | MSSQL | Version, default credentials, xp_cmdshell |
| 1521 | TCP | Oracle TNS | SID enumeration, version, default credentials |
| 2049 | TCP | NFS | Export enumeration, mount access |
| 2375 | TCP | Docker (unencrypted) | Container enumeration, API access |
| 3000 | TCP | Various dev servers | Web app frameworks (Node, Rails, React dev) |
| 3128 | TCP | Squid Proxy | Open proxy detection |
| 3268 | TCP | Global Catalog LDAP | Same as LDAP, forest-wide |
| 3269 | TCP | Global Catalog LDAPS | Same as LDAPS, forest-wide |
| 3306 | TCP | MySQL/MariaDB | Version, default credentials, database enumeration |
| 3389 | TCP | RDP | NLA status, NTLM info leak, BlueKeep (CVE-2019-0708) |
| 4444 | TCP | Meterpreter (common) | Often used by Metasploit payloads |
| 5432 | TCP | PostgreSQL | Version, default credentials, database enumeration |
| 5555 | TCP | Android Debug Bridge | Unauthenticated access |
| 5900-5903 | TCP | VNC | Authentication bypass, weak passwords |
| 5985 | TCP | WinRM (HTTP) | PowerShell Remoting enumeration |
| 5986 | TCP | WinRM (HTTPS) | Same, encrypted |
| 6379 | TCP | Redis | Unauthenticated access, data dump, RCE via modules |
| 8080 | TCP | HTTP-Proxy/Alt | Web enumeration, often Tomcat/Jenkins/dev servers |
| 8443 | TCP | HTTPS-Alt | Same as HTTPS, often admin panels |
| 8888 | TCP | Various | Jupyter, dev servers |
| 9091 | TCP | Various | WebSocket services, admin panels |
| 9389 | TCP | ADWS | Active Directory Web Services |
| 27017 | TCP | MongoDB | Unauthenticated access, database enumeration |
| 47001 | TCP | WinRM (HTTP alt) | PowerShell Remoting |
#Tool References
| Tool | Description | Link |
|---|---|---|
| Nmap | Industry-standard port scanner | https://nmap.org/ |
| Masscan | Mass IP/port scanner (Internet-scale) | https://github.com/robertdavidgraham/masscan |
| RustScan | Fast port scanner with nmap integration | https://github.com/RustScan/RustScan |
| xsltproc | XML-to-HTML report generation | Built into most Linux distros |
| Zenmap | GUI for Nmap | https://nmap.org/zenmap/ |
| AutoRecon | Automated multi-threaded enumeration | https://github.com/Tib3rius/AutoRecon |
#Source Machines
- Forest (Easy, AD) -- Standard two-phase nmap with LDAP/SMB follow-up
- Sauna (Easy, AD) -- Two-phase scan, port discovery leading to LDAP/Web/SMB enumeration
- Cascade (Medium, AD) -- Full port scan with
-Pnflag - BoardLight (Easy, Linux) -- Standard nmap with
-Pn, discovered SSH+Apache - Broker (Easy, Linux) -- Nmap reveals ActiveMQ on port 61616
- Authority (Medium, AD/Windows) -- Full-port scan revealing PWM on 8443
- Manager (Medium, AD/Windows) -- Version scan discovers MSSQL 2019 on 1433
- Soccer (Easy, Linux) -- Port 9091 unknown service discovered via full scan
- Support (Easy, Windows) -- nmap
-sC -sV -Pnreveals DC ports, LDAP, SMB, WinRM