Pentest Methodology & Recon · intermediate · ~12 min

Port, service, and OS scanning

By the end of this lesson you will be able to: - Explain the three main TCP port states — **open**, **closed**, and **filtered** — and what each tells you about the host and any firewall in front of it. - Compare **TCP connect** and **SYN (half-open)** scans, and explain why **UDP** scanning is slow and ambiguous. - Run **service/version detection** (`nmap -sV`), **OS detection** (`nmap -O`), and **banner grabbing**, and read their output correctly. - Understand scanning from **both sides**: how an authorized tester maps a host, and how a defender detects and slows that same activity. - Set up a **lab-only** scanning target on your own machine and clean it up afterward. - State the authorization and logging rules that separate legitimate testing from an attack.

Overview

Security objective. In an authorized engagement, scanning is the step that turns a bare IP address into a map of services. The asset being examined is a host's exposed network surface — every listening port is a possible door. The threat you are modelling is an attacker who reaches those ports across a network boundary. As the tester you will detect which services are reachable and which versions they run; as the defender's ally you will learn what that same scan looks like in logs so it can be caught and slowed.

This lesson builds directly on your two prerequisites. From "TCP vs UDP, ports, and the ones to know" you already know that a port is a 16-bit number (0–65535), that TCP uses a three-way handshake (SYN → SYN-ACK → ACK) while UDP is connectionless, and which well-known ports (22 SSH, 80 HTTP, 443 HTTPS, 53 DNS) matter. Scanning is simply probing those ports and reading the reply. From "The phases of an engagement" you know scanning sits in the recon / enumeration phase, after scoping and authorization, before exploitation. Nothing here makes sense outside that authorized frame.

The standard tool is Nmap (Network Mapper). Scanning proceeds in stages: (1) discover which ports are open/closed/filtered, (2) fingerprint the service and its version, (3) guess the operating system, and (4) read service banners. The version is the crown jewel — it is what links a live service to a specific list of known weaknesses and drives everything that follows.

Why it matters

In real authorized work — a penetration test, a red-team engagement, or your own asset inventory — you cannot defend or test what you have not mapped. Scanning is the bridge between "we own this IP range" and "here are the exact services running, and which are outdated."

Version detection is the highest-value step. "Port 443 is open" tells you little. "Port 443 is nginx 1.14.0" tells you precisely which published vulnerabilities to check and which are irrelevant. Professionals use this to prioritise: an internet-facing, unpatched service outranks an internal one behind a firewall.

The defensive payoff is just as real. Blue teams run the same scans against their own estate to find shadow services — a forgotten database bound to a public interface, a debug port left open after a deploy. Knowing what a scan looks like from the network and in the logs lets defenders write detections for it. In professional practice the scanner and the detector are two views of one skill, and a good tester documents both: what was found, and what evidence the target should have recorded.

Core concepts

1. Port states: open, closed, filtered

Definition. A scan classifies each probed TCP port into one of three states based on the reply it gets.

State What the host did What it means
open Replied with SYN-ACK A service is listening and accepted the probe
closed Replied with RST (reset) The host is reachable, but nothing is listening on that port
filtered No reply (or ICMP unreachable) A firewall/packet filter likely dropped the probe

How it works. For a TCP SYN probe: a SYN-ACK means a listener exists (open); an RST means the port is reachable but empty (closed); silence means something ate the packet (filtered). The difference between closed and filtered is the difference between "the door isn't there" and "someone is blocking the hallway."

When/when-not. These three cover most cases. Nmap also reports combined states like open|filtered (common in UDP, where silence is genuinely ambiguous) and unfiltered (reachable, state undetermined). Do not treat filtered as "secure" — it only means this probe got no answer.

Pitfall. Beginners read filtered as "nothing there." A filtered port can hide a very much alive service behind a firewall rule. Silence is not absence.

2. Scan types: connect vs SYN vs UDP

Definition. The technique used to probe a port. The main three:

Type Nmap flag Handshake Speed Notes
TCP connect -sT Full (SYN, SYN-ACK, ACK) Slower Uses the OS socket API; needs no special privilege; logged as a full connection
SYN / half-open -sS Partial (SYN, SYN-ACK, then RST) Faster Never completes the handshake; needs raw-socket privilege (root/admin)
UDP -sU None (UDP is connectionless) Slow "No reply" is ambiguous; relies on ICMP port-unreachable to detect closed

How it works. A connect scan asks the operating system to open a real connection — reliable, but the target sees a completed session. A SYN scan sends the SYN, reads the SYN-ACK, then sends an RST to tear down before the handshake finishes — slightly quieter and faster because no full session is established. UDP has no handshake at all: an open UDP port often stays silent, and closed is inferred only when the host returns an ICMP "port unreachable." Because that ICMP is rate-limited by most kernels, UDP scans crawl.

When/when-not. SYN is the common default when you have privilege. Use connect when you cannot get raw sockets (e.g., an unprivileged shell). Scan UDP deliberately and narrowly — you rarely need all 65535 UDP ports; target 53, 123, 161, 500 and the like.

Pitfall. Calling a SYN scan "stealthy" oversells it. Modern IDS/IPS and even basic connection-tracking firewalls log SYN floods and incomplete handshakes readily. Stealth is relative, never absolute.

3. Service and version detection (-sV)

Definition. Probing an open port to identify the software and its version, not just "something is here."

How it works. Nmap connects, reads any banner the service volunteers, and if that is not conclusive it sends a series of protocol-specific probes and matches the responses against a signature database. Output looks like 22/tcp open ssh OpenSSH 8.9p1 Ubuntu.

When/when-not. Run it once you know which ports are open — it is slower than a plain port scan, so scope it to the open ports. It is the single most useful step for prioritising later work.

Pitfall. Version strings can be wrong or spoofed. A banner can be edited, back-ported patches change behaviour without changing the version number, and load balancers lie. Treat a detected version as a strong lead, not proof.

4. OS detection (-O)

Definition. Guessing the operating system from low-level TCP/IP stack behaviour — default TTL, TCP window size, the order and presence of TCP options, how the stack responds to unusual packets.

How it works. Different OS network stacks have measurable quirks. Nmap fingerprints them and reports a best match with a confidence figure. It needs at least one open and one closed port for a good guess.

When/when-not. Useful for inventory and for narrowing exploit choices. Skip it when it adds noise you cannot afford or when the answer is already known.

Pitfall. It is an educated guess, sometimes low-confidence. NAT, virtualization, and proxies routinely fool it. Never anchor a decision on OS detection alone.

5. Banner grabbing

Definition. The simplest version check: connect to a service and read the text it announces on connection.

How it works. Many services greet you with an identifying line — SSH sends SSH-2.0-OpenSSH_8.9p1, SMTP sends a 220 line naming the mailer, HTTP returns a Server: header. You can read it with netcat, curl, or, in this course's exercises, by parsing the banner string in C.

When/when-not. Great for a quick manual confirmation of what -sV reported. Not every service offers a banner, and banners can be suppressed or faked as a hardening measure.

Pitfall. Trusting a banner blindly. Hardened servers strip or alter banners precisely to mislead scanners.

Threat model of the scanning surface

TRUST BOUNDARY (the network edge / firewall)
===============================================

   [ Attacker / Authorized tester ]        <-- untrusted side
            |  probes (SYN / connect / UDP)
            v
   +-----------------------------------+
   |  FIREWALL / packet filter         |   <-- trust boundary #1
   |  drops? -> port shows 'filtered'  |       (decides reachability)
   +-----------------------------------+
            |  allowed probes pass
            v
   +-----------------------------------+
   |  HOST (the protected asset)       |   <-- trust boundary #2
   |                                   |
   |  Entry points (listening ports):  |
   |   22/tcp  ssh   OpenSSH 8.9       |
   |   80/tcp  http  nginx 1.14        |
   |   5432/tcp postgres  <-- should   |
   |            NOT be here publicly    |
   +-----------------------------------+
            |
            v  each open port = a possible door + a log source
   [ Connection logs / IDS / firewall logs ]  <-- detection lives here

The assets are the host and its listening services. The trust boundaries are the firewall (what is even reachable) and the host's own service authentication (what a reachable service will let you do). The entry points are the open ports. Detection lives in the firewall and connection logs.

Knowledge check.

  1. A port is reported filtered. Which trust boundary produced that result, and what insecure assumption would it be to conclude "no service is there"?
  2. You find 5432/tcp open postgresql on a host meant to serve only web traffic. Which insecure assumption (about default binds / firewall rules) most likely caused this exposure, and where would you look in the logs to see when it started being reachable?
  3. Why is a SYN scan run only against a host you own or are explicitly authorized to test — what makes the identical packets legitimate in a lab but potentially unlawful elsewhere?

Syntax notes

The core command shape is nmap [scan-type] [detection] [timing] [ports] <target>. Every flag below is real Nmap syntax. Run these only against a target you own or are authorized to test (the examples use localhost / 127.0.0.1).

# Fast SYN scan of the default 1000 ports (needs root for raw sockets)
sudo nmap -sS 127.0.0.1

# Unprivileged full-connect scan (no root needed)
nmap -sT 127.0.0.1

# Service/version detection on specific open ports only
nmap -sV -p 22,80,443 127.0.0.1

# OS detection (needs root; needs 1 open + 1 closed port)
sudo nmap -O 127.0.0.1

# A narrow, deliberate UDP scan (slow; pick ports on purpose)
sudo nmap -sU -p 53,123,161 127.0.0.1

# Save evidence for a report: all formats, timestamped
nmap -sV -p 22,80 -oA scan_localhost_$(date +%F) 127.0.0.1

Annotations:

  • -sS SYN (half-open); -sT full connect; -sU UDP. Pick one scan type.
  • -sV version detection; -O OS detection. Add on top of a scan type.
  • -p 22,80,443 restrict to listed ports; -p- means all 65535 (slow — do it deliberately).
  • -oA <base> writes .nmap, .gnmap, and .xml — your report evidence.
  • Banner grab without Nmap: printf '' | nc -w 3 127.0.0.1 22 or curl -sI http://127.0.0.1.

Lesson

Scanning answers three questions: which ports are open, what is listening, and what operating system runs underneath. Nmap is the standard tool for this.

Port states

A scan classifies each port:

  • open — a service accepted the connection.
  • closed — the port is reachable, but nothing is listening (the host replied with an RST, a TCP reset).
  • filtered — no reply came back. A firewall likely dropped the probe.

Scan types

  • TCP connect completes the full three-way handshake. It is reliable but noisy.
  • SYN ("half-open") sends a SYN, reads the SYN-ACK, then never finishes the handshake. This is faster and slightly stealthier.
  • UDP is slow and ambiguous. UDP has no handshake, so "no reply" could mean the port is open or filtered. It takes care and patience.

Service and version detection

Knowing that "port 80 is open" is not enough. You also want the exact software and version.

nmap -sV does this. It reads banners and matches response signatures to fingerprint the service. The version is what maps a service to its known vulnerabilities.

OS detection

nmap -O guesses the operating system from subtle TCP/IP stack behaviors, such as default TTL values, window sizes, and the order of TCP options.

This is an educated guess, not a certainty.

Banner grabbing

Banner grabbing is the simplest version check. You connect to a service and read what it announces.

Many services state their exact version in this banner. An SSH or SMTP server, for example, often reveals its version on connect.

You can grab a banner with netcat or curl. In this course's exercises, you do it by parsing a banner string in C.

Code examples

This example is entirely local and lab-safe: you stand up a service on your own loopback interface, scan it, then remove it. Loopback (127.0.0.1) traffic never leaves your machine.

Part 1 — WARNING: intentionally vulnerable — use only in a local, isolated, authorized lab. Do not deploy.

Here is what an insecurely exposed service looks like, and why it is dangerous. Suppose an app developer starts a database and binds it to all interfaces:

# INSECURE: binds Postgres to 0.0.0.0 -> reachable from the whole network.
# Shown to illustrate the risk. Do NOT run this on a networked host.
#   postgres -c listen_addresses='*'      # 0.0.0.0:5432 exposed

A scan from anywhere on that network now sees:

PORT     STATE SERVICE    VERSION
5432/tcp open  postgresql PostgreSQL 12.x

The insecure assumption: "it's just for local development, no one will connect." Binding to 0.0.0.0 exposes the port to every host that can route to the machine — the version is now advertised to any scanner, tying it to published vulnerabilities.

Part 2 — SECURE fix

Bind the service to loopback only, and let the firewall default to deny. For the lab we will use a simple, safe HTTP service so nothing sensitive is involved:

# SECURE lab target: a throwaway web server bound to LOOPBACK ONLY.
# 127.0.0.1 is unreachable from any other host -> not network-exposed.
python3 -m http.server 8080 --bind 127.0.0.1

The general secure pattern for any real service:

  • Bind to 127.0.0.1 (or a private management interface), never 0.0.0.0, unless the service is meant to be public.
  • Firewall default-deny inbound; open only the ports that must be public.
  • Keep versions patched so a leaked version string is not also an exploitable one.

Part 3 — VERIFY (prove the fix rejects exposure and accepts intended use)

With the loopback server from Part 2 running in one terminal, in another terminal:

# (a) ACCEPT good/intended use: scanning the loopback address finds it.
nmap -sT -sV -p 8080 127.0.0.1

# Expected (abridged):
# PORT     STATE SERVICE VERSION
# 8080/tcp open  http    SimpleHTTPServer 0.6 (Python 3.x)

# (b) REJECT exposure: probe the machine's OUTWARD IP for the same port.
# Because we bound to 127.0.0.1, it must NOT be reachable there.
MY_IP=$(hostname -I 2>/dev/null | awk '{print $1}')
nmap -sT -p 8080 "$MY_IP"

# Expected: 8080/tcp is 'closed' or 'filtered' on the external IP
# -> the service is NOT network-exposed. Fix verified.

What the output means. Test (a) confirms the intended path works: the service is running and version-detectable on loopback. Test (b) is the security assertion: the same port on the machine's routable address is not open, proving the bind restricted exposure. If (b) had shown open, the fix failed and the service is exposed.

Cleanup / reset

# Stop the lab server: Ctrl-C in its terminal, or find and stop it:
pkill -f "http.server 8080"   # ends the throwaway server

There is nothing else to undo — no data was created, and nothing left loopback.

Line by line

Walking through the VERIFY block, the heart of the lesson:

  1. python3 -m http.server 8080 --bind 127.0.0.1 — starts a minimal web server. The --bind 127.0.0.1 is the whole point: the listening socket is tied to the loopback address, so the kernel will only accept connections that originate on the same machine.
  2. nmap -sT -sV -p 8080 127.0.0.1 — a full-connect scan (-sT, no root needed) with version detection (-sV) against just port 8080 (-p 8080) on loopback. Nmap completes a TCP handshake to 8080, reads the HTTP response, and matches it to the SimpleHTTPServer signature.
  3. The output line 8080/tcp open http SimpleHTTPServer ... confirms state=open and a fingerprinted version. This is the "accepts good input" half: the service works as intended on its intended interface.
  4. MY_IP=$(hostname -I ... | awk '{print $1}') — captures the machine's first routable (non-loopback) IP into a variable, so the next scan targets the outward-facing address instead of loopback.
  5. nmap -sT -p 8080 "$MY_IP" — the same probe, now aimed at the routable IP.
  6. Because the socket was bound to 127.0.0.1, the kernel has no listener on MY_IP:8080. Nmap gets an RST (closed) or, if a host firewall drops it, silence (filtered). Either way the port is not open — the "rejects bad exposure" half.
Step Target Port state Interpretation
Scan (a) 127.0.0.1:8080 open Intended local access works
Scan (b) MY_IP:8080 closed / filtered Not network-exposed — fix verified

The contrast between the two rows is the verification: the service is reachable exactly where it should be and nowhere else.

Common mistakes

1. Reading filtered as "nothing there."

  • Wrong: Seeing filtered and concluding the port is safe/empty.
  • Why wrong: filtered means the probe got no answer — usually a firewall dropped it. A live, vulnerable service can sit right behind that rule.
  • Corrected: Treat filtered as "reachability blocked for this probe," not "absent." Retry with different techniques (-sT vs -sS), from an allowed vantage point, or check host-side.
  • Prevent: Always distinguish reachability from existence.

2. Believing a version banner is ground truth.

  • Wrong: Reporting "vulnerable to CVE-XYZ" because the banner shows an old version.
  • Why wrong: Banners can be edited, back-ported patches fix bugs without bumping the version, and load balancers spoof headers. Decoding a banner is not the same as confirming exploitability.
  • Corrected: Use the version as a lead; confirm with a safe, authorized check before claiming impact.
  • Prevent: Never equate "looks old" with "is exploitable."

3. Assuming a SYN scan is invisible.

  • Wrong: Running -sS and thinking no one will notice.
  • Why wrong: Connection-tracking firewalls and IDS log SYN sweeps and half-open connections routinely.
  • Corrected: Assume you are logged. In authorized work that is fine — coordinate timing with the blue team.
  • Prevent: Drop the word "stealthy" as an absolute; stealth is always relative.

4. Scanning something you are not authorized to scan.

  • Wrong: Pointing Nmap at an internet host or a company you do not have written permission to test.
  • Why wrong: Unauthorized scanning can be unlawful and is a real ethical breach — identical packets are legitimate only inside your authorized scope.
  • Corrected: Scan only assets you own or that are named in a signed scope/authorization. Use localhost, containers, or intentionally-vulnerable VMs to practise.
  • Prevent: Confirm scope in writing before the first packet.

5. Blasting all 65535 UDP ports by reflex.

  • Wrong: nmap -sU -p- on a whole range and waiting hours for ambiguous results.
  • Why wrong: UDP scans are slow and open|filtered is often the best you get; the ICMP rate-limit throttles you.
  • Corrected: Target the UDP ports that matter (53, 123, 161, 500…) deliberately.
  • Prevent: Scope UDP narrowly and read open|filtered as "needs manual follow-up," not a finding.

Debugging tips

"All ports show filtered." A local firewall (or the target's) is dropping probes. Check: are you scanning the right IP? Is a host firewall active (iptables/pf/Windows Firewall) blocking outbound or inbound? Try an allowed vantage point or -sT instead of -sS.

"Nmap says I need to be root." -sS, -sU, and -O need raw sockets. Either run with sudo on a machine you control, or fall back to -sT (connect scan) which uses the normal socket API and needs no privilege.

"-sV returns no version, just open." The service gave no banner and no probe matched. Increase intensity (-sV --version-intensity 9), grab the banner manually (nc/curl), and remember some services are deliberately silent.

"OS detection is low-confidence or wrong." You may be behind NAT, a proxy, or scanning a VM. -O needs at least one open and one closed port. Treat the result as a guess; corroborate with service versions.

"The scan is painfully slow." UDP is inherently slow. For TCP, narrow the port list (-p), and consider a faster timing template on a lab host (-T4). Do not crank timing on production — you may cause disruption.

Questions to ask when a scan surprises you:

  • Am I hitting the interface I think I am (loopback vs routable IP)?
  • Is a firewall between me and the target changing the result?
  • Does this state mean unreachable or absent? (filtered vs closed)
  • Is the version real, or could it be spoofed/back-ported?
  • Am I inside my authorized scope?

Memory safety

Security & safety: detection and logging

Scanning is a two-sided skill. A professional tester documents what a scan should have left behind, and a defender uses exactly that to catch it.

What to log (for the defender / the target host):

  • Timestamp (with timezone) of each connection attempt.
  • Source address and source port of the probe.
  • Resource: destination port / service that was probed.
  • Result / security decision: accepted, refused (RST), or dropped by firewall — and which rule dropped it.
  • Correlation id / session id so many probes from one source can be tied together.
  • Connection-tracking counters: bursts of SYNs without completing handshakes, many distinct ports from one source in a short window.

What NEVER to log:

  • Passwords, session tokens, or cookies seen in traffic.
  • API keys or private keys.
  • Full payment card numbers (PANs) — mask them.
  • Any PII beyond what the security purpose requires.

Which events signal abuse (scan indicators):

  • One source touching many ports on one host in seconds (horizontal-in-host sweep).
  • One port probed across many hosts (a sweep for a specific service).
  • A spike of half-open connections (SYN without ACK) — classic SYN-scan signature.
  • A burst of ICMP port-unreachable replies leaving the host — a UDP scan in progress.

How false positives arise: legitimate monitoring, load balancers, uptime checkers, and vulnerability scanners your own team runs all look like scans. Backup jobs and service discovery can trip the same rules. Before alerting on a source, check whether it is a known internal scanner or health-check system — tune allowlists so real attacks are not buried under routine noise.

Authorization checklist (before any lab or scan):

  • The target is a system I own, or is explicitly named in a signed authorization/scope.
  • I am scanning localhost, a container, an intentionally-vulnerable VM, or a CTF — not a third party.
  • I have noted the start time and told the relevant blue team if the rules require it.
  • I know how to clean up / reset the lab afterward.
  • I will store evidence (-oA output) securely and share it only with authorized parties.

Real-world uses

Concrete authorized use case. A company hires you to test its external footprint. Scope is a signed list of IP ranges the company owns. You run a phased scan: a broad TCP SYN sweep of common ports across the range, then -sV on the open ports, then targeted UDP on services like DNS. You discover a 5432/tcp open postgresql on a host that should only serve HTTP — a database accidentally bound to a public interface after a deploy. You report it with evidence (the -oA output, timestamps), a remediation (rebind to loopback, add a deny rule), and a retest step. The blue team correlates your scan against their firewall logs to confirm their detection fired.

Professional best-practice habits:

  • Validation: confirm scope in writing; validate you are scanning the intended IPs, not a neighbour's.
  • Least privilege: run scans from a dedicated, minimal box; do not scan from production systems.
  • Secure defaults (for the systems you build): bind services to loopback/private interfaces, firewall default-deny, keep versions patched.
  • Logging: save scan output as evidence; expect the target to log you and coordinate.
  • Error handling: treat ambiguous states (filtered, open|filtered) as "needs follow-up," never as findings on their own.

Beginner vs advanced:

Beginner Advanced
Target localhost, one VM Whole authorized ranges, phased
Scans -sT, -sV on a few ports Tuned SYN/UDP, timing control, scripts
Interpretation Read open/closed/filtered Correlate versions to risk, weigh spoofing
Output Read on screen -oA evidence, integrate into a report
Mindset "What is open?" "What is exposed, how risky, and how is it detected?"

Practice tasks

All tasks are lab-only: use localhost, a container, or an intentionally-vulnerable VM you own. Never scan systems you are not authorized to test.

Beginner 1 — Map your own loopback

  • Objective: Run your first authorized scan and read port states.
  • Requirements: Start the lab server (python3 -m http.server 8080 --bind 127.0.0.1). In another terminal run nmap -sT -p 8080,8081 127.0.0.1.
  • Expected output: 8080 open, 8081 closed (or filtered).
  • Constraints: Loopback only. Stop the server when done.
  • Hints: -sT needs no root. Compare the two port states and explain the difference in one sentence.
  • Concepts: port states, connect scan.
  • Defensive conclusion: Note which state means "reachable but empty" vs "reachable and listening."

Beginner 2 — Fingerprint a version, then verify by banner

  • Objective: Detect a service version two independent ways.
  • Requirements: With the lab server running, run nmap -sV -p 8080 127.0.0.1. Then grab the banner manually with curl -sI http://127.0.0.1:8080.
  • Input/output: Compare the version Nmap reports against the Server: header from curl.
  • Constraints: Loopback only.
  • Hints: Do the two agree? What would it mean if they disagreed?
  • Concepts: version detection, banner grabbing.
  • Defensive conclusion: Explain in one line why a matching banner is still not proof a service is exploitable.

Intermediate 1 — Prove a service is not network-exposed

  • Objective: Verify a loopback bind actually restricts exposure.
  • Requirements: Scan 127.0.0.1:8080 (should be open) and the machine's routable IP on 8080 (should not be). Record both results.
  • Input/output: Two scans, two states; the routable one must be closed/filtered.
  • Constraints: Only your own machine.
  • Hints: Get the routable IP with hostname -I.
  • Concepts: trust boundaries, verification of a fix.
  • Defensive conclusion: State the one-line assertion this test proves, and what it would mean if the external port showed open.

Intermediate 2 — Read the scan from the defender's side

  • Objective: See your own scan in the logs.
  • Requirements: Enable connection logging on your lab host (e.g., watch the server's request log, or a host firewall log). Run a small multi-port scan against loopback and observe what gets recorded.
  • Input/output: A log excerpt showing timestamp, source, destination port, result.
  • Constraints: Lab host you control.
  • Hints: Note what is present and, importantly, what should NOT be logged (no secrets).
  • Concepts: detection, logging, correlation.
  • Defensive conclusion: List two log fields that would let a defender correlate many probes to one scanner, and one field that must never be logged.

Challenge — Write a detection rule for a port sweep

  • Objective: Design (on paper or pseudocode) a simple detection for a horizontal port sweep, and account for false positives.
  • Requirements: Define the signal (e.g., "one source hits N+ distinct ports on one host within T seconds"), pick reasonable N and T, and describe what data source feeds it.
  • Constraints: No attacking third parties; reason about your own lab traffic only.
  • Hints: Consider how your own health checks or vuln scanner would trip the rule.
  • Concepts: scan indicators, false positives, allowlisting.
  • Defensive conclusion: Specify how you would suppress false positives (allowlist known internal scanners) and how you would retest that the rule still catches a real sweep after tuning.

Summary

Main concepts. Scanning turns an IP into a service map. Each TCP port is open (SYN-ACK — a listener), closed (RST — reachable, empty), or filtered (no reply — likely firewalled). Scan types trade speed for noise: connect (-sT, no privilege, full handshake), SYN/half-open (-sS, faster, needs root), and UDP (-sU, slow and ambiguous). Layer detection on top: -sV fingerprints service/version — the highest-value step, since the version links a service to known weaknesses — -O guesses the OS from stack quirks, and banner grabbing reads what a service announces.

Key syntax. nmap -sT -sV -p 22,80,443 127.0.0.1; add -O for OS; -oA <base> to save evidence; nc/curl for manual banners.

Common mistakes. Reading filtered as "absent"; trusting a version banner as proof of exploitability; assuming SYN scans are invisible; scanning outside authorized scope; blasting all UDP ports by reflex.

What to remember. Distinguish reachable from present, and detected version from confirmed exploitable. Scanning is two-sided: know what you find and what evidence the target should log (timestamp, source, port, result, correlation id — never secrets). Only ever scan systems you own or are explicitly authorized to test, and always have a cleanup step. Nothing is ever "completely secure" — scanning tells you where to look next, on both offense and defense.

Practice with these exercises