Scanning Hosts and Networks with Nmap
Nmap ("Network Mapper") is the de facto standard tool for host discovery, port scanning, service and version detection, OS fingerprinting, and scriptable network reconnaissance. It is equally useful for legitimate security assessment and for attack reconnaissance β the exact same command that maps your own network's attack surface is what an adversary runs against it. This article is a practical how-to for using nmap for host and network scanning, with a dedicated focus on scanning safely β without crashing fragile devices, saturating constrained links, or generating an unplanned incident response.
Before you scan anything: only scan hosts and networks you own or have explicit written authorization to test. Unauthorised scanning of systems you don't control is illegal in most jurisdictions (e.g. under the US Computer Fraud and Abuse Act, the UK Computer Misuse Act, and equivalent laws elsewhere) even when no damage results. For any assessment beyond your own lab, get a signed rules-of-engagement document defining scope, timing windows, and an emergency contact before you start β and notify the network/security operations team so scan traffic isn't mistaken for a real attack.
What Nmap Does
| Capability | Purpose |
|---|---|
| Host discovery | Determine which hosts in a range are up, without necessarily port-scanning them |
| Port scanning | Determine which TCP/UDP ports are open, closed, or filtered |
| Service/version detection | Identify what software and version is listening on an open port |
| OS detection | Fingerprint the target's operating system from TCP/IP stack behaviour |
| Nmap Scripting Engine (NSE) | Run scripts for deeper enumeration, vulnerability checks, and some brute-force/authentication testing |
Basic syntax:
nmap [scan type] [options] <target>
Targets can be a single IP, hostname, CIDR range (10.0.0.0/24), range (10.0.0.1-50), or a file of targets (-iL targets.txt).
Host Discovery
Before scanning ports, it's usually more efficient β and lower-impact β to first find out which hosts in a range are actually alive.
# Ping sweep only β no port scan
nmap -sn 10.0.0.0/24
| Discovery Option | Method |
|---|---|
-PE |
ICMP echo request |
-PS<ports> |
TCP SYN ping to specified ports |
-PA<ports> |
TCP ACK ping to specified ports |
-PU<ports> |
UDP ping to specified ports |
-PR |
ARP ping (used automatically, and most reliably, on a local Ethernet segment) |
-Pn |
Skip host discovery entirely β treat every target as up |
-Pn is useful when ICMP and common probe ports are filtered by a firewall (causing real hosts to appear "down"), but it forces a full port scan against every address in the range, including ones that aren't actually live β a significant, often unnecessary, increase in scan volume. Use it deliberately, not by default.
Port Scanning Techniques
| Scan Type | Flag | How It Works | Notes |
|---|---|---|---|
| TCP SYN scan | -sS |
Sends a SYN, never completes the handshake ("half-open") | Default when run with raw-socket privileges (root/admin); fast and relatively quiet |
| TCP connect scan | -sT |
Completes the full three-way handshake via the OS socket API | Used automatically when raw sockets aren't available; more visible in target logs since it completes real connections |
| UDP scan | -sU |
Sends UDP probes; relies on ICMP port-unreachable responses to infer closed ports | Slow and can generate significant ICMP traffic β see safety notes below |
| TCP ACK scan | -sA |
Used to map firewall rule sets (filtered vs unfiltered), not to determine open/closed | Doesn't determine open ports on its own |
| FIN / NULL / Xmas scans | -sF / -sN / -sX |
Send unusual TCP flag combinations that some older/stateless firewalls don't handle correctly | Primarily useful against legacy or misconfigured stateless filtering; behaviour on modern stacks varies |
| IP protocol scan | -sO |
Determines which IP protocols (TCP, UDP, ICMP, GRE, etc.) are supported |
Port Selection
nmap -p 22,80,443 10.0.0.5 # specific ports
nmap -p 1-1024 10.0.0.5 # a range
nmap -p- 10.0.0.5 # all 65535 ports
nmap -F 10.0.0.5 # fast mode β top 100 common ports only
nmap --top-ports 1000 10.0.0.5 # the N most common ports
Scanning all 65,535 ports takes considerably longer and generates considerably more traffic than a top-ports scan β reserve -p- for hosts you've already identified as interesting, not as a default for every host in a large range.
Service, Version, and OS Detection
nmap -sV 10.0.0.5 # service/version detection
nmap -sV --version-intensity 5 10.0.0.5 # 0 (light) to 9 (try everything) β default is 7
nmap -O 10.0.0.5 # OS detection (requires raw-socket privileges)
nmap -A 10.0.0.5 # OS detection + version detection + default scripts + traceroute
-A is convenient but is the heaviest, noisiest single flag in common use β it combines several detection techniques and generates substantially more probe traffic and target interaction than a plain port scan. Treat it the same way as --script vuln: fine against a specific host you're deliberately investigating, not something to run indiscriminately across a whole subnet.
The Nmap Scripting Engine (NSE)
NSE scripts extend nmap with deeper enumeration, configuration auditing, and vulnerability/credential checks.
nmap -sC 10.0.0.5 # run the "default" script set (safe, low-impact)
nmap --script=default 10.0.0.5 # equivalent to -sC
nmap --script vuln 10.0.0.5 # vulnerability-detection scripts
nmap --script "http-*" 10.0.0.5 # all scripts matching a name pattern
nmap --script-args user=admin,pass=admin --script http-brute 10.0.0.5
| NSE Category | Risk Level | Notes |
|---|---|---|
safe |
Low | Scripts that shouldn't crash services or affect the target |
default (-sC) |
Low | The curated safe subset run automatically with -sC/-A |
discovery |
LowβMedium | Enumerates additional information (shares, users, DNS records) |
version |
Low | Assists version detection |
auth |
Medium | Tests authentication bypass β can trigger account lockouts on some systems |
brute |
High | Credential brute-forcing β noisy, can lock out accounts, always requires explicit authorisation |
vuln |
High | Checks for specific known vulnerabilities β some checks are inherently invasive |
intrusive |
High | May crash services or affect target stability; never run without authorisation and awareness |
dos |
Critical β avoid | Scripts that intentionally test denial-of-service conditions. Do not run against anything you don't explicitly intend to potentially crash, ever, in or outside a test window |
Nmap itself blocks the dos and exploit categories from running when you use --script vuln or --script default β you have to opt into them explicitly by name. Treat that as a hard boundary, not an inconvenience to work around, outside of a deliberately destructive test on a disposable lab target.
Output Formats
nmap -oN scan.txt 10.0.0.0/24 # normal human-readable output
nmap -oX scan.xml 10.0.0.0/24 # XML β parseable by other tools, SIEMs, reporting pipelines
nmap -oG scan.gnmap 10.0.0.0/24 # "grepable" format β legacy but still widely scripted against
nmap -oA scan 10.0.0.0/24 # all three formats at once, sharing the base filename
Keep scan output on file for every assessment β it's the record you'll need if a service incident is reported during or shortly after your scan window and you need to quickly confirm or rule out your scan as the cause.
Scanning Safely: Avoiding Service Impact
This is the part that matters most in any environment you actually care about staying up. Aggressive, poorly-scoped scanning is a well-documented cause of crashed devices, saturated links, and unplanned incidents β not because nmap is inherently dangerous, but because naive defaults assume a robust, high-bandwidth target that many real devices are not.
Timing Templates
nmap -T0 10.0.0.5 # paranoid β extremely slow, IDS evasion
nmap -T1 10.0.0.5 # sneaky
nmap -T2 10.0.0.5 # polite β reduces bandwidth/target load, recommended default for production
nmap -T3 10.0.0.5 # normal (nmap's default)
nmap -T4 10.0.0.5 # aggressive β assumes a fast, reliable network
nmap -T5 10.0.0.5 # insane β assumes an exceptionally fast network; high risk of missed results and target impact
Use -T2 (or explicit rate limiting, below) as the default against production networks, especially anything you don't have complete visibility into. Reserve -T4/-T5 for isolated lab environments or networks you know to be robust and lightly loaded.
Explicit Rate Limiting
Timing templates are a blunt instrument β for real control, set rates directly:
nmap --max-rate 50 10.0.0.0/24 # cap outgoing packets per second
nmap --min-rate 10 --max-rate 100 10.0.0.0/24
nmap --scan-delay 100ms 10.0.0.5 # fixed delay between probes
nmap --max-retries 1 10.0.0.5 # reduce retransmission storms against lossy/fragile links
--max-rate is the single most reliable lever for avoiding overwhelming a target or a constrained link β set it explicitly rather than trusting a timing template alone when scanning anything sensitive.
Fragile Devices Deserve a Lighter Touch
Certain device classes are well-documented as prone to instability or outright crashing under scan load β not from malicious intent, just from old, minimal, or poorly-implemented TCP/IP stacks that were never designed to handle scan traffic gracefully:
- OT/ICS equipment (PLCs, HMIs, industrial gateways) β some devices have crashed or entered a fail-safe state from ordinary port scans, let alone
-O,-A, or vulnerability scripts - Networked printers, UPS management cards, IP phones, and building-management devices β frequently run minimal embedded stacks with poor tolerance for unusual traffic
- Legacy or unmaintained servers running old OS/network stack versions
Recommended profile for fragile/OT environments:
nmap -sT -T2 --max-rate 10 --max-retries 1 -p 80,443,22,502 <target>
Prefer -sT (full connect) over -sS in these environments β counterintuitively, a clean, complete handshake is often less likely to confuse a poorly-implemented stack than a half-open SYN scan. Avoid -O, -A, and any --script beyond safe/discovery entirely. Where the environment is genuinely fragile (safety-critical OT), consider passive network monitoring or vendor-approved discovery tools instead of active scanning altogether β this is standard OT security practice for good reason.
Scope Narrowly, Escalate Deliberately
Don't run a wide, deep scan (-p- -A --script vuln) against an entire range in one pass. Use a two-phase approach instead:
# Phase 1 β lightweight discovery across the full range
nmap -sn 10.0.0.0/24 -oG discovery.gnmap
# Phase 2 β extract only the live hosts...
grep "Status: Up" discovery.gnmap | awk '{print $2}' > live_hosts.txt
# ...and run a deeper scan only against those
nmap -sV -sC -T2 --max-rate 50 -iL live_hosts.txt -oA deep_scan
This avoids wasting time and traffic on dead addresses, and confines any heavier probing to hosts you've already confirmed exist. Reserve -A, --script vuln, and -p- for a further, third pass against specific hosts of interest β not the whole range.
UDP Scanning Needs Extra Care
UDP scanning is inherently slower and noisier than TCP β closed-port detection relies on ICMP port-unreachable responses, and many networks rate-limit ICMP, causing nmap to wait out retries. Scope UDP scans to a small, specific port list rather than a full 65,535-port sweep, and expect it to generate a burst of ICMP traffic that can itself trip IDS/IPS alerting thresholds.
nmap -sU -p 53,67,123,161,500 --max-rate 20 10.0.0.0/24
Expect (and Plan For) Security Tooling Reactions
Scan traffic is exactly what intrusion detection, WAFs, and EDR are built to notice β as covered in Web Application Firewall, the Nmap Scripting Engine is explicitly named as a signature WAFs block and alert on by default. Before scanning through or near production security tooling:
- Notify the SOC/security operations team of the scan window and source IP(s) in advance
- Consider a temporary, time-boxed allowlist for the scanning source if the assessment specifically needs to reach past a WAF/IPS (only with the tooling owner's agreement β silently bypassing your own detection controls defeats the purpose of testing them)
- If the goal is specifically to validate that detection controls work, scan without an exception and confirm the expected alert fires β a legitimate, common use of nmap in a blue-team capacity
Coordinate Timing and Bandwidth
- Schedule heavier or
--script vuln-class scans outside business-critical hours where feasible, and treat it like any other change with a defined window - Throttle (
--max-rate) when scanning over constrained links (WAN, VPN, satellite) β an aggressive scan can saturate a low-bandwidth link and disrupt legitimate traffic on it long before it disrupts the targets themselves - Keep a log of exactly what was run, when, and from where β this is what lets you quickly rule your scan in or out if a service issue is reported during the window
Validating Detection Controls (Not Evading Them)
Some techniques are worth knowing specifically to test whether your own defences actually detect scanning β not to sneak past someone else's:
nmap -f 10.0.0.5 # fragment packets β tests whether IDS reassembles and inspects fragments
nmap -D RND:10 10.0.0.5 # decoy scanning β tests whether alerting correlates real source traffic correctly
nmap -g 53 10.0.0.5 # spoofed source port β tests port-based-trust firewall misconfigurations
Use these only against your own environment, with authorisation, specifically to validate that IDS/IPS/WAF alerting catches what it's supposed to β treat a scan that goes completely unnoticed as a detection gap to fix, not a success.
Pre-Scan Checklist
| Item | Priority | Notes |
|---|---|---|
| Written authorisation obtained for the specific scope and window | Critical | Non-negotiable β unauthorised scanning is illegal even without resulting damage |
| Security/network operations team notified of scan window and source IP | Critical | Prevents the scan itself from triggering an incident response |
| Target scope explicitly bounded (specific ranges, not "the whole network") | High | Avoids accidentally scanning out-of-scope or third-party systems |
Timing set to -T2 or explicit --max-rate for anything production/sensitive |
High | Default -T3/-T4 assumes a robust target that may not exist |
| OT/ICS, embedded, and legacy devices identified and given a lighter scan profile (or excluded) | Critical | These devices are the most common source of scan-induced outages |
| Two-phase approach used: discovery first, deep scan only against confirmed-live hosts | Medium | Reduces unnecessary traffic and scan time significantly |
-A, --script vuln, --script intrusive, and -p- reserved for specific hosts, not blanket range scans |
High | These are the heaviest, most impactful options in common use |
dos and exploit NSE categories never run outside a disposable, intentionally destructive lab test |
Critical | Nmap excludes these by default for good reason |
| UDP scans scoped to a specific port list, not a full sweep | Medium | UDP scanning is slow and can trigger ICMP-based alerting storms |
Scan output logged and retained (-oA) |
Medium | Needed to quickly confirm/rule out the scan if an incident is reported |
| Heavier scans scheduled outside business-critical hours where feasible | Medium | Treat as a coordinated change, not an ad hoc action |