NMAP

Find hosts, discover what they're listening on, identify the service and version, and run targeted protocol probes. A SysAdmin's single most useful network tool after ping.

Scope matters. Only scan networks and hosts you own or have written authorisation to test. Aggressive scans can trip IDS, alert SOCs, and are illegal against third-party infrastructure in most jurisdictions. Inside your own estate, announce and schedule where possible.

What Nmap actually does

Nmap ("Network Mapper") sends probes to hosts and interprets the responses to answer four questions:

  1. Host discovery. Which IPs in this range are up?
  2. Port scanning. Which TCP/UDP ports on a host will respond?
  3. Service & version detection. What software and version is listening on each port?
  4. 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
UDP is lying to you. A UDP port that doesn't reply gets classified 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

FlagNameWhen to use
-sSSYN scanDefault when running as root — fast, doesn't complete the handshake
-sTTCP connectNon-root user; completes full handshake (shows up in target logs)
-sUUDP scanProbe UDP services (DNS, NTP, SNMP). Slow. Needs root.
-sVVersion detectionWhat software and version is running on each open port
-sCDefault scriptsRun the default NSE category — safe, informational
-AAggressive-sV -sC -O --traceroute in one flag. Noisy. Informative.
-OOS detectionTCP/IP fingerprint — needs root and at least one open and one closed port
-PnNo host discoverySkip 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
On production networks, default to -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

StateWhat it means
openA service accepted the probe and responded. Something is listening.
closedHost responded with RST/ICMP-unreachable. No service listening, but host is alive and reachable.
filteredNo response at all (or an ICMP filter reply). A firewall silently dropped the probe. Inconclusive.
open|filteredCommon on UDP and some stealth TCP scans — Nmap can't distinguish the two cases.
unfilteredACK 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
Related: Linux Networking for ss, ip, and tcpdump; Wireshark to follow a suspicious conversation packet-by-packet; Certificates and openssl s_client for deeper TLS inspection.