Sooua
登录
返回文章列表
Detection Engineering··11 分钟阅读

在内核拦截还是在用户态告警:Tetragon 与 Falco 的能力边界对比

从架构、事件源、策略 DSL、enforcement 路径到运维约束,逐项拆解 Tetragon 与 Falco 的真实能力边界,给出基于场景的选型判断和落地清单。

在内核拦截还是在用户态告警:Tetragon 与 Falco 的能力边界对比

范围:Linux/Kubernetes 节点运行时检测。版本基线:Tetragon v1.7.0(2026-04-29)、Falco 0.44.0(2026-05-26),均为撰文当日 GitHub 上最新 stable。 立场:本文不评判“谁更好”,而是给出可被工程团队验证的边界条件与选型判断。

一个被滥用的等式:eBPF Runtime Security ≠ 同一种东西

CNCF runtime security 谱系里,Falco、Tetragon、Tracee、KubeArmor 经常被笼统称作“eBPF runtime security tools”。这种归类导致一种常见误读:既然底层都是 eBPF,那么换个工具就只是“规则语法不同”。

但只要打开两个项目的 release notes 和官方文档就能看到本质差异:

  • Falco 0.44.0 的 breaking change 直接 drop gRPC output、drop gVisor engine、drop legacy BPF probe,把事件采集收敛到 kernel module 与 modern BPF 驱动,规则评估和事件富化继续放在用户态 libsinsp。
  • Tetragon v1.7.0 引入 celbpf,让 CEL 表达式在 BPF 程序里直接评估,配合 OverrideNotifyEnforcer 在内核内联完成阻断。

这不是规则语法风格之争,而是“检测在哪里发生、enforcement 在哪里发生”这两个根本问题。本文围绕这两个问题,把架构差异拆成可验证的工程边界。

一、事件采集与评估路径:用户态规则引擎 vs 内核内联策略

两套工具都用 eBPF 拿数据,但拿完之后的链路完全不同。

关键差异落到三件事上:

  1. 事件源粒度。Falco 以 syscall 为中心,由 libsinsp 在用户态拼装出 fd.nameproc.exepathcontainer.id 等高级字段;Tetragon 直接挂 kprobeLSMtracepointuprobe,事件结构由 TracingPolicy 中的 args 显式声明。
  2. 过滤位置。Falco 把过滤交给用户态 DSL,事件先离开内核再被规则匹配;Tetragon 在 BPF 程序里做 selector,过滤不通过的事件根本不进 perf ring buffer。这是 Tetragon v1.7 把 CEL 编译成 BPF 的动机:让复杂判断也尽量留在内核内。
  3. 执行能力。Falco 是检测/告警工具,不做 inline 阻断;Tetragon 通过 Override 改写函数返回值、通过 NotifyEnforcer 发 SIGKILL,能在被 hook 的系统调用/LSM 返回前阻止操作完成。

理解了这点,下面的所有取舍才有意义。

二、策略 DSL:一个像 SIEM,一个像内核策略

Falco 规则面向“事件流匹配”,更接近 SIEM 视角。以官方 falco_rules.yaml 中的 Read sensitive file untrusted 为例(来源:falcosecurity/rules 主分支):

- rule: Read sensitive file untrusted
  desc: An attempt to read any sensitive file ...
  condition: >
    open_read
    and sensitive_files
    and proc_name_exists
    and not proc.name in (user_mgmt_binaries, userexec_binaries,
        package_mgmt_binaries, cron_binaries, read_sensitive_file_binaries,
        shell_binaries, hids_binaries, ...)
    and not cmp_cp_by_passwd
    and not ansible_running_python
    ...
  output: Sensitive file opened for reading by non-trusted program | file=%fd.name ...
  priority: WARNING
  tags: [maturity_stable, host, container, filesystem, mitre_credential_access, T1555]

这段规则的两个特征对工程实践影响最大:

  • 大量信任列表(信任进程豁免)来抑制误报。这是用户态后置过滤的代价,也是 Falco 规则维护的主要工作量来源。
  • MITRE 标签与 priority 已嵌入规则,方便直接对接 SIEM 与 SOAR。

Tetragon 的 TracingPolicy 走的是另一条路。下面是官方 examples/tracingpolicy/lsm_bprm_check.yaml 的真实片段:

apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
  name: "lsm"
spec:
  lsmhooks:
  - hook: "bprm_check_security"
    args:
      - index: 0
        type: "linux_binprm"
    selectors:
    - matchBinaries:
      - operator: "In"
        values:
        - "/usr/bin/zsh"
        - "/usr/bin/bash"
      matchArgs:
        - index: 0
          operator: "Postfix"
          values:
            - "contrib/tester-progs/nop"
      matchActions:
        - action: Override
          argError: -1
        - action: Post
          imaHash: true

它告诉内核:在 bprm_check_security LSM hook 里,只关心 bash/zsh 启动的、路径后缀匹配的 binary;命中后立刻 Override 返回 -1(EPERM)阻断执行,同时 Post 一条带 IMA 哈希的事件出来。

再看 examples/tracingpolicy/killer.yaml 中的 enforcement:

spec:
  lists:
  - name: "dups"
    type: "syscalls"
    values: ["sys_dup", "sys_dup2", "__ia32_sys_dup"]
  enforcers:
  - calls: ["list:dups"]
  tracepoints:
  - subsystem: "raw_syscalls"
    event: "sys_enter"
    args:
    - index: 4
      type: "syscall64"
    selectors:
    - matchArgs:
      - index: 0
        operator: "InMap"
        values: ["list:dups"]
      matchBinaries:
      - operator: "In"
        values: ["/usr/bin/bash"]
      matchActions:
      - action: "NotifyEnforcer"
        argError: -1
        argSig: 9

两件事很清晰:

  • selector 完全是“内核 API + 进程身份”的组合,没有 Falco 那种高层 sensitive_files 宏;要写好这种策略,需要懂 LSM hook 名、kprobe 函数签名、参数类型。
  • Cilium 在 2025 年 9 月的 “Linux Kernel Fundamentals for Tetragon” 博客里专门提醒:syscall kprobe 在不同架构上挂点不同,要么用 syscall: true 抽象、要么自己列出 __x64_sys_* 等架构前缀。这意味着 TracingPolicy 的可移植性需要写作者主动维护。
  • 1.7 新增的 matchParentBinaries(PR #4254)允许把过滤条件落到父进程二进制,对“apt-key 调 /usr/bin/chmod 调 chmod 系统调用”这类多层嵌套场景做精确排除,而不是粗暴 ignore 整个 chmod 调用。Falco 处理类似问题通常依赖更长的信任列表。

两套 DSL 的差异可以用一张表概括:

维度Falco 规则 (falco_rules.yaml)Tetragon TracingPolicy
抽象层级高级字段 + 命名宏(open_readsensitive_files内核 hook 名 + 参数 index + 类型
过滤位置事件出内核后,在用户态规则引擎评估在 BPF 程序内 selector / CEL-BPF 评估
父进程过滤proc.aname[N] + 信任进程列表matchParentBinaries(1.7+ 原生 selector)
MITRE / 输出tagspriorityoutput 直接在规则中定义需要外部映射;事件以 process_kprobeprocess_tracepoint 等形式输出
阻断能力不内置 inline 阻断(设计上是检测告警工具)Override 改返回值、NotifyEnforcer 发信号
适合写规则的人安全运营 / 检测工程师内核熟手 / 平台安全工程师

把这张表反过来读就是选型建议:要让 SRE/安全运营自己维护规则,Falco 上手成本明显更低;要做内核内联拦截或精确父子进程过滤,Tetragon 不可替代。

三、Enforcement 真实路径:Override 与 NotifyEnforcer 不是“通用按钮”

Tetragon 的官方 Enforcement 文档明确写出两种执行路径的前提条件:

  • Override 仅在“函数允许被 bpf_override_return 改写”时可用,典型场景是 LSM hook 和被 ALLOW_ERROR_INJECTION 注解的 kprobe,需要内核 CONFIG_BPF_KPROBE_OVERRIDE=y
  • NotifyEnforcer 通过 BPF helper 给当前任务发信号(如 SIGKILL),最早的可阻断时机依赖被 hook 的位置。如果 hook 挂在系统调用入口(sys_enter)后才能终止进程,那么部分副作用可能已经发生。

这意味着 Tetragon 的 inline enforcement 不是给任何系统调用都能加的“防火墙按钮”,它的可执行范围被三件事限制:

  1. 钩子是否在“真正能拒绝操作”的位置(LSM 在 access check,kprobe 在内核函数早期)。
  2. 内核构建是否打开了相关能力(KPROBE_OVERRIDE、LSM eBPF 等)。
  3. 策略命中后续动作是否完整(例如对长 syscall 路径,NotifyEnforcer 杀进程并不等价于回滚已发生的 I/O)。

对运维来说,重要的不是“能不能阻断”,而是“在哪种 hook、哪个内核版本、哪种发行版上可以稳定阻断”。生产环境用 Tetragon 做 enforcement 前,至少要先确认:

# 1. 内核是否启用 BTF(modern eBPF 与 CO-RE 的前提)
ls /sys/kernel/btf/vmlinux
 
# 2. 内核是否打开了 KPROBE 覆盖
grep CONFIG_BPF_KPROBE_OVERRIDE /boot/config-$(uname -r)
 
# 3. LSM eBPF 是否在 lsm 链中(5.7+ 引入,发行版会裁剪)
cat /sys/kernel/security/lsm

这三条命令不是“万能体检”,但它们决定了一条策略能不能从 Post 升级到 OverrideNotifyEnforcer没有这些前提,Tetragon 退化为一个更贴近内核的检测工具,enforcement 部分形同虚设。

四、性能与运维:用户态 ring buffer vs 内核内联过滤

学术综述(如 2025 IEEE Access 的 “An In-Depth Analysis of eBPF-Based System Security Tools in Cloud Environments”)对 Falco、Tetragon、Tracee、KubeArmor 都做了实验对照,结论的工程含义可以这样总结,需注意论文实验环境无法直接外推到生产集群:

  • 高频 syscall 场景下,Falco 的开销主要来自 ring buffer 拷贝和 libsinsp 状态机;规则越宽(如直接匹配 open_read),用户态 CPU 占用越明显,对应规则越收敛,开销下降越快。
  • Tetragon 在 BPF 内做 selector,对于“窄目标”的策略(只关心一两个 hook + 一组进程)几乎零额外用户态开销;但策略一旦覆盖大量 kprobe,BPF verifier 验证时间和内核态栈消耗会上升,错误策略可能直接被拒绝加载。
  • 两者都受 perf ring buffer 大小、节点 CPU 拓扑影响;任何 “实测开销小于 X%” 的结论都必须配上工作负载特征。

运维层面还有几个容易忽视但很重要的差异:

运维维度FalcoTetragon
规则热加载支持,重新加载规则文件TracingPolicy CRD 热加载 / 卸载,可用 kubectl 或 tetra gRPC
多源事件通过 plugin(k8saudit、cloudtrail 等)接入审计/云日志主要面向 Linux 内核事件,跨平面整合通常靠外部 SIEM
升级影响0.44 删除 legacy BPF probe、gRPC output、gVisor,需评估部署变更1.7 改默认 server-address 为 unix socket,第三方接入需更新
与 K8s 的关系默认 host 视角,依赖 container plugin 富化原生 K8s 感知(namespace、pod、labels),通过 spec.hostSelector 等做主机维度限定

把这些差异叠加,会得到一个很现实的判断:在大多数 K8s 节点上跑“检测一切异常 syscall” 的目标本身就不成立。要么把 Falco 规则收敛到关键资产,要么把 Tetragon 策略限定到具体 hook 与具体进程身份。

五、按场景选型:基于真实约束的判断

把上面的能力边界翻译成场景:

更工程化的判断准则:

  • 检测需要语义高 + 与现有 SIEM 对齐:选 Falco。它的规则可读性、MITRE 标签和插件生态在 SOC 工作流里更顺。
  • 要在内核就把动作挡掉,且能接受规则编写门槛:选 Tetragon。但要把可阻断 hook 列表、内核 config 校验、灰度路径写进运维 SOP。
  • 以上两者都要:在同一节点共存是可行的,因为两者使用不同 BPF 程序,但需要做三件事:限定各自策略范围避免重复事件、统一事件 schema(通常落到 SIEM 端做归一)、为 enforcement 留下明确的关停开关,防止策略误杀关键负载。
  • 节点不支持 BTF / modern BPF(老内核、特殊发行版):Falco 仍可走 kernel module 路径,Tetragon 的多数 selector 也需要 BTF;优先升级内核或承认能力受限。

结论

在内核拦截还是在用户态告警,不是一个非此即彼的选择。Falco 适合已知威胁的实时检测,Tetragon 适合需要执行干预的纵深防御。关键判断在于:你的团队有没有能力维护内核探针、治理误报、并在 enforcement 场景下承担误杀风险。如果没有,先从 detection-only 开始,把可观测性建起来再谈拦截。

七、结论与待验证项

把全篇收回到一句判断:Tetragon 与 Falco 不是竞品意义上的二选一,而是同一栈里两层不同的能力。

  • Falco 是“事件流上的检测引擎”,强项是规则可读性、生态插件和与 SOC 工作流的对齐。
  • Tetragon 是“在内核内联表达策略并可执行的工具”,强项是过滤与阻断都贴近内核,对内核构建与规则编写门槛要求更高。
  • 当问题是“我该告警谁”时,Falco 优先;当问题是“我必须在系统调用返回前挡住它”时,Tetragon 优先。

待验证项(适合作为后续实验记录的下一篇主题):

  1. 在同一 K8s 节点同时部署 Falco 0.44 与 Tetragon 1.7,针对一组合成攻击行为(/etc/shadow 读、/usr/bin/chmod 提权链)测量两者的事件覆盖率与重复率。
  2. 量化 Tetragon OverrideNotifyEnforcer 在不同 hook 位置的“可阻断时机”差异:到底哪些 LSM hook 能挡住 mmap 写、哪些 kprobe 只能在调用后期 SIGKILL。
  3. 用真实生产 syscall 分布(例如 cAdvisor 或自带 perf 采样)评估两套工具在同一节点上的合计开销,而不是单独基准。

这些都需要实测数据,本文不做估计。

分享

评论

登录 后参与讨论。

加载中…

相关文章