【工具推荐】eShield:单机ddos防御利器
在维护一台对外暴露服务的云主机时遇到过几次典型的网络层攻击SYN 半开连接把连接表打满、UDP 小包把带宽和 CPU 软中断拉高、ICMP Flood 让机器响应变慢。当时尝试用 iptables limit 做限流效果有限因为包已经进了内核网络栈再 drop 也消耗了协议栈处理资源。背景为什么想到做这个eBPF/XDP 主机层 DDoS 防护实践记录本文记录一个基于 eBPF/XDP 的开源项目 eShield 的设计思路、实现过程与当前状态供对内核网络层防护感兴趣的开发者参考。项目地址https://github.com/BlkSword/eShield后来了解到 XDPeXpress Data Path可以在网卡驱动层做包处理决定用 eBPF 写一个能在流量最前端拦截恶意包的实验性项目也就是 eShield。项目定位eShield 是一个主机级的 L3-L4 网络层过滤程序运行在 Linux 内核 XDP 钩子上。它不是一个完整的应用防火墙也不提供企业级安全服务而是聚焦于在单台 Linux 主机上缓解 SYN Flood、UDP Flood、ICMP Flood、端口扫描等网络层流量压力。项目经历了几个版本的迭代后v0.3.1 移除了早期实验性的 HTTP WAF 和 JS Challenge 模块把注意力重新收回到网络层清洗上以降低 eBPF verifier 的复杂度和运行时开销。技术选型为什么用 eBPF/XDPXDP 的决策点位于网卡驱动接收路径的前端可以通过返回 XDP_DROP 让恶意包不进入内核网络协议栈。与 iptables/nftables 相比这条路径更短适合处理高 pps 的异常流量。eBPF 程序会被 JIT 编译为本地机器码执行配合 BPF Map 可以在内核态维护状态表减少用户态和内核态之间的上下文切换。为什么用 Rust Aya用户态控制面选择 Rust Tokio axum主要是出于工程可维护性和内存安全考虑。eBPF 部分使用 Aya 框架加载和管理避免直接维护复杂的 libbpf C 代码。数据面与控制面之间通过 BPF Map 和 Ring Buffer 通信。v0.3.1 把核心计数器从纯 Ring Buffer 事件统计改为 eBPF Per-CPU GLOBAL_STATS 同步减少了事件丢失或重复对统计结果的影响。架构设计┌─────────────────────────────────────────────────────────────┐│ 管理面 ││ Web Dashboard (axum) │ TUI (ratatui) │ CLI (clap) │└──────────────────────────────┬──────────────────────────────┘│ REST API / Config Watch┌──────────────────────────────▼──────────────────────────────┐│ 控制面 — Rust 用户态 ││ 配置管理 │ 事件消费 │ 自适应阈值 │ 持久化 │ 指标聚合 │└──────────────────────────────┬──────────────────────────────┘│ BPF Maps / Ring Buffer┌──────────────────────────────▼──────────────────────────────┐│ 数据面 — eBPF/XDP 内核态 ││ 包解析 → 白名单 → 端口 ACL → GeoIP → SYN Proxy → UDP/ICMP ││ Flood → L7 扫描 → 速率限制 → 黑名单 → 决策 │└─────────────────────────────────────────────────────────────┘数据面按照优先级处理先匹配白名单再执行端口/协议 ACL、GeoIP 策略、SYN Cookie 代理最后走速率限制和黑名单判定。命中黑名单或 ACL drop 规则的包直接返回 XDP_DROP。控制面负责加载/卸载 eBPF 程序、管理动态规则、消费审计事件、提供 REST API 和 Web 界面并把规则持久化到 redb。主要功能模块白名单与黑名单白名单基于 LPM Trie支持 IPv4/IPv6 CIDR黑名单使用 LRU Hash命中后会在指定时间内拦截该源地址到期自动解封。速率限制使用指数衰减滑动窗口统计每个源 IP 的包速率用于识别 UDP Flood、ICMP Flood 和 CC 慢速压测类流量。SYN Cookie 代理针对 IPv4 TCP SYN FloodeShield 回复 SYN-ACK Cookie只有完成完整三次握手的合法连接才会被放行。TCP RST 回包v0.3.1 新增的可选功能。对于被丢弃的 TCP 连接主动回复 RST避免客户端持续重传造成半开连接堆积。GeoIP 与威胁情报支持加载自定义 CSV 格式的 CIDR 列表按国家或 ASN 执行放行/封禁也支持定时拉取自定义威胁情报 feed拦截已知恶意地址。L7 轻量指纹扫描检查 TCP 载荷前若干字节匹配预设特征时执行 drop。这个模块比较轻量主要用于识别常见扫描和探测行为不替代专业 DPI 工具。自适应阈值对重复触发防御规则的源 IP自动延长封禁时长减少同一批地址反复试探的情况。部署与使用环境要求Linux 内核 5.10且启用 BTFls /sys/kernel/btf/vmlinuxroot 权限或具备 CAP_BPF、CAP_NET_ADMIN 等 capabilities安装方式项目 Release 提供了 musl 静态链接的二进制文件可以通过 install.sh 一键安装curl -sSL https://raw.githubusercontent.com/BlkSword/eShield/main/scripts/install.sh | sudo bash也可以从源码构建sudo bash scripts/install.sh --build常用操作# 查看运行状态eshield status# 临时封禁某个 IPeshield block 192.0.2.1 --duration 300# 解封eshield unblock 192.0.2.1# 热加载配置sudo systemctl reload eshield测试情况我们在普通 VM veth 环境下做了基础测试工具使用 hping3 和 wrk覆盖 UDP Flood、ICMP Flood、SYN Flood 等场景。测试脚本放在 tests/full_attack_test.sh 和 tests/netns_test.sh 中。单项数据方面在单核 VM 上 XDP PASS 路径可以达到约 24 万 ppsDROP 路径因为提前返回开销比基线还略低。正常流量的额外延迟典型小于 1 µs。这些数字来自实验环境实际生产中的表现与网卡、CPU、内核版本、攻击模型都有关系仅供参考。与其他技术路线的区别与 iptables/nftablesiptables/nftables 是通用防火墙适合做细粒度的访问控制但 drop 动作发生在内核网络栈内部。eShield 只做一件事在网络栈最前端快速清掉高 pps 的恶意流量。两者可以共存互不冲突。与 Suricata/ZeekSuricata 和 Zeek 更偏向深度包检测和威胁分析能力强但资源占用更高。eShield 不追求 DPI而是用最小开销完成快速判定和 drop适合作为第一道粗筛。与 DPDKDPDK 可以实现极高的包处理性能但需要接管网卡、绑定 CPU 核心、绕过内核网络栈部署和运维成本较高。eBPF/XDP 的侵入性小得多能和现有 Linux 网络组件共存但极限性能通常低于专门调优的 DPDK。与云厂商高防云厂商高防提供大带宽和专业运营适合大规模攻击eShield 是主机层自托管方案延迟更低、策略自主但带宽受限于单台机器网卡。二者属于不同层级的防护手段。当前局限需要 Linux 5.10 和 BTF老内核无法运行防护项目目前在控制面做策略分组和持久化数据面暂未按项目维度做独立匹配L7 指纹扫描能力有限不替代专业 WAF 或 IDS文档和测试还在持续完善中后续方向接下来会围绕网络层清洗继续打磨优化 SYN Cookie 代理在复杂场景下的稳定性完善 UDP/ICMP Flood 的阈值模型增强威胁情报 feed 的解析和更新机制补充更多自动化测试和基准测试数据结语eShield 是一个还在持续迭代的开源项目初衷是探索 eBPF/XDP 在主机层 DDoS 防护中的可行性。如果对这个方向感兴趣可以到 GitHub 查看源码和文档也欢迎通过 issue 或 PR 交流。项目地址https://github.com/BlkSword/eShield免责声明eShield 为开源技术项目不提供商业安全服务承诺。在生产环境使用前请充分测试并根据自身业务需求评估风险。