Nmap Network Scanning: Host Discovery That Actually Works
- Discovery and port scanning are separate operations with separate failure modes β conflating them is why engineers trust incomplete inventories. Always run host discovery first, then scan only confirmed-live hosts. It's faster and more accurate.
- 'Filtered' does not mean 'secure.' It means secure from where you're scanning. Run your audits from multiple vantage points β external, internal, same-subnet β because an attacker after lateral movement sees a completely different firewall rule set than you do from your laptop.
- Reach for Nmap when you need fleet-level survey, OS fingerprinting, firewall rule validation, or documented audit artifacts. Reach for nc, curl, or ss when you need a quick answer about one host and one port β Nmap is a precision instrument, not a hammer.
I watched a senior engineer spend four hours trying to debug intermittent connectivity failures in a staging environment, running tcpdump, checking load balancer configs, restarting services β the whole circus. Turns out a misconfigured firewall was silently dropping ICMP packets, and every monitoring tool they had was treating those hosts as 'up' because nobody had actually verified discovery beyond a ping. One Nmap command would've cracked it in thirty seconds.
Network visibility is the thing teams ignore until it becomes the reason they're paged at 2am. In modern infrastructure β Kubernetes clusters, VPCs with complex security group rules, hybrid cloud environments stitched together with duct tape and prayer β you cannot assume you know what's running where. Services drift. Security groups get misconfigured. Shadow deployments happen. Nmap gives you ground truth when everything else is lying to you. It's not just a pentester's toy; it's a diagnostic instrument that belongs in every engineer's production toolkit, used carefully and with permission.
By the end of this, you'll know how to run targeted host discovery that doesn't trigger your own IDS, how to fingerprint services and OS versions for audit purposes, how to interpret the difference between filtered and closed ports, and how to tune scan timing so you get results without hammering a production network into the ground. You'll also know exactly when Nmap is the wrong tool β because reaching for a sledgehammer when you need a scalpel costs you uptime.
Host Discovery Without Killing the Network (or Getting Yourself Fired)
The default assumption most people bring to Nmap is that discovery equals ping. It doesn't. ICMP echo requests are the most aggressively filtered thing on most production networks. If you run nmap -sn 10.0.0.0/24 and get back a sparse list, you haven't found what's up β you've found what responds to pings. That's a very different statement.
Nmap's host discovery layer is smarter than that. It combines ICMP echo, ICMP timestamp, TCP SYN to port 443, and TCP ACK to port 80 by default when run as root. Each probe type evades a different class of firewall rule. A host that silently drops ICMP might still reply to a TCP SYN on 443 with a RST β which is enough. That RST proves the host exists. This is why discovery and port scanning are two separate phases, and treating them as the same operation is the rookie mistake that gives you a false picture of your network.
In a real infrastructure audit scenario β say you've inherited a legacy VPC and need to map what's actually reachable before a security review β you want maximum discovery coverage with minimum noise. The right move is to combine probe types explicitly, control timing, and log everything. Here's what that actually looks like against a /24 subnet in a controlled environment.
# io.thecodeforge β System Design tutorial # Scenario: Pre-security-review host discovery on an inherited VPC /24 subnet. # Goal: Maximum coverage, minimum false negatives, logged output for the audit trail. # Run as root or with sudo β raw socket access required for half-open scans. # ------ PHASE 1: DISCOVERY WITHOUT PORT SCANNING ------ # -sn : Skip port scan entirely β host discovery only. # -PE : Send ICMP echo requests (ping). Many hosts block this β we add it anyway. # -PP : Send ICMP timestamp requests. Gets past firewalls that block echo but allow timestamp. # -PS443,8443 : TCP SYN to 443 and 8443. A RST reply still proves the host is alive. # -PA80,8080 : TCP ACK to 80 and 8080. Stateless firewalls pass ACK; host sends RST = alive. # -PU53 : UDP probe to port 53. Catches DNS servers that block all TCP probes. # --min-parallelism: Run at least 100 probes in parallel β speeds up /24 significantly. # --max-retries 2 : Don't retry dropped packets more than twice β keeps scan time sane. # -oN : Normal output to file β human-readable, also your audit artifact. # -oG : Greppable output β useful for piping into other tools downstream. sudo nmap \ -sn \ -PE -PP \ -PS443,8443,22,3389 \ -PA80,8080,3306 \ -PU53,161 \ --min-parallelism 100 \ --max-retries 2 \ -oN /tmp/discovery_normal.txt \ -oG /tmp/discovery_greppable.txt \ 10.0.1.0/24 # ------ PHASE 2: PULL LIVE HOSTS FROM GREPPABLE OUTPUT ------ # grep 'Up' extracts only confirmed-alive hosts from the greppable file. # awk '{print $2}' isolates the IP address column. # This list feeds directly into Phase 2 port scanning β no guesswork. grep 'Up' /tmp/discovery_greppable.txt | awk '{print $2}' > /tmp/live_hosts.txt echo "Confirmed live hosts:" cat /tmp/live_hosts.txt # ------ PHASE 3: TARGETED PORT + SERVICE SCAN ON LIVE HOSTS ONLY ------ # -iL : Read targets from file β only scan confirmed-live hosts. # -sS : SYN scan (half-open). Faster, less likely to hit application logs. # -sV : Service version detection. Nmap sends probes and matches banner responses. # --version-intensity 5: Balanced intensity (0-9). 9 is thorough but slow; 5 catches 95% of services. # -O : OS fingerprinting. Requires root. Uses TCP/IP stack behaviour to guess OS. # --osscan-limit : Only attempt OS detection on hosts with at least one open and one closed port. # Without this flag, Nmap tries (and fails loudly) on filtered-only hosts. # -p : Scan common service ports. Adjust to your environment. # -T3 : Normal timing. T4 is faster but causes packet loss on congested networks. # --open : Only show ports that are open β cuts output noise by 80%. sudo nmap \ -iL /tmp/live_hosts.txt \ -sS \ -sV --version-intensity 5 \ -O --osscan-limit \ -p 22,80,443,3306,5432,6379,8080,8443,9200,27017 \ -T3 \ --open \ -oN /tmp/service_scan.txt \ -oX /tmp/service_scan.xml # XML output (-oX) feeds into tools like Nessus, Metasploit, or custom parsers. # Keep both formats β the XML is for machines, the normal is for humans reading the audit report. echo "Scan complete. Results in /tmp/service_scan.txt"
Host: 10.0.1.5 () Status: Up
Host: 10.0.1.12 () Status: Up
Host: 10.0.1.23 () Status: Up
Host: 10.0.1.47 () Status: Up
Confirmed live hosts:
10.0.1.5
10.0.1.12
10.0.1.23
10.0.1.47
Starting Nmap 7.94 ( https://nmap.org )
Nmap scan report for 10.0.1.5
Host is up (0.0021s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.6
80/tcp open http nginx 1.24.0
443/tcp open ssl/https nginx 1.24.0
9200/tcp open http Elasticsearch REST API 8.11.0
OS details: Linux 5.15 - 6.2
Nmap scan report for 10.0.1.12
Host is up (0.0018s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.6
3306/tcp open mysql MySQL 8.0.35
OS details: Linux 5.15 - 6.2
Nmap done: 4 IP addresses (4 hosts up) scanned in 14.32 seconds
Scan complete. Results in /tmp/service_scan.txt
nmap -sn without explicit probe flags on a cloud VPC will miss 30-60% of live hosts in my experience β security groups block ICMP by default on AWS and GCP. You'll get back a sparse list and think the network is clean. Add -PS443 -PA80 at minimum. If you're auditing and the host count looks suspiciously low, that's your sign.Port States Are a Diagnostic Language β Learn to Read Them
Open, closed, filtered. Most people understand 'open.' Far fewer understand the operational difference between 'closed' and 'filtered' β and that gap will burn you during incident response.
A closed port means the host is reachable and actively refused the connection. The TCP stack sent back a RST. This is useful information: the host exists, the network path is clear, but nothing is bound to that port. If you expect a service there and get 'closed,' the service is down. Not the network β the service.
A filtered port means Nmap sent probes and got nothing back β or got ICMP unreachable messages. Something between you and the target (or on the target itself, like iptables) is eating the packets without responding. This is the dangerous state. You can't tell if the host is even up. You can't tell if the service is running. The firewall is doing its job, which is exactly what attackers hate and what your security team loves. When you're debugging and everything is 'filtered,' you're not looking at a service problem β you're looking at a network policy problem.
Unfiltered is the fourth state people forget: the port is accessible, Nmap got through, but it can't determine open or closed. This shows up with ACK scans specifically, which are designed to map firewall rules rather than find open ports. Understanding when to use an ACK scan versus a SYN scan is the difference between debugging your firewall ruleset and actually finding services.
# io.thecodeforge β System Design tutorial # Scenario: You've deployed new security group rules in a staging environment # and need to verify exactly which ports are filtered vs closed vs open # before promoting to production. This is not pentesting β this is change validation. # ------ ACK SCAN: MAP FIREWALL RULES, NOT SERVICES ------ # -sA: ACK scan. Sends TCP ACK packets (not SYN). # Stateful firewalls drop ACK with no matching SYN in their table = FILTERED. # Stateless firewalls pass ACK through = host replies RST = UNFILTERED. # This tells you about firewall behaviour, NOT whether a service is running. # Use case: validate that your firewall is blocking what it should be blocking. sudo nmap \ -sA \ -p 22,80,443,3306,5432,6379,8080,9200 \ --reason \ 10.0.1.5 # --reason: Shows WHY Nmap assigned each state β the actual packet received. # Example output lines: # 22/tcp unfiltered ssh no-response (ACK passed, host replied RST) # 3306/tcp filtered no-response (firewall ate the packet) # Without --reason you're guessing. With it you're debugging. # ------ SYN SCAN WITH VERBOSE STATE REPORTING ------ # Now compare: what does a SYN scan show on the same host? # -sS: SYN scan. The standard. Half-open β sends SYN, interprets SYN-ACK (open) # or RST (closed) or nothing/ICMP unreachable (filtered). # -p-: Scan all 65535 ports. Expensive but complete. # Only do this on confirmed single targets, not ranges. # --reason: Essential for debugging. 'syn-ack' = open service. 'rst' = closed port. # -v: Verbose. Prints results as they arrive instead of waiting for full scan. sudo nmap \ -sS \ -p 1-1024 \ --reason \ -v \ 10.0.1.5 # ------ INTERPRETING THE RESULTS IN CONTEXT ------ # After running both scans, compare: # Port 3306: # ACK scan -> filtered (firewall is dropping) # SYN scan -> filtered (service unreachable) # Conclusion: MySQL is properly isolated. Security group is working. # # Port 9200 (Elasticsearch): # ACK scan -> unfiltered (ACK passes through) # SYN scan -> open (service is running and reachable) # Conclusion: Elasticsearch is PUBLICLY ACCESSIBLE. This is a P0 incident. # Fix: Restrict security group ingress on 9200 to internal CIDRs only. # I have personally seen Elasticsearch on 9200 exposed to the internet in THREE # separate production environments during audits. Every single time, the engineer # thought security groups were applied. They weren't. Verify with Nmap. Always.
Nmap scan report for 10.0.1.5
Host is up (0.0018s latency).
# ACK Scan output:
PORT STATE SERVICE REASON
22/tcp unfiltered ssh reset ttl 64
80/tcp unfiltered http reset ttl 64
443/tcp unfiltered https reset ttl 64
3306/tcp filtered mysql no-response
9200/tcp unfiltered http reset ttl 64
# SYN Scan output (ports 1-1024):
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 64
80/tcp open http syn-ack ttl 64
443/tcp open https syn-ack ttl 64
Nmap done: 1 IP address (1 host up) scanned in 8.41 seconds
Timing, Evasion, and Not Destroying Your Own Infrastructure
Nmap's timing templates (-T0 through -T5) are the most misused feature in the tool. Engineers see T5 ('Insane') and think 'faster is better.' Then they run it against a production database cluster and wonder why connection timeouts start spiking across the board. I've seen T5 scans cause legitimate application timeouts on the same network segment because the raw packet volume saturated the host's network interrupt handling.
Here's the actual mental model: T1 and T2 are for evading IDS. T3 is the sane default. T4 is for internal networks you control and trust. T5 is for CTF challenges and isolated lab machines, not production. There's no scenario where you should run T5 against anything a real user is touching.
Beyond timing, the evasion question comes up whenever you're scanning a network with an IDS in the path β which in a well-run organisation, is always. Nmap has fragmentation (-f), decoy scanning (-D), and source port manipulation (--source-port). None of these make you invisible. Modern IDS/IPS systems like Suricata reassemble fragmented packets before inspection. Decoys can be fingerprinted because Nmap's decoy implementation isn't perfect. These techniques buy you noise, not invisibility. Know what they do and more importantly, know their limits.
# io.thecodeforge β System Design tutorial # Scenario: Weekly automated security sweep of internal microservices in a # production VPC. Runs as a cron job. Must not cause application-level disruption. # Must complete within a 20-minute window during low-traffic period. # ------ TIMING TUNING FOR PRODUCTION NETWORKS ------ # -T3 : Normal timing. Max 1 probe per open port at a time. # Safe for production. Does not flood network buffers. # --min-rate 100 : Send at least 100 packets/second. # Without this, T3 can be painfully slow on clean networks. # --max-rate 300 : Hard cap at 300 packets/second. # Prevents Nmap from ramping up and causing collateral damage. # --scan-delay 10ms: Minimum 10ms between probes to the same host. # Critical for rate-limited hosts (some cloud instances throttle # at the hypervisor level and drop rapid repeated SYNs). sudo nmap \ -sS -sV \ -T3 \ --min-rate 100 \ --max-rate 300 \ --scan-delay 10ms \ -p 22,80,443,3000,3306,5432,6379,8080,8443,9090,9200 \ --open \ -oX /var/log/security-sweep/$(date +%Y%m%d)_sweep.xml \ 10.0.0.0/20 # ------ IDS-AWARE SCANNING: FRAGMENTATION + DECOYS ------ # This block is for educational understanding β use it only in environments # you own and only when explicitly testing IDS detection capability. # -f: Fragment packets into 8-byte chunks. # Older IDS systems can't reassemble before matching signatures. # Suricata 6+, Snort 3+: fully reassembles before inspection. -f does nothing. # Legacy appliances from 2015 and earlier: might slip through. # -D RND:10: Use 10 random decoy IP addresses alongside your real source IP. # IDS sees 11 sources scanning simultaneously β harder to attribute. # WARNING: The real source IP is still in the packet list. This is # obfuscation, not anonymisation. A careful analyst will find you. # --source-port 53: Spoof source port as 53 (DNS). # Old stateless firewalls trusted DNS source ports. # Modern stateful firewalls: this does nothing useful. # --data-length 25: Append 25 random bytes to packets. # Breaks signature matching on payload-length-sensitive rules. sudo nmap \ -sS \ -f \ -D RND:10 \ --source-port 53 \ --data-length 25 \ -T2 \ -p 80,443,22 \ 10.0.1.100 # T2 with evasion because -f + decoys slow packet processing significantly. # Running T4 with fragmentation causes your own OS to choke on reassembly. # ------ SCRIPT ENGINE FOR SERVICE-SPECIFIC CHECKS ------ # NSE (Nmap Scripting Engine) runs Lua scripts against discovered services. # These are NOT port scans β they're active probes that touch the application layer. # Run these only on confirmed non-production hosts unless the scripts are # explicitly safe (category: safe). # Check for anonymous FTP access: sudo nmap --script ftp-anon -p 21 10.0.1.0/24 # Check for HTTP security headers on all discovered web servers: sudo nmap --script http-headers -p 80,443,8080,8443 10.0.1.0/24 # Enumerate SSL/TLS cipher suites β useful for compliance audits (PCI-DSS): sudo nmap --script ssl-enum-ciphers -p 443,8443 10.0.1.5 # Check for open MongoDB with no auth (script from default category): sudo nmap --script mongodb-info -p 27017 10.0.1.0/24 # NEVER run --script=all or --script=vuln against production. # vuln category scripts actively exploit vulnerabilities. They will crash services. # I have personally watched --script=vuln take down a Redis instance # by triggering an unprotected FLUSHALL via the redis-info script chain.
Nmap scan report for 10.0.0.5
Host is up (0.0012s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1
443/tcp open ssl/https nginx 1.24.0
9090/tcp open prometheus Prometheus monitoring
Nmap scan report for 10.0.0.12
Host is up (0.0009s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1
6379/tcp open redis Redis key-value store
[ssl-enum-ciphers output for 10.0.1.5:443]
PORT STATE SERVICE REASON
443/tcp open https syn-ack
| ssl-enum-ciphers:
| TLSv1.2:
| ciphers:
| TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (ecdh_x25519) - A
| TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (ecdh_x25519) - A
| compressors: NULL
| cipher preference: server
|_ least strength: A
Nmap done: 4096 IP addresses (47 hosts up) scanned in 18 minutes 44 seconds
When Nmap Is the Wrong Tool and You're Making Things Worse
Nmap is a blunt instrument when precision is what you need. There are real scenarios where reaching for it costs you time, causes collateral damage, or gives you answers to the wrong question.
If you're debugging whether a specific service on a specific host is reachable from a specific source, curl, nc, or telnet are faster and produce less noise. Nmap takes 300ms to initialise even for a single-port scan. For a quick 'is port 5432 open from this Lambda function?' β nc -zv hostname 5432 answers in 50ms and doesn't require root or raw sockets.
If you're trying to understand traffic flows across your network β which hosts are actually talking to each other and on what ports β Nmap won't help. It shows you what's listening, not what's communicating. Use netstat, ss, or flow logs (VPC Flow Logs on AWS, Cloud Logging on GCP) for that. Nmap gives you a snapshot. Flow logs give you a timeline.
If you're in a container environment like Kubernetes, Nmap scans against pod IPs are almost useless for security auditing because the network topology underneath is ephemeral. Pods come and go. The IP that was an nginx sidecar at 9am is a Redis pod at 11am. For Kubernetes, you audit the network policies and service mesh config β not the live IP space. Tools like kube-hunter or trivy are purpose-built for that context. Nmap in a Kubernetes cluster is like using a voltmeter to debug a Kubernetes RBAC misconfiguration. Technically a tool, completely wrong tool.
# io.thecodeforge β System Design tutorial # Scenario: Deciding between Nmap and lighter tools based on the actual question. # This is the decision tree engineers skip and then wonder why their scan takes # 10 minutes to tell them something nc would've said in 2 seconds. # ------ QUESTION: Is a specific port open on a specific host? ------ # RIGHT TOOL: netcat. No root. No raw sockets. No delay. # -z: Zero I/O mode β just check connectivity, don't send data. # -v: Verbose β prints 'succeeded' or 'refused'. # -w 3: Timeout after 3 seconds. Without this, nc hangs on filtered ports forever. nc -zv -w 3 10.0.1.5 5432 # Output: Connection to 10.0.1.5 5432 port [tcp/postgresql] succeeded! # If it hangs for 3s and exits: filtered. If 'refused': closed but host is up. # ------ QUESTION: What version of a service is running on one host? ------ # RIGHT TOOL: curl or openssl for HTTP/HTTPS; nmap -sV only if banner not exposed. curl -sI https://10.0.1.5 | grep -i 'server\|x-powered-by' # Faster than nmap -sV for HTTP services. Gets you the same version banner. # Nmap -sV makes sense when the service doesn't expose version in HTTP headers. # ------ QUESTION: Who is the network talking to? ------ # RIGHT TOOL: ss (socket statistics). Shows active connections, not listening state. # -t: TCP sockets only. # -n: Don't resolve hostnames β faster, avoids DNS delays. # -p: Show process using each socket. # -a: All sockets (listening + connected). ss -tnpa # This tells you what IS communicating right now. # Nmap tells you what COULD communicate. Different questions. # ------ QUESTION: What's traversing the network between hosts? ------ # RIGHT TOOL: tcpdump. Captures actual traffic, not probed state. # -i eth0: Listen on eth0 interface. # -n: Don't resolve names β critical in production, DNS lookups slow capture. # 'host 10.0.1.12 and port 3306': Filter to MySQL traffic from/to target host. # -w: Write to pcap file for offline analysis with Wireshark. tcpdump -i eth0 -n 'host 10.0.1.12 and port 3306' -w /tmp/mysql_traffic.pcap # ------ WHEN NMAP IS ACTUALLY THE RIGHT CALL ------ # 1. You need to survey a /16 or larger and don't know what's there. # 2. You need OS fingerprinting to understand the fleet's OS diversity. # 3. You need to confirm firewall rules are working as designed (ACK scan). # 4. You're doing a formal security audit and need documented, reproducible output. # 5. You need NSE scripts to check for specific vulnerabilities (carefully). # For anything else β reach for the lighter tool first.
Connection to 10.0.1.5 5432 port [tcp/postgresql] succeeded!
# curl output:
Server: nginx/1.24.0
X-Powered-By: Express
# ss output (abbreviated):
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
ESTAB 0 0 10.0.1.5:443 203.0.113.42:51234 users:(("nginx",pid=1823,fd=12))
ESTAB 0 0 10.0.1.5:5432 10.0.1.12:49812 users:(("postgres",pid=2100,fd=8))
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1102,fd=3))
| Scan Type | Nmap Flag | Root Required | IDS Visibility | Use Case | Speed on /24 |
|---|---|---|---|---|---|
| SYN (Half-Open) Scan | -sS | Yes | Medium β RST flood pattern visible | Standard port discovery β most common | ~30 seconds at T3 |
| TCP Connect Scan | -sT | No | High β full 3-way handshake in app logs | Scanning without raw socket access (containers, unprivileged user) | ~2-5 minutes at T3 |
| ACK Scan | -sA | Yes | Low β looks like legitimate ACK traffic | Mapping firewall rules, not finding open ports | ~20 seconds at T3 |
| UDP Scan | -sU | Yes | Low β UDP rarely inspected deeply | Finding DNS, SNMP, TFTP, NTP services | ~20 minutes per 1000 ports |
| Ping Sweep (Discovery Only) | -sn | No (limited) | Very Low | Fast host enumeration before port scanning | ~5 seconds |
| Version Detection | -sV | Recommended | High β probes generate service-specific traffic | Service fingerprinting for audits | Adds 2-5x to scan time |
| OS Fingerprinting | -O | Yes | Medium β TCP option probes are detectable | Asset inventory, OS diversity auditing | Minimal overhead if combined with -sS |
| NSE Script Scan | --script | Varies | High β application-layer probes | Vulnerability checks, compliance validation | Highly variable per script |
π― Key Takeaways
- Discovery and port scanning are separate operations with separate failure modes β conflating them is why engineers trust incomplete inventories. Always run host discovery first, then scan only confirmed-live hosts. It's faster and more accurate.
- 'Filtered' does not mean 'secure.' It means secure from where you're scanning. Run your audits from multiple vantage points β external, internal, same-subnet β because an attacker after lateral movement sees a completely different firewall rule set than you do from your laptop.
- Reach for Nmap when you need fleet-level survey, OS fingerprinting, firewall rule validation, or documented audit artifacts. Reach for nc, curl, or ss when you need a quick answer about one host and one port β Nmap is a precision instrument, not a hammer.
- The counterintuitive truth: a half-open SYN scan (-sS) is less likely to appear in application logs than a full TCP connect scan (-sT), but it's MORE likely to be flagged by a modern IDS. 'Stealthy' is relative to what's watching β the application layer or the network layer. Know which threat model you're working within.
β Common Mistakes to Avoid
- βMistake 1: Running
nmap -sV -O --script=allon a production subnet β symptom: services start throwing 500 errors and one Redis instance flushes itself β fix: never combine --script=all with production targets; use specific safe scripts like--script=http-headers,ssl-enum-ciphersand explicitly exclude the 'exploit' and 'vuln' script categories with--script 'not (exploit or vuln)' - βMistake 2: Trusting -sn ping sweep results as a complete host inventory in cloud environments β symptom: your inventory shows 23 hosts, the actual VPC has 61, security review fails β fix: always combine probe types:
-PE -PP -PS443,22 -PA80at minimum; on AWS/GCP/Azure, cross-reference with the cloud provider's API (aws ec2 describe-instances) since ICMP is blocked by default - βMistake 3: Using -T5 timing on a shared network segment β symptom: application engineers report intermittent connection timeouts during the scan window, latency spikes from 2ms to 800ms, your scan never gets blamed because nobody correlates timing β fix: cap at -T3 for production-adjacent networks and always set
--max-rate 300explicitly; if speed is critical, scan in off-peak windows and document it - βMistake 4: Scanning without output flags and losing the results β symptom: you ran a 45-minute full-port scan, found 3 interesting services, closed the terminal, results gone β fix: always run with at minimum
-oN output.txt -oX output.xml; the XML output feeds directly into reporting tools and the normal output is human-readable for the audit record; treat scan output as an artifact, not a terminal session
Interview Questions on This Topic
- QNmap's SYN scan (-sS) is described as 'stealthy' but modern IDS systems detect it trivially. What does 'stealthy' actually mean in that context, what does it still hide from, and what technique would you use if you needed to genuinely reduce detectability against Suricata?
- QYou need to audit a /16 production network for exposed databases (MySQL, Postgres, MongoDB, Redis) on a weekly schedule without causing application disruption. Walk through your exact Nmap command construction β probe types, timing flags, port selection, output format β and explain every choice.
- QYou run an Nmap host discovery scan across a /24 subnet and get back 12 hosts. Your colleague insists there are at least 40 hosts in that range based on DHCP logs. What are the three most likely reasons for the discrepancy, and how do you resolve each one without touching the firewall rules?
Frequently Asked Questions
What is the difference between nmap -sS and nmap -sT and which should I use?
-sS (SYN scan) sends a SYN, waits for SYN-ACK or RST, then tears down without completing the handshake β faster, requires root, doesn't appear in application-level connection logs. -sT (TCP connect scan) completes the full 3-way handshake using the OS's socket API β slower, no root required, shows up as a real connection in service logs and is therefore more detectable by the application. Use -sS whenever you have root access and are on a network you control. Use -sT inside containers or environments where you don't have raw socket privileges β which in Kubernetes is almost always.
What's the difference between a filtered port and a closed port in Nmap output?
Closed means the host is reachable, the port is accessible, but nothing is listening β you got a RST back. Filtered means something ate the packet before it reached the target, or the target dropped it silently β no RST, just silence or an ICMP unreachable message. The practical rule: 'closed' is a service problem, 'filtered' is a network policy problem. If you expected MySQL on 3306 and got 'closed,' the database process is down. If you got 'filtered,' your firewall is doing its job and blocking you.
How do I run Nmap without triggering the IDS?
You can slow the scan with -T1 or -T2, fragment packets with -f, and use decoys with -D β but against any modern IDS like Suricata 6+ or Snort 3+, none of these make you invisible. They buy noise, not invisibility. What actually reduces detection is: lower timing (-T1), randomising port order (--randomize-hosts), and combining low-volume scanning with legitimate traffic windows. If you're legitimately auditing your own infrastructure, coordinate with the security team and whitelist your source IP in the IDS β stealth scanning your own network without coordination is just creating an incident for yourself.
Why does Nmap give different results when run as root versus a normal user?
Root access allows Nmap to use raw sockets, which is required for SYN scans (-sS), OS fingerprinting (-O), and most ICMP probe types. Without root, Nmap falls back to TCP connect scans (-sT) using the OS socket API β which is complete handshakes only, meaning you lose the half-open stealth, you can't do OS fingerprinting, and ICMP-based host discovery probes silently fall back to TCP-only probes. The result: non-root scans miss more hosts, can't fingerprint OSes, and are significantly slower because the OS socket layer adds overhead the raw socket path avoids. This matters in container environments where you almost never have root β design your scanning infrastructure accordingly.
Developer and founder of TheCodeForge. I built this site because I was tired of tutorials that explain what to type without explaining why it works. Every article here is written to make concepts actually click.