nmap is the standard network scanner. For a server admin, its most valuable use is simple: see your server the way the internet sees it. Which ports are actually reachable? Did that database get exposed by accident? Is the firewall doing what you think?
Only scan systems you own or are authorised to test. Scanning other people’s networks may break laws and providers’ terms of service.
Install
sudo apt install nmap # Debian/Ubuntu
sudo dnf install nmap # RHEL family
brew install nmap # macOS
Run scans from another machine (your computer or a second server). Scanning from the server itself shows what’s reachable locally, which bypasses the firewall’s view of the outside world.
Basic scans
nmap 203.0.113.10 # top 1000 TCP ports
nmap -p 22,80,443 203.0.113.10 # specific ports
nmap -p- 203.0.113.10 # all 65535 TCP ports (slower)
nmap -F 203.0.113.10 # fast: top 100 ports
nmap example.com # by hostname
Typical output:
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
443/tcp open https
3306/tcp filtered mysql
Port states
| State | Meaning | Action |
|---|---|---|
| open | A service accepts connections | Is it supposed to be public? |
| closed | Reachable, but nothing listens | Fine, though a firewall could hide it entirely |
| filtered | No reply: a firewall drops the packets | Expected for blocked ports |
| open|filtered | Can’t tell (common with UDP) | Verify differently |
The goal for a typical web server: only 22 (or your SSH port), 80 and 443 open. Everything else should be filtered or closed.
Service and version detection
nmap -sV -p 22,80,443 203.0.113.10
22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13.5 (Ubuntu Linux; protocol 2.0)
80/tcp open http nginx 1.24.0
443/tcp open ssl/http nginx 1.24.0
This shows what an attacker can learn. Consider hiding version banners (server_tokens off; in Nginx). See Nginx security headers.
SYN scan and OS detection (needs root)
sudo nmap -sS -p- 203.0.113.10 # SYN ("half-open") scan: faster, the default as root
sudo nmap -O 203.0.113.10 # OS guess
sudo nmap -A 203.0.113.10 # OS + versions + scripts + traceroute
UDP ports
sudo nmap -sU -p 53,123,161,500,51820 203.0.113.10
UDP scans are slow and often show open|filtered. Scan just the UDP services you run: DNS 53, NTP 123, WireGuard 51820.
Checking your firewall: a routine audit
- List what listens locally:
sudo ss -tulpn
- Scan all ports from outside:
sudo nmap -sS -p- --open 203.0.113.10
- Compare. Anything that listens but shouldn’t be public must be either bound to
127.0.0.1or blocked in the firewall. Common accidental exposures:
| Port | Service |
|---|---|
| 3306 / 5432 | MySQL / PostgreSQL |
| 6379 | Redis (attacked within minutes when exposed) |
| 27017 | MongoDB |
| 9200 | Elasticsearch |
| 2375 | Docker API (full root access!) |
| 8080, 3000, 9000 | Dev servers, admin panels, Portainer |
Docker note: ports published with -p 3306:3306 bypass UFW, because Docker inserts its own iptables rules. Publish only to localhost (-p 127.0.0.1:3306:3306), or use the DOCKER-USER chain. See UFW and check open ports.
Useful scripts (NSE)
nmap --script ssl-enum-ciphers -p 443 example.com # TLS versions and ciphers offered
nmap --script http-headers -p 443 example.com
nmap --script ssh2-enum-algos -p 22 203.0.113.10 # SSH algorithms
nmap --script http-title -p 80,443 203.0.113.0/28 # titles of web services in your range
ssl-enum-ciphers quickly shows whether old TLS 1.0/1.1 or weak ciphers are still enabled.
Scan your private network
nmap -sn 10.0.0.0/24 # ping sweep: which hosts are up (no port scan)
nmap -p 22 --open 10.0.0.0/24 # which hosts have SSH open
Speed and politeness
nmap -T4 … # faster timing (good on reliable networks)
nmap -T2 … # slower, gentler
nmap --max-rate 100 …
Aggressive scans can trigger the target’s intrusion detection. Fail2Ban or CrowdSec may ban your IP from your own server. Whitelist your admin IP, or scan from a host you don’t need to log in from.
Quick reference
| Task | Command |
|---|---|
| Top 1000 TCP | nmap host |
| All TCP ports | sudo nmap -sS -p- host |
| Only open | --open |
| Versions | nmap -sV host |
| UDP specific | sudo nmap -sU -p 53,123 host |
| TLS check | nmap --script ssl-enum-ciphers -p 443 host |
| Hosts up | nmap -sn 10.0.0.0/24 |
Related: netcat, firewall basics with UFW and Linux server hardening.