How to Use nmap for Network Scanning and Linux Server Security Auditing

Network tutorial - IT technology blog
Network tutorial - IT technology blog

Why I Started Using nmap More Regularly

When I first took over managing the network for a 50-person office and a small datacenter, I kept getting blindsided by strange ports that would suddenly appear on servers. One time, the dev team deployed an internal test service and forgot to shut it down — the service was bound to 0.0.0.0, exposing it to the internet. Fortunately, I caught it early before anything bad happened.

From that point on, nmap became a permanent fixture in my weekly checklist. Not for hacking — but to know exactly what my servers are exposing to the outside world. Instead of manually checking each service, a single nmap command can scan an entire subnet in minutes.

Installing nmap on Linux

On most popular distros, nmap is available in the official repository:

# Ubuntu / Debian
sudo apt update && sudo apt install nmap -y

# CentOS / RHEL / Rocky Linux
sudo dnf install nmap -y

# Arch Linux
sudo pacman -S nmap

Check the version after installation:

nmap --version
# Nmap version 7.94 ( https://nmap.org )

An important note: scanning your own systems with nmap is completely legitimate. Scanning someone else’s IP without permission is illegal — in the US you can be prosecuted under the Computer Fraud and Abuse Act, and similar cybercrime laws exist in most countries. I only use nmap to audit infrastructure that I’m authorized to manage.

Detailed Scanning Techniques and Configuration

1. Basic Port Scanning — See What Your Server Is Exposing

Start simple — see which ports the server is listening on:

# Scan the 1000 most common ports (default)
nmap 192.168.1.100

# Scan all 65535 ports — slower but more comprehensive
nmap -p- 192.168.1.100

# Scan a specific port range
nmap -p 22,80,443,3306,6379 192.168.1.100

Sample output:

PORT     STATE  SERVICE
22/tcp   open   ssh
80/tcp   open   http
443/tcp  open   https
3306/tcp open   mysql

Seeing MySQL (3306) open? If this server is public-facing, that’s a serious problem. I’ve actually encountered this — a developer left the default 0.0.0.0 binding during testing and forgot to change it back.

2. Service Version Detection — Critical for Vulnerability Assessment

An open port is just the surface. What matters more is the version — to cross-reference against the CVE database:

# -sV: detect service version
nmap -sV 192.168.1.100

# Combine with -sC (default scripts) for additional information
nmap -sV -sC 192.168.1.100

Much more specific results:

PORT    STATE SERVICE VERSION
22/tcp  open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 (Ubuntu Linux; protocol 2.0)
80/tcp  open  http    nginx 1.24.0 (Ubuntu)
443/tcp open  ssl/http nginx 1.24.0

OpenSSH 8.9, nginx 1.24 — head to NVD (nvd.nist.gov) right away to check for any active CVEs. This step takes 2 minutes but regularly catches critical vulnerabilities before someone else exploits them.

3. Scanning the Entire Subnet — Internal Network Audit

This is the command I run every Monday morning to check for any network changes:

# Ping scan — list all online hosts in the subnet
nmap -sn 192.168.1.0/24

# Combine with a quick port scan
nmap -sn -oG - 192.168.1.0/24 | grep 'Status: Up' | awk '{print $2}' > live_hosts.txt
nmap -iL live_hosts.txt -p 22,80,443,3306,5432,6379,27017 -oN scan_result.txt

Save the results to a file, then diff it against last week’s output. Any new IPs or unexpected ports that suddenly appear are usually services someone deployed without telling anyone.

4. OS Detection and Fingerprinting

# -O: OS detection (requires root)
sudo nmap -O 192.168.1.100

# Aggressive scan — combines multiple techniques
sudo nmap -A 192.168.1.100

The -A option combines four things in one run: OS detection, version detection, script scanning, and traceroute. Use it when you need to thoroughly audit a specific host. But avoid running it regularly on production — it generates significant traffic and leaves a clear trace in logs.

5. Stealth Scan — Lower-Noise Scanning

# SYN scan (half-open) — fast, minimal logging on target
sudo nmap -sS 192.168.1.100

# UDP scan — many critical services use UDP (DNS, SNMP, NTP)
sudo nmap -sU -p 53,123,161 192.168.1.100

UDP scans often get overlooked because they’re slower than TCP. Don’t skip them. I once discovered SNMP (port 161 UDP) enabled with the default community string “public” on a network device — which meant anyone could read the complete configuration of every switch and router on the internal network without any authentication.

6. Using NSE Scripts — In-Depth Security Checks

The NSE (Nmap Scripting Engine) ships with over 600 scripts — from vulnerability checks to detailed information enumeration:

# Check for common vulnerabilities
nmap --script vuln 192.168.1.100

# Check SSH: brute force protection, encryption algorithms
nmap --script ssh-auth-methods,ssh2-enum-algos -p 22 192.168.1.100

# Check HTTP security headers
nmap --script http-security-headers -p 80,443 192.168.1.100

# Check SSL/TLS configuration
nmap --script ssl-enum-ciphers -p 443 192.168.1.100

The ssl-enum-ciphers script is especially useful — it lists all supported cipher suites and grades each one (A/B/C/F). I use this to verify configuration after every TLS update on nginx.

Analyzing Results and Setting Up Regular Monitoring

Saving Scan Results for Comparison Over Time

Nmap supports multiple output formats. XML for scripted parsing, plaintext for direct reading:

# XML output — for parsing or importing into other tools
nmap -sV -oX scan_$(date +%Y%m%d).xml 192.168.1.0/24

# Output all formats at once
nmap -sV -oA scan_$(date +%Y%m%d) 192.168.1.0/24
# Creates: scan_YYYYMMDD.nmap, scan_YYYYMMDD.xml, scan_YYYYMMDD.gnmap

# Compare two scans to detect changes
diff scan_20240101.nmap scan_20240108.nmap

Simple Automation Script for Weekly Audits

#!/bin/bash
# /opt/scripts/weekly_nmap_audit.sh

SUBNET="192.168.1.0/24"
OUTDIR="/var/log/nmap-audit"
DATE=$(date +%Y%m%d_%H%M)

mkdir -p $OUTDIR

# Scan critical ports across the entire subnet
nmap -sV -p 22,23,80,443,3306,5432,6379,27017,11211,9200 \
  --open -oN "$OUTDIR/scan_$DATE.txt" $SUBNET

# Send alert if dangerous ports are detected (23=telnet, 11211=memcached)
if grep -E '^[0-9]+.*23/tcp|11211/tcp' "$OUTDIR/scan_$DATE.txt"; then
  echo "WARNING: Dangerous port detected!" | mail -s "[ALERT] nmap audit" [email protected]
fi

Add to crontab to run automatically:

crontab -e
# Run every Monday at 7 AM
0 7 * * 1 /opt/scripts/weekly_nmap_audit.sh

What to Watch For in Scan Results

  • Port 23 (Telnet) — shut this down immediately if you see it; Telnet transmits everything unencrypted, including passwords
  • Port 3306/5432 (MySQL/PostgreSQL) open to the internet — databases should never be directly public-facing
  • Port 6379 (Redis) without authentication — I once handled a case where Redis was compromised to run a cryptominer, with the server CPU pegged at 100% for a full week before we tracked down the root cause
  • Port 9200 (Elasticsearch) open without auth — thousands of data breaches have occurred for exactly this reason, many involving large-scale customer data exposure
  • Port 11211 (Memcached) — commonly exploited for DDoS amplification attacks, with an amplification factor that can reach 51,000x

After nearly three years of using nmap to audit systems, I’ve realized the real value isn’t in the first scan. It’s in running it regularly and comparing results over time. Infrastructure changes constantly — new services get deployed, updates open additional ports, firewall rules get reset after reboots. Regular scanning lets you catch these changes early, before someone else finds them first.

Share: