Resources Center

Knowledge material for technical stakeholders exploring Fraudnode workflows.

Back to Articles
ArticleNetworking

TCP Window Scale Is a SYN Contract

Intro

TCP’s header still advertises the receive window in 16 bits. That field tops out at 65,535 bytes. A gigabit path with any real delay cannot keep the pipe full with 64 KB in flight. RFC 1323, later RFC 7323, fixed this with Window Scale: a shift count agreed on SYN, then applied to every later window update.

The scale factor does not change mid-connection. If it was not offered on SYN, the session is stuck at 64 KB for life. That single fact makes the option a fingerprint of the stack and of the era it came from, not of the current RTT.

Fraudnode sees the scale on the same SYN as MSS. Together they answer a simple question: did this handshake come from a modern desktop stack, an embedded kernel, or something in the middle that builds TCP for a living.

Why 65,535 stopped being enough

Bandwidth-delay product is just rate times delay. A 100 ms RTT on a 100 Mbps link already wants more than a megabyte in flight. Old Windows and early Linux could live with 8–16 KB windows on dial-up. They cannot live with that on today’s last mile.

Window Scale lets each side say “treat my 16-bit field as shifted left by S,” with S from 0 to 14. Fourteen is the ceiling in the RFC, about a gigabyte of advertised window. Vista and later Windows turn scaling on by default. Linux has had it on by default since the 2.6 era. Android inherited Linux and grew the scale as phones got faster radios and more RAM.

The advertised window in later packets still moves. That is flow control: the buffer fills, the number drops, sometimes to zero. The scale does not move with it. A tiny window on a live stream is “the application is slow.” A missing scale on the SYN is “this stack never offered the modern contract.”

What different stacks actually offer

Old Windows shipped with scaling off unless someone flipped a registry key. Those SYNs look like a 64 KB world. Modern Windows auto-tunes: a modest initial window, a scale large enough to grow into megabytes, usually not the maximum 14 unless you ask for the experimental profile.

Linux exposes `tcp_rmem` and will advertise a scale that covers the max buffer. Embedded Linux, OpenWrt, and some appliances pick odd initial windows. Scanners are famous for this. Published measurements of internet-wide scanners show fixed windows that are not 65,535: a few kilobytes, a few tens of thousands, whatever the tool author hardcoded.

Apple desktop and phone stacks in ordinary browsing overwhelmingly advertise the classic 65,535 with a scale. That is a default, not a law of nature. When a session claims to be Apple and the raw window is a round multiple of MSS instead, the handshake often was not built by the same stack that filled in the User-Agent.

Window equals MSS times N

Some kernels do not start from 65,535 at all. They pick an initial window as a number of segments: MSS times 6, 10, 12. That is legitimate TCP. It shows up on older Linux profiles, some Android vendor kernels, FreeBSD in places, and a lot of proxies and load balancers that terminate TCP and open a new connection.

65,535 is not a multiple of 1460, so a true “MSS times N” window is easy to spot as a class. It is not, by itself, a verdict. A Linux box at home may do it. A scanner may do it. A proxy in front of a phone may do it while the TLS layer still looks like the phone.

The useful move is the same as with MSS. Ask whether the window rule matches the rest of the SYN: option order, scale, timestamps, claimed OS. A stack that almost always uses 65,535 and suddenly uses MSS times N is a path story. A stack that always uses MSS times N is just that stack.

Do not freeze a threshold

Publishing “scale less than 8 means VPN” is how you get false positives the week a carrier ships a conservative middlebox. Publishing “Apple plus MSS times N means proxy” as a product rule is how you leak a detector and then watch it rot.

The RFC facts stay. Scale is offered only on SYN. Maximum shift is 14. Zero window later is flow control, not a new handshake. Odd initial windows cluster on appliances, scanners, and TCP terminators.

Collect the pair with MSS. If the SYN never shows up, there is no contract to read. Fail closed, then look again.