Please note that Michal is now actively developing version 2 of p0f; please look at for more information and downloads. I have rpms of this branch below.

Up one level
COPYING 26319 Oct 13 2000
CREDITS 2362 Jul 10 15:00
ChangeLog 5631 Jul 10 15:35
INSTALL.Win32 1792 Jul 10 13:50
KNOWN_BUGS 297 Sep 11 2003
Makefile 291 Jul 10 13:48
README 43914 Jul 10 14:54
README.moreinfo.html 444 Jun 18 2003 1142 Feb 6 2003
TODO 568 Oct 10 2003
archives May 11 00:33
config.h 2947 Jul 10 13:50
cygwin-1.3.19-1.tar.bz2 1086710 Jan 24 2003
cygwin1.dll 906056 Jan 23 2003
db.sql 627 Apr 23 2002
devel Aug 14 2002
devel/COPYING 26319 Oct 13 2000
devel/CREDITS 684 May 12 2002
devel/ChangeLog 2188 May 12 2002
devel/Makefile 2683 May 13 2002
devel/Makefile.mysql 2475 May 12 2002
devel/README 15104 Aug 6 2002
devel/README.devel 281 Jan 22 2002
devel/favicon.ico 23 Apr 6 2003
devel/index.html 24285 Feb 6 2003
devel/internal-gopher-menu 32 Apr 6 2003
devel/internal-gopher-unknown 35 Apr 6 2003
devel/mysql May 12 2002
devel/mysql/db.sql 627 Apr 23 2002
devel/mysql/p0f-mysql.conf 116 Apr 22 2002
devel/p0f-1.8.1-test1.tar.gz 22393 Jan 21 2002
devel/p0f-1.8.1-test2.tar.gz 22385 Jan 21 2002
devel/p0f-1.8.1-test3.tar.gz 22970 Jan 26 2002
devel/p0f-1.8.1-test4.tar.gz 23102 Jan 27 2002
devel/p0f-1.8.2- 18218 May 12 2002
devel/p0f-1.8.2- 6158 May 12 2002
devel/p0f- 27704 May 12 2002
devel/p0f- 28213 May 13 2002
devel/p0f.1 1868 May 11 2002
devel/p0f.c 17409 May 13 2002
devel/p0f.fp 9127 May 11 2002
devel/p0f.init 1942 May 13 2002
devel/p0f.spec 2573 May 12 2002
devel/p0frep 1455 Jul 10 13:48
devel/tcp.h 1627 Jul 10 13:49
favicon.ico 20 Apr 6 2003
fpentry.h 1688 Jul 10 13:48
internal-gopher-menu 29 Apr 6 2003
internal-gopher-unknown 32 Apr 6 2003
moresigs Aug 14 2002
moresigs/README.moresigs 812 Feb 5 2002
moresigs/favicon.ico 23 Apr 6 2003
moresigs/index.html 5378 Jan 21 2003
moresigs/internal-gopher-menu 32 Apr 6 2003
moresigs/internal-gopher-unknown 35 Apr 6 2003
moresigs/p0f.fp.websigs.v0.2 113725 Jan 28 2002
moresigs/p0f.fp.websigs.v0.3 116499 Jan 28 2002
moresigs/p0f.fp.websigs.v0.3.1 104666 Jan 28 2002
moresigs/p0f.fp.websigs.v0.3.2 104924 Jan 28 2002
moresigs/p0f.fp.websigs.v0.3.3 155202 Feb 1 2002
moresigs/p0f.fp.websigs.v0.3.4 159006 Feb 3 2002
moresigs/p0f.fp.websigs.v0.3.5 155510 Feb 3 2002
moresigs/p0f.fp.websigs.v0.4.0 155275 Feb 3 2002
moresigs/p0f.fp.websigs.v0.4.1 156731 Feb 4 2002
mtu.h 1662 Jul 10 14:20
p0f-1.8.2-0.i386.rpm 67600 Feb 4 2002
p0f-1.8.2-0.src.rpm 27864 Feb 4 2002
p0f-1.8.2.exe 32106 Jan 15 2003
p0f-1.8.2.tgz 23969 Feb 4 2002
p0f-1.8.3-0.i386.rpm 71235 Feb 6 2003
p0f-1.8.3-0.src.rpm 33761 Feb 6 2003
p0f-1.8.3.exe 32162 Feb 7 2003
p0f-1.8.3.tgz 29733 Feb 6 2003
p0f-2.0.2-0.i386.rpm 108554 Sep 29 2003
p0f-2.0.2-0.src.rpm 79538 Sep 29 2003
p0f-2.0.2.tgz 74524 Sep 28 2003
p0f-2.0.3-0.i386.rpm 77677 Feb 1 2004
p0f-2.0.3-0.src.rpm 124431 Feb 1 2004
p0f-2.0.3.beta.tgz 77021 Sep 28 2003
p0f-2.0.3.spec 3139 Feb 1 2004
p0f-2.0.3.tgz 119407 Feb 1 2004
p0f-2.0.4-0.i386.rpm 81578 Jul 15 14:48
p0f-2.0.4-0.src.rpm 131612 Jul 15 14:48
p0f-2.0.4.spec 3221 Jul 13 19:53
p0f-2.0.4.tgz 126886 Jul 10 18:45
p0f-current.tgz 30489 Feb 6 2003
p0f-devel-2.0.4-beta1.tgz 124708 Feb 1 2004
p0f-mysql.conf 116 Apr 22 2002
p0f-query.c 5901 Jul 10 13:48
p0f-query.h 2394 Jul 10 13:48
p0f.1 1868 May 11 2002
p0f.1.gz 924 Nov 25 2001
p0f.c 45747 Jul 10 17:47
p0f.fp 31484 Jul 10 15:03
p0f.init 2063 Sep 29 2003
p0f.spec 3221 Jul 13 19:53
p0fa.fp 5686 Jul 10 13:48
p0fr.fp 8369 Jul 10 15:04
p0frep 1455 Jul 10 13:48
tcp.h 1627 Jul 10 13:49
tos.h 1779 Jul 10 13:49
types.h 634 Jul 10 13:49
win-memleak.txt 5081 Sep 27 2003

Boldfaced directories have been collapsed into one listing. Click on them to see their contents.


                                  p0f 2

                    "Dr. Jekyll had something to Hyde"
                      passive OS fingerprinting tool
                              version 2.0.4

     (C) Copyright 2000 - 2004 by Michal Zalewski <>

                Various ports (C) Copyright 2003 - 2004 by:

                   Michael A. Davis <>
                      Kirby Kuehl <>
                     Kevin Currie <>

      Portions contributed by numerous good people - see CREDITS file.



0. Contents

  This document describes the concept and history of p0f, its
  command-line options and extensions, and goes into some detail about
  its operation, integration with existing solutions, and so on.

  Table of contents:

   1) What's this, anyway?
   2) Why would I want to use it?
   3) What's new then?
   4) Command-line
   5) Active service integration
   6) SQL database integration
   6) Masquerade detection
   7) Fingerprinting accuracy and precision
   8) Adding signatures
   9) Security
  10) Limitations
  11) Is it better than other software?
  12) Program no work!
  13) Appendix A: Exact output format
  14) Appendix B: Links to OS fingerprinting resources

1. What's this, anyway?

  The passive OS fingerprinting technique is based on analyzing the
  information sent by a remote host while performing usual communication
  tasks - such as whenever a remote party visits your webpage, connecs to 
  your MTA - or whenever you connect to a remote system while browsing the
  web or performing other routine tasks. In contrast to active 
  fingerprinting (with tools such as NMAP or Queso), the process of passive 
  fingerprinting does not generate any additional or unusual traffic,
  and thus cannot be detected.

  Captured packets contain enough information to identify the remote OS,
  thanks to subtle differences between TCP/IP stacks, and sometimes certain
  implementation flaws that, although harmless, make certain systems quite
  unique. Some additional metrics can be used to gather information about 
  the configuration of a remote system or even its ISP and network setup.

  The name of the fingerprinting technique might be somewhat misleading - 
  although the act of discovery is indeed passive, p0f can be used for
  active testing. It is just that you are not required to send any unusual
  or undesirable traffic, and can rely what you would be getting from
  the remote party anyway. 

  To accomplish the job, p0f equips you with three different detection

    - Incoming connection fingerprinting (SYN mode, default) - whenever
      you want to know what the guy or gal who connects to you runs,

    - Outgoing connection (remote party) fingerprinting (SYN+ACK mode) -
      to fingerprint systems you or your users connect to,

    - Outgoing connection refused (remote party) fingerprinting (RST+ mode) 
      - to fingerprint systems that reject your traffic.

  P0f was the first (and I believe remains the best) fully-fledged 
  implementation of the passive fingerprinting technique. The current version 
  uses a number of detailed metrics, often invented specifically for p0f, 
  and achieves a very high level of accuracy and detail, is designed for 
  hands-free operation over an extended period of time, and has a number 
  of features to make it easy to integrate it with other solutions.

  Portions of this code are used in several IDS systems, some sniffer  
  software; p0f is also shipped with several operating systems and 
  incorporated into an interesting OpenBSD pf hack by Mike Frantzen, that 
  allows you to filter out or redirect traffic based on the source OS. 
  There is also a beta patch for Linux netfilter, courtesy of Evgeniy 
  Polyakov. In short, p0f is a rather well-established software at this 

2. Why would I want to use it?

  Oh, a number of uses come to mind:

    - Profiling / espionage - run on a server, firewall, proxy or router, 
      p0f can be used to silently gather statistical and profiling information 
      about your visitors, users, or competitors. P0f also gathers netlink
      and distance information suitable for determining remote network

    - Active response / policy enforcement - integrated with your server
      or firewall, p0f can be used to handle specific OSes in the most
      suitable manner and serve most appropriate content; you may also enforce 
      a specific corporate OS policy, restrict SMTP connections to a set of 
      systems, etc; with masquerade detection capabilities, p0f can be used
      to detect illegal network hook-ups and TOS violations.

    - PEN-TEST - in the SYN+ACK or RST+ mode, or when a returning connection
      can be triggered on a remote system (HTML-enabled mail with images,
      ftp data connection, mail bounce, identd connection, IRC DCC connection,
      etc), p0f is an invaluable tool for silent probing of a subject of
      such a test.
    - Network troubleshooting - RST+ mode can be used to debug network
      connectivity problems you or your visitors encounter.

    - Bypassing a firewall - p0f can "see thru" most NAT devices, packet
      firewalls, etc. In SYN+ACK mode, it can be used for fingerprinting
      over a connection allowed by the firewall, even if other types of
      packets are dropped; as such, p0f is the solution when NMAP and
      other active tools fail.

    - Amusement value is also pretty important. Want to know what this
      guy runs? Does he have a DSL, X.25 WAN hookup, or a shoddy SLIP 
      connection? What's Google crawlbot's uptime?

  Of course, "a successful [software] tool is one that was used to do 
  something undreamed of by its author" ;-)

3. What's new then?

  The original version of p0f was written somewhere in 2000 by Michal 
  Zalewski (that be me), and later taken over William Stearns (circa 2001). 
  The original author still contributes to the code from time to time, and 
  the version you're holding right now is his sole fault - although I'd like 
  William to take over further maintenance, if he's interested.

  Version 2 is a complete rewrite of the original v1 code. The main reason 
  for this is to make signatures more flexible, and to implement certain 
  additional checks for very subtle packet characteristics to improve 
  fingerprint accuracy. Changes include:


    - Option layout and count check,
    - EOL presence and trailing data [*],
    - Unrecognized options handling (TTCP, etc),
    - WSS to MSS/MTU correlation checks [*],
    - Zero timestamp check,
    - Non-zero ACK in initial SYN [*],
    - Non-zero "unused" TCP fields [*],
    - Non-zero urgent pointer in SYN [*],
    - Non-zero second timestamp [*],
    - Zero IP ID in initial packet,
    - Unusual auxilinary flags,
    - Data payload in control packets [*],
    - SEQ number equal to ACK number [*],
    - Zero SEQ number [*],
    - Non-empty IP options.

    [*] denotes metrics "invented" for p0f, as far as I am concerned. Other 
    metrics were discussed by certain researchers before, although usually 
    not implemented anywhere. A detailed discussion of all checks performed
    by p0f can be found in the introductory comments in p0f.fp, p0fa.fp
    and p0fr.fp.

    As a matter of fact, some of the metrics were so precise I managed
    to find several previously unknown TCP/IP stack bugs :-) See
    doc/win-memleak.txt and p0fr.fp for more information.


    - Major performance boost - no more runtime signature parsing, added 
      BPF pre-filtering, signature hash lookups - to make p0f suitable for 
      running on high-throughput devices,

    - Advanced masquerade detection for policy enforcement (ISPs,
      corporate networks),

    - Modulo and wildcard operators for certain TCP/IP parameters to make
      it easier to come up with generic last chance signatures for
      systems that tweak settings notoriously (think Windows),

    - Auto-detection of DF-zeroing firewalls,

    - Auto-detection of MSS-tweaking NAT and router devices,

    - Media type detection based on MSS, with a database of common
      link types,
    - Origin network detection based on unusual ToS / precedence bits,

    - Ability to detect and skip ECN option when examining flags,

    - Better fingerprint file structure and contents - all fingerprints
      are rigorously reviewed before being added.

    - Generic last-chance signatures to cover general OS characteristics,

    - Query mode to enable easy integration with third party software -
      p0f caches recent fingerprints and answer queries for src-dst
      combinations on a local stream socket in a easy to parse

    - Usability features: greppable output option, daemon mode, host
      name resolution option, promiscuous mode switch, built-in signature 
      collision detector, ToS reporting, full packet dumps, pcap dump
      output, etc,

    - Brand new SYN+ACK and RST+ fingerprinting modes for silent
      identifications of systems you connect to the usual way (web
      browser, MTA), or even systems you cannot connect to at all;
      now also with RST+ACK flag and value validator.

    - Fixed WSCALE handling in general, and WSS passing on little-endian,
      many other bug-fixes and improvements of the packet parser
      (including some sanity checks).

    - Fuzzy checks option when no precise matches are found (limited).

  Sadly, this will break all compatibility with v1 signatures, but it's
  well worth it.

4. Command-line

  P0f is rather easy to use. There's a number of options, but you don't
  need to know most of them for normal operation:

  p0f [ -f file ] [ -i device ] [ -s file ] [ -o file ] [ -Q socket ]
      [ -w file ] [ -u user ] [ -c size ] [ -T nn ] [ -FNDVUKAXMqxtpdlRL ] 
      [ 'filter rule' ]

  -f file   - read fingerprints from file; by default, p0f reads
              signatures from ./p0f.fp or /etc/p0f/p0f.fp (the latter on
              Unix systems only). You can use this to load custom 
              fingerprint data. Specifying multiple -f values will NOT
              combine several signature files together.

  -i device - listen on this device; p0f defaults to whatever device
              libpcap considers to be the best. On some newer systems you
              might be able to specify 'any' to listen on all devices,
              but don't rely on this.

  -s file   - read packets from tcpdump snapshot; this is an alternate
              mode of operation, in which p0f reads packet from pcap
              data capture file, instead of a live network. Useful for
              forensics (this will parse tcpdump -w output, for example). 

  -w file   - writes matching packets to a tcpdump snapshot; useful when you 
              need to save the traffic in case it has to be verified or
              reviewed later on. Also useful if you encounter any parser bugs 
              - data is being written prior to parsing.

  -o file   - write to this logfile. This option is required for -d
              and implies -t.

  -Q socket - listen on a specified local stream socket (a filesystem
              object, for example /var/run/p0f-sock) for queries. You can
              later send a packet to this socket with p0f_query structure
              from p0f-query.h, and wait for p0f_response. This is a
              method of integrating p0f with active services (web server
              or web scripts, etc). P0f will still continue to report
              events the usual way, but you can use -qKU to suppress any
              text output. Also see -c notes.

              From a shell script, you can query p0f using the p0fq tool
              provided in test/ subdirectory.

              NOTE: The socket will be created with permissions corresponding
              to your current umask. If you want to restrict access to
              this interface, use caution.

              This option is currently Unix-only.

  -c size   - cache size for -Q and -M options. The default is 128, which
              is sane for a system with a moderate load (under 10 connections
              per second or such). Setting it too high will slow down p0f
              and may result in some -M false positives for dial-up nodes,
              dual-boot systems, etc. Setting it too low will result in
              cache misses for -Q option. To choose the right value,
              use the number of connections on average per the interval
              of time you want to cache, then pass it to p0f with -c.

              P0f, when run without -q, also reports average packet ratio
              on exit. You can use this to determine the optimal -c

              This option has no effect if you do not use -Q nor -M.

  -u user   - chroot to this user's home directory after reading 
              configuration data and binding to sockets, then switch to his 
              UID, GID and supplementary groups.
              This is a security feature for the paranoid - when running 
              p0f in daemon mode, you might want to create a new 
              unprivileged user with an empty home directory, and limit the 
              exposure when p0f is compromised. That said, should such a 
              compromise occur, the attacker will still have a socket he can 
              use for sniffing some network traffic (better than rm -rf /).

              This option is Unix-only.

  -N        - do not report distances and link media. This option 
              logs only source IP and OS data.

  -F        - deploy fuzzy matching algorithm if no precise matches are
              found (currently applies to TTL only). This option is not
              recommended for RST+ modes.

  -D        - do not report OS details (just genre). This option is useful
              if you don't want p0f to elaborate on OS versions and such.

  -U        - do not display unknown signatures. Use this option if
              you want to keep your log file clean and are not interested
              in hosts that are not recognized.

  -K        - do not display known signatures. This option is only useful
              for fingerprint gathering.

  -q        - be quiet - do not display banners.

  -p        - switch card to promiscuous mode; by default, p0f listens 
              only to packets addressed or routed thru the machine it
              runs on. This setting might decrease performance, depending
              on your network design and load. On switched networks,
              this usually has little or no effect.

              Note that promiscuous mode on IP-enabled interfaces can be 
              detected remotely, and is sometimes not welcome by network 

  -t        - add human-readable timestamps to every entry (use
              multiple times to change date format, a la tcpdump).

  -d        - go into daemon mode (detach from current terminal and 
              fork into background). Requires -o.

  -l	    - outputs data in line-per-record style (easier to grep).

  -A	    - a semi-supported option for SYN+ACK mode. This option
              will fingerprint systems you connect to, as opposed to
	      systems that connect to you (default). With this option,	      
              p0f will look for p0fa.fp file instead of the usual
              p0f.fp. The usual config is NOT SUITABLE for this mode.

              The SYN+ACK signature database is sort of small at the
              moment, and still looks for a maintainer.
  -R        - go into RST+ACK/RST mode. This option will fingerprint
              several different types of traffic, most importantly
              "connection refused" and "timeout" messages.
	      It is similar to SYN+ACK mode, except that the program
	      will now look for p0fr.fp. The mode is also called RST+.
              Please refer to p0fr.fp before using it.

  -r	    - resolve host names; this mode is MUCH slower and poses some
              security risk. Do not use except for interactive runs or
              low traffic situations. NOTE: the option ONLY resolves
              IP address into a name, and does not perform any checks to
              verify this revDNS result. Do not rely on the name alone.

  -C        - perform collision check on signatures prior to running. This
              is an essential option whenever you add new signatures to
              the p0f.fp file, but is not necessary otherwise. 

  -L        - list all network interfaces. This option is Windows-only.

  -x        - dump full packet contents; this option is not compatible  with
              -l and is intended for debugging and packet comparison only.

  -X        - display packet payload; rarely, control packets we examine
              may carry a payload. This is a bug for the default (SYN)
              and -A (SYN+ACK) modes, but is (sometimes) acceptable in
              -R (RST+) mode.

  -M        - deploy masuqerade detection algotihm. The algorithm looks over 
              recent (cached) hits and looks for indications of multiple 
              systems being behind a single gateway. This is useful on routers 
              and such to detect policy violations. Note that this mode is 
              somewhat slower due to caching and lookups. 

  -T nn     - masquerade detection threshold; only meaningful with -M,
              sets the threshold for masquerade reporting.

  -V        - use verbose masquerade detection reporting. This option
              describes the status of all indicators, not only an overall

  The last part, 'filter rule', is a bpf-style filter expression for
  incoming packets. It is very useful for excluding or including certain
  networks, hosts, or specific packets, in the logfile. See man tcpdump for 
  more information, few examples:

     'src port ftp-data'
     'not dst net mask'
     'dst port 80 and ( src host or src host )'

  The baseline rule is to select only TCP packets with SYN set, no RST, no 
  ACK, no FIN (SYN, ACK, no RST, no FIN for -A mode; RST, no FIN, no SYN
  for -R mode). You cannot make the rule any broader, the optional filter 
  expression can only narrow it down.

  You also can use a companion log report utility for p0f. Simply 
  run 'p0frep' for help.

5. Active service integration

  In some cases, you want to feed the p0f output to a specific
  application to take certain active measures based on the operating system
  (handle specific visitors differently, block some unwanted OSes,
  optimize the content served).

  As mentioned earlier, OpenBSD users can simply use the pf OS fingerprinting 
  implementation, a cool functionality coded by Mike Frantzen and based on 
  p0f methodology and signature database. This software allows them to 
  redirect or block OSes any way they want. Linux netfilter users can also 
  check out patches by Evgeniy Polyakov.

  In other cases, you want to use the -Q option, and then query p0f
  by connecting to a specific local stream socket and sending a single
  packet with p0f_query struct (p0f-query.h), and receiving
  p0f_response. P0f, when running in -Q mode, will cache a number of
  last OS matches, and when queried for a specified host and port
  combination, will return what it detected. Check test/p0fq.c for
  a clean example.

  The query structure (p0f_query) has the following fields (all
  values, addresses and port numbers are in machine's native endian):

    magic	- must be set to QUERY_MAGIC,
    id		- query ID, copied literally to the response,
    src_ad	- source address,
    dst_ad	- destination address,
    src_port	- source port,
    dst_port	- destination port.

  The response (p0f_response) is as follows:

    magic	- must be set to QUERY_MAGIC,
    id		- copied from the query,
    type	- RESP_OK, RESP_BADQUERY (error), RESP_NOMATCH (cache miss),
    genre[20]	- OS genre, zero length if no match,
    detail[40]	- OS version, zero length if no match,
    dist	- distance, -1 if unknown,
    link[30]	- link type description, zero length if unknown,
    tos[30]	- ToS information, zero length if unknown,
    fw,nat	- firewall and NAT flags, if spotted,
    real	- "real" OS versus userland stack,
    score	- masquerade score (or NO_SCORE), see next section,
    mflags	- exact masquerade flags (D_*), see next section.

  The connection is one-shot. Always send the query and recv the
  response immediately after connect - p0f handles the connection in
  a single thread, and you are blocking other applications (until 
  timeout, that is, the timeout is defined as two seconds in config.h).

6. SQL database integration

  At the very moment, p0f does not feature built-in database connectivity,
  although I am looking for a willing contributor to take care of it.
  In the meantime, however, you may use p0f_db utility authored by
  Nerijus Krukauskas:

  Jonas Eckerman has some tools to make it easier to move p0f output
  from one system to another, and then to run basic visualization:

7. Masquerade detection

  Masquerade detection (-M) works by looking at the following factors for
  all known signatures that belong to operating systems (and not userland
  tools like scanners):

    - Differences in OS fingerprints for the same IP:
        -3 if the same OS
        +4 if different signature for the same OS genre
        +6 if different OS genres
    - NAT and firewall flags set:
        +4 if NAT flags differ for the same signature
        +4 if fw flags differ for the same signature
        +1 per each NAT and fw flag if signatures differ (max. 4)

    - Link type differences:
        +4 if media type differs

    - Distance differences:
        +1 if host distance differs

    - Timestamp scoring, if timestamps available:
        -1 if timestamp delta within MAX_TIMEDIF (config.h)
        +1 if timestamp delta past MAX_TIMEDIF
        +2 if timestamp delta negative

    - Time from the previous occurence:
        /2 if more than half the cache size to the previous occurence

  The final score is reported as score * 200 / 25 (25 being the highest
  score possible) and reported as a percentage.

  The higher the value, the more likely the result is accurate. Since
  the situation when all indicators are up is rather unrealistic, the
  multiplier is 200, not 100, and you can get over 100% match ;-)
  Everything above 0% should be looked at, over 20% is usually a sure
  You can configure the reporting of matches by setting the threshold
  to a value different than zero with -T switch. -T 10 might be a good
  idea. If you're looking at a local network, you can define 
  DIST_EXTRASCORE to score distance differences much higher - it is
  unlikely for a local LAN to shrink or grow, but it's not uncommon for
  routing over the Internet to change. If you are unhappy with the
  scoring algorithm and do not want to modify the sources, you can use
  -V option to report the status of every masquerade indicator. In
  conjunction with -l, -V can be used to grep for the precise set
  of signatures you're interested in. 
  Every hit is prefixed with ">> ". Combine -M, -K and -U to report
  masquerade hits only (but it is recommended to still dump packets 
  with -w to be able to examine the evidence later on). A good

    p0f -M -K -U -w evidence.bin -c 500 -l -V 'not src host my_ip'
  A quick demo: - OpenBSD 3.0-3.4 (up: 836 hrs) 
    -> (distance 6, link: GPRS or FreeS/WAN) - Linux 2.4/2.6 (NAT!) (up: 173 hrs) 
    -> (distance 6, link: GPRS or FreeS/WAN) - Windows XP Pro SP1, 2000 SP3 (NAT!) 
    -> (distance 6, link: GPRS or FreeS/WAN)

  >> Masquerade at indicators at 69%.

  That was quite evident. - Windows 2000 SP2+, XP SP1 
    -> (distance 10, link: ethernet/modem) - Windows 2000 SP4, XP SP1, patched 98 
    -> (distance 12, link: ethernet/modem)

  >> Masquerade at indicators at 43%.

  The host has a name of, so once again, a good hit.

  Verbose output looks like this:

  >> Masquerade at indicators at 26%.
     Flags: OS -far

  In this case, we have two different OSes (OS), but the time between two
  occurences is long enough to lowe the score (-far). All -V flags are:

    OS		- different OS genres
    VER		- different OS versions
    LINK	- link type difference
    DIST	- distance differences
    xNAT	- NAT flags differ (when signature)
    xFW		- FW flags differ (same signature)
    NAT1, NAT2  - NAT flags set (different signatures)
    FW1, FW2	- FW flags set (different signatures)
    FAST	- timestamp delta too high
    TNEG        - timestamp delta negative
    -time	- timestamp delta within the norm
    -far	- distant occurences

  Because the score is cummulative, it is possible to have exclusive
  flags set (e.g xNAT and NAT1) if there's a higher number of signatures
  for a specific IP in the cache. Masquerade information can be also
  retrieved via the query interface, as noted in the section above.

  The functionality depends on keeping the fingerprint database 
  clean and prefixing non-OS fingerprints (nmap, other scanner tools,
  application-induced TCP/IP stack behavior) with - prefix. Those
  fingerprints, as well as all the UNKNOWNs, are not used for masquerade 

  Note that a single host can be reported many times. The system reports
  immediately, but later on, the host might score a different result
  once new data arrives. Use the highest result for a specific host, but
  also observe the consistency of subsequent results.
  The solution uses a cyclic buffer also used in -Q mode (and affected by
  -c parameter). You should set the value to cache not more than an
  hour of traffic (and no less than a minute). Calculate the number of
  connections on average per the interval of time you wish to cache,
  then pass the value to p0f with -c.

  Setting -c too high will result in false positives for dial-up nodes,
  multiboot systems, etc. Setting it too low may miss some cases.

  The code detects NAT devices that do not rewrite packets (almost
  all packet firewalls). Ones that do rewrite packets can be detected by
  their own signatures, though.

  Masquerade detection will fail if all systems masqueraded have an
  identical configuration and network setup (which is very unlikely,
  even in a homogenous environment), or are never used at (roughly) the same 

  NOTE: You can also try to combine -M with -A, which is only really
  useful for detecting load balancers and other setups that map a single
  address to several servers; or with -R, which can be used both for
  detecting load balancers (RST) and normal incoming masquerade detection
  (RST+ACK), although it's probably less reliable.

8. Fingerprinting accuracy and precision

  Version 2 uses some more interesting TCP/IP packet metrics, and should
  be inherently more accurate and precise. We also try to use common sense
  when adding and importing signatures, which should be a great
  realiability boost. More obscure modes, such as RST+, may be inherently 
  less accurate or reliable - see section 10 for more details.

  NOTE: To avoid decreasing reliability of the database, you MUST read the 
  information provided at the beginning of p0f.fp carefully before touching
  it in any way!

  Link type identification is not particularly reliable, as some users tend
  to mess with their default MTUs for better (or worse ;-) performance.
  For most systems, it will be accurate, but if you see an unlikely
  value reported, just deal with it.

  Uptime detection is also of an amusement value. Some newly released
  systems tend to multiply timestamp data by 10 or have other clocking
  algorithms. The current version of p0f does not support those differences
  over the entire database. I will try to fix it, until then, those boxes 
  would have an artifically high uptime.

  NAT detection is merely an indication of MSS being tweaked at some point.
  Most likely, the reason for this is indeed a NATing router, but there
  are some other explanations. Linux, for example, tends to mix up MTUs
  from different interfaces in certain scenarios (when, I'm not sure, but
  it's common and is probably a bug), and if you see a Linux box tagged as 
  "NAT", it does not have to be NATed - it might simply have two network 
  interfaces. P0f can still be a useful NAT detection tool (you can examine
  changing distances and OS matches for a specific host, too), simply don't
  rely on this flag alone.

  If you see link type identified as unknown-XXXX, try to Google for
  "mtu XXXX". If you find something reasonable, you might want update
  mtu.h and recompile p0f, and submit this information to me. Keep in
  mind some MTU settings are just arbitrary and do not have to mean a

  P0f also tries to recognize some less popular combinations of precedence 
  bits, type of service and so-called "must be zero" bit in TCP headers to
  detect certain origin ISPs. Many DSL and cable operators, particularly
  in Europe, tend to configure their routers in fairly unique ways in
  this regard. This, again, is purely of an amusement value. See tos.h
  for more information.

  P0f will never be as precise as NMAP, simply because it has to rely
  on what the host sends by itself, and can't check how it responds to
  "invalid" or tweaked packets. On the other hand, in the times of
  omnipresent personal and not quite personal firewalls and such,
  p0f can often help where NMAP is confused.

  Just like with any fingerprinting utility, active or passive, it is
  possible to change TCP/IP stack settings to either avoid identification,
  or appear as some other system - although some of the changes might
  require kernel-space hacking. 

9. Adding signatures

  Please refer to p0f.fp for more information about signatures and
  their format. You NEED to read this information carefully before
  changing or adding anything.

  Do consider submitting your signature to,, or connecting from the system to We will be happy to incorporate
  this signature in the official release, and can help you make your
  signature more accurate.

  Be sure to run p0f -C after making any additions. This will run
  a collision checker and warn about shadowed or possibly incorrect
  signatures. This happens more often than you'd think.
  The same applies to p0fa.fp and p0fr.fp files. You need to
  run p0f -A -C and p0f -R -C to verify their contents.

  Rest assured, you will sooner or later find something really
  surprising. You can look at tmp/ to see a current list of
  mysteries I've stumbled upon. The museum at lists some other funky cases.
  By all means, I'd like to hear about other UFO sightings!

10. Security

  Running p0f as a daemon should pose a fairly low risk, compared to
  tcpdump or other elaborate packet parsers (Ettercap, etc). P0f does not
  attempt anything stupid, such as parsing tricky high-level protocols. 
  There is a slight risk I screwed up something with the option parser
  or such, but this code should be easy to audit. If you do not feel to
  comfortable, you can always use the -u option, which should mitigate
  the risk signigicantly.

  Do not make p0f setuid, setgid or otherwise privileged when the caller
  isn't. Running it via sudo for users you do not trust entirely is also a 
  so-so idea.

  The biggest threat is using -r option carelessly, as it enables the
  entire name resolution overhead, and introducing a potentially vulnerable 
  DNS handling code, not to mention DoS potential.

  Other than that, when running in -Q mode, you need to make sure, either
  by setting umask or calling chmod/chown after launching p0f, to set
  correct permissions on the query socket - that is, unless you don't
  see a problem with your users querying p0f, which isn't a great threat
  to the humanity.

  Do not use world-writable directories for keeping the socket. Do not
  use world-writable directories for output files or configuration.

11. Limitations

  Proxy firewalls and other high-level proxy devices are not transparent
  to any TCP-level fingerprinting software. The device itself will be
  fingerprinted, not actual source hosts. There is some software that
  lets you perform application fingerprinting, this isn't it.

  Some packet firewalls configured to normalize outgoing traffic (OpenBSD pf 
  with "scrub" enabled, for example) will, well, normalize packets. Those
  signatures will not correspond to the originating system, and probably not 
  quite to the firewall either. Checkpoint firewall, in a fairly lame attempt
  to defeat OS fingerprinting, tweaks IP ID and TTL on outgoing packets; if
  you want to work around this problem, run p0f with -F option.

  In order to obtain the information required for fingerprinting, you have
  to receive at least one SYN packet initiating a TCP connection to your
  machine or network. Note: you don't have to respond to this
  particular SYN, and it's perfectly fine to respond with RST.

  For SYN+ACK fingerprinting, you must be able to connect to at least one
  open port on the target machine to actually get SYN+ACK packet. You 
  do not need any other ports, or the ability to send awkward, multiple
  or otherwise suspicious packets to the remote host (unlike with NMAP).
  Also note that SYN+ACK fingerprints are somewhat affected by the initial
  SYN on some systems.

  If you cannot establish a connection, but the remote party at least
  sends you RST+ACK back ("Connection refused"), you can use RST+ mode of 
  p0f (-R option), but be aware this mode is inherently less accurate
  and reliable, mostly because systems usually don't bother with
  putting any options in those packets, and they all look very similar.

  SYN+ACK fingerprinting is considered (by me) to be less accurate and
  sometimes dependent on the system that initiates the connection. This is
  why I put stress on developing the SYN fingerprinting capability - but
  SYN+ACK database contributions and techniques are of course very welcome.
  Fingerprinting on a fully established (existing) TCP connection is
  currently not supported by p0f, because it is inherently less reliable,
  and seldom of any use. You can, however, implement this rather easily
  by tweaking the filter expression hardcoded in p0f.c and coming up with
  a new fingerprint database.
  What I'll be trying to do is to integrate a number of fingerprinting
  techniques, currently completely separate (SYN, SYN+ACK, ACK, FIN,
  RST, retransmission timing, etc) into a single solution for very
  high accuracy. But this is perhaps p0f 3.0.

12. Is it better than other software?

  Depends on what you need. As I said before, p0f is fast, lightweight,
  low-profile. It can be integrated with other services. It has a clean and 
  simple code, runs as a single thread and uses very little CPU power, works 
  on a number of systems (Linux, BSD, Solaris and probably others), has a 
  pretty detailed and accurate fingerprint database. Quite frankly, I
  doubt there is a program that offers better overall functionality or
  accuracy when it comes to passive fingerprinting, but I would not be
  surprised to be proven wrong one day. In other words, feel free to
  explore other alternatives.

  Of the ones I know... is it better than Siphon? Yes. Ettercap? Yes, 
  version 2 is better than v1-derived fingerprinting in Ettercap. Besides, 
  it's simply different, and intended for a different range of applications.

  Version 1 of p0f did implement many novel fingerprinting metrics that were
  later incorporated in other software, but so did version 2 - and others are
  yet to catch up.

  As to other "current" utilities, you can use masqdet by 
  Wojtek Kaniewski as an alternative to p0f -M mode. On the web, you can
  also stumble upon "n0t" and "natdet" utilities authored by "r3b00t",
  but these are just dumbed-down and inherently less reliable rip-offs
  closely inspired on p0f code. Your mileage may vary, but I recommend
  you to avoid them: they won't work any better.

13. Program no work!

  Whoops. We apologize. P0f requires the following to compile and
  run fine:

    - libpcap 0.4 or newer
    - GNU cc 2.7.x or newer 
    - GNU make 3.7x or newer, or BSD make
    - GNU bash / awk / grep / sed / textutils (for p0frep only)

  For the Windows port requirements and instructions, please read 
  INSTALL.Win32 file.

  Not every platform is supported by p0f, and compilation problems do
  happen. Please let us know if you have any problems (or, better yet,
  managed to find a solution).

  If you find a system that is either not recognized, or is fingerprinted
  incorrectly, please do not downplay this and let us know.

  Platforms known to be working fine (regression tests not done on
  a regular basis, though):

    - NetBSD 
    - FreeBSD 
    - OpenBSD
    - MacOS X 
    - Linux (2.0 and up)
    - Solaris (2.6 and up)
    - Windows (see INSTALL.Win32)
    - AIX (you need precompiled BULL libpcap)

  If p0f compiles and runs, but displays "unknown datalink" or 
  "bad header_len" warnings, it is likely that your network interface type
  is not (yet) recognized. Let us know.

14. Exact output format

  Following is a brief description of the output format of p0f v2.
  While it is recommended to use -Q mode for service integration, it
  might be still necessary to perform log post-processing, etc.

  Every line starts with an optional timestamp (enabled by -o or -t
  options). The format is as follows:


  The format is essentially the standard Unix date format. The next
  field is mandatory and specifies the source host:


  The /name part is appended only if -r option is provided, and there
  was a DNS record for this particular IP. Following is a ' - '
  separator, and the name of the system with any additional remarks:

  System_name [ version (notes) ]

  The latter part is supressed by -D option. Notes usually describe
  signature number or other specifics. Then, there is a number of
  optional notes:

  (NAT!)			- the system is behind MSS-tweaking NAT
  (NAT2!)			- the system is behind MTU-tweaking NAT
  (ECN)				- ECN enabled on the remote system
  (firewall!)			- the system has DF cleared
  \[Name\]			- provider name identified as..., OR
  \[tos XX\]			- ToS set, but provider name not identified
  \[GENERIC\]			- signature is a generic one
  \[FUZZY\]			- fuzzy match
  \*				- further details inhibited for this signature
  (up nnn hrs)			- system uptime
  (refused)			- RST+ mode: valid conn. refused packet
  (dropped)			- RST+ mode: valid conn. dropped packet
  (invalid-NN)			- RST+ mode: invalid RST packet (see p0fr.fp)

  If the signature is generic, or if -S option was used, the next line is:

    Signature: \[signature_data\]

  ...where signature_data follows the standard p0f.fp notation.

  If the system was not regognized, the format of the OS line is 
  slightly different:

  UNKNOWN \[signature_data\]

  Where signature data follows the standard p0f.fp notation. All
  options except for GENERIC, * and (firewall!) can still follow the entry.
  Signature is not repeated in the next line regardless of -S.

  Unless -N is in effect, the next line is as follows:

    -> dst_ip:port ([distance NN, ]link: description)

  ...the distance part is present only when the signature was recognized
  properly. Link description is the name of the link type, or a special
  keyword "unspecified", or a special value "unknown-NNNN". 

  The next line is present if -X mode is enabled and the packet has
  a payload. The line has the following format:

    # Payload: "...printable text..."

  Maximum length of the text to report is defined in config.h (PKT_MAXPAY).

  In -l mode, all line breaks are inhibited.

  If -x is enabled (not compatible with -l), the subsequent lines are in 
  this format:

    \[XX\] nn nn nn nn .... | AAAA...

  Where XX is a hex address, nn is a hex sequence of byte values, and
  AAAA is human-readable contents of the packet.

  Additionally, when -M option is in effect, the data described in
  section 7 may be displayed.

15. Links to OS fingerprinting resources

  Recommended RFC reading:  - TCP/IP specification - TCP/IP tutorial - performance extensions - T/TCP extensions - TCP/IP selective ACK

  Practical information:

    Active ICMP fingerprinting:

    Passive OS fingerprinting basics:

    THC Amap, application fingerprinting:

    Hmap, web server fingerprinting:

    Fyodor's NMAP, the active fingerprinter:

    User-Agent information:

    Ident fingerprinting:

  Other free tools known to have passive OS fingerprinting: - Ettercap (p0f v1) - Prelude IDS (p0f v1) - OpenBSD pf (p0f v2.0.1) - Linux netfilter - Vern Paxson's / Holger Dreger's NIDS (p0f 2.0) - pfprintd - Siphon (very out of date) (Siphon w/GUI) - n0t and natdet (ripped off, AFAIC) - masqdet (NAT detection only)


Bente Petersen wrote an article on p0f at:

My sincere thanks to Marcus Ranum, security guru, for writing an article about p0f for Information Security Magazine. The article can be found at:

Instructions for using p0f on windows

1) Download Cygwin

The cygwin environment emulates a UNIX-like environment on tp of your
windows machine.  It is available for free from:

(Bill adds: For reference, cygwin1.dll is in this directory for those
that want it; it can be downloaded from
in the most recent cygwin....tar.gz package)

2) Download WinPcap

p0f also needs the WinPcap drivers installed on the system.  These are
also free and are available from

Once these are installed, make sure to place p0f.fp in your /etc
directory in the cygwin environment or in the current directory and it
should work fine.

Thanks to Chris Connelly for getting it compile in the cygwin
environment.  If you have any trouble or have questions, feel free to
contact him at 

	(Bill: As a side note, there was a (non-cygwin) port done in
January 2001.  If anyone is interested in updating the port to current
p0f, please take a look at .  Many
thanks to Michael Davis of Datanerds for the work.)


Name        : p0f                          Relocations: (not relocateable)
Version     : 2.0.4                             Vendor: Michal Zalewski <>
Release     : 0                             Build Date: Thu Jul 15 14:48:24 2004
Install Date: (not installed)               Build Host: sparrow
Group       : Applications/Networking       Source RPM: p0f-2.0.4-0.src.rpm
Size        : 195665                           License: LGPL
Signature   : RSA/MD5, Thu Jul 15 14:48:24 2004, Key ID 012334cbf322929d
Packager    : William Stearns <>
URL         :
Summary     : passive OS fingerprinting tool
Description :
p0f performs passive OS fingerprinting technique bases on information coming
from a remote host when it establishes a connection to our system. Captured
packets contains enough information to determine OS - and, unlike
active scanners (nmap, queSO) - it is done without sending anything to
this host.

The files in this collection are part of William Stearns' software archive. If any of the links on this page do not work, you may be viewing an incomplete mirror. There is a complete list of the mirror sites at the starting page for this mirror and at the primary mirror.

Generated Wed Sep 8 15:51:49 EDT 2004 by htmlfilelist version 0.8.3