A SYN cookie is a specially crafted initial sequence number that lets a server answer a TCP connection request without storing anything about it. The server packs the connection details into the SYN-ACK it sends back, then discards them. If the client is real, its final ACK carries those details home, and the server rebuilds the connection from nothing. That single trick removes the exact resource a SYN flood is designed to drain. This guide covers how the encoding works, what it quietly costs you, how to switch it on correctly, and the point where it stops being enough.

Key Takeaways

  • A SYN cookie encodes connection state into the sequence number of the SYN-ACK, so the server allocates no memory for a half-open connection.
  • The 32-bit cookie splits into 5 bits of time counter, 3 bits of MSS index, and 24 bits of keyed hash over the address and port pair.
  • With only 3 bits for the MSS, the server rounds the client value down to one of 8 preset sizes.
  • Window scaling is disabled by default, and modern stacks recover it and SACK only when the client sends TCP timestamps.
  • Linux ships tcp_syncookies at 1, firing the mechanism only when the SYN backlog overflows.
  • A full connection block costs 736 bytes, a SYN cache entry 196 bytes, and a SYN cookie nothing at all.
  • Cookies protect host memory, not link capacity, so a flood that saturates the uplink still takes the service down.

A SYN cookie is not a file, a browser cookie, or anything stored on disk. It is a number. Specifically, it is the initial sequence number a server picks for its SYN-ACK, computed so the number itself carries every piece of state the server would otherwise have to remember.

Think of a coat check. Normally the attendant hangs your coat on a rack and writes your name in a ledger, which works until a hundred people hand over coats and vanish. A SYN cookie flips that: the attendant hands you a numbered ticket describing your coat, keeps nothing, and reconstructs the record only when you return with the ticket.

  • The cookie is generated when a SYN arrives and sent inside the SYN-ACK.
  • No connection block, no backlog slot, and no timer are created.
  • State is rebuilt only if a matching ACK returns, which spoofed sources never send.

So a server running cookies can answer unlimited connection requests without its memory footprint growing at all. The idea came from Daniel J. Bernstein in 1996, in direct response to the attacks that year, and it has shipped in production operating systems ever since. To see why it was necessary, look at what TCP does without it.

Why the TCP Three-Way Handshake Leaves Servers Exposed

TCP reserves memory the instant it hears from you, before it has any proof you exist. That single design decision is the whole vulnerability.

When a SYN arrives on a listening port, the connection moves to SYN-RECEIVED and the kernel allocates a transmission control block for the details. In the Linux 2.6.10 networking code that structure took more than 1300 bytes, and even lean implementations typically exceed 280 bytes. The server sends a SYN-ACK, then waits for a final ACK that never comes.

Comparison of a completed TCP three-way handshake against a spoofed SYN that never returns an ACK

Each spoofed SYN occupies a backlog slot until a timer expires. Because those slots are finite, the queue fills and legitimate users get refused. A SYN flood attack needs no bandwidth advantage, only enough packets to outpace the rate at which the kernel reclaims dead entries.

The economics are lopsided. Default backlogs have historically run from half a dozen to a few dozen slots, while reclamation timers are generous: 4.4BSD-Lite gave up after 511 seconds, and current Linux retransmits SYN-ACKs five times by default, reaching a final timeout at 63 seconds. Holding a slot for a minute costs the attacker one small packet. Worse, the attack hits one listening application rather than the host, so established sessions keep working and nothing looks wrong until new visitors start failing.

  • Bill Cheswick and Steve Bellovin identified the weakness as early as 1994.
  • The Project Neptune article and tool in Phrack Magazine publicized it in July 1996.
  • By September 1996 a well publicized attack on the mail servers of the ISP Panix prompted CERT advisory CA-1996-21.

So the fix has to remove the reservation, not enlarge it. That is exactly what the cookie encoding achieves.

The server compresses the state it needs into the 32 bits of the sequence number it is already obliged to send. Nothing extra goes on the wire.

In the original scheme described in RFC 4987, those bits divide three ways. The top 5 hold a counter modulo 32, where the counter advances every 64 seconds. The next 3 encode an index into a table of 8 common maximum segment sizes. The bottom 24 are a keyed function of the source and destination addresses, the ports, and that same counter.

Bit layout of a 32-bit SYN cookie showing 5 bits of counter, 3 bits of MSS index, and 24 bits of keyed hash

Each field earns its space. The counter gives the cookie an expiry, so a value captured today cannot be replayed next week. The MSS index preserves the one negotiated parameter the server cannot work without. The keyed hash is the security property: an attacker who does not know the secret cannot manufacture a sequence number that validates.

// Cookie construction, following the scheme in RFC 4987 Appendix A // Inputs: source/destination address and port, client ISN (x), counter i = largest index where msstab[i] <= client_advertised_mss // 8 entries z = MD5(sec1, saddr, sport, daddr, dport, sec1) + x + (counter << 24) + (MD5(sec2, counter, saddr, sport, daddr, dport, sec2) % (1 << 24)) cookie = (i << 29) + (z % (1 << 29)) // sent as the SYN-ACK sequence number

“SYN cookies go a step further and allocate no state at all”

Notice what is missing. There is no room for window scale, no room for selective acknowledgement, no room for anything TCP gained after the sequence number was fixed at 32 bits. That omission is the source of every drawback the technique carries.

How the Server Rebuilds a Connection When the ACK Comes Back

The server recomputes the cookie from the incoming packet and checks whether the result matches the acknowledgement number the client returned. A match proves the client received the SYN-ACK.

Since the server kept no record, it cannot look the connection up. It derives the answer instead, using the same secret keys and the address and port values now present in the ACK. Because the counter advances every 64 seconds, the server tests the current value and the last few, which bounds how long a cookie stays valid.

  1. An ACK arrives for a connection the server has no memory of.
  2. The server recomputes candidate cookies using its secrets, the address and port pair, and each recent counter value.
  3. It compares those candidates against the acknowledgement number minus one.
  4. On a match, it reads the MSS back out of the top bits and builds a full connection block.
  5. On no match, it discards the packet, having allocated nothing at any point.

 Validation flow showing an incoming ACK recomputed against the SYN cookie with match and no-match outcomes

You might be thinking this sounds forgeable. It is not. A blind guess has to land the correct 24-bit keyed value, roughly one chance in 16.7 million, against a target that rolls over every 64 seconds.

One loss is worth flagging. If the completing ACK is dropped in transit, the client believes the connection is open while the server never learns it exists, because there is no half-open record to retransmit from. That asymmetry hurts some protocols more than others, which brings us to the trade-offs.

What SYN Cookies Give Up in Exchange for Statelessness

SYN cookies buy survival by discarding TCP features that have nowhere to live inside 32 bits. The most expensive casualty is window scaling.

Yes, the server stays reachable under attack. But without window scaling the receive window caps at 65,535 bytes, which throttles throughput badly on high-latency, high-bandwidth paths. On a link with 100 milliseconds of round-trip delay, that ceiling limits a single connection to roughly 5 Mbps no matter how much capacity sits underneath.

The MSS degrades more quietly. Three bits describe 8 values, so a client advertising an unusual segment size gets rounded down to the nearest table entry. Data carried on the SYN itself is not acknowledged and has to be retransmitted. Some protocols break invisibly from the server side: when the passive end speaks first, as an SMTP server does with its greeting, a lost ACK leaves the client waiting on a connection the server never registered.

“syncookies seriously violate TCP protocol, do not allow to use TCP extensions”

Check whether your clients actually send timestamps before assuming the timestamp path will save your throughput. If a load balancer or middlebox strips the option, you silently fall back to the unscaled window.

One more limit deserves naming. The mechanism is specific to TCP handshakes, so it does nothing for connectionless traffic. A UDP flood attack carries no handshake to validate and has to be handled by filtering and capacity instead.

How to Enable and Tune SYN Cookies on Linux

Linux ships with tcp_syncookies set to 1, so the mechanism is already armed on most servers and fires only when the SYN backlog overflows. In the common case there is nothing to enable.

The three accepted values behave differently. Setting 0 disables the mechanism. Setting 1 uses it as an overflow fallback. Setting 2 generates cookies unconditionally for every connection, which the kernel documentation describes as a testing mode rather than a production setting.

# Inspect the current state sysctl net.ipv4.tcp_syncookies # Fallback mode: engage only when the backlog overflows (recommended default) sysctl -w net.ipv4.tcp_syncookies=1 # Raise the backlog so cookies stay a genuine last resort sysctl -w net.ipv4.tcp_max_syn_backlog=4096 sysctl -w net.ipv4.tcp_synack_retries=3 # Persist across reboots echo ‘net.ipv4.tcp_syncookies = 1’ >> /etc/sysctl.d/99-tcp.conf echo ‘net.ipv4.tcp_max_syn_backlog = 4096’ >> /etc/sysctl.d/99-tcp.conf sysctl –system # Watch the counters while under load nstat -az | grep -i syncookie # TcpExtSyncookiesSent cookies issued # TcpExtSyncookiesRecv cookies validated successfully # TcpExtSyncookiesFailed cookies that failed validation

Read those counters as a diagnostic, not a scoreboard. A rising SyncookiesSent value during a burst is the mechanism working. A permanently elevated value says something else: your backlog is too small for your legitimate traffic.

This is the point most tuning guides skip. The kernel documentation states outright that the feature must not be used to help heavily loaded servers cope with a normal connection rate, and that persistent SYN flood warnings without an actual flood mean the server is misconfigured. Teams who see the warning, shrug, and leave it are trading throughput for nothing.

Host tuning is one layer of a broader DDoS mitigation plan, and it should be paired with filtering that never lets the flood reach the kernel. Which raises a fair question about the alternatives.

SYN Cookies, SYN Cache, or a Bigger Backlog: Which Defense Fits

Enlarging the backlog is the weakest of the three options, the SYN cache is the balanced default, and SYN cookies are the option that never runs out. The distinction comes down to how much memory each reserves for a connection that may never complete.

Bar chart comparing memory held per half-open connection for a full TCB, a SYN cache entry, and a SYN cookie

Approach State per half-open connection TCP options preserved Fails when
Larger backlog Full block, 736 bytes All Attack scales past the new limit, and search performance degrades
Shorter SYN-RECEIVED timer Full block, briefly All Legitimate clients on slow paths get dropped
SYN cache Reduced entry, 196 bytes All Bucket limits are reached under a large enough flood
SYN cookies None Window scaling and SACK only with timestamps Never exhausts, but throughput and some protocols suffer

Increasing the backlog fails on its own terms. Implementations were not designed to scale past a few hundred entries, and the data structures degrade as the queue grows, so the defender pays a performance penalty to buy an advantage the attacker erases by sending more packets.

The SYN cache is the quieter success story. It keeps a trimmed entry rather than a full block and costs about 15% longer connection establishment while under active attack, a modest price for retaining every TCP option. Hybrid designs use the cache first and fall through to cookies when it fills, which is close to how production stacks behave today.

All three share a blind spot. Each assumes the packets arrive somewhere the kernel can make a decision about them, which is why dedicated Layer 4 protection at the network edge changes the arithmetic entirely.

Where Host-Level SYN Cookies Stop Being Enough

SYN cookies protect memory, not bandwidth. Once a flood saturates your uplink or exhausts the packet-processing capacity of the hardware in front of the server, the kernel never gets a chance to be clever.

The scale gap is not subtle. Cloudflare’s most recent half-year DDoS threat report counted 23.2 million network-layer attacks, roughly 5,343 every hour, including 935 that exceeded one terabit per second. No sysctl value has any bearing on traffic that never reaches the host.

Speed compounds it. In that dataset 90.60% of network-layer attacks finished in under ten minutes, and the largest recorded assault lasted 35 seconds. There is no realistic window in which a human reads an alert and intervenes, so mitigation has to be automatic and already in place.

You might be thinking most attacks are small enough to ignore. The reported figure that 96.62% of network-layer attacks stay under 500 Mbps sounds reassuring until you notice 100 Mbps is enough to overwhelm an ordinary server. Small is relative to the defender, not the internet.

Distributed sources make the host-level view worse. A botnet-driven DDoS arrives from thousands of real addresses rather than one spoofed range, so the SYNs look plausible, per-source rate limits barely register, and address blocking becomes unworkable.

Treat SYN cookies as the innermost layer of your defense, not the perimeter. Their job is to keep the host honest during the seconds before upstream filtering absorbs the volume, not to stand alone against it.

The practical answer is to filter transport-layer floods far upstream, where distributed capacity absorbs the volume and only validated handshakes continue on. That is the role global edge security plays alongside the kernel setting, rather than instead of it.

Final Thought on SYN Cookies

SYN cookies solve one problem with unusual elegance: they delete the resource an attacker was trying to exhaust. By encoding connection state into a number the client must return, a server stops keeping promises to strangers and stops being vulnerable to strangers who never call back. That is why the mechanism has survived three decades largely unchanged.

The discipline is treating it as what the kernel documentation calls it, a fallback. Leave tcp_syncookies at 1, size the backlog for your real traffic, verify that clients send timestamps if throughput matters, and read a permanently rising cookie counter as a sign that something needs sizing rather than proof you are protected.

Keep the layers in proportion. A stateless handshake defends host memory beautifully and link capacity not at all, so pair it with filtering that stops the flood before it becomes your server’s problem.

Common Questions About SYN Cookies

Do SYN cookies slow down a busy server?

The measurable cost is the hash computed for each SYN, and operational reports suggest that overhead is minor compared with losing the service entirely. The real cost is indirect: with window scaling disabled, throughput per connection drops on long-distance links. On constrained embedded or mobile hardware the computation itself matters more.

Should I set tcp_syncookies to 2 permanently?

No. Value 2 generates a cookie for every connection regardless of backlog pressure, imposing the TCP option penalties on all of your traffic all of the time. The kernel documentation frames it as a way to test the effects on your network, not as a hardening step. Value 1 keeps the protection while preserving normal behavior.

Do SYN cookies work with IPv6?

Yes. IPv6 support was added to the Linux implementation and the encoding works the same way, since the hash simply covers the longer address pair. One implementation caution from the record: the IPv6 flow label on the SYN-ACK should stay consistent with the rest of the flow, because bugs in early code produced random labels.