0
Hands-on Labs BEGINNER 15 min read Updated

Scanning a Target with Nmap: A Step-by-Step First Scan

Your first Nmap scan, walked through step by step: a safe lab target, host discovery, port ranges, service and version detection, scripts, saving output, and what to do with the results.

founder & security researcher · 3 writeups
Scanning a Target with Nmap: A Step-by-Step First Scan

A good Nmap scan is the first honest look you get at a target, and learning to read one is the difference between guessing and knowing. This walkthrough takes a complete beginner from an empty terminal to a saved, readable map of open ports and the services behind them. We go one flag at a time, explain what each line of output means, and finish by turning that map into a short list of next steps. Follow along on a target you are allowed to touch and you will have the whole workflow in your fingers by the end.

Read it top to bottom the first time, with a terminal open. Everything here runs against your own lab or against scanme.nmap.org, a host the Nmap project puts online specifically so people can practise scanning legally.

Scope

Scan only hosts you own or have written permission to test, a lab you built, or scanme.nmap.org, which the Nmap project provides for exactly this kind of practice. Scanning systems you do not control is a crime in most places, even when nothing breaks. Keep everything in this guide inside that line.

01Setting up a safe target to scan

Before your first Nmap scan you need somewhere safe to point it, and you have two easy options. The first is a lab host you control, such as a small Linux virtual machine or the project lab at lab.0xpriv.dev on an internal range like 10.10.10.0/24. The second is scanme.nmap.org, a machine the Nmap authors keep online so newcomers have a legal place to test. Both give you real open ports to find without touching anything you should not.

Install Nmap first. On Debian or Ubuntu that is sudo apt install nmap, on macOS brew install nmap, and on Windows the installer from the official site. Confirm it runs and note the version, because a few features depend on it.

bash
# 0xpriv.dev/labs  -- confirm nmap is installed and check the version
nmap --version
Root or not

Run scans as root (or with sudo) when you can. With root, Nmap sends raw packets and defaults to a fast SYN scan (-sS). Without root it falls back to a full TCP connect scan (-sT), which still works but is slower and noisier. The results read the same either way.

02Your very first scan and what the output means

Your very first scan is the simplest command there is: the word nmap followed by a target. No flags, no options. Nmap picks sensible defaults, checks whether the host is up, scans the 1000 most common TCP ports, and prints what it found. That one line teaches you more than any amount of reading.

bash
# the whole command is just the tool and a target
nmap scanme.nmap.org
a default scan of the practice host
$ nmap scanme.nmap.org
Starting Nmap 7.94 ( https://nmap.org )
Nmap scan report for scanme.nmap.org (45.33.32.156)
Host is up (0.098s latency).
Not shown: 996 closed tcp ports (reset)
PORT      STATE SERVICE
22/tcp    open  ssh
80/tcp    open  http
9929/tcp  open  nping-echo
31337/tcp open  Elite

Nmap done: 1 IP address (1 host up) scanned in 2.14 seconds

Read it from the top. The host is up line means Nmap's discovery probes got a reply. Not shown: 996 closed tcp ports tells you it checked 1000 ports and most answered "nothing here". The table lists the ports that were interesting. The STATE column is the part that matters most, so it gets its own table.

StateWhat it means
openA service accepted the connection. This is what you are hunting.
closedThe host replied but nothing is listening on that port right now.
filteredA firewall dropped the probe, so Nmap cannot tell if anything is there.
open|filteredNmap could not decide between open and filtered, common with UDP.

The SERVICE column is only a guess at this stage. Nmap matched the port number against a name list (22 is usually SSH, 80 usually HTTP), but it has not actually talked to the service yet. Confirming what is really running is a later step.

03How a scan runs under the hood

A single scan is really a short pipeline of phases, and knowing the order helps you read the output and choose flags. Nmap resolves the name to an address, decides whether the host is alive, scans the chosen ports, optionally fingerprints the services, and then prints and saves the result. Each flag you add switches one of these phases on, off, or into a different mode.

the phases of one scan
Resolvename to IP Discoverhost up? Port scanopen ports Detectservice/ver Save

Keep this picture in mind for the rest of the guide. Every option we add from here just changes one box.

04Host discovery and when to skip it with -Pn

Host discovery is the phase where Nmap decides whether a target is worth scanning at all. Before touching any ports it sends a small set of probes (an ICMP echo, a TCP SYN to port 443, a TCP ACK to port 80, and an ICMP timestamp when run as root) and marks the host "up" if anything replies. You can run only this phase with -sn, which is the fastest way to find live hosts on a range.

bash
# ping sweep only: list live hosts on an internal range, no port scan
nmap -sn 10.10.10.0/24
a discovery-only sweep of a lab subnet
$ nmap -sn 10.10.10.0/24
Nmap scan report for 10.10.10.5
Host is up (0.0011s latency).
Nmap scan report for 10.10.10.12
Host is up (0.0009s latency).
Nmap done: 256 IP addresses (2 hosts up) scanned in 2.98 seconds

The catch is that plenty of hosts are configured to ignore those probes. If discovery decides a host is down, Nmap skips it and you see nothing, even when services are listening. That is where -Pn comes in: it tells Nmap to skip discovery entirely and treat every target as online, so it goes straight to the port scan.

bash
# skip host discovery and scan anyway (useful when pings are blocked)
nmap -Pn lab.0xpriv.dev
When to reach for -Pn

Use -Pn when you are sure the host exists (you were given the address) but a plain scan reports it down. The trade-off is time: Nmap now scans every target in the list whether it is alive or not, so do not throw -Pn at a whole /16 without thinking.

05A top-ports scan versus a full -p- scan

Choosing a port range is a trade between speed and coverage, and Nmap gives you a dial for it. By default it scans the 1000 most common TCP ports, which is a good balance for a first pass. You can narrow that to the top 100 with -F for a quick look, set any count with --top-ports, or go all the way to every port with -p-.

bash
# a fast first look: only the 100 most common ports
nmap -F scanme.nmap.org

# pick an exact count of the most common ports
nmap --top-ports 200 scanme.nmap.org

# specific ports or ranges
nmap -p 22,80,443,8080 scanme.nmap.org

# every one of the 65535 TCP ports (slow, but thorough)
nmap -p- scanme.nmap.org

The reason -p- matters is that services hide on odd ports on purpose. An admin panel on 8443, an old app server on 8081, a database bound to 5433: none of those are in the top 1000, so a default scan walks right past them. A real assessment almost always ends with a full port scan, even if it starts with a quick one.

Fast then full

A common rhythm is to run a quick -F scan to get moving, then kick off a slow -p- scan in the background with -T4 to speed up the timing. You start working on the obvious ports while the thorough scan finishes.

06Service and version detection with -sV

Service and version detection is what turns "port 80 is open" into "this is Apache 2.4.x on Ubuntu". The port table alone only guesses from the port number. Add -sV and Nmap actually connects to each open port, reads the banner and probe responses, and matches them against its service database to name the software and, where it can, the exact version.

bash
# probe open ports to identify the service and version behind them
nmap -sV scanme.nmap.org

# push harder on stubborn services (0 is light, 9 tries everything)
nmap -sV --version-intensity 9 lab.0xpriv.dev

Version strings are the single most useful thing a first scan produces, because they tell you what to research next. An old OpenSSH build, a specific web server release, an outdated application version: each one is a thread to pull on. The intensity dial trades speed for certainty, so turn it up only on the handful of ports that refuse to identify themselves.

07Running the default scripts with -sC

The default scripts are a set of safe, useful checks that Nmap can run against each open port automatically. The flag -sC runs everything in the Nmap Scripting Engine's default category: things like grabbing an HTTP title, listing SSH host keys, pulling an SSL certificate, or reading an anonymous FTP banner. None of them are intrusive, and together they often hand you information that would take several manual steps otherwise.

bash
# run the default script set against open ports
nmap -sC scanme.nmap.org

# the beginner workhorse: version detection + default scripts together
nmap -sC -sV scanme.nmap.org

# -A rolls in -sV, -sC, OS detection (-O) and traceroute in one go
nmap -A scanme.nmap.org

For a first scan, -sC -sV is the combination to memorise. It names the services, versions them, and runs the safe scripts in a single pass. The bigger hammer, -A, adds operating-system guessing and a traceroute on top, which is handy but louder and slower, so save it for when you want the full picture.

Default is not the same as safe-for-production

The default category is chosen to be non-disruptive, but it is still active probing. On fragile or production-like lab gear, know what a script does before you run it. The --script-help flag prints a description for any script by name.

08Saving output with -oA and why it matters

Saving output is the habit that separates a quick look from real work, and -oA is how you do it. On its own a scan prints to the screen and is gone when you close the terminal. The -oA flag takes a base name and writes three files at once: a human-readable .nmap file, a machine-parsable .xml file, and a line-oriented .gnmap file that you can grep.

bash
# save every format at once under one base name
nmap -sC -sV -oA scans/scanme scanme.nmap.org
the three files -oA leaves behind
$ ls scans/
scanme.nmap  scanme.gnmap  scanme.xml
$ grep open scans/scanme.gnmap
Host: 45.33.32.156 ()  Ports: 22/open/tcp//ssh///, 80/open/tcp//http///

Keep those files. The .nmap file is what you reread while you work. The .xml file feeds other tools and report generators. The .gnmap file lets you pull "every host with 445 open" out of a big scan with one grep. If you scan without saving, you will be rescanning an hour later to answer a question you already answered, which is both slow and needlessly loud.

09Turning results into next steps

Turning results into next steps is the point of the whole exercise, and it follows the same short routine every time. A first scan is a map, not a conclusion. You read the open ports, decide which services are worth a closer look, and line up the right follow-up tool for each one. Here is that routine as a checklist you can run on any scan output.

List the open ports

Pull every open port out of the saved output and write them down. These are your only real attack surface; closed and filtered ports are noise for now.

Name the service and version

For each open port, note the -sV result. "OpenSSH 8.2", "Apache 2.4.41", "MySQL 5.7": the version is your search term.

Pick one follow-up per service

Web ports go to a browser and a directory tool, SMB goes to a share enumerator, databases get a login check. One obvious action each, no rabbit holes yet.

Run a full port scan in parallel

While you work the obvious ports, start a -p- scan so nothing on an odd port is missed. Re-read it when it finishes.

bash
# example follow-ups the first scan points you toward
curl -I http://lab.0xpriv.dev/              # look at the web server headers
nmap -p 445 --script smb-os-discovery 10.10.10.5   # enumerate an SMB host
nmap -p- -T4 -oA scans/full lab.0xpriv.dev  # the thorough pass, saved

10Reading a real example scan end to end

Reading a full example scan ties every flag above together in one block. Below is a -sC -sV scan of the practice host with output saved. Walk through it the way you would on a real engagement: confirm the host is up, read each open port, note the versions, and skim the script output for anything useful. Your own run will show different versions, because the box gets updated.

nmap -sC -sV -oA scans/scanme scanme.nmap.org
$ nmap -sC -sV -oA scans/scanme scanme.nmap.org
Starting Nmap 7.94 ( https://nmap.org )
Nmap scan report for scanme.nmap.org (45.33.32.156)
Host is up (0.096s latency).
Not shown: 996 closed tcp ports (reset)
PORT      STATE SERVICE VERSION
22/tcp    open  ssh     OpenSSH 6.6.1p1 Ubuntu 2ubuntu2.13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   1024 ac:00:a0:1a:... (DSA)
|_  2048 20:3d:2d:44:... (RSA)
80/tcp    open  http    Apache httpd 2.4.7 ((Ubuntu))
|_http-title: Go ahead and ScanMe!
|_http-server-header: Apache/2.4.7 (Ubuntu)
9929/tcp  open  nping-echo Nping echo
31337/tcp open  tcpwrapped

Service detection performed. Please report any incorrect results.
Nmap done: 1 IP address (1 host up) scanned in 11.03 seconds

Two open ports carry real services here. Port 22 is SSH, and -sC printed the host keys for you. Port 80 is a web server, and the scripts already grabbed the page title and the server header. Right away you have two leads: browse the web server, and note the SSH version to check later. That is a first scan doing its whole job.

11A note on being loud and staying in scope

Being loud is the thing beginners underestimate, so it deserves its own note. A default Nmap scan is not quiet. It opens hundreds of connections in a couple of seconds, which lights up firewall and IDS logs on any monitored network. The timing templates control this: -T0 and -T1 crawl along to stay under the radar, -T3 is the default, and -T4 pushes hard on a network that can take it.

bash
# slow and quiet for a monitored target
nmap -T1 -sV lab.0xpriv.dev

# fast and loud for a lab you control
nmap -T4 -p- lab.0xpriv.dev

The scope rule is simpler than the timing one and matters more. Only scan what you were authorized to scan. A CIDR range in an engagement letter is a boundary, not a suggestion, and scanme.nmap.org is the one public host on earth that invites you to practise. Everything else needs permission in writing. Staying in scope is not just etiquette; it is the line between security testing and a crime.

12Detecting and limiting port scans

Detecting a port scan is the defender's side of this story, and the good news is that scans are noisy by nature. A single source opening connections to many ports in a short window is the textbook signature, and it shows up in firewall logs, in an IDS like Suricata or Snort, and in simple connection-rate alerts. The slow -T0 and -T1 timings exist precisely because the fast ones are so easy to spot. For a defender, the fix is less about catching every scan and more about having little for a scan to find.

Shrinking what a scan can see
Default-deny at the firewall. Expose only the ports a service truly needs. A port that is filtered or closed gives a scanner nothing to version or script.
Retire services you forgot about. Most findings on a first scan are things nobody meant to leave running. An inventory and a regular review cut the attack surface more than any single control.
Alert on scan behaviour, not payloads. Many ports hit from one source in a short time is the pattern to watch. Tune an IDS rule or a rate limit on that shape rather than chasing specific packets.
Hide version banners where you can. Trimming server tokens and software version strings slows the research step, even though it does not fix the underlying exposure.

13FAQ

Do I need to be root to run an Nmap scan?FAQ

No, but it helps. As a normal user Nmap runs a TCP connect scan (-sT), which is slower and more visible. With root or sudo it sends raw packets and defaults to a faster SYN scan (-sS), and it can also do OS detection and some scripts. The port results are the same; root just makes the scan quicker and quieter.

Why does my scan say the host is down when I know it is up?FAQ

The host is probably configured to ignore Nmap's discovery probes, so the discovery phase marks it down and skips the port scan. Add -Pn to skip discovery and scan it anyway. This is common on hardened hosts and on networks that block ICMP.

How long should a full -p- scan take?FAQ

It depends on the target and timing, from a minute on a fast lab host with -T4 to much longer on a slow or filtered network. Because it checks all 65535 ports, start it early and let it run in the background while you work the common ports a default scan already found.

What is the difference between -sC and -sV?FAQ

-sV identifies the software and version behind each open port by reading banners and probe responses. -sC runs the default Nmap script set, which does extra safe checks like grabbing a page title or SSL certificate. Together, -sC -sV is the standard combination for a thorough first scan.

Is it legal to scan scanme.nmap.org?FAQ

Yes. The Nmap project runs that host specifically so people can learn and test scans legally, and asks only that you do not hammer it with heavy traffic. A handful of normal scans is exactly what it is for. Any other host still needs the owner's permission.

references

Was this writeup useful?
Alex Rowan Founder & Security Researcher at 0xpriv

Founder of 0xpriv, covering offensive security, web application vulnerabilities, and practical security research through PHP, Python, and hands-on technical analysis.

related writeups

more in Labs →

discussion

0 comments
`code` supported · comments are reviewed before they appear