Nmap

Nmap OS Detection (-O): How TCP/IP Fingerprinting Works

Nmap OS detection - terminal showing -O fingerprinting Linux and no exact match on Cisco gear
Table of Contents
In: Nmap, Network Security, Cisco Modeling Labs

Version detection tells you what software a port is running. OS detection (-O) tries to answer a different question: what operating system is the whole host running, even on ports that give nothing away. It does this without logging in and without trusting any banner, by reading the subtle quirks in how the target's TCP/IP stack builds packets. That makes it powerful for inventory and auditing - you can fingerprint a box you have no credentials for - but it also makes it a guess, and a guess that fails in predictable ways on lab gear and network appliances. This guide is part of the complete Nmap guide, and it walks through what -O measures, how to read every field it prints, and why it sometimes shrugs and hands you a raw fingerprint instead of an answer.

What -O actually measures

No two TCP/IP stacks are implemented identically. The RFCs leave dozens of small decisions to the developer - how to pick initial sequence numbers, which TCP options to include and in what order, what window size to advertise, how to set IP flags, how ICMP replies are formed. Those decisions are consistent within an OS and differ between operating systems. OS detection sends a battery of specially crafted probes, watches exactly how the stack responds, and matches that behavioral fingerprint against Nmap's database of known systems.

Among the things it samples are the sequence-number generation pattern (the SEQ tests, which measure how predictable the target's ISN sampling is), the set and ordering of TCP options, the advertised window size, IP fragmentation flags, and ICMP behavior. You do not need to read those raw values by hand - Nmap distills them into a plain-language guess - but knowing that is where the answer comes from explains why the technique is both clever and fallible. It is inference from stack behavior, not a lookup of anything the host willingly tells you.

Why it needs an open and a closed port

OS fingerprinting works best when Nmap can observe the stack in two states: how it responds on an open port and how it responds on a closed one. The contrast between those two behaviors is a large part of the signal. If Nmap cannot find both, it warns you, and the accuracy drops. You will see exactly that warning when scanning a host where every probed port happens to be open:

$ nmap -O -p22,80,9929,31337 scanme.nmap.org
Starting Nmap 7.95 ( https://nmap.org ) at 2026-07-05 15:06 PDT
Nmap scan report for scanme.nmap.org (45.33.32.156)
Host is up (0.018s latency).
Other addresses for scanme.nmap.org (not scanned): 2600:3c01::f03c:91ff:fe18:bb2f

PORT      STATE SERVICE
22/tcp    open  ssh
80/tcp    open  http
9929/tcp  open  nping-echo
31337/tcp open  Elite
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose|router
Running: Linux 4.X|5.X, MikroTik RouterOS 7.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5 cpe:/o:mikrotik:routeros:7 cpe:/o:linux:linux_kernel:5.6.3
OS details: Linux 4.15 - 5.19, Linux 5.0 - 5.14, OpenWrt 21.02 (Linux 5.4), MikroTik RouterOS 7.2 - 7.5 (Linux 5.6.3)
Network Distance: 15 hops

OS detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 1.97 seconds

Because the scan restricted itself to four ports that all came back open, Nmap could not sample closed-port behavior and printed OSScan results may be unreliable because we could not find at least 1 open and 1 closed port. The practical fix is simple: do not artificially limit the port list when you care about OS detection. Let Nmap scan a normal range so it naturally finds a closed port to compare against. If a host genuinely has no closed ports in reach - a tightly filtered target - accept that the guess will be softer and lean on other evidence.

Reading the OS detection fields

Notice how many guesses that scanme.nmap.org result offered. That ambiguity is the norm when the signal is weak, and it is worth unpacking each field so you know what you are looking at.

Device type
The category Nmap thinks the host is: general purpose, router, switch, firewall, printer, and so on.
Pipe-separated when unsure, e.g. general purpose|router.
Running
The OS family and rough version range.
Multiple families listed means multiple candidates fit the fingerprint.
OS CPE
Standardized machine-readable OS identifiers.
Feed these into asset databases or vulnerability tooling.
OS details
The most specific version guesses Nmap will commit to.
A range like Linux 4.15 - 5.19 is a confidence window, not a precise build.
Network Distance
How many router hops away the target is.
15 hops to an internet host; 1 hop on your own LAN.

For scanme.nmap.org, the fingerprint fit several plausible systems at once - Linux 4.15-5.19, Linux 5.0-5.14, OpenWrt 21.02, and MikroTik RouterOS 7.2-7.5 - which is why Device type hedged as general purpose|router. That kind of spread is common when scanning across the internet: 15 hops of intervening routers, rate limiting, and middleboxes all erode the fingerprint. The Network Distance: 15 hops is itself a useful clue about how far away and how filtered the path is. Contrast that with a host one hop away on your own segment, where the same technique is far more decisive.

When it nails it, and when it can't

On the local lab segment, one hop away, OS detection is much sharper - but only for hosts whose stack is in the database. Here is a run against a Cisco IOL router and a Linux host on the same LAN:

$ nmap -O -T4 10.10.10.1 10.10.10.24
Starting Nmap 7.95 ( https://nmap.org ) at 2026-06-28 05:54 UTC
Nmap scan report for 10.10.10.1
Host is up (0.0029s latency).
Not shown: 998 closed tcp ports (reset)
PORT   STATE SERVICE
22/tcp open  ssh
23/tcp open  telnet
MAC Address: AA:BB:CC:00:5B:00 (Unknown)
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.95%E=4%D=6/28%OT=22%CT=1%CU=42871%PV=Y%DS=1%DC=D%G=Y%M=AABBCC%T
OS:M=6A40B71C%P=x86_64-pc-linux-gnu)SEQ(SP=100%GCD=1%ISR=106%TI=RD%CI=RD%II
OS:=RI%TS=U)OPS(O1=M5B4SNNW2L%O2=M578SNNW2L%O3=M280SNNW2L%O4=M218SNNW2L%O5=M
OS:218SNNW2L%O6=M109SLL)WIN(W1=FFFF%W2=FFFF%W3=FFFF%W4=FFFF%W5=FFFF%W6=FFFF)
OS:ECN(R=Y%DF=N%T=100%W=FFFF%O=M5B4SNNW2L%CC=N%Q=)T1(R=Y%DF=N%T=100%S=O%A=S+
OS:%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=N%T=100%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)
OS:IE(R=Y%DFI=S%T=100%CD=S)
Network Distance: 1 hop

Nmap scan report for 10.10.10.24
Host is up (0.0036s latency).
Not shown: 999 closed tcp ports (reset)
PORT   STATE SERVICE
22/tcp open  ssh
MAC Address: 52:54:00:BB:DC:36 (QEMU virtual NIC)
Device type: general purpose
Running: Linux 4.X|5.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5
OS details: Linux 4.15 - 5.19
Network Distance: 1 hop

OS detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 2 IP addresses (2 hosts up) scanned in 13.91 seconds

The Linux host at .24 gets a clean read: Device type: general purpose, Running: Linux 4.X|5.X, OS details: Linux 4.15 - 5.19. Its stack is a mainstream Linux kernel, well represented in Nmap's database, so one hop away with an open and a closed port available, the match is confident.

The Cisco IOL router at .1 is a different story. Instead of a named result you get No exact OS matches for host followed by a block of raw TCP/IP fingerprint: data. That is not a failure of the technique - Nmap successfully measured the stack, you can see the SEQ, OPS, WIN, and ECN tests captured right there - it simply had no signature in the database that matched. This is expected on virtual and lab gear and on some network operating systems: IOL is a virtualized IOS image whose stack behavior does not perfectly match physical Cisco hardware, and it is not indexed the way a common Linux kernel is. The right response is to submit that fingerprint back to Nmap (the output tells you where) so the database improves, and in the meantime lean on other evidence.

Accuracy controls

When OS detection hedges or gives up, a few flags change how hard it tries and how much it will speculate.

  • --osscan-guess (and its equivalent --fuzzy) tells Nmap to make its best guess even when the match is not perfect, printing near-matches with their confidence percentages instead of falling back to a raw fingerprint. Useful when "probably Linux 5.x" is more helpful to you than "no exact match."
  • --osscan-limit does the opposite of guessing harder: it restricts OS detection to hosts that have at least one open and one closed port. On a large sweep this skips the hopeless cases and saves real time, since fingerprinting a host with no usable port contrast rarely pays off.
  • --max-os-tries sets how many times Nmap retries the fingerprinting probes before giving up. Lowering it speeds up big scans; raising it can squeeze a match out of a flaky or rate-limited target at the cost of time.

None of these turn a guess into certainty. They tune the balance between speed, completeness, and how willing you are to accept a probabilistic answer.

Pair -O with -sV

OS detection is strongest when it is not the only evidence you have. Look back at the Cisco router: -O could not name it, but a version detection scan of the same box reported Service Info: OS: IOS; Device: switch straight from the SSH and telnet banners. Two independent techniques, two angles on the same question. When the stack fingerprint comes back empty, the application banners often fill the gap, and when the banners are stripped, the stack fingerprint may still speak. Running -O and -sV together (or just using -A, which includes both) is the practical default for any real fingerprinting job.

It also helps to remember what OS detection assumes: that the host is up and reachable in the first place. If a target is not responding to your probes, sort out host discovery before you trust an OS result, because a filtered or half-reachable host produces exactly the kind of thin, ambiguous fingerprint that leads to a spread of bad guesses. Nmap's reference guide documents the full set of fingerprint tests if you want to read the raw SEQ and OPS lines yourself.

Key takeaways

OS detection reads the target's TCP/IP stack - sequence numbers, TCP options, window size, IP flags, ICMP behavior - and matches that fingerprint against a database, so it is inference rather than fact. It needs at least one open and one closed port to do its best work, which is why over-restricting the port list triggers the "unreliable" warning. On a mainstream Linux host one hop away it will name the kernel range confidently; on virtual lab gear or an off-database network OS like Cisco IOL it may return only a raw fingerprint for you to submit. Read the Device type, Running, OS CPE, OS details, and Network Distance fields together rather than fixating on one, tune the guess with --osscan-guess and --osscan-limit, and always pair -O with -sV so a stack-fingerprint miss can be backfilled by a banner that already said "OS: IOS." For the full workflow around discovery, scanning, and fingerprinting, work through the complete Nmap guide.

Written by
More from Ping Labz
Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to Ping Labz.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.