Nmap -- short for Network Mapper -- has been the standard tool for network discovery and security auditing since Gordon "Fyodor" Lyon first published it in Phrack Magazine Issue 51 ("The Art of Port Scanning") on September 1, 1997. In the preface to the official Nmap Network Scanning book (nmap.org/book), Lyon describes his original intent: to "consolidate the fragmented field of special-purpose port scanners into one powerful and flexible free tool, providing a consistent interface and efficient implementation." Nearly three decades later, it remains one of the first tools installed on any penetration testing distribution, any security analyst's workstation, and many a sysadmin's laptop. The latest stable release, Nmap 7.99 (March 26, 2026), fixed a reverse-DNS performance regression introduced in 7.98, resolved a macOS MAC address reporting issue, added support for VPN virtual adapters on Windows, and upgraded Npcap from 1.83 to 1.87. Before that, Nmap 7.98 (August 21, 2025) rebuilt the Windows installer against NSIS 3.11 to address CVE-2025-43715, and Nmap 7.97 (May 12, 2025) delivered additional stability fixes shortly after 7.96. Earlier in 2025, Nmap 7.96 (May 1) introduced parallel forward DNS resolution — a change that reduced the time to resolve one million website names to both IPv4 and IPv6 addresses from 49 hours to just over one hour, according to the Nmap changelog. All of this is proof of a project that continues active, community-driven development nearly 28 years after its debut.
This guide covers Nmap from the ground up. Whether you are performing your first ping sweep or writing custom NSE scripts for vulnerability detection, you will find concrete commands, explanations of the underlying mechanics, and practical advice for using Nmap responsibly.
What Is Nmap and Why It Matters
At its core, Nmap is an open-source utility for probing networks to discover hosts, identify open ports, determine what services and versions are running on those ports, and fingerprint operating systems. It runs on Linux, macOS, Windows, FreeBSD, and several other platforms, and ships with companion tools including Ncat (a flexible networking utility), Nping (packet generation and response analysis), Ndiff (scan comparison), and Zenmap (a graphical frontend).
"Nmap uses raw IP packets in novel ways to determine what hosts are available."— Gordon Lyon, Nmap Network Scanning (nmap.org/book)
Nmap's value comes from its combination of speed, accuracy, and extensibility. It can scan thousands of ports per second on a fast network, it maintains massive databases for OS and service fingerprinting (with community-contributed submissions continuously expanding coverage), and the Nmap Scripting Engine turns it into a platform that goes far beyond port scanning. Security professionals use it for vulnerability assessments, compliance auditing, network inventory, and incident response triage.
What separates Nmap from simpler port scanners is its scan engine architecture. Rather than firing packets and waiting serially for each response, Nmap uses a parallel, probe-and-timer system that tracks outstanding probes, adjusts retransmission timing based on observed round-trip times, and dynamically scales concurrency based on network conditions. This is why Nmap's -T4 can outperform naive scanners even without a higher rate limit — it wastes fewer cycles on timeouts and retransmits. The timing engine is described in detail in the Nmap official book's chapter on performance, and it is one of the aspects of the tool that most competing scanners have never fully replicated.
One detail worth knowing: the nmap-services file that drives default port selection is not arbitrary. The frequency data it contains was assembled from scanning large portions of the internet over time, and the probabilities it records reflect how often a given port is actually found open — not just whether it is an IANA-assigned port. Port 8080 has a higher open probability than port 8000, for example, which is why it appears in the default top-1000 even though neither has a special status.
Nmap's Licensing: What Commercial Use Actually Means
Nmap is distributed under the Nmap Public Source License (NPSL), version 0.95 as of Nmap 7.93. The NPSL is based on the GPL but contains important additional restrictions on commercial redistribution. The core rule: you can use Nmap freely for any purpose, including commercial security work. What requires a separate license from Insecure.com LLC is redistributing Nmap as part of a commercial product or service — bundling it into a paid scanner, shipping it inside a commercial appliance, or building a commercial SaaS offering on top of it.
For security consultants running Nmap on engagements, pen testers using it in day-to-day work, developers scripting it into internal tooling, and sysadmins running it for network management: all of this is permitted under the NPSL without any additional licensing. The license restrictions apply specifically to commercial redistribution — packaging Nmap inside something you sell. When in doubt, Insecure.com offers a commercial OEM license for vendors who need it. The full license text is at nmap.org/book/man-legal.html.
Where Nmap Fits in a Security Toolkit
Nmap is a discovery and enumeration tool, not an exploitation framework. Its role in a security assessment is to answer: what is here, what is running, and what version? The findings it produces feed into the next layer of tooling — vulnerability scanners like OpenVAS or Tenable Nessus for automated CVE checking, Metasploit for exploitation, Burp Suite for web application testing, or custom scripts for service-specific analysis. Understanding where Nmap ends and the next tool begins prevents both under-use (stopping at port discovery) and over-use (trying to replace a vulnerability scanner with NSE scripts alone).
Always obtain explicit written authorization before scanning any network you do not own. Unauthorized scanning can violate computer fraud and abuse laws in many jurisdictions, even if no damage is caused. Many organizations treat unauthorized port scans as hostile activity and may pursue legal action.
Installing Nmap
Nmap is available in the default repositories of every major Linux distribution, through Homebrew on macOS, and as a standalone installer on Windows. The Windows package bundles Npcap, the packet capture driver that Nmap requires for raw socket operations.
# Debian / Ubuntu $ sudo apt update && sudo apt install nmap # RHEL / Fedora / CentOS $ sudo dnf install nmap # Arch Linux $ sudo pacman -S nmap # macOS (Homebrew) $ brew install nmap # Verify installation $ nmap --version
On Windows, download the installer from nmap.org/download. The installer supports a silent mode (/S) if Npcap is already installed, which helps with automated deployments across fleets of machines. If you need to compile from source, download the tarball from the release archive and follow the standard ./configure && make && sudo make install workflow.
Keeping Nmap and Its Script Database Current
Package manager installs typically lag behind the upstream release by days to months depending on the distribution. If you installed Nmap via apt or dnf several months ago, you may be running a version that lacks recent NSE scripts for newly disclosed CVEs — Nmap 7.96 added MikroTik-targeting scripts, for example, and those are absent from any pre-7.96 install. Check your version with nmap --version and compare to the current release at nmap.org/changelog.html.
Updating the NSE script database separately from Nmap itself is also possible. If you have manually added scripts to the scripts/ directory, run sudo nmap --script-updatedb to regenerate script.db and make them available to --script lookups. This is distinct from downloading new scripts — it just rebuilds the index over whatever scripts are already present on disk.
# Check current version $ nmap --version # Update via package manager (Debian/Ubuntu) $ sudo apt update && sudo apt upgrade nmap # Update via package manager (RHEL/Fedora) $ sudo dnf upgrade nmap # Rebuild script database after adding custom scripts $ sudo nmap --script-updatedb # Find where data files are stored on your system $ nmap --version | grep "data files"
Many Nmap scan techniques -- including SYN scan, UDP scan, and OS detection -- require raw socket access. On Linux and macOS, this means running Nmap as root or with sudo. On Windows, you need Administrator privileges. Without elevated access, Nmap falls back to the TCP Connect scan (-sT), which uses the standard connect() system call and does not require raw sockets.
Host Discovery
Before scanning ports, you need to know which hosts are alive. Nmap's host discovery phase -- sometimes called a ping sweep -- determines which IP addresses on a target network are responsive before committing time to a full port scan.
The default discovery behavior when Nmap runs with root privileges sends four probe types simultaneously: an ICMP echo request, a TCP SYN packet to port 443, a TCP ACK packet to port 80, and an ICMP timestamp request. This combination maximizes the chance of getting a response even when individual probe types are blocked by firewalls.
The -sn flag tells Nmap to perform host discovery only and skip port scanning entirely. This is useful for building a list of live targets quickly. If you are scanning from outside the local broadcast domain, ICMP probes may be blocked -- in that case, you can specify custom probe types.
# TCP SYN discovery on ports 22, 80, and 443 $ sudo nmap -sn -PS22,80,443 10.0.0.0/24 # TCP ACK discovery on port 80 $ sudo nmap -sn -PA80 10.0.0.0/24 # UDP discovery on port 53 (DNS) $ sudo nmap -sn -PU53 10.0.0.0/24 # Skip discovery entirely -- treat all hosts as online $ sudo nmap -Pn 10.0.0.1 # ARP discovery (local network only, very fast) $ sudo nmap -sn -PR 192.168.1.0/24
The -Pn flag is particularly important. It disables host discovery entirely and proceeds directly to port scanning. Use this when you know the target is online but ICMP and other discovery probes are being dropped by a firewall. Without -Pn, Nmap may skip hosts that are actually alive but not responding to discovery probes.
Something worth understanding about the default probe set: the ICMP timestamp request (-PP) is often overlooked but is included because some hosts that block ICMP echo still allow ICMP timestamp — either by firewall misconfiguration or by deliberate policy on older systems. When Nmap sends all four discovery probe types in parallel, a host only needs to respond to one for discovery to succeed. This is why the default discovery rate on diverse real-world networks is significantly higher than ICMP-only tools achieve. If you are doing asset inventory on an internal network and wondering why some hosts show up in Nmap but not in a simple ping sweep, the answer is usually this four-probe difference.
Additional Discovery Probe Types
Beyond the default four-probe set, Nmap exposes individual probe flags for fine-grained control over what discovery traffic is generated:
-PE — ICMP echo request (included by default). The classic ping. Blocked by many perimeter firewalls but often allowed on internal networks.
-PP — ICMP timestamp request (included by default). Queries the host's time, often allowed through when echo is blocked.
-PM — ICMP address mask request. Less commonly used; some older network devices respond when they block echo. Not included in the default probe set.
-PS[ports] — TCP SYN to specified ports (default includes port 443). A SYN/ACK or RST response confirms the host is up. Works well against hosts that filter ICMP entirely but expose TCP services.
-PA[ports] — TCP ACK to specified ports (default includes port 80). Because stateless firewalls sometimes allow ACK packets through (they look like return traffic from established connections), this can reach hosts that block SYN probes.
-PU[ports] — UDP to specified ports. Sends a UDP packet; if the port is closed the host returns ICMP port unreachable, confirming it is up. Useful for discovering hosts that run only UDP services.
-PY[ports] — SCTP INIT probe. Sends an SCTP INIT chunk; an INIT-ACK or ABORT confirms the host is up. Relevant in telecom environments where TCP is filtered but SCTP is permitted.
# ICMP-only discovery (fastest when ICMP is allowed) $ sudo nmap -sn -PE -PP 10.0.0.0/24 # TCP-only discovery (for environments that block all ICMP) $ sudo nmap -sn -PS22,80,443,8080 -PA80,443 10.0.0.0/24 # Maximum coverage: all probe types simultaneously $ sudo nmap -sn -PE -PP -PM -PS22,80,443 -PA80 -PU53 10.0.0.0/24 # SCTP INIT discovery for telecom environments $ sudo nmap -sn -PY36412,36422 10.0.0.0/24
Scanning Multiple Disconnected Subnets
Large engagements often involve multiple non-contiguous subnets. Nmap accepts multiple target specifications on a single command line, and they can be freely mixed with -iL target files. Understanding how Nmap groups targets internally matters for scan efficiency: Nmap groups hosts that share the same route and interface into host groups for parallel scanning. Hosts in different subnets that route through different interfaces are scanned in separate groups, which is why a scan of two adjacent /24 subnets in different routing domains takes longer than two adjacent /24s on the same LAN.
# Sweep multiple non-contiguous subnets in one command $ sudo nmap -sn 10.0.1.0/24 10.0.2.0/24 172.16.5.0/24 # Combine command-line targets with a file list (Nmap 7.96+) $ sudo nmap -sn -iL additional_subnets.txt 192.168.1.0/24 # Randomize host order across all subnets (reduces temporal clustering) $ sudo nmap -sn --randomize-hosts 10.0.0.0/16 # List all targets that WOULD be scanned without actually scanning $ nmap -sL 10.0.0.0/24 10.1.0.0/24 | grep "Nmap scan report"
The --randomize-hosts flag shuffles the target order before scanning. This reduces the temporal signature of a scan — instead of hitting 10.0.0.1 through 10.0.0.254 in sequence (a pattern immediately visible in firewall logs), Nmap probes addresses in random order. IDS correlation engines that look for sequential port/host sweeps will produce fewer alerts, though behavioral detection that simply counts unique destinations from one source still fires regardless of order.
Port Scanning Techniques
Port scanning is Nmap's core function. It determines which ports on a target are open, closed, or filtered, giving you a map of the target's attack surface. Nmap supports over a dozen distinct scanning methods, each with different advantages depending on the target environment, your access level, and how stealthy you need to be.
Understanding Port States
Before examining individual scan types, it is worth understanding exactly what Nmap means when it classifies a port. Nmap reports six possible states, and misreading them is one of the most common sources of confusion.
open — An application is actively accepting connections on this port. This is the primary result you are looking for during a security assessment: it confirms a service is present and reachable.
closed — The port is accessible (Nmap's probes reached the host) but no application is listening. A closed port responds to SYN probes with RST. Closed ports are still useful: they confirm the host is up, and they are necessary for reliable OS fingerprinting.
filtered — Nmap cannot determine whether the port is open because a packet filter is silently dropping probes. No response arrives, so Nmap must retransmit and wait for timeouts before giving up. This is why heavily filtered networks take so long to scan.
unfiltered — The port is reachable but Nmap cannot determine open or closed. This state appears only with ACK scans (-sA), which are used to map firewall rulesets rather than identify services.
open|filtered — Nmap cannot distinguish between an open port silently dropping the probe and a firewall doing the same. Common with UDP, FIN, NULL, and Xmas scans.
closed|filtered — Cannot determine if closed or filtered. Appears only with the IP ID idle scan (-sI).
Nmap suppresses closed and filtered ports from output by default to reduce noise. Add --reason to any scan to see the specific packet event (RST received, no response, ICMP unreachable, etc.) that drove each classification. This is invaluable when results look wrong.
What "tcpwrapped" actually means
If you run version detection and see tcpwrapped in the VERSION column, it means the TCP handshake completed successfully — the port is open and the host accepted your connection — but the remote service closed the connection immediately without sending any application data. Nmap's NULL probe (which just listens for a banner) timed out waiting, and no other probe matched either.
This is not a scan error and not a filtered state. It is a deliberate service behavior. The name comes from the tcp_wrappers access control system used widely on Unix systems, which can accept TCP connections and then immediately drop them if the connecting host fails an ACL check. In practice, tcpwrapped on modern systems usually means one of: a service protected by tcp_wrappers that blocked your source IP, a host-based firewall accepting the connection at the TCP level but blocking at the application layer, or a service that requires TLS immediately and discards non-TLS connections. Adding -sV --version-intensity 9 and trying from a different source address can help distinguish between them.
TCP SYN Scan (-sS)
The SYN scan is Nmap's default when running with root privileges, and for good reason. It sends a SYN packet to each target port. If the port is open, the target responds with SYN/ACK. Nmap then immediately sends RST to tear down the connection before the three-way handshake completes. If the port is closed, the target responds with RST. If no response arrives (or an ICMP unreachable error is returned), the port is classified as filtered.
This "half-open" approach is fast -- Nmap can scan thousands of ports per second on an unfiltered network -- and it avoids completing TCP connections, which means many application-level logging mechanisms do not record the connection attempt. That said, intrusion detection systems are well aware of SYN scan patterns and will flag them.
TCP Connect Scan (-sT)
When you do not have root privileges, Nmap uses the operating system's connect() system call to establish a full TCP connection with each port. This completes the three-way handshake, which makes it slower and more conspicuous -- target applications are more likely to log completed connections. However, it works without elevated access and through certain types of proxies.
UDP Scan (-sU)
UDP scanning is essential because many critical services -- DNS (53), SNMP (161), DHCP (67/68), NTP (123), TFTP (69) -- run exclusively over UDP. Nmap sends a UDP packet to each target port. If an ICMP port unreachable error returns, the port is closed. If a UDP response comes back, the port is open. If nothing comes back after retransmissions, Nmap marks it as open|filtered because it cannot distinguish between a port that is open (with a service that silently drops the probe) and a port that is behind a firewall.
UDP scanning is inherently slow. Many operating systems rate-limit ICMP unreachable messages -- Linux, for example, defaults to one per second -- which means a full 65,535-port UDP scan against a Linux target can take over 18 hours. Combine UDP with a TCP scan type to check both protocols in a single run.
TCP FIN, NULL, and Xmas Scans (-sF, -sN, -sX)
These scan types exploit a subtlety in the TCP specification (RFC 793): when a closed port receives a packet that is not a SYN and is not part of an existing connection, it should respond with RST. An open port, by contrast, should silently drop the packet. A FIN scan sends only the FIN flag, a NULL scan sends no flags at all, and an Xmas scan sets FIN, PSH, and URG simultaneously.
The practical advantage is that these scans can sometimes bypass non-stateful firewalls and packet filters that only block SYN packets. The disadvantage is that they cannot distinguish open from filtered ports (both produce no response), and they do not work against Windows systems, which send RST regardless of the port state -- violating the RFC but making these scans useless against Windows targets.
TCP ACK Scan (-sA)
The ACK scan does not determine whether ports are open or closed. Instead, it maps firewall rulesets. By sending ACK packets and observing which ones are silently dropped (filtered) versus which ones elicit RST responses (unfiltered), you can determine whether a firewall is stateful or stateless and which ports it allows through.
TCP Idle Scan (-sI)
The idle scan is one of Nmap's advanced techniques. It uses a third-party "zombie" host to probe the target, making the scan appear to originate from the zombie rather than from your machine. It works by exploiting predictable IP ID sequence numbers on the zombie host. This is the stealthiest scan Nmap offers, but it requires finding a suitable zombie host with globally incrementing IP IDs -- increasingly rare on modern systems.
Finding a usable zombie is the real challenge in practice. The ipidseq NSE script automates the search — run nmap --script ipidseq -p 80 <candidate> against a candidate host, and Nmap will report whether its IP ID sequence is Incremental (usable), Random (unusable), or All zeros (unusable). Network printers, older embedded devices, and aging Windows XP-era systems are historically good zombie candidates because they tend to use simple incrementing IP IDs. Modern Linux, macOS, and current Windows systems use randomized IP IDs per-destination, which makes them unsuitable.
By default, Nmap scans the 1,000 most commonly used ports based on frequency data in its nmap-services database. To scan all 65,535 TCP ports, use -p-. To scan a specific range, use syntax like -p 1-1024 or -p 22,80,443,8080. For the fastest common-port coverage, -F scans only the top 100 ports.
Horizontal Scanning: Finding One Service Across Many Hosts
The workflow described so far scans all ports on a set of hosts — a vertical scan. Horizontal scanning inverts this: scan one specific port across an entire network to find every host running a particular service. This is one of the most useful patterns in practice for tasks like finding all SSH servers, all RDP instances, or all hosts with port 445 open before running targeted SMB scripts.
# Find all hosts with SSH (22) open across an entire /16 $ sudo nmap -sS -p 22 --open -T4 10.0.0.0/16 -oA ssh_sweep # Find all RDP (3389) hosts, skip host discovery $ sudo nmap -sS -p 3389 --open -Pn -T4 10.0.0.0/16 -oA rdp_sweep # Find all SMB hosts and immediately run vuln scripts against them $ sudo nmap -sS -p 445 --open -T4 10.0.0.0/16 -oG smb_hosts.gnmap $ grep "445/open" smb_hosts.gnmap | awk '{print $2}' > smb_targets.txt $ sudo nmap -sV --script "smb-vuln-*" -p 445 -iL smb_targets.txt -oA smb_vuln_results
Horizontal scanning is dramatically faster than vertical scanning when you know what you are looking for. A SYN sweep of port 22 across a /16 (65,536 addresses) at -T4 typically completes in under five minutes. The --open flag suppresses all non-open results so the output contains only actionable targets, and piping the grepable output into awk builds a clean target list for the next scan phase without manual filtering.
FTP Bounce Scan (-sB)
The FTP bounce scan exploits a design quirk in the original FTP protocol (RFC 959): an FTP server's PORT command can instruct the server to establish a data connection to any host and port, not just the client. By directing an FTP server to connect to a third-party target on each port being probed, Nmap can scan that target while the traffic appears to originate from the FTP server.
This technique is almost entirely historical. Modern FTP servers detect and block FTP bounce attempts, and any FTP server permissive enough to allow it should be considered a critical misconfiguration on its own. It is included here because it appears in Nmap documentation and certification exam material, not because you are likely to use it in practice. The syntax is nmap -sB ftp.vulnerable.example.com targethost.
SCTP INIT and Cookie-Echo Scans (-sY, -sZ)
Stream Control Transmission Protocol (SCTP) is a transport layer protocol used primarily in telecommunications infrastructure — SS7/SIGTRAN gateways, Diameter protocol endpoints, and some VoIP platforms. Nmap provides two scan types for SCTP: the INIT scan (-sY) and the Cookie-Echo scan (-sZ).
The SCTP INIT scan (-sY) is the SCTP equivalent of the TCP SYN scan. It sends an INIT chunk (the SCTP equivalent of a SYN) to each target port. An INIT-ACK response indicates an open port. An ABORT response means the port is closed. No response indicates filtered. Like SYN scanning, it never completes the four-way SCTP handshake, so it avoids logging by SCTP applications.
The Cookie-Echo scan (-sZ) is more advanced and harder to detect with simple stateless packet inspection. It sends a COOKIE-ECHO chunk rather than an INIT. Open ports silently drop the packet (no response); closed ports respond with ABORT. This inverts the logic from the INIT scan and is harder to distinguish from legitimate SCTP traffic in logs.
# SCTP INIT scan (analogous to TCP SYN scan) $ sudo nmap -sY -p 36412,36422,9900 192.168.1.10 # SCTP Cookie-Echo scan (harder to detect) $ sudo nmap -sZ -p 36412,36422 192.168.1.10 # Common SCTP service ports to check on telecom infrastructure # 36412 = S1-MME (LTE), 36422 = X2-CP, 2905 = M3UA, 2944 = Megaco, 9900 = IUA
SCTP scanning requires root and is primarily relevant during assessments of telecommunications infrastructure, 4G/LTE core networks, and media gateway environments. If you encounter SCTP ports during a general assessment, version detection with -sV combined with -sY can identify SS7 and Diameter services — which carry authentication and call routing traffic and represent significant attack surface in carrier environments.
Port Specification and Scan Scope
Nmap provides flexible syntax for defining exactly which ports and targets to scan.
# Scan a single port (TCP Connect -- no root needed) $ nmap -p 22 192.168.1.1 # Scan a range of ports $ sudo nmap -sS -p 1-1024 192.168.1.1 # Scan specific ports $ sudo nmap -sS -p 22,80,443,3306,8080 192.168.1.1 # Scan all 65535 TCP ports $ sudo nmap -sS -p- 192.168.1.1 # Scan top N ports by frequency $ sudo nmap -sS --top-ports 100 192.168.1.1 # Specify TCP and UDP ports separately $ sudo nmap -sS -sU -p T:80,443,U:53,161 192.168.1.1 # Scan a CIDR block (SYN scan, root required) $ sudo nmap -sS 10.0.0.0/24 # Scan targets from a file $ sudo nmap -sS -iL targets.txt # Exclude specific hosts $ sudo nmap -sS 10.0.0.0/24 --exclude 10.0.0.1,10.0.0.254
The nmap-services file contains frequency data collected from scanning tens of millions of internet addresses, combined with contributions from large enterprises. This data drives the --top-ports option and the default 1,000-port selection, ensuring that Nmap prioritizes the ports statistically most likely to be open.
Excluding Ports from a Scan
The --exclude-ports flag removes specific ports from the scan scope entirely. The most practical use case is excluding port 9100 — the JetDirect printer protocol — which some printers respond to by printing every byte Nmap sends them as a test payload. Nmap's nmap-service-probes file already excludes 9100 from version detection by default, but --exclude-ports also removes it from the port scan phase. Use it whenever your target range includes printer subnets.
The IP Protocol scan is one of Nmap's lesser-known capabilities. Instead of scanning TCP or UDP ports, it enumerates which IP protocol numbers the target host supports — determining whether the target speaks ICMP (1), TCP (6), UDP (17), IGMP (2), GRE (47), ESP (50), OSPF (89), SCTP (132), and so on. It works by sending bare IP headers with no payload and observing the responses: an ICMP Protocol Unreachable error indicates the protocol is not supported, while any other response (or no response) indicates it may be.
Protocol scanning is particularly useful on routers, firewalls, and network appliances where you want to understand which tunneling or routing protocols are active. A router that speaks GRE and OSPF but not SCTP has a meaningfully different attack surface than one that does not. The output uses the same open/closed/filtered state model as port scanning, applied to protocol numbers rather than port numbers.
Advanced Target Specification
Nmap's target notation is more flexible than most guides cover. Beyond basic CIDR and single IPs, you can combine several forms in a single command:
# Octet range: scan .1 through .5 in the last octet $ sudo nmap -sS 192.168.1.1-5 # Wildcard: scan all addresses in 192.168.1.x $ sudo nmap -sS 192.168.1.* # Comma list in any octet $ sudo nmap -sS 192.168.1,2.1-10 # Mix CIDR, ranges, and individual IPs in one command $ sudo nmap -sS 10.0.0.0/24 192.168.1.5 172.16.0.1-20 # Randomize target order (useful for large scans) $ sudo nmap -sS --randomize-hosts 10.0.0.0/24 # Generate target list without scanning (for review) $ nmap -sL 192.168.1.0/24
The -sL (List scan) flag is particularly useful for validating scope before you start. It expands your target specification, performs reverse DNS lookups on each address, and prints the complete list — without sending a single scan packet. This lets you confirm you have not accidentally included out-of-scope addresses in a CIDR range before committing to a full scan. For large engagements, reviewing -sL output against the signed scope document should be standard procedure.
Service and Version Detection
Knowing that port 80 is open tells you very little. Is it Apache? Nginx? A custom application? Which version? Version detection (-sV) goes beyond port state to interrogate open ports and determine what software is running, including application name, version number, and sometimes even the underlying operating system. On a local host you can also identify which process is using a port directly from the OS — useful for correlating Nmap findings against your own systems.
$ sudo nmap -sV 192.168.1.10 Starting Nmap 7.99 ( https://nmap.org ) Nmap scan report for 192.168.1.10 Host is up (0.0032s latency). Not shown: 995 closed ports PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu2 (protocol 2.0) 80/tcp open http nginx 1.24.0 443/tcp open ssl/http nginx 1.24.0 3306/tcp open mysql MySQL 8.0.36-0ubuntu0.22.04.1 8080/tcp open http-proxy Varnish httpd 7.4 Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Nmap's version detection system works by sending protocol-specific probes to open ports and matching the responses against regular expressions in the nmap-service-probes database. As of Nmap 7.95, this database covers 1,246 protocols with approximately 6,500 pattern matches — spanning services from ACAP and AFP to XML-RPC and Zebra. The 1,246-protocol figure was confirmed in the official 7.95 release announcement on SecLists; the full probe grammar is documented at nmap.org/book/man-version-detection.html. When SSL/TLS is detected, Nmap connects with OpenSSL to probe the service behind the encryption layer, identifying services like HTTPS, IMAPS, and POP3S that would otherwise be opaque.
You can control the aggressiveness of version detection with --version-intensity, which ranges from 0 (lightest, only the most common probes) to 9 (send every probe). The default intensity is 7. Lowering it speeds up scans significantly at the cost of potentially missing uncommon services, while level 0 is particularly useful for speeding up UDP version detection.
What the documentation does not spell out clearly: version detection is the single largest contributor to scan time after UDP scanning. A SYN scan of all 65,535 ports on a single host typically takes under 2 minutes at -T4. Adding -sV at the default intensity can push that to 20 minutes or more if the host has many open ports, because each open port may receive multiple probe-and-response cycles. The --version-light alias (equivalent to --version-intensity 2) cuts this significantly with minimal accuracy loss for common services. Reserve full -sV for ports you have already identified as interesting rather than running it against all 65,535 in a single pass.
Version detection with -sV automatically runs NSE scripts in the version category. These scripts supplement the probe-and-match system by performing more sophisticated version queries. You do not need to enable them separately.
-sV vs -sC: When to Use Each and When to Combine Them
-sV (version detection) and -sC (default scripts) are independent features that complement each other but do different things. -sV interrogates open ports to identify what software is running and its version — it produces the VERSION column in Nmap output. -sC runs a curated set of Lua scripts that perform additional tasks after port and version information is gathered: grabbing SSL certificate details, enumerating HTTP headers, discovering SMB shares, checking for anonymous FTP access, and so on.
The key interaction: several default scripts require version information to operate correctly. The ssl-cert script only runs against ports that version detection identified as SSL/TLS. The http-auth script targets ports identified as HTTP. Running -sC alone — without -sV — means those scripts either skip ports they should check or make less accurate decisions about what to probe. For routine enumeration, always pair them: -sV -sC or equivalently -A (which adds OS detection and traceroute on top). If you need to keep scan time down, run -sV --version-light -sC rather than dropping -sV entirely.
Nmap's OS detection (-O) identifies the operating system of a remote host by analyzing how its TCP/IP stack responds to a carefully crafted series of probes. Different operating systems implement the TCP/IP specification in subtly different ways -- variations in initial TTL values, TCP window sizes, option ordering, fragmentation handling, and ICMP response behavior create a unique fingerprint for each OS.
"Nmap sends a series of TCP and UDP packets and examines practically every bit."— Nmap Network Scanning, Chapter 8: Remote OS Detection (nmap.org/book/osdetect.html)
The OS fingerprinting engine sends up to 16 distinct probe packets and analyzes the responses across multiple dimensions simultaneously: TCP ISN (initial sequence number) generation patterns, TCP options supported and their ordering, IP ID generation sequences, TCP window sizes, don't-fragment bit behavior, and ICMP response quirks. Each dimension narrows the candidate OS list, and the results are compared against the nmap-os-db database, which contains over 6,000 fingerprints contributed by the community.
A frequently overlooked detail: OS detection accuracy degrades significantly across NAT boundaries and load balancers. If multiple hosts sit behind a NAT device, Nmap fingerprints the NAT gateway's TCP stack, not the internal hosts. Similarly, some cloud environments present a hypervisor or host OS fingerprint rather than the guest. When Nmap reports a match confidence below 95%, treat it as a hypothesis rather than a fact, and corroborate with version detection output.
$ sudo nmap -O 192.168.1.10 ... Device type: general purpose Running: Linux 5.X|6.X OS CPE: cpe:/o:linux:linux_kernel:5 cpe:/o:linux:linux_kernel:6 OS details: Linux 5.15 - 6.5 Network Distance: 1 hop
OS detection works best when Nmap finds at least one open and one closed TCP port on the target. The diverse response patterns from open ports (which complete parts of the handshake) and closed ports (which send RST packets) give the fingerprinting engine enough data points to make an accurate determination. Use --osscan-limit to skip OS detection on hosts that do not meet this criteria, saving time during large-scale scans.
When Nmap cannot find a perfect match, it provides its best guesses with confidence percentages. The --osscan-guess flag makes Nmap more aggressive in its guessing. If Nmap encounters an unrecognized fingerprint and conditions are good, it prints a submission URL so you can contribute the fingerprint to the community database.
OS detection and version detection complement each other. Version detection may reveal the OS indirectly -- if Nmap identifies Microsoft Exchange running on a port, the OS is necessarily Windows. Combine both with -A, which enables OS detection, version detection, script scanning, and traceroute in a single pass.
OS Detection
Nmap's OS detection (-O) identifies the operating system of a remote host by analyzing how its TCP/IP stack responds to a carefully crafted series of probes. Different operating systems implement the TCP/IP specification in subtly different ways — variations in initial TTL values, TCP window sizes, option ordering, IP ID generation, fragmentation handling, and ICMP response behavior create a unique fingerprint for each OS family and version.
"OS detection requires at least one open and one closed TCP port."— Nmap Network Scanning, OS Detection Requirements (nmap.org/book/osdetect-methods.html)
The fingerprinting engine sends up to 16 distinct probe packets and analyzes the responses across multiple independent dimensions simultaneously. Understanding each dimension explains why the technique is so accurate — and why it degrades in specific conditions:
TCP ISN (Initial Sequence Number) generation — How predictable or random is the ISN? Different OS kernels implement different ISN generation algorithms. Linux uses a time-based algorithm with random offsets. Older Windows versions used simpler patterns. The variance and predictability of the ISN is a distinct fingerprint signal.
TCP options ordering and values — When a host responds to a SYN with SYN/ACK, the TCP options it includes (MSS, SACK permitted, Timestamps, Window Scale) and their ordering are OS-specific. Linux, macOS, and Windows each have characteristic option sets and orderings.
IP ID generation — How does the host increment the IP ID field? Random, zero, globally incrementing, per-destination incrementing? This is also the same property exploited by the idle scan.
TCP window size — The initial window size advertised in SYN/ACK responses is OS-specific. Windows 10 advertises 65535 by default; Linux typically uses 29200; macOS uses 65535 with a different scaling factor.
Don't-Fragment (DF) bit behavior — Whether the host sets the DF bit on its TCP probes is characteristic.
ICMP response quirks — When Nmap sends probes that elicit ICMP errors, it examines how the ICMP response is constructed. Different OS kernels quote different amounts of the original packet back in the ICMP error, and some set flags in the quoted IP header differently.
The combination of all these dimensions produces a fingerprint string that is compared against the nmap-os-db database. As of Nmap 7.99, this database contains over 6,000 fingerprints contributed by the global user community.
# Basic OS detection $ sudo nmap -O 192.168.1.10 # OS + version detection + scripts + traceroute (the -A shortcut) $ sudo nmap -A 192.168.1.10 # Skip OS detection on hosts with no open+closed port pair (speeds up large scans) $ sudo nmap -O --osscan-limit 192.168.1.0/24 # Make Nmap more aggressive in guessing when no perfect match exists $ sudo nmap -O --osscan-guess 192.168.1.10 # Limit guesses to top N candidates $ sudo nmap -O --max-os-tries 1 192.168.1.10
The output looks like this for a good match:
Device type: general purpose Running: Linux 5.X|6.X OS CPE: cpe:/o:linux:linux_kernel:5 cpe:/o:linux:linux_kernel:6 OS details: Linux 5.15 - 6.5 Network Distance: 1 hop
Requirements for Reliable OS Detection
OS detection works best — and sometimes only works — when Nmap finds at least one open TCP port and one closed TCP port on the target. Here is why this matters: open ports respond to SYN probes with SYN/ACK, which triggers the full handshake exchange that reveals TCP option behavior and window sizes. Closed ports respond with RST, which reveals how the OS constructs RST packets — a distinct and highly differentiating signal. Without both types, the fingerprinting engine has too few data points to make confident determinations.
Use --osscan-limit to automatically skip hosts that do not meet this criterion during large-scale scans. Without it, Nmap will attempt OS detection on all hosts regardless — generating probes and delays on hosts it has no hope of fingerprinting.
When OS Detection Degrades or Fails
NAT and load balancers — If multiple hosts sit behind a NAT device, Nmap fingerprints the NAT gateway's TCP stack, not the internal hosts. Similarly, load balancers may present a consistent TCP fingerprint regardless of which backend server responds. Cloud environments often present a hypervisor or host OS fingerprint rather than the guest OS.
Security hardening — Some administrators deliberately modify OS TCP/IP stack parameters — changing window sizes, disabling timestamps, randomizing IP IDs — specifically to confuse fingerprinting tools. A heavily hardened host may return no match or a wildly incorrect guess.
Virtual machines — Guest OS TCP stacks sometimes behave identically regardless of the underlying OS because the hypervisor normalizes packet handling. A Windows VM running under KVM may fingerprint as Linux or produce ambiguous results.
Low confidence results — When Nmap cannot find a perfect match, it prints its best guesses with percentage confidence scores alongside the --osscan-guess output. A result showing 72% confidence means Nmap found no entry in the database that perfectly matches all fingerprint dimensions — treat it as a hypothesis, not a finding, and corroborate with version detection and banner information.
Contributing OS Fingerprints
When Nmap encounters a host it cannot identify and conditions are good (it found both an open and closed port), it prints a block of fingerprint data and a URL like https://nmap.org/submit/. Submitting this fingerprint adds it to the community database — it is the primary mechanism by which nmap-os-db has grown to over 6,000 entries. New operating systems, firmware versions, embedded devices, and unusual network stacks all benefit from community submissions. The submission is reviewed and merged by the Nmap project maintainers.
Version detection and OS detection are complementary. If Nmap identifies Microsoft Exchange on a port, the OS is necessarily Windows — even if -O returns an uncertain match. Conversely, if -O says Linux but version detection shows IIS, something is wrong with your scope (you may be scanning a reverse proxy rather than the actual server). Use both flags together and compare the results against each other.
The Nmap Scripting Engine (NSE)
The Nmap Scripting Engine is what transforms Nmap from a port scanner into a comprehensive security assessment platform. NSE allows users to write and execute Lua scripts that run during the scan process, performing tasks from enhanced service enumeration to full vulnerability detection and exploitation.
"Scripts are not run in a sandbox and thus could accidentally damage your system."— Nmap Scripting Engine documentation (nmap.org/book/nse-usage.html)
This warning from the official documentation is worth taking seriously in a way that most tutorials gloss over. When you run --script vuln, you are executing Lua code against a live target. Some scripts in the vuln category send payloads that incomplete or fragile services may mishandle — not as exploitation, but as a side effect of probing. The http-slowloris-check script, for instance, uses a timing-based approach that consumes server connections during the test. On an already-stressed server, this can cause a brief outage. Treat the vuln category as you would a light intrusion test, not as a passive scan category.
A detail that distinguishes NSE from simpler scan plugins: scripts run in four distinct phases relative to the scan, controlled by their rule type. A prerule script fires before any hosts are scanned — useful for broadcast discovery (like broadcast-dhcp-discover). A hostrule script fires once per live host. A portrule script fires per open port that matches its criteria. A postrule script fires after the entire scan completes — useful for aggregating results across all hosts. This phased architecture is why scripts like dns-zone-transfer can use a prerule to feed new targets into the scan queue before port scanning begins.
NSE ships with 612 scripts and 139 supporting libraries, organized into 14 categories that reflect their function and risk level: auth (authentication testing), broadcast (local network discovery), brute (credential guessing), default (safe, commonly useful scripts), discovery (additional enumeration), dos (denial of service testing), exploit (active exploitation), external (third-party service queries), fuzzer (protocol fuzzing), intrusive (potentially disruptive), malware (backdoor detection), safe (non-disruptive), version (extended version detection), and vuln (vulnerability checking). The 612-script total was reached in Nmap 7.96, which added three new scripts including mikrotik-routeros-version (querying MikroTik WinBox) and mikrotik-routeros-username-brute (exploiting CVE-2024-54772); the count is verified at nmap.org/nsedoc.
# Run default scripts (-sC is equivalent to --script=default) $ sudo nmap -sC -sV 192.168.1.10 # Run a specific named script $ sudo nmap --script ssl-heartbleed -p 443 192.168.1.10 # Run all scripts in the vuln category (-sV required by many vuln scripts) $ sudo nmap -sV --script vuln 192.168.1.10 # Run scripts matching two categories (boolean expression) $ sudo nmap --script "default and safe" 192.168.1.10 # Run all http scripts against port 80 $ sudo nmap --script "http-*" -p 80 192.168.1.10 # Pass arguments to a script $ sudo nmap --script http-brute --script-args userdb=users.txt,passdb=pass.txt -p 80 192.168.1.10 # Get help and usage info for a script $ nmap --script-help ssl-heartbleed # Update script database after adding new scripts $ sudo nmap --script-updatedb
The -sC shortcut is equivalent to --script default and runs the curated set of scripts in the default category. In practice, -sC is almost always paired with -sV, since several default scripts rely on version information to function correctly. These scripts are considered safe for routine scanning and include checks like SSH host key retrieval, HTTP title grabbing, robots.txt enumeration, SSL certificate inspection, and SMB OS discovery.
Vulnerability Detection with NSE
The vuln category contains scripts that check for specific known vulnerabilities. When the Heartbleed vulnerability (CVE-2014-0160) was disclosed and affected hundreds of thousands of servers worldwide, the Nmap community released a detection script within 48 hours. Other commonly used vulnerability scripts include the smb-vuln-* family (which checks for EternalBlue/MS17-010 and other critical SMB flaws) and http-slowloris-check (which tests for Slowloris denial-of-service susceptibility).
# Check for Heartbleed $ sudo nmap --script ssl-heartbleed -p 443 192.168.1.10 # Check all SMB vulnerabilities (-sV needed by several smb-vuln scripts) $ sudo nmap -sV --script "smb-vuln-*" -p 445 192.168.1.10 # Run all vulnerability scripts (-Pn skips discovery on firewalled hosts) $ sudo nmap -sV -Pn --script vuln 192.168.1.10
Scripts in the exploit, dos, and brute categories can cause real damage to target systems. Never run these against production infrastructure without explicit written authorization and a clear understanding of the risks. Even the vuln category should be used with care in production environments.
NSE for HTTP and Web Application Enumeration
HTTP is the most script-covered protocol in NSE — there are over 100 http-* scripts spanning basic reconnaissance through targeted vulnerability checks. These are among the most practically useful scripts for web-facing assessments, and they are not covered by running --script vuln alone because several belong to the discovery or default categories rather than vuln.
# Grab HTTP server headers and response codes $ sudo nmap -sV --script http-headers -p 80,443,8080 192.168.1.10 # Enumerate HTTP methods (detects PUT, DELETE, TRACE) $ sudo nmap --script http-methods -p 80,443 192.168.1.10 # Retrieve and display the SSL/TLS certificate details $ sudo nmap --script ssl-cert -p 443 192.168.1.10 # Check for expired or soon-to-expire certificates across a range $ sudo nmap --script ssl-cert -p 443 --open 10.0.0.0/24 # Enumerate supported TLS cipher suites $ sudo nmap --script ssl-enum-ciphers -p 443 192.168.1.10 # Detect web application frameworks (WordPress, Drupal, etc.) $ sudo nmap -sV --script http-generator -p 80,443 192.168.1.10 # Find open directories and interesting paths $ sudo nmap --script http-enum -p 80,443 192.168.1.10 # Check for HTTP TRACE (can enable XST attacks) $ sudo nmap --script http-methods --script-args http.useragent="Mozilla" -p 80 192.168.1.10
The ssl-enum-ciphers script deserves special attention: it sends a series of TLS ClientHello messages with different cipher suite proposals and grades each accepted cipher from A (strong) through F (broken or legacy). This is one of the fastest ways to identify hosts still accepting RC4, export-grade ciphers, or SSLv3. The http-enum script probes a built-in wordlist of common paths — /admin, /login, /phpinfo.php, /.git, and hundreds more — and reports any that return non-404 responses, making it a quick first-pass for exposed management interfaces and sensitive files.
NSE Authentication and Brute-Force Scanning
The auth category contains scripts that test authentication configurations — not by guessing credentials, but by checking for authentication bypass and misconfiguration. The most commonly run auth scripts include ftp-anon (anonymous FTP access), http-auth-finder (what auth scheme a web server uses), smtp-open-relay (whether an SMTP server will relay mail for unauthorized senders), and x11-access (whether an X11 display is accessible without authentication — a critical finding on Linux desktops).
The brute category performs active credential guessing against services. Scripts exist for SSH, FTP, Telnet, MySQL, PostgreSQL, Redis, MongoDB, SMB, HTTP Basic Auth, and dozens of other services. All brute scripts generate authentication logs on the target and should never be run against production systems without explicit written authorization scoping that activity. A representative usage:
# Check for anonymous FTP access $ sudo nmap --script ftp-anon -p 21 192.168.1.0/24 # Test SMTP relay misconfiguration $ sudo nmap --script smtp-open-relay -p 25,587 192.168.1.10 # Check for unauthenticated X11 access $ sudo nmap --script x11-access -p 6000 192.168.1.0/24 # Brute-force SSH (authorized targets only) $ sudo nmap --script ssh-brute --script-args userdb=users.txt,passdb=passwords.txt -p 22 192.168.1.10 # Brute-force MySQL (authorized targets only) $ sudo nmap --script mysql-brute --script-args userdb=users.txt,passdb=passwords.txt -p 3306 192.168.1.10 # Run all auth-category scripts (safe, no credential guessing) $ sudo nmap -sV --script auth 192.168.1.10
NSE Broadcast and Discovery Scripts
The broadcast category is different from all others: these scripts do not target specific hosts. They send broadcast or multicast packets on the local network and listen for responses, discovering hosts and services that are not in your initial target list. This makes them useful for identifying assets that a traditional ping sweep might miss.
# Discover DHCP servers on the local network $ sudo nmap --script broadcast-dhcp-discover # Discover DNS-SD (Bonjour/mDNS) services on the local network $ sudo nmap --script broadcast-dns-service-discovery # Discover NetBIOS names on the local subnet $ sudo nmap --script broadcast-netbios-master-browser # Discover UPnP devices $ sudo nmap --script broadcast-upnp-info # Run all broadcast scripts (requires no target — uses local network) $ sudo nmap --script broadcast
Broadcast scripts run in the prerule phase, before host scanning begins. When combined with the newtargets NSE argument, they can feed discovered hosts directly into the scan queue: sudo nmap --script broadcast-dhcp-discover --script-args newtargets -sV. This causes Nmap to automatically scan any hosts discovered by the broadcast phase.
The external category queries third-party services — WHOIS registries, DNS lookup APIs, and similar external data sources — to gather information about scan targets. Scripts like whois-domain and dns-brute belong here. Be aware that running external scripts sends information about your target to third-party services, which may be inappropriate in some engagement contexts.
Writing Custom NSE Scripts
NSE scripts are written in Lua and follow a consistent structure: metadata fields (description, categories, author), one or more rules that determine when the script should run (portrule, hostrule, prerule, or postrule), and an action function that executes the script's logic. Scripts are stored in the scripts/ subdirectory of the Nmap data directory, and the script database (script.db) must be updated after adding new scripts with nmap --script-updatedb.
description = [[ Reports open TCP ports with a custom message. ]] categories = {"safe"} portrule = function(host, port) return port.protocol == "tcp" and port.state == "open" end action = function(host, port) return "Port " .. port.number .. " is open and responding." end
Timing and Performance
Nmap provides six timing templates that control scan speed, probe timeouts, retransmission limits, and parallelism. They range from -T0 (paranoid -- extremely slow, designed to evade IDS) through -T5 (insane -- maximum speed, suitable only for fast, reliable networks).
"Nmap dynamically adjusts its scan timing to account for network conditions."— Nmap Network Scanning, Chapter 6: Optimizing Nmap Performance (nmap.org/book/man-performance.html)
A point that trips up experienced users: -T4 and --min-rate are not the same thing. -T4 is an adaptive template — Nmap still adjusts timing based on observed network conditions, just with more aggressive initial parameters (10ms initial RTT timeout, 1.25s max RTT, 5000ms host timeout). --min-rate 1000 is a hard floor — Nmap will send at least 1000 packets per second regardless of what the network says. On a lossy or congested network, forcing a high --min-rate can trigger rate limiting on firewalls and actually produce less reliable results than letting -T4's adaptive logic back off when it detects congestion. Use -T4 as the default for internal LAN scans; reserve --min-rate for environments where you have confirmed the network can handle it and you need a predictable scan duration.
The -T0 and -T1 templates are the only ones that serialize scanning — each probe waits for the previous one to complete or timeout before firing. At -T0's 5-minute interval, scanning 1,000 ports against a single host takes over 83 hours. These are not practical scanning speeds; they are evasion strategies for environments with IDS that detect scan rates.
# T0: Paranoid -- 5-minute intervals between probes # T1: Sneaky -- 15-second intervals # T2: Polite -- 0.4-second intervals # T3: Normal -- default, balances speed and reliability # T4: Aggressive -- faster timeouts, more parallelism # T5: Insane -- maximum speed, may miss results $ sudo nmap -T4 -sS -p- 192.168.1.0/24
For more granular control, Nmap exposes individual timing parameters. --min-rate and --max-rate set packet-per-second floors and ceilings. --max-retries limits how many times Nmap retransmits an unanswered probe. --host-timeout sets a ceiling on total time spent per host. --scan-delay inserts a fixed pause between probes, useful for avoiding rate limiting or detection.
# Send at least 1000 packets per second $ sudo nmap --min-rate 1000 -p- 192.168.1.10 # Limit retries and set host timeout $ sudo nmap --max-retries 2 --host-timeout 5m 10.0.0.0/24 # Add delay between probes (IDS evasion) $ sudo nmap --scan-delay 500ms -sS 192.168.1.10
Verbosity and Debugging
Long scans against large networks leave you staring at a blank terminal for minutes or hours. Nmap's verbosity and debugging flags give you real-time feedback on what it is doing, which is essential for diagnosing slow scans, unexpected results, and script behavior.
The -v flag enables verbose output. Nmap starts reporting open ports as they are discovered rather than waiting until the scan completes, and it prints additional timing and progress information. Adding a second -v (-vv) increases verbosity further, showing closed ports, filtered ports, and additional internal state. You can also increase verbosity mid-scan without restarting it -- pressing v during a running scan raises the verbosity level on the fly.
# Standard verbose output $ sudo nmap -v -sS 192.168.1.0/24 # Very verbose -- shows closed and filtered ports too $ sudo nmap -vv -sS 192.168.1.0/24 # Debug level 1 -- internal probe/response details $ sudo nmap -d -sV 192.168.1.10 # Debug level 2 -- very detailed internals $ sudo nmap -d2 -sV 192.168.1.10 # Show reason for each port state $ sudo nmap --reason -sS 192.168.1.10 # Print host interfaces and routes (useful for diagnosing source IP issues) $ nmap --iflist
The -d flag enables debug output. Where -v tells you what Nmap found, -d tells you how it is trying to find it -- probe retransmissions, TCP state machine transitions, version detection probe selection, and NSE script execution details. Debug output is verbose enough that piping it through less or redirecting to a file is usually necessary. Levels run from -d (level 1) through -d9 (maximum).
For NSE-specific troubleshooting, --script-trace prints every packet sent and received by scripts during execution. This is the primary tool for debugging custom scripts or understanding why a built-in script is producing unexpected output. For deeper packet-level inspection during or after a scan, piping tcpdump through SSH into Wireshark gives you a live view of exactly what Nmap is sending and what the target is returning.
One level deeper than --script-trace is --packet-trace, which shows every packet Nmap itself sends and receives across all scan phases — not just NSE script packets. The output includes the hex representation of each packet, the source and destination, and the decoded flags. This is the right tool when you suspect Nmap is generating unexpected traffic, when a firewall is behaving differently than expected, or when you need to verify exactly which TCP flags are being set in a FIN, NULL, or Xmas scan. The output is verbose enough that it should be redirected to a file for analysis: sudo nmap --packet-trace [options] target 2>&1 | tee trace.txt.
# Trace all packets for a SYN scan (combine with -p for scope) $ sudo nmap --packet-trace -sS -p 22,80,443 192.168.1.10 # Trace NSE script packets only $ sudo nmap --script-trace --script ssl-cert -p 443 192.168.1.10 # Both together: full packet trace + script trace (very verbose) $ sudo nmap --packet-trace --script-trace -sS -sV -p 443 192.168.1.10 2>&1 | tee full_trace.txt
During any running scan, pressing p prints a progress status and estimated time remaining. Pressing d or v adjusts debug or verbosity mid-scan. These interactive controls are far more useful than restarting a long scan with higher verbosity from the beginning.
Controlling DNS Resolution
DNS behavior during scanning affects both performance and operational security, and Nmap gives you fine-grained control over it. By default, Nmap performs reverse DNS lookups on discovered hosts to display hostnames alongside IP addresses. On large scans, this adds measurable time and generates DNS queries that can be logged by network monitoring infrastructure.
# Disable all DNS resolution (fastest, no DNS traffic) $ sudo nmap -n -sS 10.0.0.0/24 # Force reverse DNS on all hosts, even those marked down $ sudo nmap -R -sS 10.0.0.0/24 # Use a specific DNS server instead of the system resolver $ sudo nmap --dns-servers 8.8.8.8 -sS 10.0.0.0/24 # Use the system DNS resolver (bypasses Nmap's parallel resolver) $ sudo nmap --system-dns -sS 10.0.0.0/24 # Resolve all matching IPs for a hostname (not just the first) $ sudo nmap --resolve-all example.com
The -n flag is worth using on any large internal scan where you do not need hostnames, because reverse DNS lookups can double scan time on networks with slow or unreliable internal resolvers. Conversely, --dns-servers lets you point Nmap at an internal DNS server that has authoritative records for internal hostnames — more useful than relying on the system resolver when the scan machine's DNS settings do not include the internal zone. The --resolve-all flag matters when a hostname has multiple A records (load balancing or CDN) and you want Nmap to scan every address it resolves to, not just the first one returned.
Firewall and IDS Evasion
When scanning hardened targets, default Nmap behavior may be insufficient. Firewalls drop probes, IDS systems flag scan patterns, and rate limiters slow you down. Nmap includes several techniques for navigating these defenses.
"Many Internet pioneers believed that transparency was key to a functional Internet."— Gordon Lyon, The Art of Port Scanning, Phrack Issue 51 (nmap.org/p51-11.html)
Something not widely documented: the --badsum flag, which sends packets with deliberately incorrect TCP/UDP checksums, is primarily a diagnostic tool. Real TCP stacks discard bad-checksum packets without responding. If a host does respond to a --badsum probe, it usually indicates that a firewall or IDS appliance is responding on behalf of the host — and that appliance is not performing checksum validation. This is a useful signal when mapping what is a firewall versus what is an actual endpoint.
Packet fragmentation (-f) splits probe packets into smaller IP fragments, with each fragment carrying 8 bytes of data by default. Some older or misconfigured firewalls and IDS systems fail to reassemble fragments before inspection, allowing probes to pass through undetected. Using -f twice (-f -f) doubles the fragment data size to 16 bytes. You can also set a precise MTU with --mtu, which must be a multiple of 8.
Decoy scanning (-D) makes it appear that multiple hosts are scanning the target simultaneously. Nmap spoofs scan packets from the decoy addresses alongside your real packets. The target sees scans from five or ten different IPs and cannot easily determine which one is the real attacker. However, all decoy addresses must be online (otherwise, the target may be SYN-flooded), and the technique does not work for TCP Connect scans or version detection.
# Fragment packets $ sudo nmap -f -sS 192.168.1.10 # Use decoys (ME = your real address) $ sudo nmap -D 10.0.0.5,10.0.0.6,10.0.0.7,ME 192.168.1.10 # Spoof source port (some firewalls allow DNS/53 traffic) $ sudo nmap -g 53 -sS 192.168.1.10 # Spoof MAC address (use 0 for random, or a manufacturer name, or full MAC) $ sudo nmap --spoof-mac Dell 192.168.1.10 # Set a custom TTL $ sudo nmap --ttl 64 -sS 192.168.1.10 # Append random data to packet payloads $ sudo nmap --data-length 50 -sS 192.168.1.10 # Send packets with bad checksums (test IDS inspection) $ sudo nmap --badsum -sS 192.168.1.10
Source port spoofing (-g or --source-port) sets the source port of outgoing packets. Some poorly configured firewalls allow traffic from "trusted" source ports like 53 (DNS) or 80 (HTTP). Setting your scan source port to one of these values can bypass such rules.
Data Payload and Checksum Manipulation
Random data padding (--data-length N) appends N bytes of random data to the payload of each probe packet. Some IDS signatures are written to match on exact packet lengths — a 40-byte SYN probe matches a signature, but a 90-byte SYN probe with padding does not. This is not a reliable bypass against modern IDS, but it can help against signature-based detection that has not been tuned for variable-length probes.
Bad checksum probes (--badsum) intentionally generate packets with invalid TCP/UDP checksums. A real host's TCP stack will silently discard them without responding. If a device responds to a bad-checksum packet, it means an intermediate device (a firewall, IDS, or load balancer) is answering on the host's behalf without validating checksums — a useful diagnostic signal when mapping what is a real endpoint versus a security appliance.
Custom data in probe payloads (--data, --data-string) lets you specify the exact hex bytes or ASCII string to include in probe payloads. This is primarily useful for protocol-specific testing where you need the probe to match a specific format rather than containing random bytes.
Interface and Source Address Control
When a machine has multiple network interfaces, Nmap by default chooses the interface based on routing. Use -e interface to force a specific interface (e.g., -e eth1), and -S source_ip to spoof the source IP address on raw packets. Note that -S requires that the spoofed address is reachable from the target — responses go to the spoofed address, not to you, so you will not receive them unless the spoofed address is one you control or can intercept.
# Add 25 random padding bytes to probe payloads $ sudo nmap --data-length 25 -sS 192.168.1.10 # Force a specific source IP (must be routable; responses go to that IP) $ sudo nmap -S 10.0.0.5 -e eth0 -sS 192.168.1.10 # Scan from a specific interface $ sudo nmap -e eth1 -sS 192.168.2.0/24 # Test whether a device validates checksums (diagnostic) $ sudo nmap --badsum -p 80,443 192.168.1.10 # Combine: decoys + fragmentation + random padding + source port spoof $ sudo nmap -f --data-length 20 -D RND:5 -g 53 -T1 -p 80,443 192.168.1.10
How Nmap Scans Are Detected (The Blue Team View)
Understanding what Nmap looks like from the defender's side makes you a better scanner and a better defender. Every technique in the evasion section has a corresponding detection signature, and knowing both helps you calibrate what your scans actually reveal about themselves.
What SYN scans look like in logs
A default SYN scan sends a SYN to each port and receives a SYN/ACK or RST in response, but never completes the handshake. Most application-layer logs (web server access logs, SSH auth logs) record completed connections only, so SYN scans often go unlogged at the application level. However, network-level detection is straightforward: a single source IP sending SYN packets to dozens or hundreds of ports in rapid succession is a textbook scan pattern. Firewall and IDS logs will record every SYN that hits a filtered or closed port. Snort and Suricata both ship with rules that fire on exactly this pattern. The characteristic signature is high port diversity from a single source within a short time window.
What -sC (default scripts) looks like
Default NSE scripts leave significantly more forensic evidence than a plain port scan. ssh-hostkey initiates an SSH handshake and reads the server's host key — this shows up in the SSH daemon log as a connection attempt that never authenticated. http-title sends a full HTTP GET request with Nmap's default User-Agent string (Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)), which appears in web server access logs verbatim. smb-os-discovery initiates SMB Session Setup, generating Windows Security event log entries. Anyone reviewing logs after a -sC scan has a clear trail to follow.
Timing as a detection signal
IDS systems that implement threshold-based detection look for a port scan rate that exceeds a count per time window — typically something like 15 distinct ports from one source in 10 seconds. -T4 blows through this threshold in under a second. -T1 and -T0 are designed to stay under it, but the trade-off in scan duration makes them impractical for anything except very targeted single-host checks. Behavioral detection systems that baseline normal traffic patterns can detect even slow scans by recognizing that a host is attempting connections to ports it has never communicated with before, regardless of rate.
What decoys (-D) actually conceal
Decoy scanning does not hide your scan — it hides which source IP is the real scanner. The target still receives probes from every listed address including yours, and a packet capture records all of them. A defender with full packet capture can potentially reconstruct the real scanning IP by correlating probe timing, TTL values, and TCP ISN generation patterns across the decoy addresses. Decoys are effective against log-based analysis tools but less effective against a careful analyst with raw traffic data.
If you are running authorized red team assessments, documenting the exact scan commands used — timing template, script categories, source IP — makes deconfliction with blue team detections far cleaner. A log entry at 14:32 UTC matching -T4 -sS --top-ports 1000 from your known scanner IP is an easy true-positive to exclude. An undocumented scan from an unexpected IP creates unnecessary incident response work.
Output Formats
Nmap supports five output formats, and using -oA to save in three formats simultaneously is standard practice for professional engagements.
One thing worth knowing before you start saving output: Nmap does not warn you if it overwrites an existing file. If you run a second scan with the same base name as a previous -oA run, your baseline is silently gone. Establish a timestamped naming convention from the start — something like -oA scans/$(date +%Y%m%d_%H%M)_target — and you will never lose a baseline to an accidental overwrite.
# Normal output (human-readable) $ nmap -oN scan_results.txt 192.168.1.10 # XML output (for tool integration) $ nmap -oX scan_results.xml 192.168.1.10 # Grepable output (for command-line filtering) $ nmap -oG scan_results.gnmap 192.168.1.10 # All three formats at once (recommended) $ nmap -oA scan_baseline 192.168.1.10 # Script kiddie output (just for fun) $ nmap -oS scan_l33t.txt 192.168.1.10
The XML output is particularly valuable. It integrates with tools like Metasploit, OpenVAS, and Nessus, and can be converted to HTML reports using XSL stylesheets. The --webxml flag references a stylesheet hosted on nmap.org for portable HTML conversion. For ongoing monitoring, the ndiff utility compares two XML scans and reports differences -- new hosts, changed ports, modified service versions -- making it ideal for change detection in scheduled scan workflows.
The grepable format puts all information about a host on a single line, making it easy to extract data with standard Unix tools like grep, awk, and cut. Need a quick list of all hosts with port 22 open? Run grep " 22/open" scan_results.gnmap.
Integrating Nmap XML Output with Metasploit
Metasploit's db_import command ingests Nmap XML directly into the Metasploit database, making all discovered hosts, ports, and services immediately available for subsequent exploitation modules. This is one of the most widely used Nmap integration workflows in professional penetration testing.
# Step 1: Run Nmap with XML output and full enumeration $ sudo nmap -sS -sV -sC -O -T4 -oX target_scan.xml 10.0.0.0/24 # Step 2: Start Metasploit and connect to its database $ msfconsole msf6 > db_status # confirm database connection # Step 3: Import the Nmap XML results msf6 > db_import /path/to/target_scan.xml # Step 4: Query the imported data msf6 > hosts # all discovered hosts msf6 > services # all open ports with service names msf6 > services -p 445 # filter by port msf6 > vulns # vulnerabilities if vuln scripts were run # Alternatively, run Nmap directly from inside Metasploit msf6 > db_nmap -sS -sV -T4 10.0.0.0/24
The db_nmap command inside Metasploit runs Nmap with the same arguments you would use on the command line and automatically imports results into the database — skipping the intermediate XML file entirely. Note that db_nmap requires PostgreSQL to be running and Metasploit connected to its database. If the database connection is down, db_nmap behaves like a normal Nmap run without import. The imported service data populates the RHOSTS option for many Metasploit modules, letting you run exploitation attempts against every discovered instance of a service with a single module invocation.
Real-World Scanning Workflows
Professional network assessments typically follow a phased approach rather than a single monolithic scan. Here is a workflow that balances thoroughness with efficiency.
# Phase 1: Host discovery $ sudo nmap -sn -oA phase1_discovery 10.0.0.0/24 # Extract live hosts from grepable output $ grep "Status: Up" phase1_discovery.gnmap | awk '{print $2}' > live_hosts.txt # Phase 2: Fast TCP port scan of top 1000 ports $ sudo nmap -sS -T4 --open -iL live_hosts.txt -oA phase2_tcp_fast # Phase 3: Full TCP port scan of interesting hosts $ sudo nmap -sS -p- -T4 --open -iL interesting_hosts.txt -oA phase3_tcp_full # Phase 4: Version detection, default scripts, OS detection $ sudo nmap -sV -sC -O -T4 -v -iL interesting_hosts.txt -oA phase4_enumeration # Phase 5: UDP scan on highest-value ports $ sudo nmap -sU --top-ports 50 -iL live_hosts.txt -oA phase5_udp # Phase 6: Vulnerability scripts (sV required by many vuln scripts) $ sudo nmap -sV --script vuln -iL interesting_hosts.txt -oA phase6_vuln # Compare with previous baseline scan $ ndiff previous_scan.xml phase4_enumeration.xml
This phased approach has several advantages. Host discovery is fast and identifies the scope. The quick port scan reveals the obvious attack surface. Full port scans and version detection are directed only at interesting targets, saving hours of scan time. UDP scanning is narrowly scoped to the ports where services are commonly found. And vulnerability scripts run last, after you understand what services exist.
Use the --open flag to show only open ports in output. This dramatically reduces noise, especially when scanning large networks. Combine it with --reason to see exactly why Nmap classified each port the way it did (SYN/ACK received, RST received, no response, ICMP unreachable, etc.).
Scanning Cloud Infrastructure (AWS, Azure, GCP)
Scanning cloud environments with Nmap introduces behaviors that differ significantly from internal LAN scans, and some of those differences will produce misleading results if you do not account for them.
The most important difference is that AWS, Azure, and GCP all have security groups, network ACLs, or firewall rules that silently drop packets by default. When you scan an EC2 instance that has port 22 closed in its security group, Nmap will report the port as filtered, not closed — because no RST reaches you. This means you cannot use filtered-versus-closed patterns to infer host liveness on cloud targets without already knowing the host is up. Always use -Pn when scanning cloud instances whose security group state you know, since the discovery probes will also be filtered.
A second issue: cloud providers use shared public IPs and elastic IP addresses. An IP that belonged to a running instance this morning may have been released and reassigned to a different customer by afternoon. Before scanning a cloud IP range, confirm you have a current inventory. Scanning recently-released IPs that have been reassigned is scanning someone else's infrastructure without authorization.
All three major cloud providers have policies governing security scanning of their infrastructure. AWS requires that you notify them via their vulnerability reporting portal before scanning IP ranges other than those you own — though AWS instances you own are generally exempt from prior notification for standard port scans. GCP and Azure have similar policies. Check the current acceptable use policy for your provider before scanning, and maintain a record of the policy version you reviewed. These policies change, and "I did not know" is not a defense.
# Use -Pn for cloud targets — discovery probes will be filtered $ sudo nmap -Pn -sS -sV -T3 --top-ports 1000 203.0.113.10 # Use -T3 (not T4/T5) to avoid triggering cloud provider rate limiting $ sudo nmap -Pn -sS -T3 --max-retries 2 203.0.113.0/28 # Scan from inside the VPC/VNet for accurate results (no security group filtering) $ sudo nmap -sS -sV 10.0.1.0/24 # from within the cloud network
For the most accurate results, scan from inside the cloud environment rather than from the public internet. When scanning from a machine within the same VPC or VNet, traffic between instances often bypasses external security groups and gives you a view of the actual attack surface visible to another compromised instance — which is what matters during an internal assessment.
Scanning OT, ICS, and SCADA Networks
Operational technology networks — those running industrial control systems, SCADA, PLCs, and building management systems — require a fundamentally different scanning approach than IT infrastructure. The devices on these networks were often designed without network security in mind, and they can fail, reboot, or enter fault states in response to inputs that any typical IT device would handle without issue.
An aggressive Nmap scan on an OT network can cause real-world physical consequences. Sending SYN floods or even moderate scan rates to a PLC managing a water pump, conveyor belt, or HVAC system has caused unplanned shutdowns in documented incidents. On OT networks, always scan at -T1 or slower, scan only specific known ports rather than broad ranges, and coordinate with the operations team before any scanning activity.
The standard approach for OT network scanning is to use -T1 or -T2, limit the port scope to known OT protocol ports, and run no NSE scripts at all on the initial pass. OT protocols commonly found on these networks include Modbus (502/tcp), DNP3 (20000/tcp and udp), EtherNet/IP (44818/tcp and udp), BACnet (47808/udp), and IEC 61850 MMS (102/tcp). Nmap's NSE includes dedicated scripts for several of these — modbus-discover, enip-info, bacnet-info — but even these should be used cautiously and only after confirming the target device can tolerate scripted interaction.
Keeping Nmap Databases and Scripts Current
Nmap ships with three databases that improve scan accuracy and that grow stale over time: nmap-os-db (OS fingerprints), nmap-service-probes (version detection patterns), and the NSE script collection. How you update them depends on how Nmap was installed.
If you installed Nmap through a package manager (apt, dnf, brew), the databases update when the package updates. Run sudo apt upgrade nmap or the equivalent for your distribution. The package manager version may lag behind the upstream release by weeks or months — Kali Linux typically tracks upstream closely, but stable Debian and Ubuntu releases do not.
If you need current databases without a full Nmap upgrade, or if you have added custom NSE scripts, use:
# Rebuild the NSE script.db index after adding or removing scripts $ sudo nmap --script-updatedb # Check the location of Nmap's data files $ nmap --version | grep "data files" # On Linux, data files are typically in /usr/share/nmap/ # Replace individual files (e.g. nmap-os-db) with fresh copies from nmap.org/svn $ ls /usr/share/nmap/ # Verify current script.db is current after any manual script changes $ sudo nmap --script-updatedb && nmap --script-help default | head -5
For production security tooling where current fingerprints matter, the cleanest approach is to compile Nmap from source using the latest tarball from nmap.org. This ensures you get both the current binary and the latest databases simultaneously. The compile process on Linux is straightforward: download, extract, run ./configure, then make and sudo make install. Custom scripts placed in /usr/local/share/nmap/scripts/ persist across updates.
Companion Tools
Nmap ships with several companion utilities that extend its capabilities.
Ncat is Nmap's reimplementation of the classic Netcat utility. It supports TCP, UDP, and SSL connections, can act as a client or server, proxy traffic, transfer files, and create bind or reverse shells. It is indispensable during penetration testing and general network debugging.
Nping is a packet crafting and analysis tool bundled with Nmap. It can generate custom TCP, UDP, ICMP, and ARP packets, making it useful for firewall testing, latency measurement, and protocol-level troubleshooting.
Ndiff compares two Nmap XML scans and reports what changed: new or removed hosts, ports that opened or closed, and service version changes. It is the right tool for baseline monitoring workflows — run a scheduled scan, diff it against the previous run, and investigate any delta. The output is human-readable by default and can be formatted as XML for tool integration. A command like ndiff last_week.xml this_week.xml surfaces exactly what shifted in your environment without manually diffing thousands of lines of output.
Zenmap provides a graphical interface for Nmap with topology mapping, scan profile management, and result browsing. Nmap 7.96 added a dark mode to Zenmap, accessible via Profile → Toggle Dark Mode or by setting window::dark_mode in zenmap.conf. As of Nmap 7.99, Zenmap is distributed as a universal Python wheel (zenmap-7.99-py3-none-any.whl) instead of an RPM, which means it can be installed on any system with Python 3 using pip install zenmap-7.99-py3-none-any.whl. While command-line Nmap is the standard for professional use, Zenmap's topology view is genuinely useful for visualizing how hosts relate across network segments.
Ncat: Practical Usage Patterns
Ncat (ncat or nc on systems where it replaces netcat) is more capable than its name suggests. Beyond the basic client/server pattern, these are the usage patterns most relevant to security work:
# Banner grab: connect and receive the service banner $ ncat 192.168.1.10 22 # Send a raw HTTP request and capture the response $ echo -e "HEAD / HTTP/1.0\r\nHost: 192.168.1.10\r\n\r\n" | ncat 192.168.1.10 80 # SSL/TLS connection to inspect certificate or test a TLS service $ ncat --ssl 192.168.1.10 443 # Listen and log all incoming connections (useful for testing callbacks) $ ncat -l -p 4444 -k --keep-open | tee received.log # File transfer: send a file to a listening Ncat $ ncat -l -p 9999 > received_file.txt # receiver $ ncat 192.168.1.10 9999 < file_to_send.txt # sender # Proxy: forward connections from local port 8080 to a remote service $ ncat -l -p 8080 --sh-exec "ncat internal-host.local 80"
The --keep-open flag (-k) keeps the listener running after each connection closes, which is essential for testing against tools that make multiple connections. The --sh-exec pattern is useful for building simple port-forwarding tunnels during pivot testing when a full SOCKS proxy is unavailable.
Nping: Packet Crafting and Network Testing
Nping generates custom packets at the command line without requiring a Python script or Scapy. It is the right tool for testing whether a firewall allows specific traffic before committing to a full Nmap scan, and for measuring round-trip times to specific ports rather than just ICMP.
# Measure TCP round-trip time to port 443 $ sudo nping --tcp -p 443 --count 5 192.168.1.10 # Send a SYN and see what comes back (firewall test) $ sudo nping --tcp --flags SYN -p 80 192.168.1.10 # Send an ACK (test whether stateless firewall allows it) $ sudo nping --tcp --flags ACK -p 80 192.168.1.10 # ICMP echo with custom data $ sudo nping --icmp --icmp-type echo 192.168.1.10 # UDP probe to a specific port $ sudo nping --udp -p 53 192.168.1.1
Nmap 7.96 Parallel Forward DNS: A Major Operational Change
Nmap 7.96 (May 2025) introduced parallel forward DNS resolution — a change with significant practical impact for anyone scanning large lists of hostnames. Previously, Nmap resolved hostnames using blocking system calls, which forced serial resolution and prevented progress reporting. The new parallel engine, which had handled reverse-DNS reliably for years, was extended to forward lookups in this release.
The performance difference is substantial. According to the Nmap changelog, resolving one million website names to both IPv4 and IPv6 went from 49 hours to just over one hour. For engagements involving large third-party target lists, domain-based scope definitions, or asset inventories stored as hostnames rather than IPs, this improvement alone makes upgrading from 7.95 or earlier worthwhile. Additionally, 7.96 added support for specifying targets both on the command line and in an input file with -iL simultaneously — previously, command-line targets were silently ignored when -iL was used.
Scanning Through a Proxy or SOCKS Tunnel
Nmap can route TCP Connect scans (-sT) through a SOCKS4 or SOCKS5 proxy using the --proxies flag. This is useful when scanning a target network that is only reachable through a pivot host or when you want scan traffic to exit from a different IP address.
# Scan through a SOCKS4 proxy $ nmap -sT --proxies socks4://127.0.0.1:1080 192.168.1.10 # Scan through a SOCKS5 proxy (e.g., SSH dynamic forwarding) $ nmap -sT --proxies socks5://127.0.0.1:9050 192.168.1.10 # Chain through an SSH dynamic forward: set up the tunnel first $ ssh -D 9050 -N user@pivot-host & $ nmap -sT -Pn --proxies socks5://127.0.0.1:9050 10.10.10.0/24
There are hard limitations to proxy scanning that you need to know before relying on it. Only TCP Connect scans work through proxies — raw packet techniques like SYN scan, UDP scan, OS detection, and most evasion options require raw socket access that cannot be routed through a SOCKS proxy. Version detection works (it runs over the established TCP connection), but NSE scripts that open additional connections may behave unpredictably. For full capability through a pivot, the standard approach is to copy the Nmap binary to the pivot host and run it there directly, or use a tool like ProxyChains to intercept system calls.
IPv6 Scanning
Nmap has supported IPv6 since version 3.10, but IPv6 scanning has important differences from IPv4 that affect nearly every phase of a scan. Enable IPv6 mode with the -6 flag.
The most significant difference is host discovery. IPv6 subnets are enormous -- a standard /64 contains over 18 quintillion addresses, making brute-force ping sweeps completely impractical. The workaround is to obtain a list of IPv6 targets through other means: extract them from DNS (AAAA records), grab them from router neighbor discovery tables (ip -6 neigh on Linux), consult your CMDB or asset inventory, or capture them from traffic. Once you have a list, pass it with -iL as usual.
On a local link, Nmap can use multicast neighbor discovery to find hosts automatically. Scanning the link-local all-nodes multicast address will elicit responses from every IPv6-capable host on the local segment:
# Scan a specific IPv6 host $ sudo nmap -6 -sS -sV 2001:db8::42 # Scan from a target list (preferred for IPv6) $ sudo nmap -6 -iL ipv6_targets.txt -oA ipv6_scan # OS detection over IPv6 $ sudo nmap -6 -O 2001:db8::42 # Run default scripts over IPv6 $ sudo nmap -6 -sC -sV 2001:db8::42 # Discover link-local hosts via multicast (local network only) $ sudo nmap -6 -sn ff02::1%eth0
Most of Nmap's scan techniques work over IPv6 with minimal changes. SYN scans, version detection, OS detection, and NSE all function normally once you add -6. The main exceptions are scan types that rely on IPv4-specific features: decoy scanning (-D) and idle scanning (-sI) are not supported over IPv6 because IPv6 makes IP address spoofing considerably harder at the network level.
OS detection accuracy over IPv6 is lower than over IPv4. The fingerprint database has fewer IPv6-specific signatures, and many network stacks behave similarly across IPv6 implementations. Version detection and NSE scripts are generally the more reliable path to host characterization over IPv6.
Many organizations have weaker monitoring and filtering on their IPv6 infrastructure than on IPv4, partly because IPv6 rollouts are often less mature. A thorough assessment must include both protocol families. Scanning only IPv4 can leave an entire attack surface unexamined.
IPv6 Address Enumeration Techniques
Because brute-force sweeping is impractical against IPv6 /64 subnets, building the target list requires alternative enumeration techniques. These are the most reliable methods in practice:
DNS AAAA record harvesting — Zone transfers, brute-force subdomain enumeration, and certificate transparency logs often reveal IPv6 addresses. The dns-brute NSE script handles brute-force DNS enumeration and returns both A and AAAA records when available.
Router neighbor discovery tables — On Linux, ip -6 neigh show lists all IPv6 neighbors the router has recently communicated with. On Cisco IOS, show ipv6 neighbors provides the same. These tables are authoritative for recently active hosts on each segment.
Passive traffic capture — A brief tcpdump or Wireshark capture on the local segment will reveal IPv6 addresses in ICMPv6 neighbor solicitations, router advertisements, and DHCPv6 exchanges. A 60-second capture on an active office LAN typically reveals dozens of active IPv6 hosts.
DHCPv6 server logs — If the network uses stateful DHCPv6, the DHCP server logs contain the complete assignment history. This is the most complete internal source for IPv6 addresses on managed networks.
Dual-Stack Scanning: Covering Both Protocols in One Assessment
Most modern infrastructure is dual-stack — hosts have both IPv4 and IPv6 addresses, but the services exposed on each may differ. A web server might listen on port 443 on its IPv4 address (behind a load balancer) but expose the same service directly on its IPv6 address (bypassing the load balancer entirely). This is a real-world misconfiguration pattern that a pure IPv4 assessment would never find.
When a hostname resolves to both A and AAAA records, Nmap 7.96+ with --resolve-all scans both addresses in the same run. For assessments that must cover both protocols, the cleanest approach is two parallel runs against the same target set — one normal IPv4 scan, one with -6 against the AAAA equivalents — saved to separate output files and diffed with ndiff for comparison.
# Harvest IPv6 neighbors from the local router $ ip -6 neigh show | awk '{print $1}' | grep -v '^fe80' > ipv6_targets.txt # DNS brute-force including AAAA records $ sudo nmap --script dns-brute --script-args dns-brute.domain=example.com -6 # Scan a hostname resolving all addresses (IPv4 + IPv6 with --resolve-all) $ sudo nmap --resolve-all -sV example.com # Parallel dual-stack assessment $ sudo nmap -sS -sV -T4 -iL ipv4_targets.txt -oA ipv4_scan & $ sudo nmap -6 -sS -sV -T4 -iL ipv6_targets.txt -oA ipv6_scan & $ wait && ndiff ipv4_scan.xml ipv6_scan.xml
How to Perform a Comprehensive Nmap Network Scan
Step 1: Install Nmap on your system
Install Nmap using your distribution package manager. On Debian and Ubuntu, run apt install nmap. On RHEL, Fedora, and CentOS, run dnf install nmap. On macOS, use brew install nmap or download the .dmg installer from nmap.org. On Windows, download the installer from nmap.org, which bundles the required Npcap packet capture driver. Verify the installation by running nmap --version to confirm the binary is accessible.
Step 2: Discover live hosts on the target network
Run a ping sweep against the target subnet using nmap -sn followed by the CIDR range, for example 192.168.1.0/24. This sends ICMP echo requests plus TCP SYN to port 443 and TCP ACK to port 80 when run as root, identifying which hosts are online without performing a port scan. Save the output to a file for use in subsequent steps.
Step 3: Scan ports with SYN scan and enable version detection
Target the live hosts discovered in the previous step by running a SYN scan with version detection enabled. Use nmap -sS -sV followed by the target addresses or an input file specified with -iL. Add -p- to scan all 65535 TCP ports, or use --top-ports 1000 for a faster pass. The SYN scan identifies open, closed, and filtered ports, while version detection interrogates open ports to determine the specific application and version running on each one.
Step 4: Enable OS detection and run default NSE scripts
Add the -O flag to enable OS detection and -sC to run the default set of NSE scripts. Alternatively, use the -A flag, which combines OS detection, version detection, script scanning, and traceroute into a single option. OS detection works best when Nmap finds at least one open and one closed TCP port on the target. Review the script output for additional service details, SSL certificate information, and potential misconfigurations.
Step 5: Save results in multiple output formats for analysis
Use the -oA flag followed by a base filename to save results simultaneously in normal text, XML, and grepable formats. The XML output integrates with tools like Metasploit, OpenVAS, and custom parsers. Review the normal output for a readable summary. Use the grepable format for quick command-line filtering with grep and awk. For HTML reports, convert the XML output using an XSLT stylesheet.
Frequently Asked Questions
A TCP SYN scan (-sS) sends a SYN packet and immediately sends RST after receiving SYN/ACK, never completing the three-way handshake. This is faster and less likely to be logged by applications. A TCP Connect scan (-sT) completes the full three-way handshake using the operating system connect() call, which is slower and generates log entries on the target, but does not require root or administrator privileges to run.
Many of Nmap's scanning techniques require root or administrator privileges because they rely on sending raw packets. Without elevated access, Nmap falls back to a TCP Connect scan (-sT), which uses the standard connect() system call. SYN scans, UDP scans, OS detection, and several other advanced features all require raw socket access, which means root on Linux and macOS or Administrator on Windows.
NSE allows users to write and execute Lua scripts that automate networking tasks during a scan. It extends Nmap beyond basic port scanning into vulnerability detection, brute-force authentication testing, advanced service enumeration, and even exploitation. NSE ships with 612 scripts and 139 libraries organized into 14 categories including auth, brute, default, discovery, exploit, safe, and vuln, and users can write custom scripts to meet specialized requirements.
As of early 2026, the latest stable release is Nmap 7.99, released March 26, 2026. It fixed a reverse-DNS performance regression introduced in 7.98, resolved a macOS issue with incorrect MAC address reporting, added support for VPN virtual adapters on Windows (including OpenVPN TAP adapters), and updated bundled libraries to OpenSSL 3.0.19, libpcap 1.10.6, and Npcap 1.87. Nmap 7.98 (August 2025) had addressed CVE-2025-43715 by rebuilding the Windows self-installer with NSIS 3.11 — a race condition in earlier NSIS versions that could allow local privilege escalation if the installer was run as SYSTEM, though the Nmap installer does not run as SYSTEM by default. The full changelog is available at nmap.org/changelog.html.
UDP scans are inherently slower because open and filtered ports rarely respond, forcing Nmap to wait for timeouts. To speed things up, scan only the ports you care about with -p instead of scanning all 65535. Use --version-intensity 0 with -sV to limit version detection probes. Increase the minimum packet rate with --min-rate. Scan from behind the firewall when possible to avoid ICMP rate limiting imposed by the target host. On Linux, the kernel limits ICMP port unreachable messages to one per second by default, which alone can make a full UDP scan take over 18 hours.
A closed port is reachable -- Nmap's probes successfully arrived at the host -- but no application is listening, so the host responds with a TCP RST packet. A filtered port produces no response at all because a firewall or packet filter is silently discarding Nmap's probes before they reach the host, or is discarding the replies before they return. Closed ports are confirmed absences of services. Filtered ports are ambiguous: the service might be there but protected. Filtered results also slow scans considerably because Nmap must retransmit probes and wait for configurable timeouts before accepting that no response is coming.
The -A flag is a convenience shortcut that enables four features simultaneously: OS detection (-O), version detection (-sV), default NSE script scanning (-sC), and traceroute (--traceroute). It produces a comprehensive profile of a target in one command at the cost of being more intrusive and slower than a simple port scan. Because it runs scripts and sends additional probes, it is more likely to be logged by the target. Use it when thoroughness matters more than stealth, and always with proper authorization.
Yes. Add the -6 flag to enable IPv6 mode. Most of Nmap's scan types -- SYN scans, version detection, OS detection, and NSE scripts -- work over IPv6 with no other changes required. The main limitation is host discovery: IPv6 subnets are too large to brute-force sweep, so you need a pre-built target list from DNS AAAA records, router neighbor tables, or asset inventory. On a local network segment, scanning the link-local all-nodes multicast address (ff02::1) can enumerate IPv6-capable hosts. Decoy scanning and idle scanning are not supported over IPv6.
Nmap itself is a lawful tool, and using it is legal on networks you own or have explicit written permission to scan. The legal risk arises from scanning without authorization. In the United States, unauthorized network scanning can violate the Computer Fraud and Abuse Act (CFAA). The EU's Computer Misuse legislation and the UK's Computer Misuse Act contain similar provisions. Several countries treat unauthorized port scanning as a criminal act regardless of whether damage occurs. Even on cloud infrastructure like AWS, Azure, and GCP, scanning your own instances may require prior notification under the provider's acceptable use policy. The practical rule: scan only what you own or have a signed authorization to test, keep that authorization in writing, and confirm cloud provider policy before running any scan.
A port listed as tcpwrapped in the VERSION column means the TCP three-way handshake completed — the port is genuinely open and the host accepted the connection — but the remote service closed the connection immediately without sending any application data. Nmap's probes received no banner or response to match against, so it could not identify the service. The name comes from the tcp_wrappers access control system, which accepts connections and then immediately drops them if the connecting host fails an ACL check. In practice, tcpwrapped results usually indicate: tcp_wrappers blocking your source IP, a host-based firewall accepting at the TCP level but blocking at the application layer, or a service that demands immediate TLS and discards plaintext connections. Trying from a different source address or adding --version-intensity 9 can help identify which situation applies.
Masscan and Rustscan are purpose-built for raw speed. Masscan can theoretically scan the entire IPv4 internet in under six minutes at maximum rate; Rustscan wraps Nmap with a fast async port discovery step to reduce total scan time. Neither has Nmap's version detection, OS fingerprinting, NSE scripting, or output ecosystem. They are best used as a first-pass to rapidly identify open ports across large address spaces, with Nmap then directed at the results for detailed enumeration. Shodan is fundamentally different — it is a search engine over continuously updated scan data collected by Shodan's own infrastructure. You query it rather than running scans yourself, which means it requires no authorization to search but returns data that may be days or weeks old and cannot be targeted at a specific moment in time. Nmap is what you use when you need current, precise, deep data about a specific authorized target. Shodan is what you use to understand an organization's internet-facing exposure at a high level before a scoped engagement.
The open|filtered state means Nmap received no response — it cannot distinguish between a port that is open but silently dropping probes and a firewall dropping them. The practical resolution steps are: first, try a TCP Connect scan (-sT) on that port — if it completes the handshake, the port is open and a stateful firewall is blocking the SYN scan. Second, try version detection (-sV) on that specific port — if a service responds to the version probe, the port is open. Third, try scanning from a different source address or using -g 53 (source port spoofing) to see whether the firewall rules are source-dependent. If none of these produce a response and the port remains open|filtered, it is most likely filtered rather than open — but the only certain way to know is to scan from a position with less filtering between you and the target.
The standard approach is to schedule periodic Nmap scans with cron or a task scheduler, save results in XML format with timestamped filenames, and use ndiff to compare consecutive scans. A minimal weekly monitoring setup on Linux looks like this: schedule sudo nmap -sS -sV -T4 -oX /var/nmap/$(date +%Y%m%d).xml 10.0.0.0/24 in cron, then run ndiff /var/nmap/last_week.xml /var/nmap/this_week.xml to surface any new hosts, closed services, or version changes. Ndiff's output is human-readable and can be emailed or piped into a ticketing system. For larger environments, commercial tools like Tenable.io and Qualys build on this pattern with a more complete asset tracking layer, but for internal network baselines, scheduled Nmap plus ndiff covers the core use case without additional tooling.
-sV performs version detection: it interrogates each open port and identifies the software name and version running on it, populating the VERSION column in Nmap output. -sC runs the default NSE scripts: it executes a curated set of Lua scripts that perform additional tasks beyond version identification, such as grabbing SSL certificate details, enumerating HTTP headers, checking for anonymous FTP, and discovering SMB shares. They address different questions — -sV answers "what software is this?" while -sC answers "what else can I learn about it?" Several default scripts require version information to decide whether to run, so omitting -sV when using -sC causes those scripts to skip ports they should check. For thorough enumeration, always pair them: nmap -sV -sC.
NSE has targeted scripts for both. For SSL certificates, run nmap --script ssl-cert -p 443 target to retrieve certificate subject, issuer, validity dates, and SANs. To check cipher suite strength, run nmap --script ssl-enum-ciphers -p 443 target — it grades each accepted cipher from A to F and flags legacy protocols. For HTTP server headers, run nmap -sV --script http-headers -p 80,443 target. For HTTP method enumeration (detecting PUT, DELETE, TRACE), run nmap --script http-methods -p 80,443 target. The http-enum script probes hundreds of common paths looking for exposed admin panels, configuration files, and directories. Run nmap --script http-enum -p 80,443 target for a fast first-pass against a web server.
Nmap installed via a Linux package manager may lag the upstream release by weeks or months. If you installed it over six months ago, run nmap --version and compare to the current version at nmap.org/changelog.html. To update via apt, run sudo apt update && sudo apt upgrade nmap; via dnf, run sudo dnf upgrade nmap. For Windows, download the latest installer from nmap.org/download. If you have manually added scripts to the scripts directory, rebuild the index with sudo nmap --script-updatedb — without this step, Nmap cannot find scripts by name or category. The scripts directory location on your system is shown by running nmap --datadir.
Common Mistakes and What They Actually Mean
Even experienced practitioners run into these. Each one involves a behavior that is technically documented but rarely explained in plain terms.
Scanning without -Pn and getting no results on live hosts
If you run a port scan and get "0 hosts up" on a network you know has live machines, the first thing to check is whether ICMP is being filtered. Nmap's default discovery sends ICMP echo and TCP probes before port scanning — if all of them are blocked, Nmap marks hosts as down and skips the port scan entirely. Add -Pn to skip discovery and scan unconditionally. You will get results even on hosts that silently drop all discovery probes.
Getting "filtered" on every port of an apparently live host
All-filtered results usually mean one of three things: a stateful firewall is dropping all inbound SYN packets, the host is behind a NAT device that is not forwarding the traffic, or the host is responding only on non-standard ports. Switch to -sA (ACK scan) to map the firewall ruleset. If ACK probes get RST responses on certain ports, those ports are reachable even though they appear filtered to SYN scans. This gives you the firewall's allow list without the port actually being open.
Using -A against production systems
The -A flag is convenient for lab use but inappropriate for scanning production infrastructure during business hours without explicit approval for each component it enables. OS detection sends unusual probe patterns. Default NSE scripts actively interact with services — http-auth attempts authentication, smb-os-discovery makes SMB connections, ssl-cert initiates TLS handshakes. Each of these leaves entries in application logs. A conservative approach for production scans is to run phases separately: port scan first, then selectively run only the specific scripts needed rather than the full default set.
Confusing -sV slowness for a hung scan
A scan that appears to stall on a specific port is almost always version detection waiting for a service response timeout. Services like filtered ports, half-open firewalls, and certain custom daemons can hold a TCP connection open without sending data, forcing Nmap to wait out the probe timeout. Check the scan status by pressing p — if you see a port listed as currently being probed with a high retry count, this is what is happening. Use --host-timeout to cap total time per host, and consider adding --max-retries 2 to reduce retransmission cycles on unresponsive ports.
Treating nmap-services port names as authoritative
When Nmap reports "80/tcp open http," it is not confirming HTTP is running — it is saying a service is listening on a port associated with HTTP in the nmap-services file. The actual service could be anything. This matters because security tools that generate reports from Nmap XML often inherit this assumption and label the finding as an HTTP issue when the underlying service is entirely different. Always run -sV to confirm what is actually serving on an open port before drawing conclusions about the service type.
Mistaking a clean scan for a failed scan
When Nmap finishes and shows no open ports, beginners often assume something went wrong. Nmap distinguishes between a scan that found nothing and a scan that did not run properly. A successful scan that found nothing produces output like Not shown: 1000 closed ports or Not shown: 1000 filtered ports — these messages confirm Nmap reached the host and received responses. A scan that silently skipped a host produces Note: Host seems down followed by suggestions to use -Pn. If you see a completed scan report with a host and a port table but no open ports, the scan worked — the host just has no listening services on the ports you checked. If you see no host entries at all, Nmap did not consider those hosts up.
Scanning Docker containers and cloud instances
Container networking introduces a subtlety that catches people scanning their own infrastructure. Docker containers by default use bridge networking with internal IPs (typically 172.17.0.0/16) that are not directly routable from the host's external interface. Scanning the host's external IP does not scan the container — it scans whatever ports Docker has explicitly published with -p. To scan a container directly, either scan from within the Docker bridge network, use the container's internal IP, or run Nmap inside the container itself. On cloud instances, security groups and network ACLs at the cloud layer may block probes before they reach the instance, making a scan from outside the VPC produce all-filtered results even if the instance itself has no host firewall at all. Scanning from within the same VPC or subnet gives you the actual instance exposure rather than the filtered external view.
Sources and Further Reading
The commands, flag descriptions, and technical claims in this guide are verified against primary Nmap documentation. Key sources used in research and fact-checking:
Nmap 7.99 Changelog — nmap.org/changelog.html. The authoritative release history for all Nmap versions. Documents CVE-2025-43715 in 7.98 (the Nmap installer does not run as SYSTEM by default, so exploiting the vulnerability required a non-default installation scenario), the Npcap upgrades through 1.87 in 7.99, VPN virtual adapter support added in 7.99, the macOS MAC address fix in 7.99, and the parallel forward DNS improvement and three new NSE scripts added in 7.96.
Nmap Network Scanning (Official Book) — nmap.org/book. Gordon Lyon's full technical reference, covering the scan engine phases, timing algorithms, OS detection fingerprinting, and version detection probe matching in depth. Freely available online.
Nmap Service and Version Detection Documentation — nmap.org/book/man-version-detection.html. Official documentation describing the nmap-service-probes file format, version intensity levels 0–9, and how SSL/TLS wrapping is handled during service interrogation.
NSEDoc Reference Portal — nmap.org/nsedoc. The complete index of all current NSE scripts and 139 libraries, with documentation for each script's arguments, categories, and usage. The script count as of Nmap 7.96 reached 612; subsequent releases may have added additional scripts.
Nmap Man Page: Timing and Performance — nmap.org/book/man-performance.html. Official documentation confirming T0 serializes scanning with a 5-minute delay between probes, T1 uses 15 seconds, and T2 uses 0.4 seconds.
Phrack Magazine Issue 51, Article 11 — nmap.org/p51-11.html. The original "Art of Port Scanning" article by Fyodor (Gordon Lyon), published September 1, 1997 — the document that introduced Nmap to the world.
Nmap 7.95 Release Announcement — seclists.org/nmap-announce/2024/0. Primary source confirming that the nmap-service-probes database covers 1,246 protocols as of the 7.95 release (April 2024). The protocol count has not decreased in subsequent releases.
Nmap Scripting Engine Documentation — nmap.org/book/man-nse.html. Official reference for NSE script selection syntax, script arguments, script categories, and the --script-trace and --script-updatedb flags.