As a red teamer or penetration tester, one of the most important skills you can possess is scanning and enumerating a target network. It’s the digital equivalent of casing a bank: you need to see the cameras, the guards, and the open windows before you make your move. Reconnaissance is not a box to check off before the “real” hacking begins - it is the foundation of every successful operation.

In this deep dive, we will move beyond the basic nmap -sC -sV and explore the tactical application of network scanning in a professional engagement. We’ll cover TCP/IP fundamentals that underpin scan behavior, advanced NSE usage, firewall evasion, modern Rust-based tooling, and detailed service enumeration strategies for common protocols.


1. TCP/IP Fundamentals: Why Scans Work

Before we can understand how scanning tools detect services, we need to understand the underlying protocols.

The TCP Three-Way Handshake

TCP (Transmission Control Protocol) establishes a reliable, ordered connection between two hosts using a three-way handshake:

  1. SYN: The client sends a SYN (synchronize) packet to the server, requesting a connection.
  2. SYN-ACK: If the port is open and listening, the server responds with SYN-ACK (synchronize-acknowledge).
  3. ACK: The client sends an ACK (acknowledge), and the connection is established.

If the port is closed, the server responds with an RST (reset) packet instead of SYN-ACK. If the port is filtered by a firewall, the packet is simply dropped, and the client receives nothing (or an ICMP unreachable message).

UDP: No Handshake

UDP (User Datagram Protocol) is connectionless. There is no handshake. You send a packet, and you hope it arrives. If a UDP port is open, the service may or may not respond. If it’s closed, the host typically sends an ICMP “Port Unreachable” message. If it’s filtered, you get nothing.

This makes UDP scanning inherently slower and less reliable than TCP scanning.

ICMP: The Control Layer

ICMP (Internet Control Message Protocol) is used for diagnostic and error messages. Key ICMP types include:

  • Type 0 (Echo Reply): Response to a ping.
  • Type 3 (Destination Unreachable): Indicates a closed port or network issue.
  • Type 8 (Echo Request): A ping.
  • Type 11 (Time Exceeded): Used by traceroute.

Many scans use ICMP for host discovery before port scanning.


2. Nmap: The Heart of Reconnaissance

Nmap (Network Mapper) is the undisputed king of network scanning tools, maintained by Gordon Lyon (Fyodor) since 1997. While most people know the basic flags, a red teamer uses its advanced features to extract maximum intelligence while managing their forensic footprint.

Host Discovery (Ping Scans)

Before scanning ports, Nmap determines which hosts are alive. By default, it uses a combination of techniques:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Default host discovery (ICMP echo, TCP SYN to 443, TCP ACK to 80, ICMP timestamp)
nmap -sn 192.168.1.0/24

# Skip host discovery and scan all targets (useful if ICMP is blocked)
nmap -Pn 192.168.1.10

# Use specific discovery probes
nmap -PS22,80,445 192.168.1.0/24   # TCP SYN ping to specific ports
nmap -PA80,443 192.168.1.0/24      # TCP ACK ping
nmap -PU53,161 192.168.1.0/24      # UDP ping
nmap -PE 192.168.1.0/24            # ICMP Echo ping only

[!TIP] On internal networks where ICMP is often blocked, use -PS with ports likely to be open (22, 80, 445) for more reliable host discovery.

TCP Scan Types

SYN Scan (-sS):

The default and most common scan. Also called “half-open” or “stealth” scan.

  1. Nmap sends a SYN packet.
  2. If the port is open, the target responds with SYN-ACK.
  3. Nmap sends RST to tear down the connection before it completes.

Because the TCP handshake is never finished, this scan is less likely to be logged by applications (which only see completed connections). However, modern firewalls and IDS/IPS systems do log SYN scans.

1
sudo nmap -sS 192.168.1.10

TCP Connect Scan (-sT):

Completes the full three-way handshake. Used when you don’t have root/admin privileges (SYN scan requires raw sockets).

1
nmap -sT 192.168.1.10

ACK Scan (-sA):

Sends ACK packets instead of SYN. Doesn’t determine if a port is open or closed - it determines if a port is filtered by a stateful firewall. Firewalls that track connection state will drop unsolicited ACK packets.

1
sudo nmap -sA 192.168.1.10

FIN, Xmas, and Null Scans (-sF, -sX, -sN):

These scans send packets with unusual flag combinations (FIN only, FIN-PSH-URG, or no flags). According to RFC 793, a closed port should respond with RST, while an open port should ignore the packet. In practice, these scans are noisy on modern systems and often unreliable, but they can sometimes bypass older stateless firewalls.

Idle Scan (-sI):

The ultimate stealth scan. It uses a “zombie” host on the network (a host with a predictable IP ID sequence, like an old printer) to scan the target on your behalf. Your IP address never sends a packet directly to the target port.

1
sudo nmap -sI zombie_host target_host

This is complex but extremely valuable for stealthy reconnaissance in high-security environments.

UDP Scan (-sU)

UDP scanning is critical because many important services run on UDP: DNS (53), SNMP (161), NTP (123), TFTP (69), DHCP (67/68), and more. However, UDP scanning is painfully slow because:

  1. Open ports often don’t respond, so Nmap must wait for a timeout.
  2. Many systems rate-limit ICMP “Port Unreachable” messages.
1
2
3
4
5
# Scan top 20 UDP ports (much faster than all 65k)
sudo nmap -sU --top-ports 20 192.168.1.10

# Combine with version detection for better accuracy
sudo nmap -sU -sV --top-ports 100 192.168.1.10

[!TIP] Never scan all 65,535 UDP ports unless you have hours to spare. Target the top 100 or use a custom list of security-relevant UDP ports.

Version Detection (-sV)

Once ports are identified, Nmap can probe them to determine the running service and version.

1
2
3
4
nmap -sV 192.168.1.10

# Increase intensity for more thorough (but slower/noisier) probing
nmap -sV --version-intensity 9 192.168.1.10

Operating System Detection (-O)

Nmap analyzes TCP/IP stack behavior (TTL values, window sizes, TCP options) to fingerprint the target’s operating system.

1
2
3
4
sudo nmap -O 192.168.1.10

# Require at least one open and one closed port for more accurate results
sudo nmap -O --osscan-limit 192.168.1.10

Combining Flags: The Classics

1
2
3
4
5
6
7
8
# The "default recon" scan (SYN scan + version + default scripts)
sudo nmap -sS -sV -sC 192.168.1.10

# Full port scan with version and OS detection
sudo nmap -sS -sV -O -p- 192.168.1.10

# Aggressive scan (OS, version, scripts, traceroute) - LOUD
sudo nmap -A 192.168.1.10

3. Weaponizing the Nmap Scripting Engine (NSE)

The NSE is what transforms Nmap from a port scanner into a vulnerability scanner and enumeration platform. Scripts are written in Lua and located in /usr/share/nmap/scripts/ on most Linux systems.

Script Categories

Nmap scripts are organized into categories:

  • auth: Authentication-related scripts.
  • broadcast: Discover hosts via broadcast.
  • brute: Brute-force credential attacks.
  • default: Safe scripts run with -sC.
  • discovery: Service discovery and enumeration.
  • dos: Denial of service (use with extreme caution).
  • exploit: Attempt to exploit vulnerabilities.
  • external: Scripts that query external services.
  • fuzzer: Fuzzing scripts.
  • intrusive: Scripts likely to crash services or be detected.
  • malware: Detect malware infections.
  • safe: Scripts unlikely to crash services.
  • version: Version detection helpers.
  • vuln: Vulnerability detection.

Running Scripts

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Run default scripts
nmap -sC 192.168.1.10

# Run a specific script
nmap --script http-title 192.168.1.10

# Run all scripts in a category
nmap --script vuln 192.168.1.10

# Run scripts matching a pattern
nmap --script "smb-*" 192.168.1.10

# Combine categories (run safe AND vuln scripts)
nmap --script "safe and vuln" 192.168.1.10

Targeted Enumeration Examples

SMB Enumeration (Port 445):

1
2
3
4
5
# Enumerate shares, users, and check for EternalBlue (MS17-010)
nmap -p 445 --script smb-enum-shares,smb-enum-users,smb-vuln-ms17-010 192.168.1.10

# Full SMB enumeration
nmap -p 139,445 --script "smb-enum*,smb-vuln*,smb-os-discovery" 192.168.1.10

HTTP Enumeration (Ports 80, 443):

1
2
3
4
5
# Web server headers, methods, and directory enumeration
nmap -p 80,443 --script http-headers,http-methods,http-enum 192.168.1.10

# Check for common vulnerabilities
nmap -p 80,443 --script http-vuln* 192.168.1.10

SSH (Port 22):

1
2
3
4
5
# Check supported authentication methods
nmap -p 22 --script ssh-auth-methods 192.168.1.10

# Brute force (intrusive!)
nmap -p 22 --script ssh-brute --script-args userdb=users.txt,passdb=pass.txt 192.168.1.10

LDAP (Port 389):

1
2
3
4
5
# Enumerate LDAP root DSE (often reveals domain information)
nmap -p 389 --script ldap-rootdse 192.168.1.10

# Search LDAP for sensitive objects
nmap -p 389 --script ldap-search 192.168.1.10

Script Arguments

Many scripts accept arguments to customize their behavior:

1
2
3
4
5
# HTTP enum with custom paths
nmap -p 80 --script http-enum --script-args http-enum.basepath=/api/ 192.168.1.10

# SMB brute force with credentials
nmap -p 445 --script smb-brute --script-args smbuser=admin,smbpass=password 192.168.1.10

Updating the Script Database

1
2
3
4
5
6
# Update scripts from the Nmap repository
sudo nmap --script-updatedb

# Download new scripts manually (e.g., from GitHub)
sudo wget -O /usr/share/nmap/scripts/my-custom.nse https://example.com/script.nse
sudo nmap --script-updatedb

Writing Your Own NSE Scripts

Sometimes you need to check for a specific indicator (like a specific favicon hash, banner, or HTTP response).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
-- /usr/share/nmap/scripts/http-confidential-check.nse
local http = require "http"
local shortport = require "shortport"
local stdnse = require "stdnse"

description = [[
Checks for the presence of "Company Confidential" in HTTP responses.
]]

author = "UncleSp1d3r"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"discovery", "safe"}

portrule = shortport.http

action = function(host, port)
    local response = http.get(host, port, "/")
    if response.body and response.body:find("Company Confidential") then
        return "Found 'Company Confidential' on homepage!"
    end
end

4. Stealth and Evasion: Staying Below the Threshold

Modern EDRs, IDSs, and SIEM solutions are very good at spotting Nmap’s default patterns. As a red teamer, you must learn to fly under the radar.

Timing Templates (-T)

Nmap’s timing templates control the speed and aggressiveness of scans.

TemplateNameDescription
-T0ParanoidSends one packet every 5 minutes. For extremely high-security targets.
-T1SneakyOne packet every 15 seconds. Still very slow but more practical.
-T2PoliteOne packet every 0.4 seconds. Avoids overloading fragile systems.
-T3NormalDefault timing. Balances speed and stealth.
-T4AggressiveFaster, assumes a fast and reliable network.
-T5InsaneMaximum speed, high packet loss expected. For CTF, not real engagements.

For real engagements, consider -T2 or custom timing controls:

1
2
# Custom timing: wait 500ms between probes, limit parallelism
nmap --scan-delay 500ms --max-parallelism 10 192.168.1.10

Packet Manipulation

Decoys (-D):

Spoof your scan from multiple IP addresses. The target sees traffic from 10 IPs; one is real, nine are fake. This makes attribution difficult.

1
2
3
4
5
# Scan from 5 random IPs plus your own (ME)
sudo nmap -sS -D RND:5,ME 192.168.1.10

# Use specific decoy IPs
sudo nmap -sS -D 10.0.0.1,10.0.0.2,10.0.0.3,ME 192.168.1.10

[!WARNING] Decoys must appear to be valid hosts on the network, or they will be obviously fake. Do not use decoys across the internet - they are typically only effective on LANs.

Source Port Spoofing (-g or --source-port):

Many poorly configured firewalls allow traffic from “trusted” source ports like DNS (53) or HTTP (80).

1
2
# Force scan traffic to originate from port 53
sudo nmap -sS -g 53 192.168.1.10

IP Fragmentation (-f):

Split TCP headers into tiny 8-byte fragments. This can bypass simple packet filters that look for specific flag combinations but don’t reassemble fragments.

1
2
3
4
sudo nmap -sS -f 192.168.1.10

# Double fragmentation (16 bytes per fragment)
sudo nmap -sS -f -f 192.168.1.10

MTU Control (--mtu):

Specify a custom Maximum Transmission Unit for fragmentation.

1
sudo nmap -sS --mtu 24 192.168.1.10

Randomize Host Order (--randomize-hosts):

When scanning a subnet, randomize the order to avoid sequential detection.

1
nmap --randomize-hosts 192.168.1.0/24

Spoof MAC Address (--spoof-mac):

Useful on LANs to impersonate a different device type.

1
2
3
4
5
# Use a random vendor MAC
sudo nmap --spoof-mac Apple 192.168.1.10

# Use a specific MAC
sudo nmap --spoof-mac 00:11:22:33:44:55 192.168.1.10

5. Output Formats and Reporting

Nmap supports multiple output formats for different use cases.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Normal output (human-readable)
nmap 192.168.1.10 -oN scan.txt

# Greppable output (for scripting)
nmap 192.168.1.10 -oG scan.gnmap

# XML output (for parsing and reporting tools)
nmap 192.168.1.10 -oX scan.xml

# All formats at once
nmap 192.168.1.10 -oA scan_results

Parsing Nmap Output

The XML output can be parsed with tools like xsltproc or Python’s python-nmap library.

1
2
# Convert XML to HTML report
xsltproc scan.xml -o scan.html

6. Modern High-Speed Alternatives

While Nmap is accurate and feature-rich, its single-threaded-per-host architecture makes it slow for large networks. Modern alternatives sacrifice some accuracy for speed.

RustScan: The Modern Speed Demon

Written in Rust, RustScan finds open ports in seconds by:

  1. Adjusting the system’s ulimit to allow thousands of concurrent connections.
  2. Using asynchronous I/O for massively parallel port scanning.
  3. Piping the discovered open ports to Nmap for deep analysis.
1
2
3
4
5
6
7
8
# Scan all 65535 ports on a target, then run Nmap scripts on open ports
rustscan -a 192.168.1.10 -- -sV -sC

# Scan a subnet with a high connection limit
rustscan -a 192.168.1.0/24 --ulimit 5000

# Scan specific ports
rustscan -a 192.168.1.10 -p 22,80,443,445

RustScan can complete a full 65k port scan of a single host in under 10 seconds on a fast network.

Masscan: Internet-Scale Scanning

Masscan uses its own custom TCP/IP stack (bypassing the OS kernel) to transmit millions of packets per second. It is entirely stateless - it does not track connections.

1
2
3
4
5
6
7
8
# Scan a /16 for port 445
sudo masscan 10.10.0.0/16 -p445 --rate 10000

# Scan for common web ports
sudo masscan 10.10.0.0/16 -p80,443,8080,8443 --rate 50000

# Output in Nmap-compatible format
sudo masscan 10.10.0.0/16 -p445 -oG masscan.gnmap

[!WARNING] Masscan at high rates will overwhelm consumer-grade routers and may violate network usage policies. Use on VPSes with dedicated network interfaces or in lab environments, though you may violate the terms of service of your VPS provider.

Naabu: Another Fast Scanner

From ProjectDiscovery, Naabu is a Go-based port scanner designed for speed.

1
2
3
4
5
# Fast port scan
naabu -host 192.168.1.10 -p 1-65535

# Scan from a list of hosts
naabu -list targets.txt -p 22,80,443

7. Detailed Service Enumeration Strategies

Once ports are identified as open, the real work begins. Each service type requires a specific enumeration approach.

SMB (Ports 139, 445)

SMB is a goldmine for internal networks - shares, usernames, password policies, and often critical vulnerabilities.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Nmap scripts
nmap -p 445 --script smb-enum-shares,smb-enum-users,smb-os-discovery 192.168.1.10

# CrackMapExec (CME) for quick enumeration
crackmapexec smb 192.168.1.10

# Enum4linux-ng (updated Python version)
enum4linux-ng -A 192.168.1.10

# List shares with smbclient
smbclient -L //192.168.1.10/ -N

SNMP (Port 161 UDP)

SNMP often leaks process lists, installed software, network interfaces (dual-homed hosts!), and even credentials (SNMPv1/v2 use community strings in cleartext).

1
2
3
4
5
6
7
8
# Guess community strings
onesixtyone -c /usr/share/seclists/Discovery/SNMP/common-snmp-community-strings.txt 192.168.1.10

# Deep enumeration with snmpwalk
snmpwalk -v2c -c public 192.168.1.10

# User-friendly enumeration
snmp-check 192.168.1.10 -c public

NFS (Port 2049)

Network File System exports often have weak permissions. Look for no_root_squash which allows root access.

1
2
3
4
5
6
# List exports
showmount -e 192.168.1.10

# Mount and explore
sudo mkdir /mnt/nfs
sudo mount -t nfs 192.168.1.10:/share /mnt/nfs

LDAP (Port 389)

LDAP servers (Active Directory, OpenLDAP) can leak the entire directory structure.

1
2
3
4
5
# Anonymous bind and enumerate
ldapsearch -x -H ldap://192.168.1.10 -b "DC=corp,DC=local"

# Nmap scripts
nmap -p 389 --script ldap-rootdse,ldap-search 192.168.1.10

DNS (Port 53)

DNS misconfigurations can reveal internal hostnames and network structure.

1
2
3
4
5
# Zone transfer attempt
dig axfr @192.168.1.10 corp.local

# Reverse DNS sweep
dnsrecon -r 192.168.1.0/24 -n 192.168.1.10

SMTP (Port 25)

SMTP can be used to enumerate valid usernames via VRFY and EXPN commands.

1
2
3
4
5
6
7
# Manual enumeration
nc 192.168.1.10 25
VRFY admin
VRFY root

# Automated with smtp-user-enum
smtp-user-enum -M VRFY -U users.txt -t 192.168.1.10

8. Organizing Your Reconnaissance

On a real engagement, you will scan many hosts and services. Organization is critical.

Directory Structure

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
project/
  recon/
    nmap/
      initial-tcp.nmap
      full-tcp.nmap
      udp.nmap
      vuln-scan.xml
    masscan/
      full-range.txt
    enum/
      smb/
      snmp/
      ldap/

Tools for Aggregation

  • Zenmap: Nmap’s GUI; can aggregate and compare scans.
  • Nessus/OpenVAS: Vulnerability scanners with built-in scanning.
  • Faraday: Collaborative penetration testing IDE.
  • Reconftw: Automated reconnaissance framework.

Conclusion

Network scanning is not a “fire and forget” task. It is a methodical process of uncovering the target’s attack surface while managing your own forensic footprint. By understanding TCP/IP fundamentals, mastering Nmap’s advanced features and NSE scripting, implementing stealth timing and packet manipulation, and leveraging high-speed tools like RustScan and Masscan, you transform from a script kiddie into a surgical operator.

The network is the terrain. Know it better than the defenders do. Every open port is a potential door. Every service version is a potential CVE. Every misconfiguration is a potential foothold.

Happy hunting!


References