Layer 7 Denial of Service Attack Mitigation Using eBPF and XDP Filtering
Learn how to combine eBPF and XDP to block malicious traffic at the application layer before it exhausts your web server resources.
Summary
- Network-level filtering with eBPF prevents the excessive CPU consumption caused by traditional user-space packet processing.
- XDP enables dropping malicious packets directly at the network interface card driver prior to kernel memory allocation.
- Identifying patterns in HTTP requests inside the kernel requires efficient strategies to bypass TLS encryption without losing performance.
- Real-time metrics integration ensures immediate visibility into anomalous traffic behavior and distributed attacks.
- Modern mitigation strategies combine rapid packet inspection with intelligent rate-limiting controls per IP address.
The Challenge of Malicious Traffic at the Application Layer
When we think of Denial of Service (DDoS) attacks, the first image that usually comes to mind is a website going offline due to an excess of simultaneous visits. In practice, attacks targeting Layer 7 — the application layer where the HTTP protocol operates — are especially tricky. An attacker can send just a few requests per second, but engineer them to force the web server to execute heavy database operations, complex cryptography, or disk reads. This quickly exhausts available connections, leaving legitimate users unattended.
Historically, defending against this type of behavior was handled by traditional application firewalls and reverse proxies positioned at the edge of the infrastructure. The problem is that once the malicious packet reaches the application or even the operating system space where web servers run, the system has already spent precious processor and memory resources just to receive and interpret the message. During traffic peaks or under heavy attack, this overhead paralyzes the service before traditional blocking rules can kick in.
The Role of eBPF and XDP in Modern Defense
To solve this performance limitation, modern network engineering has adopted eBPF, or Extended Berkeley Packet Filter, which works as a secure virtual machine capable of executing small programs directly inside the operating system core, the kernel. In practice, this means we can inject custom code to inspect and modify network traffic at the exact moment it enters the machine, without needing to alter the kernel source code and with an extremely high level of security.
The great partner of eBPF in this mission is XDP, an acronym for eXpress Data Path. While eBPF operates at various points within the operating system, XDP operates at the lowest possible level of the network stack: right at the network card, the exact moment the physical hardware driver receives the electrical or optical packet and turns it into digital data. By combining eBPF and XDP, we can inspect traffic and make drop decisions in microseconds, completely ignoring unwanted packets before the operating system even needs to allocate memory for them.
Architecture of Packet Filtering and Inspection
Building an efficient XDP-based barrier requires understanding how data travels through the network card. When a packet arrives, the XDP hook executes a program that receives a pointer to the raw message data. The developer writes restricted C-language logic, compiled into bytecode, which checks Ethernet, IP, and TCP headers looking for known attack signatures or suspicious request patterns.
If the check indicates that the traffic is legitimate, the program returns an instruction called XDP_PASS, allowing the packet to proceed on its normal path through the operating system to the application. Otherwise, if the packet belongs to a blocked IP or shows anomalous behavior, the program returns XDP_DROP. In this scenario, the network card simply drops the packet immediately, freeing up hardware resources and avoiding any waste of processor clock cycles.
#include <linux/bpf.h> #include <linux/if_ether.h> #include <linux/ip.h> #include <linux/tcp.h> #include <bpf/bpf_helpers.h> SEC("xdp") int xdp_ddos_filter(struct xdp_md *ctx) { void *data = (void *)(long)ctx->data; void *data_end = (void *)(long)ctx->data_end; struct ethhdr *eth = data; if ((void *)(eth + 1) > data_end) return XDP_PASS; if (eth->h_proto != __constant_htons(ETH_P_IP)) return XDP_PASS; struct iphdr *ip = data + sizeof(*eth); if ((void *)(ip + 1) > data_end) return XDP_PASS; // Simplified malicious IP inspection logic if (ip->saddr == 0x0100007f) { // Example: 127.0.0.1 return XDP_DROP; } return XDP_PASS; } char _license() SEC("license") = "GPL";Application Layer Challenges and XDP Limitations
Although XDP is extremely fast for filtering traffic at the transport and network layers, Layer 7 presents a complex structural challenge: encryption. The vast majority of current web traffic uses HTTPS, meaning the content of the request — including URLs, HTTP headers, and cookies — travels fully encrypted. An XDP program executed on the network card does not possess the private keys required to decrypt the TLS flow, making it impossible to directly inspect application content before the secure handshake finishes.
To bypass this architectural restriction, modern defenses use hybrid approaches. XDP acts as a primary shield against volumetric attacks, port scans, and known transport-level patterns, while the load balancer or reverse proxy handles TLS termination and applies complementary rules based on requests per second, JavaScript challenges, or session-level behavior verification.
Practical Implementation of a Rate Filter with eBPF Maps
One of the most powerful tools in the eBPF ecosystem is maps, shared data structures between the kernel and user space that allow storing counters, blocklists, and configuration tables at runtime. We can use a hash-type map to track the number of requests originating from each IP address within a specific time window, implementing extremely efficient rate limiting.
When a packet arrives, the eBPF program queries the map using the source IP as a key. If the associated counter exceeds the established limit for that time interval, the IP is temporarily added to a blocklist and subsequent packets are dropped instantly. Otherwise, the counter is incremented and the traffic is allowed through. This logic protects the application against resource exhaustion attempts without overloading the system with excessive logs.
Operational Considerations and Production Validation
Adopting low-level technologies like eBPF and XDP in production environments requires technical rigor and exhaustive testing. Because the code executed by XDP runs directly in the kernel context, a logic error, an infinite loop, or an invalid pointer can cause a kernel panic, requiring a physical system reboot. Therefore, using static verification tools provided by the kernel ecosystem is mandatory before loading any program.
Additionally, it is crucial to continuously monitor drop metrics and network card resource usage to ensure the filter is operating as expected. With a well-designed strategy and consistent testing in staging environments, eBPF-based filtering radically transforms the security posture of any internet-facing infrastructure.
Final Considerations
Protection against denial of service attacks has evolved considerably with the arrival of performance-oriented, kernel-level technologies. By offloading malicious traffic inspection and dropping to the network card driver through XDP and eBPF, engineering teams gain a crucial competitive advantage against volumetric and resource-exhaustion attacks.
Although encryption and Layer 7 complexity demand a layered architecture combining packet inspection with intelligent proxies, introducing programmable filters into the kernel redefines the resilience standard for modern high-scale systems.