If you run a computer network, be it home WiFi or a global enterprise system, you need a way to investigate the machines connected to your network. When ping and traceroute won't cut it, you need a port scanner.
nmap is the port scanner. It's a powerful, sophisticated tool, not to mention a movie star. The documentation on nmap is voluminous: there's an entire book, with a free online edition, as well as a detailed manpage. In this post I'll show you just a few of the cool things nmap can do.
The law and ethics of port scanning are complex. A network scan can be detected by humans or automated systems, and treated as a malicious act, resulting in real costs to the target. Depending on the options you choose, the traffic generated by nmap can range from "completely innocuous" to "watch out for admins with baseball bats". A safe rule is to avoid scanning any network without the explicit permission of its administrators — better yet if that's you.
You'll need root privileges on the scanning system to run most interesting nmap commands, because nmap likes to bypass the standard network stack when synthesizing esoteric packets.
Let's start by scanning my home network for web and SSH servers:
root@lyle# nmap -sS -p22,80 192.168.1.0/24 Nmap scan report for 192.168.1.1 PORT STATE SERVICE 22/tcp filtered ssh 80/tcp open http Nmap scan report for 192.168.1.102 PORT STATE SERVICE 22/tcp filtered ssh 80/tcp filtered http Nmap scan report for 192.168.1.103 PORT STATE SERVICE 22/tcp open ssh 80/tcp closed http Nmap done: 256 IP addresses (3 hosts up) scanned in 6.05 seconds
We use -p22,80 to ask for a scan of TCP ports 22 and 80, the most popular ports for SSH and web servers respectively. If you don't specify a -p option, nmap will scan the 1,000 most commonly-used ports. You can give a port range like -p1-5000, or even use -p- to scan all ports, but your scan will take longer.
We describe the subnet to scan using CIDR notation. We could equivalently write 192.168.1.1-254.
The option -sS requests a TCP SYN scan. nmap will start a TCP handshake by sending a SYN packet. Then it waits for a response. If the target replies with SYN/ACK, then some program is accepting our connection. A well-behaved client should respond with ACK, but nmap will simply record an open port and move on. This makes an nmap SYN scan both faster and more stealthy than a normal call to connect().
If the target replies with RST, then there's no service on that port, and nmap will record it as closed. Or we might not get a response at all. Perhaps a firewall is blocking our traffic, or the target host simply doesn't exist. In that case the port state is recorded as filtered after nmap times out.
You can scan UDP ports by passing -sU. There's one important difference from TCP: Since UDP is connectionless, there's no particular response required from an open port. Therefore nmap may show UDP ports in the ambiguous state open|filtered, unless you can prod the target application into sending you data (see below).
To save time, nmap tries to confirm that a target exists before performing a full scan. By default it will send ICMP echo (the ubiquitous "ping") as well as TCP SYN and ACK packets. You can use the -P family of options to customize this host-discovery phase.
nmap has the ability to generate all sorts of invalid, useless, or just plain weird network traffic. You can send a TCP packet with no flags at all (null scan, -sN) or one that's lit up "like a Christmas tree" (Xmas scan, -sX). You can chop your packets into little fragments (--mtu) or send an invalid checksum (--badsum). As a network administrator, you should know if the bad guys can confuse your security systems by sending weird packets. As the manpage advises, "Let your creative juices flow".
There's a second benefit to sending weird traffic: We can identify the target's operating system by seeing how it responds to unusual situations. nmap will perform this OS detection if you specify the -O flag:
root@lyle# nmap -sS -O 192.168.1.0/24 Nmap scan report for 192.168.1.1 Not shown: 998 filtered ports PORT STATE SERVICE 23/tcp closed telnet 80/tcp open http MAC Address: 00:1C:10:33:6B:99 (Cisco-Linksys) Device type: WAP|broadband router Running: Linksys embedded, Netgear embedded, Netgear VxWorks 5.X ... Nmap scan report for 192.168.1.100 Not shown: 998 filtered ports PORT STATE SERVICE 139/tcp open netbios-ssn 445/tcp open microsoft-ds MAC Address: 00:1F:3A:7F:7C:26 (Hon Hai Precision Ind.Co.) Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port Device type: general purpose Running (JUST GUESSING) : Microsoft Windows Vista|2008|7 (98%) ... Nmap scan report for 192.168.1.104 All 1000 scanned ports on 192.168.1.104 are closed MAC Address: 7C:61:93:53:9F:E5 (Unknown) Too many fingerprints match this host to give specific OS details TCP/IP fingerprint: SCAN(V=5.21%OT=%CT=1%CU=42921%PV=Y%DS=1%DC=D%G=N%M=7C6193%TM=4D6079CD) SEQ(CI=Z%II=I) T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=) ...
Since the first target has both an open and a closed port, nmap has many protocol corner cases to explore, and it easily recognizes a Linksys home router. With the second target, there's no port in the closed state, so nmap isn't as confident. It guesses a Windows OS, which seems especially plausible given the open NetBIOS ports. In the last case nmap has no clue, and gives us some raw findings only. If you know the OS of the target, you can contribute this fingerprint and help make nmap even better.
It's all well and good to discover that port 1234 is open, but what's actually listening there? nmap has a version detection subsystem that will spam a host's open ports with data in hopes of eliciting a response. Let's pass -sV to try this out:
root@lyle# nmap -sS -sV 192.168.1.117 Nmap scan report for 192.168.1.117 Not shown: 998 closed ports PORT STATE SERVICE VERSION 443/tcp open ssh OpenSSH 5.5p1 Debian 6 (protocol 2.0) 8888/tcp open http thttpd 2.25b 29dec2003
nmap correctly spotted an HTTP server on non-standard port 8888. The SSH server on port 443 (usually HTTPS) is also interesting. I find this setup useful when connecting from behind a restrictive outbound firewall. But I've also had network admins send me worried emails, thinking my machine has been compromised.
nmap also gives us the exact server software versions, straight from the server's own responses. This is a great way to quickly audit your network for any out-of-date, insecure servers.
Since a version scan involves sending application-level probes, it's more intrusive and can cause more trouble. From the book:
In the nmap-service-probes included with Nmap the only ports excluded are TCP port 9100 through 9107. These are common ports for printers to listen on and they often print any data sent to them. So a version detection scan can cause them to print many pages full of probes that Nmap sends, such as SunRPC requests, help statements, and X11 probes.
This behavior is often undesirable, especially when a scan is meant to be stealthy.
It's a common (if questionable) practice for servers or firewalls to trust certain traffic based on where it appears to come from. nmap gives you a variety of tools for mapping these trust relationships. For example, some firewalls have special rules for traffic originating on ports 53, 67, or 20. You can set the source port for nmaps TCP and UDP packets by passing --source-port
You can also spoof your source IP address using -S, and the target's responses will go to that fake address. This normally means that nmap won't see any results. But these responses can affect the unwitting source machine's IP protocol state in a way that nmap can observe indirectly. You can read about nmaps TCP idle scan for more details on this extremely clever technique. Imagine making any machine on the Internet — or your private network — port-scan any other machine, while you collect the results in secret. Can you use this to map out trust relationships in your network? Could an attacker?