在开源和独立开发这条路上,最让人无奈的事情是什么?
不是代码写不出 Bug,也不是服务器续费捉襟见肘,而是:你辛辛苦苦用爱发电写的一个开源项目、搭的一个公共测试节点、或者和小伙伴一起开的独立游戏服,突然被网线对面的某些“脚本小子”无休止地恶意攻击。
这种攻击往往没有任何商业利益驱动,纯粹是宣泄式的恶搞——海量的 SYN Flood、UDP 垃圾包像暴雨一样倾泻过来。
随后就是熟悉的悲剧循环:
- CPU 瞬间被
ksoftirqd(内核软中断)干到 100%; - 连接表瞬间被撑爆,SSH 敲回车五分钟没反应;
- 云厂商直接发来“黑洞通知”,服务器对外彻底断网。
看着群里嗷嗷待哺的用户,很多人第一反应是“加防护”。但现实往往兜头一盆冷水:
- 上商业高防 IP?动辄一个月几千上万块,对于个人项目和微型业务来说,这无异于天方夜谭;
- 套免费 CDN?很多项目压根不是常规的 HTTP 网站,私有 UDP 协议、游戏服、音视频节点、自建代理中继……CDN 根本套不上去;
- 用
iptables/Fail2ban挡一挡?洪水真正打过来的时候,几万、几十万 PPS(数据包/秒)一冲,内核协议栈连包都还没来得及传给 iptables,机器就已经假死了。
我亲眼见过太多开发者,在日复一日的骚扰和高防账单面前,心力交瘁,最后只能默默留下一句“成本有限,服务器关闭,后会有期”,黯然离场。
凭什么用爱发电的开发者,就活该成为被网络恶霸随意拿捏的沙袋?
没有预算、用不了 CDN,单机就真的没有生存空间了吗?
带着这股不服气的念头,我决定自己动手,做一款属于独立开发者和中小站长的主机级“硬骨头”防御盾——XuanArmor(原名 eShield)。
01. 一场本不该低头的妥协
要搞明白为什么普通小服务器会被轻易打死,必须先看一眼 Linux 内核的处理链路:
[网卡接收数据包] │ ▼ [分配 sk_buff 内存] ──▶ [触发软中断] ──▶ [进入内核网络栈 (iptables/netfilter)] ──▶ [用户态应用]传统的iptables、nftables或firewalld,是在数据包已经分配了内存(sk_buff)、已经触发了系统软中断、已经进了内核协议栈之后才开始判决的。
当攻击者用百兆带宽打来每秒上百万个假 IP 的 UDP/SYN 垃圾包时,你的 CPU 所有的算力都用来给这些垃圾包“分配内存 -> 挂载链表 -> 触发中断”了。哪怕你的 iptables 规则写了DROP,你的系统其实已经被累死了。
破局的唯一解法:在数据包刚摸到网卡驱动的一瞬间,在分配任何内核内存之前,把它当场拍死。
这就是XDP(eXpress Data Path)和eBPF的用武之地。
02. 为什么传统方案不行?差在哪了?
XuanArmor 的核心思路非常暴力且直接:降维拦截。
我们将过滤逻辑用 Rust 编写成 eBPF 字节码,直接挂载到网卡驱动层的 XDP 钩子上:
[网卡接收数据包] │ ▼ 【 XuanArmor (XDP 层秒杀) 】──▶ [XDP_DROP 垃圾包直接湮灭在网卡层,CPU 毫无波动] │ (合法的包才放行) ▼ [进入内核协议栈] ──▶ [正常服务响应]在网卡驱动层,处理一个包只需要短短十几条 CPU 指令,甚至不需要内核给它分配内存。这意味着,原本几万 PPS 就能让你服务器失联的攻击,在 XDP 面前,单机能够抗住数十万甚至数百万的包速率而不影响业务系统。
但,我不想再做一个“纯极客的半成品 Demo”
市面上懂 eBPF 的大厂很多,但大部分开源的 XDP 工具要么是学术界的简陋脚本,要么是巨头专属的大型云原生怪物(比如 Cilium,部署起来复杂到令人绝望)。
我希望XuanArmor 是一个开箱即用、有温度、真正能让普通站长轻松用起来的产品:
- 纯单二进制,毫无负担:采用纯 Rust + Aya 框架实现,不依赖庞大的 JVM、Python 或 Node.js 运行时。下载一个可执行文件,开箱即跑,内存占用极低。
- 自带现代化 Web 控制台与 TUI:我没有引入沉重的外部前端依赖,而是手写了一个仅几百 KB 的极轻量单文件 SPA,直接编译嵌进二进制里。
- 黑色高密度运维面板;
- 实时看 PPS 流量折线、DROP 拦截走势、Top 攻击源;
- 黑白名单动态下发、端口 ACL、自适应频控、分片策略检查,点点鼠标就能搞定。如果你喜欢纯终端,还自带优雅的 TUI 界面。
- 无感平滑升级(Zero-downtime Upgrade):玩网络工具最怕“重启就断网”。XuanArmor 将 eBPF link pin 到了
bpffs,控制面程序重启、更新时,底层数据面过滤不中断,新旧进程原子替换,保证防御永远在线。 - 填补绕过漏洞的实战防御:
- 默认开启“协议 + 目的端口聚合限速”,堵死黑客用海量伪造源 IP 穿透单 IP 频控的套路;
- 针对恶意的 IPv4 分片攻击,制定了专门的分片防御策略;
- 针对 TCP SYN Flood,内置了 XDP 级的 SYN Cookie 代理机制。
03. 实测数据:它到底有多快、多轻?
很多人担心加了 eBPF 防火墙会不会拖慢正常网络。下面这组官方基准测试数据,可以给出一个相对直观的答案。
测试基准环境:Linux Kernel 7.0,8 vCPU,Netns + veth(网络命名空间虚拟网卡),测试工具:
iperf3 -c <server> -t 5 -P 4大包 TCP(1500B MTU)。
3.1 核心性能概览
- 微秒级延迟:合法正常流量通过时,仅增加一次 eBPF Map 查表与轻量分支判断,典型数据包延迟增加小于 1 µs。
- 极低的过滤开销:相比于完全不做任何逻辑的“空裸 XDP 程序(Minimal XDP_PASS)”,XuanArmor 完整的规则匹配体系仅带来约 7% ~ 10% 的微弱损耗。
- 模块热旁路优化:在未触发攻击时,即便开启速率限制、信誉评估(Trust Score)、连接跟踪等全部高级模块,额外吞吐损耗低于 1%(实测约 0.3%)。
3.2 吞吐量基准测试
| 测试场景 / 模式 | 吞吐量(Throughput) | 性能特征与对比结论 |
|---|---|---|
| Baseline(无任何 XDP) | 274.44 Gbps | veth 虚拟网卡在本机内存拷贝的物理理论上限。 |
| 最小 XDP_PASS(Native 原生驱动模式) | 12.83 Gbps | 虚拟网卡在内核原生驱动层挂载 XDP 的自身瓶颈。 |
| XuanArmor PASS(Native 原生模式,空规则) | 11.85 Gbps | 相对最小 XDP 程序仅损耗约 7.6%。 |
| XuanArmor PASS(Native 原生模式,开启全模块) | 11.81 Gbps | 模块全部启用但未触发丢包,相对空规则仅下降 0.3%。 |
| 最小 XDP_PASS(SKB 通用模式) | 124.62 Gbps | 通用 SKB 模式在 veth 虚拟网卡场景下转发更快。 |
| XuanArmor PASS(SKB 通用模式,空规则) | 112.30 Gbps | 相对最小 SKB 程序仅损耗约 9.9%。 |
3.3 包转发速率(PPS)
- 大包场景(1500B):Native 模式约1 Mpps,SKB 通用模式约9 ~ 10 Mpps;
- 单核小包单机环境:在普通虚拟机单核单队列下,XDP 处理速率约24 万 PPS;
- 物理网卡扩展能力:在搭载硬件 RSS(多队列接收)的千兆/万兆物理网卡驱动下,借助多核并发可轻松线性扩展至数百万至千万级 PPS。
3.4 面对高频洪水攻击的“写路径降载与采样”机制
在大流量 SYN/UDP 洪水攻击期间,如果每个攻击包都去实时更新 BPF Map 或向用户态发送通知,CPU 很容易因内存总线锁(Lock Contention)和写放大而耗尽。XuanArmor 在数据面采用了非常工程化的批量与概率采样写入策略:
| 攻击路径 / Map 目标 | 优化策略(Optimization) | 收益与设计目的 |
|---|---|---|
| 合法流量 Trust PASS 更新 | 1/64 采样写入,单次按 64 倍权重补偿 | 避免正常高并发流量把信任评分 Map 刷爆。 |
| 恶意流量 Trust DROP 更新 | 1/16 采样写入(仅针对信用已扣光的源) | 对已经被判定死刑的恶意 IP 降低写锁开销。 |
| 动态黑名单 Hit Count | 1/16 采样写入,单次增加 16 | 降低原子计数(Atomic Increment)开销。 |
| Top 攻击源排行榜 | 1/16 采样写入,单次增加 16 | 统计排行平滑逼近,不占用宝贵数据面周期。 |
| 黑名单命中 RingBuffer 事件 | 完全静默抑制 | 拦截包不再每包推向用户态 RingBuffer,由 Per-CPU 全局计数覆盖,防止用户态通信通道在洪峰下雪崩。 |
3.5 极轻量的系统资源占用
- 发布产物与依赖:采用
x86_64-unknown-linux-musl纯静态编译,单二进制即可运行,零外部动态库或运行时依赖。 - 内嵌控制台前端(Console):内置的 Vue 3 单文件控制台产物仅约239 KB(经过 gzip 压缩后仅约80 KB);放弃了重型可视化图表库(如 ECharts),图表全采用原生内联轻量 SVG 手写组件,做到极低浏览器内存开销。
- 容量与规则规格(严格遵守内核 Verifier 边界):
- 防护项目(Defense Projects):支持精确 IPv4 匹配,上限达8,192 条;
- 端口 ACL:硬上限32 条;
- L7 特征扫描规则:上限8 条(在满足 Linux Kernel 7.0+ Verifier 复杂度上限前提下取得平衡)。
04. 丑话说在前头:它的能力边界在哪里?
作为一个工程项目,我必须对所有使用者诚实,不做虚假夸大:
- 它突破不了物理带宽的极限:如果你的服务器上行带宽只有 1Gbps,而黑客用 10Gbps 的机房大带宽直接把你机房上游的网线打爆了,那么没有任何单机软件能救你,这种依然只能靠运营商或机房清洗中心;
- 它不是全能的 7 层 WAF:XDP 位于数据链路层/网络层初始处,无法处理复杂的 HTTPS 解密和深度业务层防刷(比如爬虫、业务逻辑撞库)。
但它能做到的是:在你的物理带宽没有被绝对打死之前,只要攻击流量涌进这台机器,它就能死死守护住你的宿主机 CPU、内存和 Linux 内核协议栈,确保系统不宕机、SSH 依然秒连、内部服务依然平稳运转!
05. 开源,为了不再妥协
这个项目我命名为XuanArmor(玄甲),寓意为每一台在公网上裸奔的弱小服务器,披上一套坚不可摧的轻量黑甲。
项目采用Apache 2.0 开源协议,完全开放,目前已经迭代到了v0.5.x版本:
- 项目地址:https://github.com/BlkSword/XuanArmor
- 适用场景:
- 无法挂载 CDN 的独立游戏私有服务端(Minecraft、CS、幻兽帕鲁等自建服);
- 海外廉价 VPS / 裸金属服务器的自防御;
- 音视频流媒体、自建代理中继、各类测试节点;
- 个人站长用于兜底源站的“最后一道内生防线”。
写这个项目的初衷,就是想给每一个用心维护项目的普通开发者多一种选择、多一份底气。
当恶意的洪流再次拍打过来时,我希望你不再需要无奈地敲下关服公告,而是可以平静地打开终端或面板,看着拦截计数器疯狂跳动,而你的服务依然岁月静好。
如果你也曾被恶意攻击恶搞折磨过,或者对 Rust、eBPF/XDP 技术感兴趣,欢迎来 GitHub 给我点个 Star,或者提个 Issue / PR,我们一起把这面盾牌打磨得更硬一点!