NMAP
What Nmap actually does
Nmap ("Network Mapper") sends probes to hosts and interprets the responses to answer four questions:
- Host discovery. Which IPs in this range are up?
- Port scanning. Which TCP/UDP ports on a host will respond?
- Service & version detection. What software and version is listening on each port?
- NSE probing. Run targeted scripts (check ciphers, grab banners, detect known vulns).
Each mode has a separate set of flags. Most real scans combine several — e.g. discover, then TCP port-scan, then version-detect, then run a script.
Minimal scans you'll use daily
# "Which hosts in my /24 are up right now?"
nmap -sn 10.0.0.0/24 # -sn = ping scan, no ports
# "What's this one box listening on?" (top 1000 TCP ports)
nmap 10.0.0.5
# "Scan everything — all 65535 TCP ports, with service versions"
nmap -p- -sV 10.0.0.5
# "Scan just the ports I care about, report service and version"
nmap -p 22,80,443,3306 -sV host.example.com
# "Give me SSH banners for the whole VLAN"
nmap -p 22 -sV --open 10.0.0.0/24
--open hides closed and filtered ports in the output — usually what you want during operational scans.
Choosing which ports to scan
# Default: top 1000 TCP ports (fast)
nmap host
# Specific ports
nmap -p 22,80,443 host
nmap -p 8000-9000 host # range
# Top N by frequency
nmap --top-ports 100 host # 100 most common
nmap --top-ports 1000 host # default
nmap --top-ports 65535 host # everything
# Every TCP port — shorthand
nmap -p- host # 1-65535
# UDP ports (slow and easy to misread, see below)
nmap -sU -p 53,67,123,161 host
# Both TCP and UDP in one pass
nmap -sS -sU -p T:22,80,443,U:53,123 host
open|filtered — Nmap literally cannot tell the difference between "service is listening and silent" and "firewall dropped the probe". Use -sV on UDP to get a real answer via application-layer probes where possible.
Scan types and when each matters
| Flag | Name | When to use |
|---|---|---|
-sS | SYN scan | Default when running as root — fast, doesn't complete the handshake |
-sT | TCP connect | Non-root user; completes full handshake (shows up in target logs) |
-sU | UDP scan | Probe UDP services (DNS, NTP, SNMP). Slow. Needs root. |
-sV | Version detection | What software and version is running on each open port |
-sC | Default scripts | Run the default NSE category — safe, informational |
-A | Aggressive | -sV -sC -O --traceroute in one flag. Noisy. Informative. |
-O | OS detection | TCP/IP fingerprint — needs root and at least one open and one closed port |
-Pn | No host discovery | Skip ping; treat host as up. Use when the target drops ICMP. |
# Classic "tell me everything about this box" scan
sudo nmap -p- -sV -sC -O --open --reason host
# Quick inventory scan — version only, top ports
sudo nmap --top-ports 100 -sV --open 10.0.0.0/24
# Firewall drops ICMP — force scan anyway
sudo nmap -Pn -sS -p 22,443 host
--reason adds a "why" column (e.g. syn-ack, no-response, reset) — invaluable for understanding what the network actually did.
Timing and stealth
# Timing templates: -T0 paranoid … -T5 insane
nmap -T4 host # sane default for internal networks
nmap -T3 host # default; safer on busy links
nmap -T2 host # polite; slower, lower load
# Explicit rate limiting
nmap --min-rate 100 --max-rate 1000 host
nmap --max-retries 2 host # give up faster on filtered ports
# Split large scans to avoid IDS "avalanche" alerts
nmap --scan-delay 500ms host
-T3 and --max-retries 2. Aggressive timings have taken down flaky firewalls, load balancers, and printers more than once. There is no prize for finishing the scan faster.
NSE — the scripting engine
Nmap ships with ~600 Lua scripts grouped by category (default, safe, discovery, version, vuln, auth, brute, exploit, intrusive, malware). You pick them with --script.
# Run one script
nmap --script ssl-enum-ciphers -p 443 host # full TLS cipher inventory
nmap --script ssh-auth-methods -p 22 host # what SSH auth is accepted
nmap --script http-title -p 80,443 host # grab HTTP title tags
nmap --script smb-os-discovery -p 445 host # SMB version + OS hints
nmap --script dns-recursion -p 53 host # open recursive resolver?
# Script categories
nmap --script default host # safe, informational
nmap --script "safe and version" host
nmap --script vuln host # known CVE checks (noisy)
# Pass arguments to scripts
nmap --script http-title --script-args http.useragent="SysAdmin-check" host
# Help on a script
nmap --script-help ssl-enum-ciphers
Don't run --script vuln or intrusive categories without authorisation. They include active checks that can crash fragile services.
Output formats
# Human-readable only (default)
nmap -oN scan.txt host
# Grepable (line-oriented, awk/sed-friendly)
nmap -oG scan.gnmap host
# XML (for nmap-parsers, Metasploit, etc.)
nmap -oX scan.xml host
# All three at once with a shared basename
nmap -oA scan-$(date +%F) host
# Creates scan-YYYY-MM-DD.nmap / .gnmap / .xml
# Resume an aborted scan from any of those files
nmap --resume scan-2026-04-12.gnmap
Reading results: open vs filtered vs closed
| State | What it means |
|---|---|
open | A service accepted the probe and responded. Something is listening. |
closed | Host responded with RST/ICMP-unreachable. No service listening, but host is alive and reachable. |
filtered | No response at all (or an ICMP filter reply). A firewall silently dropped the probe. Inconclusive. |
open|filtered | Common on UDP and some stealth TCP scans — Nmap can't distinguish the two cases. |
unfiltered | ACK scan only; firewall is not blocking, but state can't be determined. |
# "Host seems down" but you know it's up?
# Probably ICMP is blocked. Force the scan.
nmap -Pn host
# Want to know why each port is in its state?
nmap --reason host
Practical SysAdmin recipes
Is this port actually open from my vantage point?
nmap -Pn -p 443 api.example.com
# open = working path, TLS listener present
# filtered = firewall path issue (corporate outbound, security group, etc.)
# closed = reachable but no listener (wrong host? DNS?)
What TLS versions and ciphers does this service actually serve?
nmap --script ssl-enum-ciphers -p 443 host.example.com
# Scan output grades each cipher (A/B/C) and flags weak suites.
# Useful for compliance checks and for verifying
# config changes on /nginx-config/ or /postfix-config/.
Which of these 40 hosts has SSH on a non-standard port?
nmap -p 22,2022,2222 -sV --open -oG - 10.0.0.0/24 \
| awk '/22\/open|2022\/open|2222\/open/ {print $2, $0}'
Inventory sweep — just the live IPs
# Ping scan on a /16, pull only the "Up" lines
nmap -sn 10.0.0.0/16 -oG - \
| awk '/Up$/ {print $2}' \
| sort -V > live-hosts.txt
wc -l live-hosts.txt
Has anything new appeared on this subnet since last week?
# Store a baseline
nmap --top-ports 100 -oX baseline.xml 10.0.0.0/24
# Later, rescan and diff
nmap --top-ports 100 -oX today.xml 10.0.0.0/24
ndiff baseline.xml today.xml
Quick firewall sanity after a change
# From outside the VPC
nmap -p 22,80,443 --reason api.example.com
# From inside the VPC
nmap -p 22,80,443,5432 --reason db01.internal
Companion tool: ncat
ncat ships with Nmap. It's a modern nc: better TLS, Unix sockets, exec mode, broker mode. Useful alongside Nmap when you want to actually talk to the port you just found.
# Is the SSH banner what I expect?
ncat -v host 22 </dev/null
# Test a TLS service manually
ncat --ssl --ssl-verify host 443
# Listener for quick one-shot file receive
ncat -l 9000 > got.bin # receiver
ncat host 9000 < sendme.bin # sender
# HTTP request by hand
printf 'GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n' \
| ncat example.com 80
ss, ip, and tcpdump; Wireshark to follow a suspicious conversation packet-by-packet; Certificates and openssl s_client for deeper TLS inspection.