L7防火墙植入内核
速览
这项技术将L7防火墙直接集成到内核空间,避免了用户态与内核态间的数据拷贝,大幅提升性能。内核态防火墙能更精确分析应用层协议,增强安全防护。该技术对容器网络和云原生环境有重要影响。
AI 深度解读
背景
传统上,对应用层数据(如 HTTP 头部)进行决策的防火墙几乎总是以用户空间代理的形式运行。数据包需要从内核复制到用户空间,重新构建 TCP 流,执行检测引擎,再将结果复制回内核。这种模式尽管可行,但每个请求会带来毫秒级的延迟。很长时间里,在内核中直接对 HTTP 层做决策被认为不切实际,这并非偶然:eBPF 的验证器会拒绝任何无法证明循环一定会终止的程序,这扼杀了大多数本能想到的解析方式。2024 年一项关于 eBPF 中 L7 头部解析的研究只能匹配约 48 字节的有效载荷,远不足以对真实的 HTTP/2 头部块做出决策。然而,近期内核工作已将内核内 L7 匹配能力从几十字节推升至千字节级别,为新的实现方式打开了可能。
核心内容
我们(作者团队)构建了一款防火墙,它利用 eBPF 在内核中做出决策,并将策略编写为 JavaScript 应用。决策时间降至纳秒级,更改策略无需重建、重新部署或重启,且已实际运行在企业级流量前端。
内核决策机制
正常的数据包过滤器基于五元组(源 IP、目的 IP、源端口、目的端口、协议)匹配,即 L3/L4。我们的防火墙则匹配 HTTP/2 内部的值::authority(主机)、User-Agent、源地址,并支持在位于可信负载均衡器后方时解析 X-Forwarded-For 和 PROXY 协议。规则可组合布尔逻辑,例如:
host == "api.example.com" && src in 127.0.0.0/8 && ua ~ "Diffbot"
常见的用途是按 User-Agent 拦截爬虫和代理(如 GPTBot、ClaudeBot、PerplexityBot、curl/ 等),并附加源地址约束。
XDP 钩子
匹配在 XDP 层(NIC 驱动中的 eBPF 钩子)执行,早于内核分配套接字缓冲区、早于数据包触及网络栈。决策(放行或丢弃)直接在此发生。这与学术工作(如 L7FP)不同:L7FP 在套接字层钩住,此时内核已重组 TCP 流并解密 TLS,获得干净的字节流;但 XDP 的早期钩子牺牲了方便性(需自行重组流),却换来了更低的成本——在 XDP 丢弃的数据包永远不会成为套接字缓冲区,也永远不会进入网络栈,这是 Linux 中最廉价的丢弃方式。同时,强制策略位于用户空间之下,即便用户空间进程被攻破也无法悄悄停用防火墙。
策略更新
策略以 JavaScript 编写提交,运行时将其编译成内核程序读取的结构。更新规则只需 git push,无需重建、部署或重启。
Aho-Corasick DFA
为了在验证器限制内高效匹配多个 User-Agent 模式,我们采用了 Aho-Corasick 自动机(DFA)。它逐字节扫描头部,单次遍历即可报告所有命中的模式。扫描时间与头部长度呈线性关系,不随模式数量增加而变慢(10 个模式或 10,000 个模式,头部仍为几百字节,只需一次遍历)。更多规则只会增加表大小,不影响扫描时间。这种结构也是唯一能通过 eBPF 验证器进入内核的形式——验证器只接受能证明循环终止的程序,而一个按字节查表、上限为头部长度的有界循环很容易被验证器接受。反之,逐模式嵌套循环则很难通过验证。
自动机使用 16 位状态 ID,支持最多 32,767 个状态。实际中约可容纳 4,000 个 User-Agent 模式(由于公共前缀压缩,实际容量更大),并已规划扩展至约 16,000 个模式。规则变更时,自动机在后台重新编译(通常数秒完成),然后原子切换,不影响包匹配路径。
性能数据
单核每秒可处理约 500 万个 HTTP/2 头部决策,且该数字不随规则增加而下降。每个决策的开销低于一次系统调用。我们将每包处理时间通过 Prometheus 直方图从内核程序导出:p50 远低于 200 纳秒,p95 约 775 纳秒,p99 通常在 1 微秒以下,高负载下可能升至几微秒;远尾偶有至 3 毫秒的峰值。需要说明的是:这是内核决策时间,而非端到端设备延迟。用户空间检测层因系统调用、拷贝、TCP 重组和调度,每请求消耗毫秒级时间。该数字不直接与供应商公布的端到端延迟比较,且当前数据取自低到中等负载,生产部署正在验证尾延迟在高负载下的表现。
关键要点
- 防火墙在 XDP 层(NIC 驱动 eBPF 钩子)执行 L7 决策,早于套接字缓冲区和网络栈分配。
- 决策基于 HTTP/2 头部字段(:authority、User-Agent、源地址)及 X-Forwarded-For/PROXY 协议,规则支持布尔逻辑组合。
- 策略以 JavaScript 编写,更新通过 git push 完成,无需重建、部署或重启。
- 采用 Aho-Corasick DFA 实现多模式匹配,保证单次扫描、线性时间、不受模式数量影响,且能通过 eBPF 验证器。
- 单核每秒约 500 万次 HTTP/2 头部决策,p50 决策时间 <200 纳秒,p95 <1 微秒(低到中负载)。
- 丢弃数据包在 XDP 完成,跳过内核网络栈,成本极低。
- 自动机有限制(32,767 状态,约 4,000 个模式),但可通过编译时调整扩展至约 16,000 个模式。
- 规则变更采用后台编译+原子切换,不影响当前包匹配。
意义与影响
该工作实质性地推动了内核级应用层防火墙的可行性。过去 L7 防火墙必须依赖用户空间代理,带来毫秒级延迟;而借助 eBPF 和 Aho-Corasick DFA,决策时间降至纳秒级,并将策略变更的部署周期从“重建、重启”压缩为一次 git push。对于需要实时、低延迟过滤的应用(如反爬虫、API 网关),这种设计可以显著降低开销并简化运维。与学术界(ETH Zürich/NYU/Nvidia/Politecnico di Milano 的 L7FP)相比,本方案在 XDP 层更早介入,进一步减少了包处理成本,同时保持策略表达力(通过 JavaScript 编译)。若其尾延迟在高负载下始终保持稳定,则可能成为未来高性能网络安全的范式之一:将应用层策略下沉至内核数据面,同时保留用户空间的便利性。
