Step 81. Mastering nmap — The Standard Tool of Reconnaissance
Level 1 — Programming and the Inside of a Computer | Difficulty ★★★☆☆ | Estimated time: 3 hours
Prerequisites: Steps 79–80 complete. You’ve built the principles of port scanning (connect, SYN) with your own code. A Linux terminal (including WSL) is ready.
- What you need: a Linux terminal and nmap. Today’s scan target is strictly
127.0.0.1(your own computer) and nothing else. - Caution: ⚠️ All exercises in this chapter are for your own lab and legal platforms only. Applying them to unauthorized systems is a crime. Every hands-on measurement in this chapter was performed against
127.0.0.1only, on WSL Linux (Nmap 7.94SVN).
In Step 79 we built a port scanner ourselves. It worked well, but the world has a tool that has been honing this craft for over 25 years: nmap (Network Mapper). The first page of almost every penetration test report carries nmap’s output. Over the last two chapters you built the principles by hand, so today we handle the standard tool with those principles baked in. nmap’s output is compressed information — and you already have the knowledge to decompress it.
1. Learning Objectives
By the end of this chapter, you will be able to:
- Choose the right nmap option (
-sT/-sS/-sV/-O/--script) for the situation - Read nmap output and organize "open ports, services, versions, operating system"
- Explain experimentally the difference between a default scan (1000 ports) and a full scan (
-p-) - Save scan results to a
-oNfile to create a reproducible record
2. Background Knowledge — Today’s Tools and Concepts
Today’s Tools at a Glance
| Category | Details |
|---|---|
| Language/environment | Linux terminal (WSL or lab VM), nmap 7.94 |
| Today’s commands | nmap target, -sT/-sS (scan methods), -sV (version), -O (operating system), -sn (ping scan), --script (NSE), -p- (full scan), -oN (save to file) |
| Concepts needed | Port states (open/closed), banners, TCP 3-way handshake, the scanning principles from Steps 79–80 |
| Today’s artifact | A reconnaissance report on your own computer, scan_localhost.txt |
2-1. A Map of Scan Methods
nmap offers several scan methods as options. Let’s connect them to the principles we know.
-sT(connect scan): exactly the method we built in Step 79. It completes the connection to the end, so it’s accurate, but it leaves a connection record in the target’s logs. It’s the default when you don’t have privileges.-sS(SYN scan): the method we built in Step 80. It sends a SYN, listens only for the answer (SYN-ACK/RST), and never completes the connection. Fast and quiet, but because it must craft raw packets, administrator privileges (sudo) come along.-sU(UDP scan): inspects UDP ports (like DNS 53) instead of TCP. Since "no answer" is normal for this protocol, it’s slow and finicky.
2-2. Detection Options — From "What’s Open" to "Who Is There"
Port numbers alone aren’t enough. Even on the same port 80, which web server program it is matters.
-sV(version detection): connects to open ports, reads banners, and sends probe signals when needed to learn the service’s name and version. The evolved form of our banner grabbing.-O(OS guessing): guesses the operating system from the subtle habits of response packets (initial TTL, window size, and so on). Remember it’s a guess, not a confirmation — today’s measurements reveal this limit plainly.-sC/--script(NSE scripts): nmap ships with hundreds of built-in inspection scripts (NSE, Nmap Scripting Engine). They automatically perform tasks like reading web page titles and checking for known vulnerabilities.
2-3. Scope and Output
- Default scan: checks only the 1000 well-known ports. Fast, but it misses things.
-p-: checks every port (1–65535).--top-ports N: checks only the N most common ports.-oN file: saves results to a text file. The artifact of reconnaissance is always left as a file.
3. Follow Along
3-1. Preparation — Open a Practice Service
Scanning an empty computer teaches nothing, so let’s open a practice web server inside your own computer. It’s the simple server bundled with Python.
Input (terminal 1)
mkdir -p steplab && cd steplab
echo "<h1>hello plain world</h1>" > index.html
python3 -m http.server 8000
How to read it: this means "serving HTTP on port 8000." Don’t close this window for the rest of the exercises.
3-2. First Scan — The Basic Command
Input (terminal 2)
nmap 127.0.0.1
Output (measured 2026-09-09):
Starting Nmap 7.94SVN ( https://nmap.org ) at 2026-09-09 13:33 KST
Nmap scan report for localhost (127.0.0.1)
Host is up (0.0000020s latency).
Not shown: 999 closed tcp ports (reset)
PORT STATE SERVICE
8000/tcp open http-alt
Nmap done: 1 IP address (1 host up) scanned in 0.07 seconds
How to read it: three columns — port/protocol, state (STATE), and service name. The default scan checked the 1000 well-known ports; 999 of them were closed and only port 8000 was open. Here, http-alt in the SERVICE column is a conventional guess from the port number, not an actual verification. Real verification is -sV.
Why: this step familiarizes you with the simplest form of the output structure. You’ll see the shape of this table hundreds of times.
3-3. Version Detection — Revealing the True Identity
Input
nmap -sV -p 8000 127.0.0.1
Output (measured 2026-09-09):
PORT STATE SERVICE VERSION
8000/tcp open http SimpleHTTPServer 0.6 (Python 3.12.3)
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 6.21 seconds
How to read it: the VERSION column reveals the true identity. Not the conventional name http-alt, but the real thing — "SimpleHTTPServer 0.6 from Python 3.12.3." And look at the time: the default scan took 0.07 seconds, while version detection took 6.21 seconds. That’s the cost of nmap actually connecting, reading banners, and sending probe signals.
Why: this is why a penetration tester’s report says "OpenSSH 8.9p1 is running" instead of "a port is open." A version is an index into known vulnerabilities.
3-4. Make a Prediction — Do -sT and -sS Give Different Results?
Here’s a prediction. If you scan the same target with -sT (connect) and -sS (SYN) separately, will the result tables differ?
Input
nmap -sT -p 8000 127.0.0.1
sudo nmap -sS -p 8000 127.0.0.1
Output (measured 2026-09-09):
# -sT
8000/tcp open http-alt
Nmap done: 1 IP address (1 host up) scanned in 0.01 seconds
# -sS
8000/tcp open http-alt
Nmap done: 1 IP address (1 host up) scanned in 0.08 seconds
How to read it: the port lists of the two results are identical. The basis of judgment (completed connection vs. answer to a SYN) differs, but the conclusion — "which ports are open" — is the same. What differs is the process: speed, and the traces left in the target’s logs.
Why: verifying that "different methods reach the same conclusion" becomes grounds for trusting the tool. Conversely, on a day the results differ, it means a firewall treated the two differently — which is itself a discovery.
3-5. OS Guessing — A Guess Is a Guess
Input
sudo nmap -O 127.0.0.1
Output (measured 2026-09-09, excerpt):
PORT STATE SERVICE
8000/tcp open http-alt
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.94SVN%E=4%D=9/9%OT=8000%CT=1%CU=34824%PV=N%DS=0%DC=L%G=Y%TM=6AA0E19E ...
Network Distance: 0 hops
Nmap done: 1 IP address (1 host up) scanned in 11.27 seconds
How to read it: perhaps because responses from the loopback (yourself) are too clean, nmap honestly answered "No exact OS matches" and printed only the fingerprint. And it took 11.27 seconds — OS detection is a heavy inspection that sends many kinds of probe packets.
Why: a fine example of a tool’s output including the tool’s limits. The answer from -O is a clue, not a diagnosis, and "I don’t know" is also an honest answer.
3-6. Full Scan — What the Default Scan Misses
Input
nmap -p- 127.0.0.1
Output (measured 2026-09-09):
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE
8000/tcp open http-alt
33211/tcp open unknown
Nmap done: 1 IP address (1 host up) scanned in 0.35 seconds
How to read it: checking all 65535 ports turned up one more port absent from the default scan — 33211, whose service name is unknown. Something that was quietly running on this computer (actually a container management service) had been outside the default scan’s field of view. Scanning 65535 ports in 0.35 seconds — loopback responds instantly, so it’s fast.
Why: attackers look for services hiding outside the default 1000 ports. Defenders must look with the same eyes for "open doors I don’t know about on our equipment." The full scan is a fundamental skill for both sides.
3-7. The Identity of unknown — There Are Things Even -sV Doesn’t Know
Let’s run version detection against that port 33211.
Input
nmap -sV --version-intensity 2 -p 33211 127.0.0.1
Output (measured 2026-09-09, excerpt):
PORT STATE SERVICE VERSION
33211/tcp open unknown
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint ...
SF:(GetRequest,8F,"HTTP/1\.0\x20404\x20Not\x20Found\r\n ... \r\n404:\x20Pa
SF:ge\x20Not\x20Found") ...
Nmap done: 1 IP address (1 host up) scanned in 6.20 seconds
How to read it: the answer is "it returns data, but I can’t tell what service it is (unrecognized despite returning data)." Looking at the fingerprint, you can see a clue that this service answers something HTTP-like, "404 Page Not Found" — nmap sent a GET request as a probe and received a 404. --version-intensity 2 is an option that lowers the intensity of probe signals, ending conversations with finicky services quickly.
Why: -sV is not omnipotent. Absence from the output doesn’t mean there’s no service, and a name doesn’t mean it’s real. A critical reading eye is skill.
3-8. NSE Scripts — Attaching an Automatic Investigator
Input
nmap --script http-title -p 8000 127.0.0.1
Output (measured 2026-09-09):
PORT STATE SERVICE
8000/tcp open http-alt
|_http-title: Site doesn't have a title (text/html).
Nmap done: 1 IP address (1 host up) scanned in 0.11 seconds
How to read it: the indented line starting with |_ is extra information dug up by the NSE script. The http-title script connected to the web page, read its title, and reported that our practice page has no title. You can ask what a script does.
Input
nmap --script-help http-title
Output (measured 2026-09-09, excerpt):
http-title
Categories: default discovery safe
Shows the title of the default page of a web server.
The script will follow up to 5 HTTP redirects, using the default rules in the http library.
Why: nmap’s true power lies in this script ecosystem. You can’t memorize hundreds of them, so the ability to ask with --script-help and combine them is the substance of proficiency.
3-9. Ping Scan and Saving to a File
Before looking at ports, here’s the ping scan that only asks "are you alive?", plus how to save results to a file.
Input
nmap -sn 127.0.0.1
nmap -sV --version-intensity 2 -p- -oN scan_localhost.txt 127.0.0.1
Output (measured 2026-09-09):
# -sn
Nmap scan report for localhost (127.0.0.1)
Host is up.
Nmap done: 1 IP address (1 host up) scanned in 0.00 seconds
The first line of the saved file scan_localhost.txt (measured 2026-09-09):
# Nmap 7.94SVN scan initiated Wed Sep 9 13:37:10 2026 as: nmap -sV --version-intensity 2 -p- -oN scan_full.txt 127.0.0.1
How to read it: a file saved with -oN automatically records the scan date/time and the full command used on its first line. A "reproducible record" is made for free. This file is raw material we’ll parse with Python in the next chapter (Step 82) and turn into a risk table.
Why: a beginner scans and finishes; a professional scans and records. The only person who can answer when their future self asks, three months later, "what was open on this machine back then?" is the person who left a file with -oN today.
4. Missions & Exercises
Mission — Reconnaissance Report on Your Own Computer
- Open one more practice service. Add another simple server on a different port (e.g.,
python3 -m http.server 8080). - Create a default-scan report with
nmap -sV -oN scan_localhost.txt 127.0.0.1, and a full-scan report withnmap -p- -oN scan_full.txt 127.0.0.1. - Compare the two files and write in your notes "ports the default scan alone misses."
- If the full scan found ports you don’t recognize, investigate their identity with
-sV, and write the process and conclusion at the end of your report. - Check that the report’s header contains the scan date/time, target, and command used (recorded automatically by
-oN).
Exercises
Exercise 1. The result tables of -sT and -sS are the same — why do both methods exist? Explain what differs in the "process."
Exercise 2. The default scan’s SERVICE column says http-alt, while the -sV SERVICE column says http. Which should you trust, and on what grounds?
Exercise 3. A full scan (-p-) discovered 33211/tcp open unknown, which the default scan didn’t show. From a defender’s perspective, explain the meaning of this discovery and the next action.
Exercise 4. -sV answered "1 service unrecognized despite returning data." What does this mean, and where in the output is the clue for deducing the identity?
5. Model Answers & Completion Criteria
Mission Model Answer
Example mission run (based on the 2026-09-09 measurement environment):
# 1. Second practice service
cd steplab && python3 -m http.server 8080
# 2. Two reports
nmap -sV -oN scan_localhost.txt 127.0.0.1
nmap -p- -oN scan_full.txt 127.0.0.1
The default-scan report shows only ports 8000 and 8080, while the full-scan report additionally reveals a "quietly running service" like port 33211 (in the measurement environment, 33211/tcp open unknown — 2026-09-09). In your notes, write: "there can be open doors outside the default 1000, so inspections finish with a full scan."
Example of investigating an unknown port’s identity:
nmap -sV --version-intensity 2 -p 33211 127.0.0.1
ss -tlnp | grep 33211 # which program opened it (requires admin privileges)
In the measurement, the 404: Page Not Found response in the fingerprint confirmed "a service that answers in an HTTP-like way," and the ss command finally confirmed the port was opened by a container management program. How to verify: ① both report files exist with the full command on the first line. ② "missed ports" are written in the notes as concrete numbers. ③ the reasoning process for the unknown port’s identity (which commands you used and what you based your judgment on) is recorded.
Exercise Answers
Answer 1. The conclusion (the list of open ports) is the same, but the process differs. -sT completes the connection to the end, so it leaves a connection record in the target service’s logs; -sS stops the handshake midway, so it leaves fewer traces and is faster. Privilege requirements differ too — -sS needs administrator privileges because it must craft raw packets.
Answer 2. Trust -sV. The default scan’s name is merely a conventional guess from the port number (a lookup in the port-number table), not an actual verification. -sV actually connects and analyzes banners and responses, so it has grounds. In the measurement too, the same port 8000 changed from http-alt (guess) to http — SimpleHTTPServer 0.6 (confirmed).
Answer 3. It means "there’s an open door I don’t know about on this equipment," which is exactly a hidden square of the attack surface. Next actions: investigate the identity with -sV, confirm which program opened it with a command like ss -tlnp, then shut it down or block it if it’s unnecessary. Leaving an unknown port unknown is the worst choice.
Answer 4. It means "the service responds, but its shape isn’t in nmap’s database." The clue is in the fingerprint printed right below — in the measured fingerprint, the response to the GetRequest probe reads HTTP/1.0 404 Not Found, letting you deduce that this service answers in HTTP format.
Completion Criteria Checklist
- [ ] I can explain the difference in the SERVICE column between a default scan and
-sV - [ ] I can explain the difference between
-sTand-sSin terms of process (traces, privileges) - [ ] I found ports the default scan misses using a
-p-full scan - [ ] I confirmed experimentally that
-O‘s answer is a "guess" (No exact OS matches) - [ ] I used at least one NSE script
- [ ] I saved a reproducible report file with
-oN - [ ] Mission: I completed two reconnaissance reports on my own computer
6. Common Pitfalls & Fixes
Wall 1. I get an error using -sS without sudo
Symptom (measured 2026-09-09, run as a regular user):
You requested a scan type which requires root privileges.
QUITTING!
Cause: a SYN scan is the act of crafting raw packets directly, which the operating system permits only to administrators (review Step 80).
Fix: add sudo. In an environment without privileges, use -sT (connect scan) — the conclusion is the same (see the measurement in section 3-4).
Wall 2. -sV takes strangely long or seems stuck
Symptom (measured 2026-09-09): running -sV at default intensity against an unidentified service ate dozens of seconds on a single port, and combined with a full scan it hit the time limit, occasionally printing Skipping host ... due to host timeout.
Cause: when a service accepts connections but answers evasively, nmap spends time waiting on probe signals.
Fix: lower the probe intensity with --version-intensity 2. It drops to around 6 seconds per port (measured in section 3-7). Save the full-scan-plus-version combination for last, and run it only on the ports you need.
Wall 3. The scan says nothing is open
Symptom (measured 2026-09-09, before starting the practice server):
All 1000 scanned ports on localhost (127.0.0.1) are in ignored states.
Not shown: 1000 closed tcp ports (reset)
Cause: literally, all 1000 well-known ports are closed. It’s not a malfunction.
Fix: "no open doors" is also a valid diagnostic result. For practice, open the simple server from 3-1 and scan again, or widen your view with -p- — in the measurement environment, the full scan discovered port 33211.
Wall 4. It says Host seems down
Symptom (Screen example): the machine is clearly on, but it reports "seems to be down."
Cause: nmap does a liveness check (ping) before scanning, and sometimes a firewall blocks only that check.
Fix: add the -Pn (skip liveness check) option. Note that against a machine that really is off, you’ll wait on every port, so it takes longer.
Wall 5. I take the SERVICE column name at face value
Symptom: you see 9999/tcp open abyss and write in your report, "an abyss service is running."
Cause: the default scan’s name is just a convention from the port-number table. abyss is the conventional name for port 9999, not the real thing.
Fix: mark service names as "guess" until you verify with -sV. In the measurement too, http-alt (guess) was corrected to SimpleHTTPServer 0.6 (the real thing).
7. Summary
Today’s Concepts
| Concept | One-line explanation |
|---|---|
| Reconnaissance | The first step common to attack and defense — identifying a target’s open doors |
| Port states | open (service waiting) / closed (shut, RST response) / filtered (firewall) |
| Conventional name vs. real thing | The SERVICE column name is a number-table guess; the real thing is confirmed by -sV |
| NSE | nmap’s built-in script engine — automatic investigation like title reading and vulnerability checks |
| Fingerprint | A response sample from an unidentified service — shows "the shape of the response" rather than the identity |
| Attack surface | The sum total of contact points open to the outside — including ports beyond the default scan |
Today’s Commands
| Command | What it does |
|---|---|
nmap target |
Default scan of 1000 well-known ports |
nmap -sT / sudo nmap -sS |
connect scan / SYN scan (same conclusion, different traces) |
nmap -sV |
Detect a service’s real name and version (slow) |
sudo nmap -O |
Guess the operating system (just a guess; reports failure honestly) |
nmap -sn range |
Check liveness only, no port scanning (ping scan) |
nmap -p- |
Full scan of all 65535 ports |
nmap --script name |
Run an NSE script; look up descriptions with --script-help |
nmap -oN file |
Save a reproducible report with the full command recorded |
An Instinct More Important Than Commands
A single page of nmap output is, to an attacker, the table of contents of an intrusion plan; to a defender, a checklist. Exactly the same data. That’s why every time you turn on this tool, you must first ask, "do I have permission to examine this target?" — which is why all of today’s measurements were done on 127.0.0.1.
And attach three habits to your body. First, distinguish names from real things — the eye that looks for SimpleHTTPServer 0.6, not http-alt. Second, know the limits of the default field of view (1000 ports) — just as port 33211 popped out in today’s full scan. Third, scan and record. The full command on the first line of an -oN file will save you three months from now. For you, who built the principles by hand first, nmap’s black-and-white output is now the familiar face of an old friend.
Once every box is checked, Step 81 is complete. Click the checkbox in the sidebar to save your progress.