Andrew Mercer
on this page

References

  • https://nmap.org/nsedoc/scripts/dhcp-discover.html
  • man nmap, nmap --script-help all for the full NSE catalog

1. Scan types — what's actually happening on the wire

Flag Scan Mechanism Needs root?
-sS TCP SYN scan ("half-open") sends SYN, reads SYN/ACK or RST, never completes handshake yes
-sT TCP connect scan full 3-way handshake via the OS socket API no
-sU UDP scan sends UDP probe, absence of ICMP unreachable ⇒ open filtered
-sA ACK scan maps firewall rulesets (stateless firewalls only) yes
-sN/-sF/-sX Null/FIN/Xmas scans abuse RFC-compliant TCP stacks to slip past simple packet filters yes
-sP / -sn Ping/host-discovery only, no port scan ARP (local) or ICMP/TCP probes (remote) no (varies)
-sV Version detection grabs banners / sends protocol probes against open ports no
-O OS fingerprinting analyzes TCP/IP stack quirks (window size, TTL, options ordering) yes

-sS is nmap's default when run as root because it's fast and doesn't complete connections (less logging on the target, lower overhead at scale). Without root, nmap silently falls back to -sT.

2. Your notes, expanded

Scan a subnet for an open port

nmap -p22 --open 192.168.0.0/24

--open suppresses closed/filtered hosts from the output — essential on a /24 or you'll drown in noise. Add -T4 for faster timing on a LAN, and --min-rate 500 to force a floor on packets/sec if nmap's adaptive timing is being too conservative:

nmap -p22 --open -T4 --min-rate 500 192.168.0.0/24

DHCP server discovery without taking an IP

nmap -sU -p 67 --script=dhcp-discover 192.168.0.1
PORT   STATE SERVICE
67/udp open  dhcps
| dhcp-discover:
|   DHCP Message Type: DHCPACK
|   Server Identifier: 192.168.0.1
|   Subnet Mask: 255.255.255.0
|   Broadcast Address: 192.168.0.255
|   Domain Name Server: 192.168.0.1, 192.168.0.1
|_  Router: 192.168.0.1

This is an NSE (Nmap Scripting Engine) script — it crafts a real DHCPDISCOVER, parses the DHCPOFFER/ACK, and reports the lease parameters without actually completing a lease (no IP is consumed/bound). Genuinely useful for finding rogue DHCP servers on a network — run it broadcast-style against the whole subnet:

nmap -sU -p 67 --script=dhcp-discover 192.168.0.255   # broadcast address — surfaces every DHCP server that answers

Host discovery (subnet sweep)

nmap -sP 192.168.13.0/24

Note: -sP is deprecated in modern nmap in favor of -sn (same behavior, "no port scan"). On a local subnet this uses ARP requests, not ICMP, so it works even against hosts that firewall off ping.

UDP version scan

nmap -sUV <host>

UDP scanning is inherently slow and unreliable (no handshake, and many stacks rate-limit the ICMP "port unreachable" responses nmap relies on to infer closed ports) — expect this to take much longer than an equivalent TCP scan, and expect a lot of open|filtered results that need manual verification (see §4).

Service/version detection

nmap -sV home.andrewmercer.net

-sV sends nmap's probe database against each open port and pattern-matches the response — this is how it distinguishes "OpenSSH 8.9" from "some other thing on port 22." Bump intensity if it's not confident:

nmap -sV --version-intensity 9 home.andrewmercer.net   # 0 (light) - 9 (try everything)

OS fingerprinting

nmap -O <host>

Needs at least one open and one closed/filtered TCP port on the target to fingerprint reliably; combine with -sV for nmap's overall best-guess ("OS and Service detection performed"):

nmap -A <host>     # equivalent to -sV -O --script=default --traceroute, nmap's "give me everything" flag

Logging — all formats at once

nmap -sP 192.168.13.0/24 -oA network-192.168.13

Produces network-192.168.13.nmap (human-readable), .gnmap (grep-friendly, one host per line — great for grep/awk pipelines), and .xml (machine-readable, feeds into other tools). If you only need one:

nmap ... -oN scan.nmap     # normal
nmap ... -oG scan.gnmap    # grepable
nmap ... -oX scan.xml      # XML

Turn XML into an HTML report with the bundled XSL stylesheet:

xsltproc scan.xml -o scan.html

Reason codes

nmap -sV --reason 23.233.1.230
PORT     STATE    SERVICE      REASON      VERSION
135/tcp  filtered msrpc        no-response
9999/tcp open     ssh          syn-ack     OpenSSH 6.6.1 (protocol 2.0)

--reason shows why nmap classified a port the way it did — no-response (filtered, likely a firewall dropping silently), conn-refused (closed, RST received), syn-ack (open). This is the difference between "the port is closed" and "something is silently eating my probes" — worth turning on by default when triaging a firewall.

3. Advanced techniques not in your notes

Timing templates (speed vs. stealth)

nmap -T0   # paranoid — 5min between probes, IDS evasion
nmap -T1   # sneaky
nmap -T2   # polite — reduces load on the target/network
nmap -T3   # normal (default)
nmap -T4   # aggressive — assumes a reliable fast network, good for internal LANs/homelab
nmap -T5   # insane — fastest, sacrifices accuracy

Firewall/IDS evasion

nmap -f <host>                         # fragment packets
nmap -D RND:10 <host>                  # decoy scan — spoof 10 random source IPs alongside yours
nmap --source-port 53 <host>           # spoof source port (some firewalls trust traffic "from" DNS)
nmap -sA <host>                        # ACK scan to map stateless firewall rules

Full-range / specific port sets

nmap -p- <host>                        # all 65535 ports
nmap -p 1-1024,8080,8443 <host>        # custom ranges + individual ports
nmap -F <host>                         # nmap-services "fast" list (~100 most common ports)
--top-ports 20                         # just the N most common ports

NSE — the real power of nmap

The scripting engine (--script) is where nmap goes from "port scanner" to "vulnerability/recon framework." Categories: auth, broadcast, brute, default, discovery, dos, exploit, external, fuzzer, intrusive, malware, safe, version, vuln.

nmap --script=default <host>                      # the scripts -A runs
nmap --script=vuln <host>                         # check for known CVEs against detected services
nmap --script=http-title,http-headers <host> -p80  # quick web recon
nmap --script=ssl-enum-ciphers -p443 <host>        # enumerate supported TLS ciphers/protocol versions
nmap --script=smb-vuln* -p445 <host>               # SMB vulnerability checks
nmap --script-help ssl-enum-ciphers               # see what any script actually does before running it

Kubernetes / homelab-relevant scanning

# Sweep a k8s node's pod CIDR for anything listening (useful when a Service isn't routing as expected)
nmap -sn 10.244.1.0/24

# From inside the cluster (a debug pod) since nodes often can't reach pod IPs directly depending on CNI:
kubectl run nmap --rm -it --image=instrumentisto/nmap -- nmap -sV -p 1-65535 target-service.default.svc.cluster.local

Rate control for shared/production networks

nmap --max-rate 50 --scan-delay 100ms <target>   # be gentle — avoid tripping IDS or overloading old gear

Idle/zombie scan (advanced, situational)

nmap -sI zombie_host:port target

Uses a third "zombie" host's IP-ID sequence to scan a target without ever sending a packet with your own source IP — mostly of academic/red-team interest now since it requires an increasingly rare kind of predictable IP-ID stack.

4. Interpreting results correctly

  • open — something is actively listening and responded.
  • closed — reachable, but nothing listening (RST received on TCP).
  • filtered — nmap can't tell if it's open or closed; a firewall/ACL is dropping probes silently. Combine with --reason and try a different scan type (-sA, fragment with -f) to get more signal.
  • open|filtered — typical UDP result; no response could mean open-and-silent, or filtered. Try -sV on that specific port for a protocol-aware probe, or fall back to an application-level test (e.g. nc -u sending an actual expected payload, or a protocol-specific NSE script).
  • unfiltered (ACK scan only) — reachable, but state (open/closed) unknown.

5. Quick cheat sheet

nmap -sn 192.168.1.0/24                       # host discovery only
nmap -p22 --open 192.168.1.0/24               # find one open port across a subnet
nmap -sV -sC <host>                           # version detection + default safe scripts
nmap -A <host>                                # everything: OS, version, scripts, traceroute
nmap -p- -T4 <host>                           # full port range, fast
nmap --script=vuln <host>                     # known-CVE check
nmap -oA report <host>                        # log to .nmap/.gnmap/.xml simultaneously
nmap -sU -p 67 --script=dhcp-discover <host>  # find DHCP servers safely