3 minutes
Exploiting TCP Handshake Quirks for IP Verification
It’s an incredibly frustrating reality that we’re still battling TCP SYN Floods with spoofed IPs in 2026.
ISPs completely ignoring BCP38 is a rant for another day. Right now, I want to talk about how we can actually solve the problem using a beautiful quirk in the TCP stack.
The core concept relies entirely on how operating systems handle unexpected ACK numbers, and how we can weaponize that behavior for defensive purposes.
The Problem With SYN-ACKs
During a normal TCP 3-Way Handshake, the client sends a SYN, the server fires back a SYN-ACK, and the client closes the loop with an ACK.
But in a spoofed attack, the attacker blasts your server with SYN packets from thousands of random, fake IP addresses. Your server politely allocates state, sends out SYN-ACKs into the absolute void, and waits.
Eventually, the connection table fills up and the server tips over. T_T
To survive this without dumping massive amounts of money into proprietary hardware, we need a way to verify the source IP before allocating any state in the kernel.
The Beautiful Quirk
Enter eBPF and XDP. We can hook right into the NIC driver and intercept every incoming SYN packet before the Linux networking stack even knows it exists.
Instead of passing the SYN up the stack, we do something slightly evil. We craft an entirely bogus SYN-ACK with a deliberately wrong ACK number and send it right back to the client.
sequenceDiagram
participant C as Client
participant O as eBPF/XDP Hook
participant S as Server
C->>O: SYN (Valid Request)
Note over O: Intercept & Generate Challenge
O-->>C: SYN-ACK (Wrong ACK Number!)
So what happens to the attacker?
If the initial SYN was spoofed, that garbage SYN-ACK we just sent goes nowhere. The actual owner of that spoofed IP will silently drop it, and the attacker couldn’t care less.
No state was allocated on our end. The NIC handles it at linerate. We win.
But what about legitimate users?
This is where the magic happens.
If it’s a real, legitimate user trying to connect, their TCP stack receives our garbage SYN-ACK. The OS looks at the ACK number and immediately thinks, “What in the world is this? This ACK is complete nonsense.”
According to the RFCs, a compliant TCP stack must reject this invalid ACK. It does so by immediately firing back an RST (Reset) packet.
sequenceDiagram
participant C as Legit Client
participant O as eBPF/XDP Hook
participant S as Backend Server
C->>O: SYN
O-->>C: SYN-ACK (Wrong ACK)
Note over C: "This ACK is nonsense!"
C->>O: RST
Note over O: IP Verified & Whitelisted!
Note over C: OS retries after RTO (~1s)
C->>O: SYN (Retransmit)
O->>S: SYN (Forwarded)
S-->>C: SYN-ACK (Real)
C->>S: ACK
Note over C,S: Connection Established!
The absolute moment we see that RST come back in response to our challenge, we know the IP address belongs to a real machine with a real TCP stack.
We can then safely whitelist the IP at the edge.
After the RST, the OS’s RTO timer kicks in. That’s typically around 1 second. Once it fires, the client transparently retries the connection. This time, our XDP hook sees the verified IP and lets the SYN pass straight through to the backend server.
The user eats roughly one second of delay on their very first connection, but every subsequent connection sails through unimpeded. A small price to pay for an infrastructure completely shielded from spoofed floods.
Sometimes the most elegant defensive mechanisms involve breaking the rules just a little bit. :)
Associated Content:
Related Content: