TCP Fingerprinting: What One Packet Tells a Server About Your OS
A web server learns something about your machine before it parses a single header. The SYN packet that opens every TCP connection carries a hop budget, a window size, a segment size and a list of options, and your operat
A web server learns something about your machine before it parses a single header. The SYN packet that opens every TCP connection carries a hop budget, a window size, a segment size and a list of options, and your operating system picked all of them. TCP fingerprinting reads those values and guesses the OS behind the connection. It needs no JavaScript and no cookies, and the visitor never sees it happen.
A browser can claim any operating system. The first packet shows what the kernel behind the connection does, and a mismatch check only needs the two to disagree.
How TCP fingerprinting reads a SYN packet
The handshake starts with the client's SYN, short for synchronize. The standards define each field but leave most values to the implementer, so every network stack fills the SYN in with its own defaults. Four of them carry signal, strongest first:
- The TCP options and their order. The standard fixes how an option is encoded but not where it sits in the list, so each kernel has its own layout. In default settings, Linux writes SACK permitted and the timestamp right after the MSS and puts window scale last, Windows puts window scale second and sends no timestamp, and Apple systems send a timestamp and finish with an end-of-list byte. On their own these usually separate the three families, though versions and settings shift them.
- Initial TTL, the hop budget in the IP header. It is coarse, as the next section shows.
- Window size, how much data the sender accepts before it expects an acknowledgment, and the window scale option that multiplies it. Both follow buffer memory, version and tuning, so one system can show several numbers and different systems can show the same one.
- MSS, the biggest payload the sender will take in one segment. It describes the link, not the OS: the MTU minus the IP and TCP headers, so systems on the same Ethernet link normally send 1460 over IPv4.
TTL 64 vs 128: the clue everyone quotes
TTL, time to live, starts at the OS default, and every router on the path subtracts one. The server receives the starting value minus the number of hops, then rounds up to the nearest common start: 64, 128 or 255. A reading of 54 means a start of 64 and ten routers on the way. A reading of 117 means a start of 128 and eleven.
The rule of thumb says 64 is Linux and 128 is Windows. Android runs on the Linux kernel and starts at 64, and so do macOS and iOS. That makes TTL a one-question test: Windows or Unix-like. It cannot tell a Linux server from a Mac, and either side can change it with a single system setting. IPv6 calls the field the hop limit, and a router can announce which default hosts should use, so the network may override what the OS would pick.
Passive OS fingerprinting vs Nmap OS detection
Nmap's OS detection is the active kind. It sends up to 16 TCP, UDP and ICMP probes to open and closed ports on the target, built to exploit gaps in the standard, and matches the replies against a database of thousands of fingerprints. Passive tools such as p0f send nothing. They read packets that cross the wire anyway, often just one SYN. A website has little choice but the second kind for its visitors. Nmap itself works best when it finds at least one open and one closed TCP port, and a probe aimed at a visitor's public address lands on the home router, not on the laptop behind it.
| Passive (p0f, JA4T) | Active (Nmap OS detection) | |
|---|---|---|
| Packets the observer sends | None | Up to 16 probes |
| What it studies | The client's SYN; p0f also reads the server's SYN+ACK | Replies to crafted probes |
| What it needs from the target | A connection that arrives anyway | A reachable address and, for best results, a mix of open and closed ports |
| Does the target notice | No | Probes can set off alarms |
| Typical user | A website classifying its own visitors | An admin auditing a network they own |
| Typical answer | OS family and rough generation | A ranked OS and version guess |
The active tools are visible to the passive ones: p0f ships signatures for Nmap's SYN scan and for its OS detection probes. JA4T takes the passive route and writes four values into one string a server can log per connection: window size, option order, MSS and window scale. It leaves out the TTL, which shifts with distance. The signature formats and licensing are covered in the passive OS fingerprinting guide. Application code rarely sees a SYN, so the reading usually happens at the edge: a firewall, load balancer or sensor.
TCP fingerprint anomaly: when the packet and the browser disagree
The server fingerprints whoever opened the connection to it. A tunnel VPN carries your packets as they are, so your SYN arrives intact. A proxy opens a second connection, so the website is looking at the proxy's kernel, often Linux on a rented server. A CDN or load balancer that ends TCP shows the origin its own SYN and keeps yours for itself, and Tor does the same at its exit relays. VPN vs proxy vs Tor lays out which tools forward packets and which open a connection of their own.
Set that against the browser's claim, which an extension can rewrite in seconds, and you have a TCP fingerprint anomaly. Take a Windows laptop behind a Linux proxy: the User-Agent says Windows, the SYN says Linux, and the address often sits in a hosting network. Each signal is weak alone. Anti-fraud systems tend to weigh such signals together, so the visitor can end up with a CAPTCHA or a second sign-in prompt instead of a block. Automation hits the same check: a scraper in a Linux container can send any User-Agent, but its kernel sends a Linux SYN.
The two directions carry different weight:
- A Linux SYN under a Windows or Apple claim is common and often innocent: a proxy, a relay service or a corporate gateway.
- A Windows or Apple SYN under a different claim is rarer, because few proxy servers run on those systems. It usually points to an edited claim, from a browser extension or an anti-detect profile.
p0f has a flag for this check: it reports 1 when the User-Agent differs from the OS in a way proxying can explain, and 2 for an outright mismatch.
A mismatch does not say which layer is wrong, or why. Matching proves little in the other direction, because some proxy providers offer a setting that makes the proxy's SYN look like another system. The SYN gives a family, not a version or a device, and p0f's own label for recent Macs adds "sometimes iPhone or iPad". It also needs TCP to be there at all. HTTP/3 runs on QUIC over UDP and has no SYN, though browsers first hear about HTTP/3 through a response header or a DNS record, so many connections still start on TCP.
Check your own TCP fingerprint
- Go to the Privacy & Trust Index and wait for the scan to complete. The TCP/OS Fingerprint card compares the system your connection points to with the one your browser reports.
- Read the status. OS MATCH means the two agree. OS MISMATCH means the connection reveals a different system than the browser reports, and the details can name what carried it, such as a VPN or a datacenter network. OS HIDDEN BY TOR means an exit relay opened the connection. PROBE UNREACHABLE means the fingerprint could not be read this time.
- Open the Connection Fingerprint panel lower on the page. Its TCP / IP rows show the Detected OS and Initial TTL, the raw Window, MSS and Window Scale values, the Options and your JA4T. Compare the TTL with 64 and 128, and the options with the layouts above.
- Turn a VPN or proxy on and scan again, then compare the Detected OS and the status with the first run.
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.