Because why just scan when you can scan smartly and safely?
Nmap (Network Mapper) is a powerful, open-source tool for network discovery and security auditing. It's used by:
Nmap is the de facto standard for network reconnaissance. Understanding it is crucial for: 1. Penetration Testing: Gathering information about targets 2. Network Security: Identifying unauthorized services 3. Compliance Audits: Verifying security controls 4. Incident Response: Analyzing network compromises
# See if nmap already exists (it probably doesn't)
nmap --version
# Update package list
sudo apt update
# Install Nmap
<div align="center">
<img src="carbon.png" width="500" style="border:1px solid #6a2bd6; border-radius:10px;">
</div>
# Verify installation
nmap --version
# Using DNF
sudo dnf install nmap -y
# Or using YUM (older versions)
sudo yum install nmap -y
# Verify
nmap --version
sudo pacman -S nmap
nmap --version
# Install Homebrew first (if needed)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Install Nmap
brew install nmap
# Verify
nmap --version
Option 1: Download Installer
1. Visit https://nmap.org/download.html
2. Download the .exe file
3. Run with admin privileges
4. Accept all defaults
5. Verify in CMD: nmap --version
Option 2: Add to PATH (PowerShell as Admin)
setx PATH "%PATH%;C:\Program Files (x86)\Nmap"
# Restart PowerShell and test
nmap --version
wget https://nmap.org/dist/nmap-7.94.tar.bz2
tar -xvf nmap-7.94.tar.bz2
cd nmap-7.94
./configure
make
sudo make install
nmap --version
Ports are logical communication endpoints on a system: - Port Range: 0 - 65,535 - Well-Known Ports: 0 - 1,023 (SSH, HTTP, HTTPS, DNS, etc.) - Registered Ports: 1,024 - 49,151 - Dynamic Ports: 49,152 - 65,535
| State | Meaning |
|---|---|
| Open | Port is accepting connections |
| Closed | Port responds but not accepting |
| Filtered | No response received (firewall blocking) |
| Unfiltered | Port responds to ACK |
| Open|Filtered | Likely open but may be filtered |
Client Server
| |
|--- SYN -------> |
| |
| <---- SYN/ACK ---|
| |
|--- ACK -------> |
| |
Understanding this is key to understanding scan types.
TCP SYN Scan (-sS) - Fastest and most popular - Requires root/admin privileges - Never completes full connection - Stealthier than full connects
TCP Connect Scan (-sT) - Uses OS socket connection - Works without root/admin - More likely to be logged - Slower than SYN
UDP Scan (-sU) - Scans UDP ports (DNS, SNMP, DHCP) - Slower than TCP - Can combine with TCP
nmap --version
Expected: Version number like "Nmap version 7.94"
If error: Install Nmap (see Installation section above)
nmap 192.168.1.10
What it does: - Scans the 1,000 most common TCP ports - Performs a SYN scan (default) - Takes 10-30 seconds depending on network
Output Example:
Nmap scan report for 192.168.1.10
Host is up (0.05s latency).
Not shown: 997 filtered ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
443/tcp open https
Beginner Task: Replace 192.168.1.10 with your router's IP (usually 192.168.1.1)
nmap -sn 192.168.1.0/24
What it does:
- Discovers live hosts on your network
- Doesn't scan ports (super fast)
- /24 means the entire subnet
Output Example:
Nmap scan report for 192.168.1.1
Host is up (0.001s latency).
Nmap scan report for 192.168.1.100
Host is up (0.050s latency).
Nmap scan report for 192.168.1.105
Host is up (0.045s latency).
Beginner Task: Run this on your network and count how many devices you find.
# Single port
nmap -p 22 192.168.1.10
# Multiple ports
nmap -p 22,80,443 192.168.1.10
# Port range
nmap -p 1-1000 192.168.1.10
# All 65535 ports (slow!)
nmap -p- 192.168.1.10
Output Example:
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
443/tcp closed
nmap -sV 192.168.1.10
What it does: - Identifies services running on open ports - Attempts to guess service versions - Useful for vulnerability research
Output Example:
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH_8.2p1 Ubuntu
80/tcp open http Apache httpd 2.4.41
443/tcp open https Apache httpd 2.4.41 (SSL/TLS)
Pro Tip: Google the version to find known vulnerabilities.
sudo nmap -O 192.168.1.10
What it does:
- Attempts to identify the target OS
- Uses TCP/IP stack fingerprinting
- Requires sudo for accurate results
Output Example:
Device type: general purpose
Running: Linux 4.X|5.X
OS details: Linux 4.15 - 5.10
sudo nmap -A 192.168.1.10
What it does: - OS Detection (-O) - Version Detection (-sV) - Script Scanning (-sC) - Traceroute (--traceroute) - Everything combined = "Aggressive"
Warning: Slower but comprehensive.
nmap -F 192.168.1.10
What it does: - Scans only 100 most common ports - Much faster than full scan - Good for quick recon
nmap -Pn 192.168.1.10
What it does: - Assumes target is online - Skips ping phase - Useful if firewall blocks ICMP
nmap -v 192.168.1.10
nmap -vv 192.168.1.10 # Extra verbose
What it does: - Shows scan progress in real-time - Displays what ports are being probed
# Human-readable format
nmap -oN results.txt 192.168.1.10
# XML format (machine-readable)
nmap -oX results.xml 192.168.1.10
# All formats
nmap -oA results 192.168.1.10
# Produces: results.nmap, results.xml, results.gnmap
Automate scanning, parse results, integrate with other tools, build custom dashboards. Let's go!
File: basic_scan.py
import subprocess
target = "scanme.nmap.org"
try:
result = subprocess.run(
["nmap", target],
capture_output=True,
text=True,
check=True
)
print("=== Nmap Output ===")
print(result.stdout)
except FileNotFoundError:
print("Error: nmap is not installed or not in PATH.")
except subprocess.CalledProcessError as e:
print(f"Nmap failed with exit code: {e.returncode}")
print(f"Error: {e.stderr}")
Run it:
python3 basic_scan.py
What it does:
- Runs nmap scanme.nmap.org
- Handles errors gracefully
- Prints results
File: port_scan.py
import subprocess
import sys
# Get target from command line or use default
target = sys.argv[1] if len(sys.argv) > 1 else "192.168.1.10"
ports = "22,80,443,3306,5432,8080"
cmd = ["nmap", "-sV", "-p", ports, target]
print(f"Scanning {target} on ports: {ports}")
print(f"Command: {' '.join(cmd)}\n")
result = subprocess.run(cmd, capture_output=True, text=True)
print(result.stdout)
# Save to file
with open(f"scan_{target}.txt", "w") as f:
f.write(result.stdout)
print(f"\nResults saved to scan_{target}.txt")
Run it:
python3 port_scan.py 192.168.1.10
python3 port_scan.py scanme.nmap.org
File: parse_ports.py
import subprocess
import re
target = "scanme.nmap.org"
cmd = ["nmap", "-sV", target]
result = subprocess.run(cmd, capture_output=True, text=True)
open_ports = []
# Parse each line looking for "PORT STATE SERVICE"
for line in result.stdout.splitlines():
# Pattern: "80/tcp open http Apache httpd 2.4.x"
if re.match(r"^\d+/tcp\s+open", line):
parts = line.split()
port_proto = parts[0] # "80/tcp"
state = parts[1] # "open"
service = parts[2] # "http"
open_ports.append({
'port': port_proto,
'state': state,
'service': service,
'raw': line
})
print(f"\n=== Open Ports on {target} ===")
for port_info in open_ports:
print(f"Port {port_info['port']} - {port_info['service']}")
print(f"\nTotal: {len(open_ports)} open ports")
Run it:
python3 parse_ports.py
File: subnet_scan.py
import subprocess
import re
import time
subnet = "192.168.1.0/24"
print(f"Scanning subnet: {subnet}")
print("This may take 1-2 minutes...\n")
cmd = ["nmap", "-sV", "--top-ports", "20", subnet]
result = subprocess.run(cmd, capture_output=True, text=True)
hosts = {}
# Parse results and group by host
current_host = None
for line in result.stdout.splitlines():
# Look for "Nmap scan report for XXX"
if "Nmap scan report for" in line:
current_host = line.split("for ")[-1].split(" ")[0]
hosts[current_host] = []
# Look for open ports
elif current_host and re.match(r"^\d+/tcp\s+open", line):
hosts[current_host].append(line.strip())
# Display results
for host, ports in hosts.items():
if ports: # Only show hosts with open ports
print(f"\n{host}:")
for port in ports:
print(f" {port}")
print(f"\nFound {len(hosts)} hosts with open ports")
Run it:
python3 subnet_scan.py
File: csv_export.py
import subprocess
import csv
import re
from datetime import datetime
target = "scanme.nmap.org"
cmd = ["nmap", "-sV", "-p", "1-1000", target]
result = subprocess.run(cmd, capture_output=True, text=True)
# Parse results
results = []
for line in result.stdout.splitlines():
if re.match(r"^\d+/tcp\s+", line):
parts = line.split()
results.append({
'timestamp': datetime.now().isoformat(),
'target': target,
'port': parts[0],
'state': parts[1],
'service': parts[2] if len(parts) > 2 else 'unknown',
})
# Save to CSV
filename = f"scan_{target}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
with open(filename, 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=['timestamp', 'target', 'port', 'state', 'service'])
writer.writeheader()
writer.writerows(results)
print(f"Saved {len(results)} results to {filename}")
Run it:
python3 csv_export.py
# Opens the CSV in Excel or text editor
File: port_checker.py
import subprocess
def check_port_open(target, port):
"""Check if a specific port is open"""
cmd = ["nmap", "-p", str(port), target]
result = subprocess.run(cmd, capture_output=True, text=True)
return "open" in result.stdout
target = "scanme.nmap.org"
important_ports = {
22: "SSH",
80: "HTTP",
443: "HTTPS",
3306: "MySQL",
5432: "PostgreSQL",
6379: "Redis",
27017: "MongoDB"
}
print(f"Checking important ports on {target}:\n")
for port, service in important_ports.items():
if check_port_open(target, port):
print(f"✓ Port {port:5} ({service:15}) - OPEN")
else:
print(f"✗ Port {port:5} ({service:15}) - CLOSED/FILTERED")
Run it:
python3 port_checker.py
File: compare_scans.py
import subprocess
import re
from datetime import datetime
def scan_and_parse(target):
"""Scan and return set of open ports"""
cmd = ["nmap", "-p", "1-1000", target]
result = subprocess.run(cmd, capture_output=True, text=True)
ports = set()
for line in result.stdout.splitlines():
if re.match(r"^\d+/tcp\s+open", line):
port = line.split('/')[0]
ports.add(port)
return ports
target = "scanme.nmap.org"
print("Performing baseline scan...")
baseline = scan_and_parse(target)
print("Waiting 5 seconds...")
import time
time.sleep(5)
print("Performing second scan...")
current = scan_and_parse(target)
print(f"\n=== Scan Comparison ===")
print(f"Baseline ports: {sorted(baseline)}")
print(f"Current ports: {sorted(current)}")
new_ports = current - baseline
closed_ports = baseline - current
if new_ports:
print(f"\n⚠️ NEW PORTS OPEN: {sorted(new_ports)}")
else:
print(f"\n✓ No new ports opened")
if closed_ports:
print(f"✓ Ports closed: {sorted(closed_ports)}")
Run it:
python3 compare_scans.py
File: safe_scan.py
import subprocess
import sys
import time
def safe_scan(target, ports="1-1000", max_retries=3):
"""Perform scan with error handling"""
for attempt in range(max_retries):
try:
print(f"Scanning {target} (attempt {attempt + 1}/{max_retries})...")
cmd = ["nmap", "-sV", "-p", ports, target]
result = subprocess.run(
cmd,
capture_output=True,
text=True,
timeout=300 # 5 minute timeout
)
if result.returncode == 0:
return result.stdout
else:
print(f"Error: {result.stderr}")
except subprocess.TimeoutExpired:
print(f"Scan timed out on attempt {attempt + 1}")
except FileNotFoundError:
print("Error: nmap not found. Install it first!")
sys.exit(1)
except Exception as e:
print(f"Error: {e}")
if attempt < max_retries - 1:
print("Retrying...")
time.sleep(2)
return None
# Usage
output = safe_scan("scanme.nmap.org")
if output:
print("\n=== Scan Results ===")
print(output)
else:
print("Scan failed after all retries")
Run it:
python3 safe_scan.py
File: beginner_lab.py
#!/usr/bin/env python3
"""
Beginner Lab: Complete Network Audit in Python
Performs: Host discovery → Port scan → Service detection → Report
"""
import subprocess
import re
from datetime import datetime
from pathlib import Path
def run_command(cmd):
"""Run command and return output"""
try:
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
return result.stdout
except subprocess.CalledProcessError as e:
return f"Error: {e.stderr}"
except FileNotFoundError:
return "Error: nmap not found"
def main():
print("=" * 60)
print("NMAP BEGINNER LAB - Complete Network Audit")
print("=" * 60)
# Task 1: Verify Nmap installation
print("\n[Task 1] Checking Nmap installation...")
version = run_command(["nmap", "--version"])
if "version" in version.lower():
print(f"✓ {version.strip()}")
else:
print("✗ Nmap not found. Install it first!")
return
# Task 2: Host discovery
target = input("\n[Task 2] Enter subnet to scan (e.g., 192.168.1.0/24): ")
print(f"Performing host discovery on {target}...")
discovery = run_command(["nmap", "-sn", target])
hosts = re.findall(r"Nmap scan report for ([\d\.]+)", discovery)
print(f"✓ Found {len(hosts)} live hosts")
# Task 3: Port scan on first 3 hosts
for host in hosts[:3]:
print(f"\n[Task 3] Scanning ports on {host}...")
scan = run_command(["nmap", "-sV", "--top-ports", "10", host])
open_ports = re.findall(r"(\d+/tcp)\s+open", scan)
print(f" Open ports: {', '.join(open_ports) if open_ports else 'None'}")
# Task 4: Save report
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
report_file = f"lab_report_{timestamp}.txt"
with open(report_file, "w") as f:
f.write("NMAP BEGINNER LAB REPORT\n")
f.write(f"Date: {datetime.now()}\n")
f.write(f"Target: {target}\n")
f.write(f"Hosts Found: {len(hosts)}\n\n")
f.write("Discovery Results:\n")
f.write(discovery)
print(f"\n✓ Report saved to {report_file}")
print("\n[Lab Complete!] Review the report for findings.")
if __name__ == "__main__":
main()
Run it:
python3 beginner_lab.py
# Scan multiple IPs
nmap 192.168.1.1 192.168.1.2 192.168.1.3
# Scan IP range
nmap 192.168.1.1-50
# Scan entire subnet
nmap 192.168.1.0/24
# Scan from file
nmap -iL targets.txt
# Save targets to file first:
echo "192.168.1.1" > targets.txt
echo "192.168.1.10" >> targets.txt
nmap -iL targets.txt
# Very slow (stealthy)
nmap -T0 target.com
# Slow (stealth attempt)
nmap -T1 target.com
# Polite (considerate)
nmap -T2 target.com
# Normal (default)
nmap -T3 target.com
# Aggressive (fast)
nmap -T4 target.com
# Insane (very fast, may miss)
nmap -T5 target.com
# Exclude specific hosts
nmap 192.168.1.0/24 --exclude 192.168.1.1,192.168.1.2
# Exclude from file
nmap 192.168.1.0/24 --excludefile exclude.txt
# Exclude specific ports
nmap --exclude-ports 22,23,25 target.com
# Fragment packets (old technique)
nmap -f target.com
# Custom MTU size
nmap --mtu 32 target.com
# Source port spoofing
nmap --source-port 53 target.com
# IP decoy
nmap -D 192.168.1.1,192.168.1.2 target.com
# SYN scan (requires sudo, stealthy)
sudo nmap -sS target.com
# TCP connect (slower, full connection)
nmap -sT target.com
# UDP scan
nmap -sU target.com
# FIN scan (firewall evasion)
sudo nmap -sF target.com
# NULL scan
sudo nmap -sN target.com
# Xmas scan
sudo nmap -sX target.com
# Set minimum rate
nmap --min-rate 1000 target.com
# Set maximum rate
nmap --max-rate 100 target.com
# Host timeout
nmap --host-timeout 10m target.com
# Scan delay between probes
nmap --scan-delay 1s target.com
# Maximum retries
nmap --max-retries 2 target.com
# Run default scripts
nmap -sC target.com
# Run specific script
nmap --script ssh-hostkey target.com
# Run script category
nmap --script vuln target.com
nmap --script safe target.com
# Multiple scripts
nmap --script ssh-hostkey,ssl-cert target.com
# SSH enumeration
nmap --script ssh-hostkey,ssh-auth-methods target.com
# HTTP enumeration
nmap -p 80 --script http-enum,http-title target.com
# DNS zone transfer
nmap --script dns-zone-transfer target.com
# SMB enumeration
nmap --script smb-os-discovery,smb-enum-shares target.com
# Vulnerability scanning
nmap --script vuln target.com
sudo nmap --script-updatedb
# Human-readable
nmap -oN results.txt target.com
# XML (machine-readable)
nmap -oX results.xml target.com
# Grepable (awk-friendly)
nmap -oG results.gnmap target.com
# All formats
nmap -oA results target.com
import xml.etree.ElementTree as ET
def parse_nmap_xml(filename):
tree = ET.parse(filename)
root = tree.getroot()
for host in root.findall('host'):
status = host.find('status').get('state')
addr = host.find('address').get('addr')
print(f"\nHost: {addr} ({status})")
ports = host.find('ports')
if ports:
for port in ports.findall('port'):
port_id = port.get('portid')
state = port.find('state').get('state')
service = port.find('service')
service_name = service.get('name') if service else 'unknown'
print(f" Port {port_id}: {state} ({service_name})")
parse_nmap_xml('results.xml')
# Generate XML first
nmap -sV -oX scan.xml target.com
# Convert to HTML
xsltproc /usr/share/nmap/nmap.xsl scan.xml -o scan.html
# View in browser
firefox scan.html
# Discover your network
nmap -sn 192.168.1.0/24
# Save results
nmap -sn -oN discovery.txt 192.168.1.0/24
# Count live hosts
nmap -sn 192.168.1.0/24 | grep "Host is up" | wc -l
# Scan official Nmap test site (permission granted)
nmap scanme.nmap.org
# With version detection
nmap -sV scanme.nmap.org
# Save to XML
nmap -sV -oX lab2.xml scanme.nmap.org
# Comprehensive scan
nmap -A scanme.nmap.org
# With default scripts
nmap -sC -sV scanme.nmap.org
# Save results
nmap -A -oA lab3 scanme.nmap.org
# Run vulnerability scripts
nmap --script vuln scanme.nmap.org
# Check for specific CVE
nmap --script ssl-heartbleed -p 443 scanme.nmap.org
# Save report
nmap --script vuln -oX vuln_report.xml scanme.nmap.org
"Permission denied" - Need Root
# Problem
nmap -sS target.com
# Error: Operation not permitted
# Solution
sudo nmap -sS target.com
# Or use TCP connect (no root needed)
nmap -sT target.com
"Unknown host"
# Problem
nmap invalidhost
# Solution: Use valid IP or hostname
nmap 8.8.8.8
nmap google.com
"Port out of range"
# Problem
nmap -p 99999 target.com
# Solution: Valid ports are 1-65535
nmap -p 1-1000 target.com
"Failed to resolve hostname"
# Problem: DNS issue
nmap invalid-domain.xyz
# Solution: Use IP or valid domain
nmap 192.168.1.1
nmap google.com
"Couldn't open/read file"
# Problem
nmap -iL nonexistent.txt
# Solution: Create file first
echo "192.168.1.1" > targets.txt
nmap -iL targets.txt
# Enable debug output
nmap -d target.com
# Maximum debug
nmap -ddd target.com
# If scan timing out
nmap --host-timeout 30m target.com
# Use polite timing
nmap -T2 target.com
# Increase max retries
nmap --max-retries 5 target.com
# ⚠️ NEVER scan without permission
# These are ILLEGAL:
nmap random-company.com
nmap 10.0.0.0/8
nmap government-site.gov
# These are LEGAL and authorized:
nmap scanme.nmap.org # Official test site
nmap YOUR_OWN_NETWORK
nmap YOUR_OWN_SERVER
# Use appropriate timing for production systems
nmap -T2 production-server.com
# Only scan necessary ports
nmap -p 80,443,22 target.com
# Avoid aggressive options on shared networks
nmap --script safe target.com # Not intrusive
# Step 1: Light reconnaissance
nmap -sn -oA 01_discovery 192.168.0.0/16
# Step 2: Port scan
nmap -sS -oA 02_portscan 192.168.0.0/16
# Step 3: Service detection
nmap -sV -oA 03_services 192.168.0.0/16
# Step 4: Safe scripts
nmap --script safe -oA 04_scripts 192.168.0.0/16
# Step 5: Vulnerability check
nmap --script vuln -oA 05_vuln 192.168.0.0/16
# Include metadata
echo "Scan Date: $(date)" > report.txt
echo "Target: target.com" >> report.txt
echo "Authorized by: [Name]" >> report.txt
nmap -oX - target.com >> report.txt
# Scan results contain sensitive data
# Make them read-only
chmod 600 *.xml *.nmap *.gnmap
# Encrypt if needed
gpg -c results.xml
# Optimize for subnet scanning
nmap --min-rate 1000 --max-rate 2000 \
--min-hostgroup 256 --max-hostgroup 512 \
192.168.0.0/16 -oA largescan
# Quick recon
nmap -A -T4 target.com
# Stealthy scan
sudo nmap -sS -T2 -Pn target.com
# Vulnerability assessment
nmap -A --script vuln target.com
# Network discovery
nmap -sn -oA discovery 192.168.0.0/16
# Complete audit
nmap -A -sS -sU --script default,vuln \
-p- -oA audit target.com
✓ How to install Nmap on any OS
✓ Perform basic and advanced scans
✓ Detect services and vulnerabilities
✓ Use NSE scripts
✓ Parse results with Python
✓ Document and report findings
Last Updated: November 2025
Difficulty: Beginner to Advanced
Estimated Time: 40-60 hours of hands-on learning
License: Educational Use Only
Now you have everything you need to wield Nmap like a pro. Practice responsibly, scan ethically, and keep learning!