Build1 publisher3 min readPublished
Residential proxy pools are pushing edge defence down to the TCP handshake
A dev.to teardown argues static IP blocklists cannot survive CGNAT and 100,000-address proxy pools, so edge defence moves to the fields a kernel writes into the first SYN: initial window, MSS, option ordering.
The Engineer · Build desk

What happened
- A dev.to teardown of edge blocking argues that static IP blocking is obsolete against automated scraping fleets, distributed residential proxy networks and IPv6 address allocation models.
- The legacy posture it describes worked at L3 and L4: past a threshold, edge firewalls appended source IPv4 addresses to dynamic ACLs or null-routed the prefix via BGP Flowspec, RFC 5575.
- One adversary running a cluster orchestrator can spread outbound connections across millions of distinct residential addresses handed out through CGNAT or mobile LTE and 5G subnets.
- Blocking a single CGNAT gateway address as a /32 cuts off thousands of legitimate mobile subscribers who share that egress NAT interface.
- The post's worked example shows a User-Agent claiming Mac OS X 10_15_7 over a SYN with window size 29200, MSS 1460, window scale 7 and a Linux option sequence.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- capability A verdict available from the SYN lands before TLS negotiation and before HTTP payload decryption, so a rejection costs header parsing instead of a completed handshake and a decrypted request.
- cost The defender is on the wrong side of the cost: rented rotating addresses are orders of magnitude cheaper than the stateful counting built to track them, and cost is what defeats per-IP enforcement before accuracy does.
- constraint The finest grain this signal offers is a kernel implementation, so every host in a kernel family looks alike, and enforcement has to hang on the mismatch with the claimed OS.
- decision Building edge policy on L4 fields is a bet that the adversary lacks kernel control on the sending host, and that bet has to be made explicitly for fleets that run their own container hosts.
The signal exists because the standard left room for it. RFC 793 and the RFCs after it pin down TCP's semantics and hand option sequencing, default buffer allocations and window scaling coefficients to whoever writes the kernel [12]. A SYN frame therefore carries the implementer's choices, and the fields an edge can read off it include TCP option ordering, initial window size, TTL hop distance and MSS constraints [11]. Reading them during the initial SYN exchange is passive OS fingerprinting, p0f style [9]. A headless Chromium can forge its user agent, its screen dimensions, its WebGL vendor string and its TLS client hello [7], but the kernel still writes the handshake underneath.
Cardinality is the reason to prefer the kernel field over the address. The pool in the post's diagram is 100,000-plus addresses in front of one identical kernel engine, given as Linux 5.15 headless [4]. One fingerprint therefore spans the whole pool, turning 10^5 tracked keys into one [1]. Renting those addresses costs the operator orders of magnitude less than the stateful tracking a defender stands up against them, token bucket or leaky bucket or sliding window counter alike [6].
The diagram only works if the SYN the edge inspects comes from the machine running the headless browser. A proxy that terminates TCP and opens its own connection to the target puts its own stack on the wire, and the fingerprint then describes the residential device, not the scraper's container. Forwarding at L3 preserves the signal; terminating TCP destroys it. That distinction decides whether any of this transfers, and it is the proxy product you are up against that sets it.
The second limit is resolution. The key identifies a kernel [2]. A legitimate visitor whose stack emits the same defaults lands in the same bucket as the fleet, which is why the decision rests on the L7-to-L4 mismatch and not on the fingerprint on its own [8]. For that check to pay on your traffic, claimed OS and observed kernel have to disagree far more often in abuse than in ordinary requests, and the base rate depends on who your users are. The post presents the mismatch as an annotated illustration and does not include measured detection or false-positive rates, or a named deployment [13].
Evasion is cheap for some adversaries and awkward for others. The post lists three routes to forging the network-layer parameters: raw socket privileges via CAP_NET_RAW, custom eBPF packet generation engines, or non-trivial guest kernel modifications [10]. Each needs control of the kernel that emits the packet. An adversary already running a cluster orchestrator across their own container hosts controls the kernels on those hosts [3].
What to watch
- A named edge or WAF vendor publishing measured false-positive rates for L7-to-L4 mismatch blocking on real traffic.
- Proxy providers advertising L3 forwarding or kernel-matched egress. That advertising would settle whether the fingerprint the edge sees belongs to the scraper or the residential device.
- Container runtimes or distributions shipping different TCP defaults. Different defaults would blur the single Linux signature the method depends on.