Nmap Part 1: Install, Host Discovery & Scan Types
Nmap Part 1: Install, Host Discovery & Scan Types
This is Chapter 2 of the Scanning & Enumeration notebook. Chapter 1 produced a validated, prioritised list of live hosts using multi-probe host discovery. This chapter and the next take that list and interrogate each host directly with Nmap — the single most important tool in the scanning phase and one of the most important in the whole discipline. Where Chapter 1 answered "which hosts are alive?", Nmap answers "which ports are open, what's listening on them, what version is it, and what OS is underneath?" — the questions that turn a live IP into an attack surface.
Nmap ("Network Mapper") is a free, open-source scanner written by Gordon Lyon (Fyodor) and under active development since 1997. It is not one tool but a toolkit: a host-discovery engine, a dozen port-scan techniques, a service/version-detection system, an OS-fingerprinting engine, and a full scripting engine (NSE) with thousands of scripts that push it into light vulnerability scanning and exploitation. This chapter (Part 1) covers installation, target specification, command anatomy, and the scan types — the core of how Nmap probes ports and interprets the answers. The next chapter (Part 2) covers service/version detection, OS detection, timing/performance tuning, NSE, and output/reporting in depth.
The reason to learn Nmap deeply rather than memorising a few commands is that its every scan type is a direct expression of how TCP/IP works. -sS, -sF, -sA are not magic flags; they are specific packets that exploit specific rules in RFC 793, and the states Nmap reports (open, closed, filtered) are logical deductions from what came back. Once you see the packets, you can pick the right scan for any firewall situation, explain every result, and never be fooled by an ambiguous one. That packet-level understanding is exactly what this chapter builds.
Everything here is active and touches the target directly. Running these scans against hosts you do not own or lack explicit written authorisation to test is unlawful in most jurisdictions. Scope and authorisation are hard boundaries, covered in Part 11 and assumed throughout.
flowchart LR
A[Live host list<br/>from Ch.1] --> B[Target spec<br/>+ command anatomy]
B --> C{Scan type}
C --> D[-sS SYN<br/>default for root]
C --> E[-sT connect<br/>default unprivileged]
C --> F[-sU UDP]
C --> G[-sF/-sN/-sX<br/>flag scans]
C --> H[-sA/-sW/-sM<br/>firewall mapping]
D & E & F & G & H --> I[Port states:<br/>open/closed/filtered/...]
I --> J[Output -oA]
J --> K[Part 2:<br/>-sV -O timing NSE]
Part 1: What Nmap Is and How It Works
1.1 The architecture
Nmap's job is to send carefully-chosen packets to a target's ports and classify each port's state from the response (or lack of one). Internally it is:
- A target-and-port generator that expands your specification (
10.0.0.0/24,-p 1-1000) into a work list. - A packet engine that crafts and sends probes — using raw sockets when privileged, the OS TCP stack when not.
- A response classifier that maps replies to the six port states.
- Layered on top: host discovery (Chapter 1), service/version detection (
-sV), OS detection (-O), and the Nmap Scripting Engine (NSE) — all covered across these two chapters.
flowchart TD
A[Your command] --> B[Target + port generation]
B --> C[Host discovery -sn/-Pn]
C --> D[Port scanning<br/>-sS/-sT/-sU/-sF...]
D --> E[Response classifier<br/>-> 6 port states]
E --> F[Service/version -sV]
E --> G[OS detection -O]
F & G --> H[NSE scripts --script]
H --> I[Output: -oN/-oG/-oX/-oA]
1.2 Privileged vs unprivileged — the single biggest behaviour switch
This determines which scans you can even run:
- Root/sudo: Nmap uses raw sockets and can craft arbitrary packets — SYN scans (
-sS), the flag scans, custom ICMP, ARP, OS detection. This is the normal, capable mode. Its default TCP scan is SYN (-sS). - Unprivileged: Nmap can only use the OS
connect()system call, so its default (and often only) TCP scan is connect (-sT), and it cannot do SYN/FIN/ACK/UDP-raw probing or OS detection.
Always run Nmap with sudo unless you have a specific reason not to. Half of the "why doesn't -sS work?" confusion is running unprivileged.
1.3 The six port states
Every Nmap result reduces to one of six states. Understanding them precisely is the whole game:
| State | Meaning | How Nmap concludes it |
|---|---|---|
| open | An application is actively accepting connections | SYN→SYN/ACK (TCP); UDP→a UDP reply |
| closed | Reachable, but nothing listening | SYN→RST; ICMP port-unreachable (UDP) |
| filtered | A firewall is blocking the probe; Nmap can't tell open/closed | No response, or ICMP admin-prohibited |
| unfiltered | Reachable but Nmap can't tell open/closed (ACK scan only) | RST returned to an ACK probe |
| open|filtered | Open or filtered — can't distinguish (no reply to a scan where open ports stay silent) | UDP, FIN, NULL, Xmas with no reply |
| closed|filtered | Closed or filtered — can't distinguish (Idle scan only) | rare |
The two ambiguous "either/or" states are not failures — they are honest reporting that the probe type used cannot disambiguate those cases. Choosing a different scan type is how you resolve them (e.g. a UDP open|filtered often resolves with a version probe that elicits a service reply).
1.4 Why "port open" is only half the answer
A scan that reports 443/tcp open has found a door, not what's behind it. Two hosts can both show 443 open while one runs a patched nginx serving a static page and the other runs an unpatched Jira behind a self-signed cert — utterly different attack surfaces. The scan-type work in this chapter answers "which doors are open, and is a firewall in the way?". Turning that into "what software, what version, what OS, and what known weaknesses?" is service/version detection, OS detection and NSE — the subject of the next chapter. Keep the distinction clear: this chapter finds and classifies ports; the next identifies and interrogates what listens on them. A common beginner error is stopping at "open" and never running -sV, which is like listing the doors in a building without ever checking who's inside.
Part 2: Installing Nmap
2.1 On Kali and Debian/Ubuntu
# Kali ships with Nmap, but update it
sudo apt update && sudo apt install -y nmap
nmap --versionNmap version 7.94 ( https://nmap.org )
Platform: x86_64-pc-linux-gnu
Compiled with: liblua-5.4.4 openssl-3.0 libssh2-1.10 ...
Compiled without:
Available nsock engines: epoll poll select
The "Compiled with" line matters: OpenSSL enables TLS service probes, libssh2 enables SSH scripts, liblua enables NSE. A stripped build silently lacks capabilities.
2.2 Other platforms and from source
# macOS
brew install nmap
# From source (newest features, e.g. latest NSE + fingerprints)
curl -O https://nmap.org/dist/nmap-7.94.tar.bz2
bzip2 -cd nmap-7.94.tar.bz2 | tar xvf -
cd nmap-7.94
./configure && make && sudo make installNmap installs several companion binaries you'll meet later: ncat (a modern netcat), nping (packet crafting, Chapter 1), and ndiff (diff two scans — the basis of scan-based monitoring).
2.3 The Npcap/root note
On Linux, raw scans need root. On Windows, Nmap needs the Npcap driver for raw packets. On any platform, the rule stands: privileged = full capability.
2.4 The data files that drive Nmap
Nmap's intelligence lives in flat data files (usually under /usr/share/nmap/) that you can read and even edit:
| File | Drives |
|---|---|
nmap-services |
The port→service names and the frequency data behind --top-ports |
nmap-service-probes |
-sV version-detection probes and match patterns |
nmap-os-db |
-O OS fingerprints |
nmap-mac-prefixes |
MAC-vendor lookups (OUI) |
nmap-payloads |
UDP probe payloads for -sU |
scripts/ + nse_main.lua |
The NSE script library |
Keeping these current (via a fresh Nmap or nmap --script-updatedb for NSE) is what makes version/OS detection accurate — an old nmap-service-probes misses new software. When --top-ports "misses" a port, it's because that port ranks low in nmap-services frequency data, which you can inspect: grep -P "\t(80|3389)/tcp" /usr/share/nmap/nmap-services.
Part 3: Target Specification and Command Anatomy
Before scan types, be fluent in what you point Nmap at and how a command is structured — errors here silently scan the wrong things.
3.1 Specifying targets
nmap 10.0.0.5 # single IP
nmap scanme.nmap.org # hostname (Nmap's official legal-to-scan test host)
nmap 10.0.0.1 10.0.0.5 10.0.0.9 # list
nmap 10.0.0.0/24 # CIDR block (256 addresses)
nmap 10.0.0.1-50 # octet range
nmap 10.0.0.1,5,9-12 # comma + range within an octet
nmap 10.0.0.* 192.168.1.* # wildcards
nmap -iL targets.txt # from a file (your Ch.1 output) — the usual way
nmap --exclude 10.0.0.200-207 10.0.0.0/24 # subtract out-of-scope
nmap --excludefile oos.txt 10.0.0.0/24 # exclusions from a file
nmap -iR 100 # 100 RANDOM internet hosts — NEVER do this (unauthorised)scanme.nmap.org is explicitly provided by the Nmap project for you to practise against legally (a few scans; don't hammer it). -iL targets.txt is the normal professional input — you feed the validated list from Chapter 1. Never use -iR against the internet: those are real, random, unauthorised hosts.
3.2 The anatomy of a command
Every Nmap command has the same shape:
nmap [scan type(s)] [options] [port spec] [output] [target spec]
sudo nmap -sS -sV -p 1-1000 -T4 --reason -oA scan1 -iL targets.txt
# │ │ │ │ │ │ │
# │ │ │ │ │ │ └─ targets (file)
# │ │ │ │ │ └─ output (all formats, base "scan1")
# │ │ │ │ └─ show reason per port
# │ │ │ └─ timing template
# │ │ └─ port range
# │ └─ service/version detection (Part 2)
# └─ SYN scan typeOrder is flexible, but this left-to-right reading — type, options, ports, output, target — makes any command legible.
3.3 Port selection
-p 80 # single port
-p 1-1000 # range
-p 22,80,443,3389 # list
-p- # ALL 65535 ports (thorough; slower)
-p U:53,161,T:80,443 # mix UDP and TCP explicitly
--top-ports 100 # the 100 most common ports (by Nmap's frequency data)
-F # "fast": top 100 ports
(no -p) # default: top 1000 portsNmap's default is the top 1000 ports (not 1–1000 — the 1000 statistically most common, from real scan data in nmap-services). Know the difference: --top-ports 1000 ≈ default; -p 1-1000 is the first 1000 numerically, which misses common high ports like 3389, 8080, 8443. For thoroughness, -p- scans everything; for speed, --top-ports/-F.
3.4 Discovery mode: the -sn / -Pn / default triad
Nmap couples host discovery (Chapter 1) with port scanning, and which of three modes you're in is set by two flags. Getting this wrong either wastes hours or misses hosts:
| Flag | Discovery? | Port scan? | Use when |
|---|---|---|---|
-sn |
Yes | No | You only want a live-host list (Chapter 1) |
-Pn |
No (treat all up) | Yes | Hosts filter discovery but you know they're alive |
| (neither) | Yes | Yes (on hosts found up) | Normal: discover, then scan the survivors |
sudo nmap -sn 10.0.0.0/24 # discovery only -> live list
sudo nmap -Pn -p- 10.0.0.5 # skip discovery, scan all ports
sudo nmap -p 1-1000 10.0.0.0/24 # default: discover then scan the up hostsThe default mode is efficient — Nmap doesn't waste port probes on addresses that never answered discovery. But if the perimeter drops all discovery probes (Chapter 1, Part 4), the default silently scans nothing because every host looked down. That's the number-one reason a scan "finds no open ports on a host you know is live": you needed -Pn. On CTF targets — which very frequently filter ICMP — -Pn is close to a default habit.
3.5 Discovery-probe flags carry into a port scan
The -P* probe flags from Chapter 1 aren't just for -sn; they tune the discovery stage of a full scan. Combine a discovery probe set with a port scan so the right hosts get scanned:
# use TCP-SYN discovery to common ports, THEN port-scan whoever answered
sudo nmap -PS22,80,443,3389 -PA80 -p- -T4 10.0.0.0/24
# skip reverse-DNS during the whole thing for speed/quiet
sudo nmap -n -PS443 -p 1-1000 10.0.0.0/24Remember the independence from Chapter 1: -P* controls the discovery probes; -p/-s* controls the port scan. A well-formed scan of a firewalled range often looks like "SYN-ping discovery to a handful of ports (-PS), plus -Pn fallback on the ranges that still show nothing", then a port scan of the resulting live set. -n (no reverse-DNS) and privilege behave exactly as in Chapter 1 — run as root, and drop -n only when you want the names.
Part 4: The TCP Handshake — The Foundation of Every TCP Scan
Every TCP scan type is a variation on manipulating the three-way handshake, so nail this first (it was introduced in the Networking notebook's TCP chapter; here it's the basis of the scans).
sequenceDiagram
participant C as Scanner
participant S as Target port
Note over C,S: Normal 3-way handshake (open port)
C->>S: SYN
S->>C: SYN/ACK
C->>S: ACK
Note over C,S: Connection established
Note over C,S: Closed port
C->>S: SYN
S->>C: RST
The rules that every scan exploits:
- SYN to an open port → SYN/ACK. The port wants to talk.
- SYN to a closed port → RST. Reachable, nothing listening.
- A completed handshake (SYN, SYN/ACK, ACK) establishes a real connection the OS logs.
- RFC 793 behaviour for out-of-state packets (FIN/NULL/Xmas to an open port → silence; to a closed port → RST) is what the "flag scans" exploit.
- A firewall dropping the probe → silence, which is the ambiguity that produces
filtered.
Part 5: TCP Connect Scan (-sT)
5.1 What it does
-sT completes the full three-way handshake on every port using the OS connect() call — exactly like a normal client connecting.
nmap -sT -p 1-1000 10.0.0.5- Open port: SYN → SYN/ACK → ACK (handshake completes, then Nmap tears it down).
- Closed port: SYN → RST.
5.2 When to use it
- When you're not root — it's the only TCP scan available unprivileged, and Nmap's default in that case.
- Through a SOCKS proxy / pivot (Chapter 1's proxychains scenario) — only full connects traverse a proxy.
- When you want maximum reliability on a network where crafted packets get mangled.
5.3 The cost
Because it completes the handshake, -sT is slower (more packets, OS overhead) and louder: the connection is fully established, so the target application often logs it (a web server records the request, an SSH daemon logs the connection attempt). If you want to stay out of application logs, -sT is the wrong choice — use -sS.
Blue team usage: connect scans are the easiest to detect precisely because they complete — every touched service sees a real, logged connection. A burst of connect-and-immediately-close events across many ports is a textbook scan signature in application logs.
5.4 What a connect scan leaves behind
Because -sT completes the handshake, the target's services log a real connection. An SSH daemon records an attempt, a web server logs a request line, a database logs a connection from your IP:
# target /var/log/auth.log during an -sT scan of port 22
sshd[2141]: Connection from 10.10.0.66 port 55123 on 10.0.0.5 port 22
sshd[2141]: Connection closed by 10.10.0.66 port 55123 [preauth]
# target nginx access.log during an -sT of port 80
10.10.0.66 - - "GET / HTTP/1.0" 400 ... (or an empty/aborted request)
Multiply that by every open port on every host and a connect scan writes an unmistakable trail across the estate's application logs — which is precisely why -sS, whose half-open probes never reach the application, is preferred whenever avoiding those logs matters.
Part 6: SYN / Half-Open Scan (-sS) — The Default
6.1 What it does
-sS sends a SYN but never completes the handshake — hence "half-open" or "stealth" scan.
sequenceDiagram
participant C as Scanner (-sS)
participant S as Target port
Note over C,S: Open port
C->>S: SYN
S->>C: SYN/ACK
C->>S: RST (tear down before completing!)
Note over C,S: Closed port
C->>S: SYN
S->>C: RST
Note over C,S: Filtered port
C->>S: SYN
Note right of S: (no reply / ICMP unreachable)
- Open: SYN → SYN/ACK → Nmap sends RST to abort before the handshake completes.
- Closed: SYN → RST.
- Filtered: no response (or ICMP unreachable).
6.2 Why it's the default and "stealthy"
Because the handshake never completes, the connection is never fully established, so many applications never log it — the OS TCP stack handled a SYN it then reset, and the listening app was never handed a connection. It's also faster (fewer packets, no OS connection setup) and gives clean state classification. This is why -sS is Nmap's default when run as root, and the workhorse of virtually every professional scan.
sudo nmap -sS -p- 10.0.0.5 # full SYN scan of all ports
sudo nmap -sS --top-ports 1000 -T4 10.0.0.0/246.2b Reading a real SYN-scan result
sudo nmap -sS -sV -p- -T4 --reason 192.168.56.20Nmap scan report for 192.168.56.20
Host is up, received arp-response (0.00038s latency).
Not shown: 65530 closed tcp ports (reset)
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 64 OpenSSH 8.9p1 Ubuntu
80/tcp open http syn-ack ttl 64 nginx 1.18.0
139/tcp open netbios-ssn syn-ack ttl 64 Samba smbd 4
445/tcp open netbios-ssn syn-ack ttl 64 Samba smbd 4
8080/tcp filtered http-proxy no-response
MAC Address: 08:00:27:1A:2B:3C (Oracle VirtualBox virtual NIC)
Read every line: received arp-response confirms local-subnet ARP discovery; Not shown: 65530 closed ... (reset) means those ports RST'd (reachable, nothing listening); each open port shows syn-ack as the reason and ttl 64 (Linux); 8080 is filtered (no-response — a firewall swallowed the SYN); and the MAC vendor outs it as a VirtualBox VM. This one output tells you the host's OS family, its role (SSH + web + SMB = a Linux file/web server), and that something guards 8080 — before any dedicated OS detection.
6.3 The "stealth" caveat
-sS avoids application logs, but it is not invisible. Modern firewalls, IDS/IPS (Suricata/Zeek) and endpoint tools readily detect SYN scans by the fan-out pattern (Chapter 1's detection section) and by half-open connections that never complete. "Stealth" here means "avoids app-layer logging", not "undetectable". For genuine evasion you still need slow timing, decoys and small batches (Chapter 1, Part 7; more in Part 2's timing section).
Red team usage: -sS at slow timing with decoys is the standard reconnaissance scan when the objective includes avoiding detection — but assume network-level sensors can still see it and plan accordingly.
Part 7: The Flag Scans — FIN, NULL, Xmas (-sF, -sN, -sX)
7.1 The RFC 793 trick
These exploit a specific rule in the TCP RFC: a compliant stack receiving a segment with no SYN/RST/ACK flags set should respond with RST if the port is closed, and nothing if the port is open. So you send a weird packet and read the silence:
- Open (or filtered) port → no reply → Nmap reports
open|filtered. - Closed port → RST → Nmap reports
closed.
The three variants differ only in which flags they set:
| Scan | Flags set | Packet nickname |
|---|---|---|
-sN NULL |
none at all | "null" |
-sF FIN |
FIN only | "fin" |
-sX Xmas |
FIN + PSH + URG | "christmas tree" (lit up) |
sudo nmap -sF -p 1-1000 10.0.0.5
sudo nmap -sN -p 1-1000 10.0.0.5
sudo nmap -sX -p 1-1000 10.0.0.57.2 What they're for, and their big limitation
The point of flag scans is firewall/IDS evasion: a stateless packet filter configured to block SYN packets may let a lone FIN through, and older IDS signatures keyed on SYN scans miss them. They can also slip past some non-stateful ACLs.
Their limitation is fatal on modern targets: they rely on strict RFC-793 compliance, and Windows (and many modern stacks, CISCO devices, some firewalls) send RST for both open and closed ports, breaking the technique — everything comes back closed. So flag scans are mainly useful against older Unix-like stacks and specific stateless-filter situations. They also can never distinguish open from filtered (both are silent), so they yield open|filtered, not open.
CTF relevance: flag scans occasionally reveal ports on older/Unix CTF targets that a SYN scan shows as filtered, and knowing the RFC-793 behaviour is a common exam/interview question. On a real modern estate they're a situational tool, not a default.
Part 8: ACK, Window and Maimon Scans (-sA, -sW, -sM) — Mapping Firewalls
These scans don't primarily find open ports — they map firewall rules, telling you whether a port is filtered rather than open/closed.
8.1 ACK scan (-sA)
sudo nmap -sA -p 1-1000 10.0.0.5Sends a bare ACK. The logic:
- A live host (open or closed port) replies RST to an unexpected ACK → Nmap marks it
unfiltered(reachable; can't tell open from closed). - A stateful firewall that drops out-of-state packets returns nothing (or ICMP admin-prohibited) →
filtered.
So -sA answers a different question: "is there a stateful firewall in front of this port?" Run it alongside a SYN scan to distinguish "no firewall, port closed" from "firewall dropping the probe". This is invaluable for understanding a perimeter.
8.2 Window scan (-sW)
-sW is an ACK scan that additionally inspects the TCP window field of the returned RST. On some (older) systems, open ports return a RST with a non-zero window and closed ports a zero window — occasionally letting -sW distinguish open from closed where -sA cannot. It's unreliable across modern stacks; treat any positive result as a lead to verify.
8.3 Maimon scan (-sM)
-sM (named for Uriel Maimon) sends a FIN/ACK. Per RFC 793 the target should RST regardless of state, but some BSD-derived stacks drop the packet for open ports — leaking open ports on those specific systems. Like -sW, it's a niche tool for particular stacks.
8.5 Idle (zombie) scan (-sI) — scanning without your IP touching the target
The idle scan is Nmap's most elegant technique: it port-scans a target without ever sending a packet from your own address to it, by bouncing probes off a third "zombie" host and inferring results from the zombie's IP ID counter.
sequenceDiagram
participant A as Attacker
participant Z as Zombie (idle host)
participant T as Target
A->>Z: probe, read IP ID (say 1000)
A->>T: SYN spoofed as coming FROM Z
Note over T,Z: If port OPEN: T sends SYN/ACK to Z;<br/>Z replies RST -> Z's IP ID increments
A->>Z: probe again, read IP ID
Note over A,Z: ID jumped by 2 = port OPEN;<br/>jumped by 1 = port closed/filtered
sudo nmap -sI zombie_ip:port target_ip -Pn -p 1-1000It works only if the zombie is truly idle (predictable, incrementing IP ID — increasingly rare on modern OSes that randomise IP IDs) and reachable. Its payoff is total source anonymity toward the target and the ability to test trust relationships (scan the target as if you were the zombie, bypassing IP-based ACLs that trust the zombie). It's slow and finicky, but conceptually important and a favourite exam/interview topic.
Red team usage: where an internal host is trusted by a target's firewall, an idle scan through that host can reveal ports your own source could never reach — a trust-relationship probe with no direct attribution.
8.6 IP protocol scan (-sO) and FTP bounce (-b)
Two more specialised scans round out the family:
-sO(IP protocol scan) doesn't scan ports — it discovers which IP protocols (TCP=6, UDP=17, ICMP=1, GRE=47, ESP=50, etc.) a host supports, by sending bare IP packets for each protocol number and watching for ICMP protocol-unreachable. Useful for finding tunnelling/VPN protocols (GRE, ESP) on routers and gateways.
sudo nmap -sO 10.0.0.1 # which IP protocols does this gateway speak?-b(FTP bounce) abuses the old FTPPORTcommand to make a misconfigured FTP server scan a third host on your behalf. Almost every modern FTP server disables it, so it's historical — but it's the ancestor of the idle scan's "scan via a proxy host" idea and still appears in CTFs and exams.
8.4 How they fit together
flowchart TD
A[Want to know...] --> B{Question}
B -->|Is the port open?| C[-sS / -sT / -sU]
B -->|Is there a stateful firewall?| D[-sA -> filtered vs unfiltered]
B -->|Evade a SYN-blocking stateless filter?| E[-sF / -sN / -sX]
B -->|Squeeze open/closed from a quirky stack?| F[-sW / -sM]
The professional pattern: -sS (or -sT) to find open ports, -sA to understand the firewall in front of them. The exotic scans are situational supplements, not replacements.
Part 9: UDP Scan (-sU) — The Neglected Half of the Attack Surface
Most scanning focuses on TCP, but critical services run on UDP: DNS (53), SNMP (161), DHCP (67/68), NTP (123), TFTP (69), IKE/VPN (500), NetBIOS (137), and many game/IoT protocols. Skipping UDP misses entire attack paths — SNMP with a default community string alone can dump a device's whole configuration.
9.1 Why UDP scanning is hard
UDP is connectionless — there's no handshake. The classification logic:
- Closed port → ICMP port-unreachable (type 3, code 3) →
closed. - Open port → usually silence (the service got a datagram it didn't understand and stayed quiet) →
open|filtered. - Open port that does reply (a real UDP response) →
open. - Filtered → silence →
open|filtered(indistinguishable from the silent-open case).
So a bare UDP scan produces mostly open|filtered — unhelpful. Worse, hosts rate-limit ICMP unreachables (Linux caps them at ~1/second by default), which makes UDP scanning extremely slow: Nmap must wait for each possible reply, and a full 65535-port UDP scan can take many hours.
9.1b High-value UDP services worth the wait
| Port | Service | Why it matters |
|---|---|---|
| 53 | DNS | Zone transfers, cache snooping, version.bind |
| 67/68 | DHCP | Network layout, rogue-DHCP potential |
| 69 | TFTP | Often unauthenticated config/firmware transfer |
| 123 | NTP | monlist amplification, host enumeration |
| 137/138 | NetBIOS | Names, shares, domain info on Windows |
| 161/162 | SNMP | Community-string config dump — a top easy win |
| 500/4500 | IKE/IPsec | VPN endpoints, aggressive-mode PSK capture |
| 1900 | SSDP/UPnP | Device enumeration, amplification |
| 5353 | mDNS | Hostnames, services on the segment |
These are the ports to feed -sU -sV. Each has protocol-specific NSE scripts (Chapter 3) that turn "open" into real data — snmp-info, dns-zone-transfer, ntp-monlist, ike-version.
9.2 Making UDP scanning useful
The fix is version detection with protocol-specific payloads: instead of an empty datagram, send a probe the service will actually answer (a real DNS query to 53, an SNMP get to 161), which turns open|filtered into a definitive open with a service banner.
# targeted UDP scan of the common UDP services WITH version probes — the practical approach
sudo nmap -sU -sV --top-ports 20 10.0.0.5
# specific high-value UDP ports
sudo nmap -sU -sV -p 53,67,123,161,500,137,138,69 10.0.0.5
# combine with a fast TCP SYN scan in one run
sudo nmap -sS -sU -p T:1-1000,U:53,161,123,500 10.0.0.5Practical rules for UDP:
- Never run
-sU -p-across many hosts as a first move — it's punishingly slow. Scan the top ~20–50 UDP ports with-sV. - Add
--version-intensityand accept UDP takes far longer than TCP. - Pair UDP with TCP in a single command (
-p T:...,U:...) so you cover both halves of the surface.
Bug bounty / red team relevance: exposed SNMP (161/udp) with public/private community strings is a recurring high-impact finding — it can leak full device configs, credentials and routing. UDP is where a lot of easy wins hide precisely because so many testers skip it.
Blue team usage: because UDP scans are slow and rate-limited, a sustained trickle of UDP probes to closed ports (triggering ICMP-unreachable floods) is both detectable and a sign someone is doing the thorough work most attackers skip — monitor for it.
Part 10: Choosing a Scan Type — The Decision Framework
Put it together. Given a situation, which scan?
| Situation | Scan | Why |
|---|---|---|
| Default, running as root | -sS |
Fast, clean states, avoids app logs |
| Not root / through a proxy | -sT |
Only option; traverses SOCKS |
| Need UDP services | -sU -sV (targeted) |
UDP surface; version probes disambiguate |
| Map the firewall | -sA |
filtered vs unfiltered |
| Evade a stateless SYN-blocking filter | -sF/-sN/-sX |
Lone FIN may pass; RFC-793 trick |
| Quirky/old stack hiding ports | -sW/-sM |
Stack-specific leaks |
| Maximum thoroughness | -sS -sU -p- |
Everything, both protocols (slow) |
| Maximum stealth | -sS -T1 -D... -f small batches |
Slow, decoyed, fragmented |
| Zero source attribution to target | -sI zombie target |
Bounces off an idle zombie host |
| Discover IP protocols on a gateway | -sO |
GRE/ESP/ICMP support, not ports |
The everyday professional command is a targeted combination, not a single exotic scan:
sudo nmap -sS -sV -p- -T4 --reason -oA full_tcp 10.0.0.5 # thorough TCP with versions
sudo nmap -sU -sV --top-ports 25 -T4 -oA top_udp 10.0.0.5 # practical UDP pass10.0b Scan ordering and parallelism (a preview)
How Nmap sequences probes affects both speed and stealth; timing is Chapter 3's topic, but two facts matter now:
| Concern | Lever | Effect |
|---|---|---|
| Too slow on big scope | --min-rate, -T4 |
Forces throughput |
| Too loud / fragile host | -T2/-T1, --max-rate |
Spreads probes, gentler |
| One host stalls the scan | --host-timeout |
Abandons black-hole hosts |
| Randomise target order | --randomize-hosts |
Less obvious sequential sweep |
A common mistake is a -p- -sU scan across a /24 with default timing that runs for a day; the fix (targeted ports, -T4, splitting TCP/UDP) is methodology, not a single flag. Chapter 3 covers the full timing model.
10.1 Fragmentation and other packet tricks (-f, --mtu)
For authorised evasion, -f fragments probe packets into tiny IP fragments to slip past simple packet inspection; --mtu sets a custom fragment size; --data-length pads packets to look less like scans. These are supplements to the timing/decoy techniques from Chapter 1, and like those they matter only in evasion-in-scope engagements.
sudo nmap -sS -f -p 80,443 10.0.0.5 # fragment probes
sudo nmap -sS --data-length 25 10.0.0.5 # pad to disguisePart 11: Hands-On Lab — Every Scan Type, Watched on the Wire
Run against scanme.nmap.org (Nmap's legal practice host, gently) or, better, your own VM lab so you can capture packets on both ends. Never against hosts you don't own or aren't authorised to scan.
11.1 Setup
sudo apt update && sudo apt install -y nmap tcpdump
nmap --version | head -1
# a safe target VM on your lab subnet, e.g. 192.168.56.20 running some services
TARGET=192.168.56.20; IFACE=eth011.2 Watch the packets while you scan
# terminal 1 — capture the scan traffic
sudo tcpdump -i $IFACE -n "host $TARGET and (tcp or udp or icmp)"
# terminal 2 — run each scan and read terminal 111.3 Connect vs SYN — see the difference
sudo nmap -sT -p 22,80,443 --reason $TARGETtcpdump shows the full handshake on open ports (SYN, SYN/ACK, ACK, then teardown):
IP scanner.55123 > target.80: Flags [S]
IP target.80 > scanner.55123: Flags [S.]
IP scanner.55123 > target.80: Flags [.] <- ACK: handshake COMPLETED (-sT)
IP scanner.55123 > target.80: Flags [R.] <- teardown
sudo nmap -sS -p 22,80,443 --reason $TARGETtcpdump shows the half-open pattern — the ACK never comes; Nmap RSTs instead:
IP scanner.55124 > target.80: Flags [S]
IP target.80 > scanner.55124: Flags [S.]
IP scanner.55124 > target.80: Flags [R] <- RST, no ACK: handshake ABORTED (-sS)
Seeing those two captures side by side is the single clearest way to understand why -sS avoids application logs and -sT doesn't.
11.4 Closed vs filtered
sudo nmap -sS -p 22,81,443 --reason $TARGETPORT STATE SERVICE REASON
22/tcp open ssh syn-ack
81/tcp closed hosts2-ns reset <- got a RST: reachable, nothing listening
443/tcp open https syn-ack
Now add a firewall rule on the target to DROP port 81 and re-scan — its state flips from closed to filtered (reset → no-response):
# on target: sudo iptables -A INPUT -p tcp --dport 81 -j DROP
sudo nmap -sS -p 81 --reason $TARGET
# 81/tcp filtered ... no-response <- the firewall swallowed the probeThis reproduces the exact distinction between closed (RST) and filtered (silence) that Part 1's state table describes.
11.5 Flag scan behaviour
sudo nmap -sF -p 22,81,443 --reason $TARGET # against a Linux targetOn an RFC-793-compliant Linux host, open ports show open|filtered (silence) and closed ports closed (RST). Run the same -sF against a Windows VM and note that everything comes back closed — the concrete demonstration of the flag-scan limitation from Part 7.
11.6 ACK scan — firewall mapping
sudo nmap -sA -p 22,81,443 --reason $TARGET22/tcp unfiltered ssh reset <- RST back = no stateful firewall on this port
81/tcp filtered ... no-response <- dropped = stateful firewall in front
-sA didn't tell you open/closed — it told you where the firewall is, which is its job.
11.7 UDP
sudo nmap -sU -sV -p 53,161,123 --reason $TARGETObserve how much slower UDP is, how closed ports produce ICMP unreachables in tcpdump, and how -sV's protocol probes turn a silent open port into a named service. If the target runs DNS on 53, you'll get open with a version string rather than open|filtered.
11.8 Save it properly
sudo nmap -sS -sV -p- -T4 --reason -oA lab_full_tcp $TARGET
ls lab_full_tcp.* # .nmap (human), .gnmap (grep), .xml (machine)
grep open lab_full_tcp.gnmaplab_full_tcp.* is your reproducible record and the input to service enumeration in later chapters.
11.9 Bonus — protocol scan and reading --packet-trace
sudo nmap -sO 192.168.56.20 # which IP protocols does the host speak?
sudo nmap -sS -p 22 --packet-trace 192.168.56.20 | head--packet-trace prints each probe and reply inline, e.g.:
SENT (0.0021s) TCP 192.168.56.10:55201 > 192.168.56.20:22 S ttl=...
RCVD (0.0025s) TCP 192.168.56.20:22 > 192.168.56.10:55201 SA ttl=64
Reading SENT ... S (your SYN) then RCVD ... SA (the target's SYN/ACK) is the same evidence tcpdump gave you, but produced by Nmap itself — the fastest way to confirm exactly what a scan did without a second tool.
Part 12: Reading and Saving Output
12.1 The output formats
sudo nmap -sS -sV 10.0.0.5 -oN scan.nmap # normal (human-readable)
sudo nmap -sS -sV 10.0.0.5 -oG scan.gnmap # greppable (one host per line)
sudo nmap -sS -sV 10.0.0.5 -oX scan.xml # XML (for tools/parsers)
sudo nmap -sS -sV 10.0.0.5 -oA scan # ALL THREE at once (base name "scan")Always use -oA. You get the human view for reading, the greppable view for quick extraction, and the XML for tooling — for the cost of one flag. Losing scan output means re-scanning, which wastes time and adds noise.
12.2 Extracting from output
# open ports per host from greppable output
grep -oP '\d+/open' scan.gnmap
awk '/Ports:/{print $2, $0}' scan.gnmap
# hosts with a specific open port
grep "443/open" scan.gnmap | awk '{print $2}'
# XML -> anything, via the xml or with tools like `nmap-parse-output`
xmllint --xpath '//port[state/@state="open"]/@portid' scan.xml 2>/dev/null12.3 Diffing scans with ndiff
sudo nmap -sS -oX before.xml 10.0.0.0/24
# ...later...
sudo nmap -sS -oX after.xml 10.0.0.0/24
ndiff before.xml after.xml # what changed: new hosts, new open portsndiff turns Nmap into a change-monitoring system — the same diff-and-alert pattern as the recon pipeline in the previous notebook. A newly-open port on a production host is exactly what a blue team wants paged.
12.4 Verbosity and debugging
sudo nmap -sS -v 10.0.0.5 # verbose (progress, findings as they happen)
sudo nmap -sS -vv 10.0.0.5 # more verbose
sudo nmap -sS -d 10.0.0.5 # debug (packet-level detail)
sudo nmap -sS --packet-trace 10.0.0.5 # show every packet sent/received--packet-trace is the learning superpower — it prints every probe and response inline, so you can watch the scan logic without a separate tcpdump.
12.5 Turning output into a working list
# every open port:service pair across all hosts (greppable)
awk -F'\t' '/Ports:/{print $1}' scan.gnmap # host + ports blob
# just hosts running SMB (445 open) -> feed to the SMB-enum chapter
grep -E "445/open" scan.gnmap | awk '{print $2}' > smb_hosts.txt
# web hosts (80/443/8080/8443 open) -> feed to web tooling / httpx
grep -oP "\d+\.\d+\.\d+\.\d+" <(grep -E "(80|443|8080|8443)/open" scan.gnmap) | sort -u > web_hosts.txt
# open ports as CSV from XML
xmllint --xpath '//host[status/@state="up"]' scan.xml 2>/dev/null | \
grep -oP 'addr="\K[0-9.]+|portid="\K\d+'The pattern is always the same: scan once with -oA, then slice the greppable/XML output into per-service target lists that feed the enumeration chapters. This is the join between scanning and the rest of the engagement — smb_hosts.txt, web_hosts.txt, ssh_hosts.txt become the inputs to everything that follows.
Part 13: Detection, Defense, OPSEC and Scope
13.1 How scans are detected
- Connect scans (
-sT) appear in application logs as real, immediately-closed connections across many ports — the easiest to catch. - SYN scans (
-sS) are caught at the network layer by the half-open/fan-out pattern (IDS/IPS, firewall scan-detection, NetFlow), even though apps don't log them. - Flag/ACK/UDP scans use unusual packets (lone FIN, out-of-state ACK, UDP to closed ports) that legitimate traffic rarely produces — signatures key on exactly these.
- Volume and rate are the giveaway for all of them: one source touching many ports/hosts quickly.
13.2 Defending
- IDS/IPS (Suricata, Zeek) with scan-detection rules; firewall scan throttling; rate-limits; tarpits (e.g. an iptables tarpit that holds scanner connections open to slow them). Alert on the fan-out signature above all.
- Minimise the surface: close unused ports, filter at the perimeter, and run your own Nmap scans regularly (with
ndiff) so you know your exposure before an attacker maps it. - Understand the limits of "stealth":
-sSavoids app logs, not network sensors — don't assume a quiet host means an undetected scan.
13.3 OPSEC and scope
- Authorisation is mandatory and per-target. Active scanning of hosts outside your written scope is unlawful;
--exclude/--excludefileare scope controls, not conveniences. - Fragile hosts. Aggressive scans (
-T5,-p-, high parallelism) can crash embedded/ICS/medical/legacy devices. Drop to polite timing and confirm which ranges are fragile before scanning them. - Never
-iR(random internet hosts) — those are real, unauthorised systems. - Data handling. Scan output maps a client's estate — store it encrypted and dispose of it per the engagement terms.
CTF relevance: almost every box starts with sudo nmap -sS -sV -p- -oA nmap/initial <ip> (often -Pn, since CTF targets frequently filter ICMP). The full-port scan matters — CTF authors love hiding the intended service on a high, non-default port that --top-ports would miss.
13.4 A concrete detection signature
What distinguishes each scan to a defender is the packet shape and volume. A simple layered detection:
# half-open (SYN scan): many SYNs with no completing ACK from one source
IF count(SYN without matching ACK) BY src > 50 WITHIN 30s -> "SYN scan"
# connect scan: many complete-then-immediately-close connections
IF count(established+closed < 1s) BY src, across >20 dst_ports -> "connect scan"
# flag/UDP scan: unusual packets legit traffic rarely sends
IF seen(FIN-only | NULL | Xmas | ACK-to-closed | UDP-to-many-closed) -> "exotic scan"
The fan-out (one source, many destinations/ports, little data per flow) is the common thread across all of them and the highest-value single rule. This is why a red-team operator spreads probes over time and sources — and why, in a standard assessment where detection is expected, none of it needs hiding.
Part 14: Common Pitfalls
- Scanning
-p 1-1000and thinking it's "the top 1000". It's the first 1000 numerically and misses 1433, 3389, 8080, 8443. Use--top-portsor-p-. - Forgetting
-p-on CTFs / thorough tests. The one open port is on 31337. Default top-1000 misses it. - Running unprivileged and wondering why
-sSfails. No root = connect scan only. Usesudo. - Skipping UDP entirely. Half the easy wins (SNMP, DNS, TFTP) are UDP. Do a targeted
-sU -sVpass. - Bare
-sU -p-across many hosts. Punishingly slow due to ICMP rate-limiting. Target top UDP ports. - Trusting flag scans on modern/Windows targets. They report everything
closedthere. Situational only. - Reading
open|filteredas "open". It means the probe couldn't disambiguate — resolve with a different scan (-sV,-sA). - Not saving output (
-oA). Lose the record, re-scan, add noise. - Assuming
-sSis invisible. It avoids app logs, not network detection. - Aggressive timing on fragile hosts.
-T5 -p-can knock over embedded devices. Match timing to the environment. - Ignoring
--reason. It turns every state into evidence — indispensable when a result surprises you. - Confusing
-snand-Pn.-sn= discovery only (no port scan);-Pn= port scan only (no discovery). Mixing them up either skips the scan or skips discovery. - Leaving
-Pnoff against a ping-filtering host so the scan finds nothing because the host "looked down" — the classic cause of an empty result on a live target.
Part 15: Practice Labs & Resources
- scanme.nmap.org — the Nmap project's legal-to-scan host; run each scan type gently and read the results.
- Your own VM lab — the correct place for the packet-capture lab (Part 11); you control both ends.
- TryHackMe — "Nmap" module ("Nmap Basic Port Scans", "Nmap Advanced Port Scans", "Nmap Post Port Scans") — drills exactly this chapter's scan types and flags, room by room.
- HackTheBox — Starting Point + easy boxes — practise the standard
-sS -sV -p- -Pnopening and full-port discipline. - PortSwigger / OWASP targets — for what to do with the web ports Nmap finds (feeds later web chapters).
- "Nmap Network Scanning" by Fyodor — the authoritative book; the port-scanning-techniques chapters are the definitive reference for every
-s*scan and the RFC-793 logic. - The official
man nmapand https://nmap.org/book/ — free, complete, and worth reading end to end.
Memory Hooks
-sS= SYN/half-open, the root default — fast, avoids app logs, clean states.-sT= full connect — unprivileged/proxy only, slower, gets logged by apps.-sU= UDP — slow, mostlyopen|filtered; always add-sVand target top ports.-sF/-sN/-sX= RFC-793 flag scans — evade stateless SYN filters; break on Windows (allclosed).-sA= firewall map — filtered vs unfiltered, not open vs closed.- 6 states: open, closed, filtered, unfiltered, open|filtered, closed|filtered — the either/ors mean "this probe can't tell".
- Any reply classifies; silence is ambiguous. Resolve
open|filteredwith a different scan. - Default = top 1000, NOT 1-1000.
-p-for all;--top-ports/-Ffor speed. - Root or nothing — unprivileged silently downgrades to connect scans.
-oAalways;--reasonwhen surprised;--packet-traceto learn.
Final Revision / Summary
This chapter taught Nmap from zero through the complete family of scan types. Part 1 explained Nmap's architecture (target generation → packet engine → response classifier, with discovery/version/OS/NSE layered on), the decisive privileged-vs-unprivileged switch (root → SYN default and full capability; unprivileged → connect only), and the six port states that every result reduces to — including why the "either/or" states (open|filtered, closed|filtered) are honest reporting that a given probe can't disambiguate. Parts 2–3 covered installation (Kali, source, the capability implications of the build) and command fluency: target specification (-iL, CIDR, --exclude, and never -iR), the anatomy of a command, and port selection (the critical difference between the default top-1000 and a numeric 1-1000).
Part 4 grounded everything in the TCP handshake and the RFC-793 out-of-state rules. Parts 5–9 then taught each scan at the packet level: connect (-sT, full handshake, logged, proxy-capable), SYN (-sS, half-open, the fast log-avoiding default), the flag scans (-sF/-sN/-sX, RFC-793 evasion that breaks on modern/Windows stacks), the firewall-mapping scans (-sA unfiltered-vs-filtered, plus the niche -sW/-sM), and UDP (-sU, why it's slow and mostly open|filtered, and how -sV protocol probes make it useful — with SNMP as the headline easy win). Part 10 tied them into a decision framework and added fragmentation/padding evasion. Parts 11–12 put it on the wire — a packet-capture lab showing connect-vs-SYN, closed-vs-filtered, the flag-scan limitation, ACK firewall-mapping and UDP — and covered output (-oA always, ndiff for change monitoring, --packet-trace for learning). Parts 13–15 handled detection/defense, OPSEC/scope, pitfalls and practice.
You can now choose and justify the right scan for any host-and-firewall situation, read every state as a deduction from a packet, and produce saved, reproducible results. What you cannot yet do is reliably identify what is running on an open port and which OS underlies it, tune timing for large scopes, or automate checks with scripts. That is exactly the next chapter — Nmap Part 2: service/version detection (-sV), OS detection (-O), timing and performance, the Nmap Scripting Engine (NSE), and output/reporting at depth — which turns "port 443 is open" into "nginx 1.18.0 on Ubuntu, with these three NSE findings".
Cheat Sheet / Quick Reference
# ---- SCAN TYPES ----
sudo nmap -sS ... # SYN / half-open (root default; fast; avoids app logs)
nmap -sT ... # TCP connect (unprivileged/proxy; full handshake; logged)
sudo nmap -sU ... # UDP (slow; add -sV; target top ports)
sudo nmap -sF/-sN/-sX ... # FIN / NULL / Xmas (RFC-793 evasion; break on Windows)
sudo nmap -sA ... # ACK (firewall map: filtered vs unfiltered)
sudo nmap -sW/-sM ... # Window / Maimon (niche stack leaks)
# ---- TARGETS & PORTS ----
-iL targets.txt # from file (usual) 10.0.0.0/24 10.0.0.1-50 10.0.0.*
--exclude / --excludefile # scope exclusions (never -iR = random internet hosts)
-p 22,80,443 -p- (all 65535) -p U:53,T:80 --top-ports 100 -F (top 100)
# DEFAULT = top 1000 (NOT 1-1000)
# ---- COMMON REAL COMMANDS ----
sudo nmap -sS -sV -p- -T4 --reason -oA full_tcp -iL targets.txt # thorough TCP
sudo nmap -sU -sV --top-ports 25 -T4 -oA top_udp <ip> # practical UDP
sudo nmap -sS -sA -p- <ip> # ports + firewall map
sudo nmap -sS -Pn -p- <ip> # CTF opener (skips discovery)
# ---- 6 STATES ----
open | closed | filtered | unfiltered | open|filtered | closed|filtered
# any reply -> classified ; silence -> ambiguous ; resolve open|filtered with -sV/-sA
# ---- OUTPUT / DIAGNOSE ----
-oA base # .nmap/.gnmap/.xml (ALWAYS)
--reason # why each state --packet-trace # every packet (learn)
-v/-vv/-d # verbosity/debug
ndiff before.xml after.xml # change monitoring
# ---- EVASION (authorised) ----
-T0/-T1 -D decoy1,decoy2,ME -f --data-length N --source-port 53The one rule: pick the scan that answers your question — -sS/-sT/-sU for "is it open?", -sA for "is there a firewall?", flag scans for "can I evade this filter?" — and read every state as a deduction from a packet.
Practice Questions & Labs
- SYN vs connect. Explain, at the packet level, exactly how
-sSand-sTdiffer and why-sS"avoids application logs" while-sTdoes not. In which two situations must you use-sTeven though-sSis available, and why? - State reasoning. For each result, state what packet Nmap saw and what it means:
80/tcp open,81/tcp closed,82/tcp filtered,161/udp open|filtered. Then explain how you'd resolve theopen|filteredinto a definite state. - Flag-scan limits. Describe the RFC-793 behaviour that makes
-sF/-sN/-sXwork, then explain precisely why they return every port asclosedagainst a Windows target. Give one real situation where a flag scan still adds value over-sS. - UDP done right. Why does a bare
-sUscan produce mostlyopen|filtered, and why is-sU -p-across a subnet a bad idea? Write the command you'd actually run to enumerate UDP services efficiently, and name the single UDP service whose exposure most often yields an easy high-impact finding. - Full lab (hands-on). On a VM you own, capture packets while running
-sT,-sS,-sFand-sAagainst the same host. Produce the tcpdump excerpts that prove: the connect handshake completes but the SYN scan aborts with RST; a closed port RSTs while a firewalled port is silent; and the ACK scan reportsunfiltered/filteredrather than open/closed. Save everything with-oAand write two sentences on how each scan would appear to a defender.