DDoS Protection
Aegis includes a kernel-level DDoS protection engine built on Linux XDP (eXpress Data Path) and eBPF. Packets are inspected and dropped at the network device driver level — before they reach the kernel’s TCP/IP stack — making it one of the fastest possible filtering points in the Linux networking pipeline.
Requirements
On non-Linux platforms, the DDoS service returns a stub message indicating the feature requires Linux.
Architecture Overview
How It Works
Kernel-Level Filtering (XDP)
The XDP programaegis_xdp_filter attaches directly to the network interface and processes every inbound packet:
- Check enable state — reads
config_map[0]; if disabled, returnsXDP_PASS - Parse Ethernet/IP headers — extracts source IP, destination IP, protocol
- Parse L4 headers — if TCP, checks the SYN flag; if UDP, extracts ports
- Ban map lookup — checks
ban_map[src_ip]; if found and not expired, drops immediately withXDP_DROP - Rate limit check — looks up
rate_map[src_ip]for per-IP packet and SYN counters within a 1-second sliding window; drops if thresholds exceeded - Pass — increments stats and returns
XDP_PASS
BPF Maps
Kernel Data Structures
Ban Entry:Rule Types
ip_ban — Direct Kernel-Level Ban
The most direct kernel rule. When you save an ip_ban rule, the Go service writes the IP into the BPF ban_map immediately. The XDP program checks ban_map on every packet and returns XDP_DROP for matches.
- Enforcement: Kernel-level, per-IP
- Latency: Immediate — packets never reach the TCP/IP stack
cidr_ban — CIDR Block Ban
Currently only /32 CIDRs (single IPs) are synced into the kernel ban map. Broader CIDRs (e.g., /24) are not yet implemented in the XDP program — the service logs a warning for non-/32 entries.
- Enforcement: Kernel-level for /32 only
- Broader CIDR support: Planned
rate_limit — Packets Per Second Threshold
Rate limit rules are not independently represented in the kernel. Instead, the service computes a single effective global PPS threshold from all enabled rate_limit rules and the default config, then writes that value into config_map. The XDP program enforces one packets_per_second value against per-IP counters.
Threshold computation:
- Start with the configured
DefaultPPS - For each enabled
rate_limitrule with apackets_per_secondvalue > 0: take the minimum - The strictest enabled rule wins
- Adding a stricter
rate_limitrule changes the kernel threshold immediately - Adding a looser rule has no effect if a stricter enabled rule already exists
- The XDP program always reads one current
packets_per_secondvalue fromconfig_map - Enforcement: Kernel-level, single global threshold
syn_limit — SYN Packets Per Second Threshold
Same architecture as rate_limit. The service computes one effective SYN/sec threshold and writes it to config_map. The XDP program enforces that threshold against per-IP SYN counters.
- Enforcement: Kernel-level, single global threshold
Rule Lifecycle
Every time a DDoS rule is created, updated, or deleted:- The service reloads all rules from the database
- Recomputes effective global thresholds (minimum across all enabled rules + default)
- Writes updated values into the kernel
config_map - For
ip_banand/32cidr_banrules: syncs theban_mapdirectly
Auto-Ban
When the kernel drops a packet due to rate or SYN threshold violations, it emits an event through the ring buffer. The userspace Go service reads these events and can automatically promote threshold violations into full bans:- Kernel drops packet, emits
drop_rateordrop_synevent readEvents()goroutine parses the event from the ring bufferprocessEvents()goroutine callshandleAutoBan()- Auto-ban TTL is computed as the maximum of:
- Global
AutoBanDurationconfig value - The
auto_ban_duration_secof the first enabled matching rule
- Global
- If TTL > 0: the source IP is written into the kernel
ban_mapwith that TTL - Subsequent packets from that IP are dropped at the XDP level without rate-map evaluation
Ban Entry Lifecycle
- Bans are stored with a monotonic expiration timestamp
- The XDP program checks expiry on every lookup — expired entries are deleted inline
- A
cleanupLoop()goroutine runs every 30 seconds to sweep expired bans from userspace
Ban Reasons
Event System
Event Types
Event Sampling
To reduce ring buffer overhead on high-traffic deployments:- Drop events: Emitted every 100th dropped packet per ban entry
- Pass events: Sampled at the configurable
event_sample_rate(default: 1 in 1,000)
Event Data
Each event includes:- Source and destination IP
- Source and destination port
- Protocol (TCP, UDP, other)
- Event type
- Packets in current window
- Drop count
Configuration
Location: Admin UI -> Config -> DDoS ProtectionReal-Time Statistics
The stats endpoint reads directly from kernel BPF maps:
The admin dashboard displays a live traffic chart with a 5-minute window showing passed vs. dropped packets per second.
Service Lifecycle
Startup
- Remove memory lock limit (
rlimit.RemoveMemlock) - Load pre-compiled BPF bytecode (x86-64 or ARM64)
- Attach XDP program to the configured network interface
- Create ring buffer reader for kernel events
- Sync configuration, rules, and bans to kernel maps
- Launch goroutines:
readEvents(),processEvents(),cleanupLoop()
Shutdown
- Close ring buffer reader
- Detach XDP program from network interface
- Close BPF map file descriptors
Concurrency
API Endpoints
Current Limitations
The UI is currently more expressive than the kernel implementation. Multiple
rate_limit or syn_limit rules are collapsed into a single effective global threshold (the strictest enabled value). This means individual rules serve as policy definitions that influence the global kernel enforcement, not as independent kernel-level filter objects.
