falco必须用ebpf或内核模块,因其需实时捕获系统调用(如execve、openat),而纯用户态方案(auditd/strace)会漏子进程、seccomp限制调用或因调度延迟丢事件。

为什么 Falco 必须用 eBPF 或内核模块,而不是纯用户态方案
Falco 的核心能力依赖于对系统调用(execve、openat、connect 等)的实时捕获,这在 Linux 上无法绕过内核——纯用户态工具(比如基于 auditd 或 strace 模拟)会漏掉容器进程 fork 后的子进程、被 seccomp 限制的调用,或因调度延迟导致事件丢失。Falco 默认优先尝试加载 eBPF 探针(falco-bpf-probe),失败时回退到 Sysdig 内核模块(falco.ko)。若你看到日志里反复出现 Failed to load eBPF probe 或 could not load kernel module,说明 Falco 实际处于“降级模式”,可能完全不工作。
常见原因包括:
- 内核版本太旧(e.g. CentOS 7 默认的 3.10 不支持部分 required eBPF 功能)
- 禁用了
CONFIG_BPF_SYSCALL=y或CONFIG_BPF_JIT=y - 容器运行时(如 containerd)启用了
no-new-privileges=true,阻止了--privileged权限生效
helm install falco 后 pod 一直 CrashLoopBackOff 怎么办
这是最常遇到的部署失败现象,本质是 Falco 守护进程启动后无法完成初始化。先用 kubectl logs -n falco deployment/falco --previous 查看上一轮崩溃日志,重点关注三类错误:
-
unable to find kernel headers:Kubernetes 节点缺少linux-headers-$(uname -r),需在每个节点手动安装(Ubuntu/Debian 用apt-get install linux-headers-$(uname -r);RHEL/CentOS 用yum install kernel-devel-$(uname -r)) -
failed to open /dev/falco0: no such device:eBPF 探针加载失败且内核模块也未 fallback 成功,检查kubectl get nodes -o wide确认节点内核是否统一,混合内核版本集群必须为每种内核单独构建falco-bpf-probe -
cannot create directory /etc/falco: permission denied:Helm chart 中securityContext.privileged: true未生效,确认节点 CRI 配置未全局禁用 privileged 容器(例如 containerd 的unmask或no_new_privs设置)
自定义规则里 fd.sip.name 为什么经常为空
fd.sip.name 是 Falco 从 DNS 解析缓存中反查得到的域名,它**不等于**原始 connect() 系统调用传入的 IP 地址或主机名。只有当连接建立后、内核完成 reverse DNS 查询(且该查询命中本地缓存或成功返回),fd.sip.name 才会被填充。因此以下情况它必然为空:
- 目标服务使用私有 IP(如
10.96.0.1)且未配置内部 DNS 反查 - 容器内
/etc/resolv.conf配置错误,或 DNS 请求超时丢弃 - 连接是 UDP(如 DNS 自身查询),
fd.sip.name不触发解析
替代方案是直接匹配 fd.sip(IP)或 fd.cip(客户端 IP),再结合外部威胁情报库做离线比对;若必须用域名,应改用 proc.cmdline contains "curl" + fd.sip.name exists 组合过滤,避免空值导致规则失效。
检测权限提升时 proc.cmdline contains "sudo" 为什么不可靠
仅靠字符串匹配 proc.cmdline 是脆弱的防御方式。攻击者可轻易绕过:
- 用 base64 编码命令:
echo "c3VkbyBsbHM=" | base64 -d | sh - 拆分关键字:
su && do或用变量拼接:cmd="su"; $cmd - 调用绝对路径绕过:
/usr/bin/sudo ls可能被规则忽略(若规则没覆盖全路径)
更健壮的做法是利用 Falco 的原生能力检测 **实际权限变化**:
- 用
evt.type=execve and proc.uid != proc.loginuid捕获 UID 切换(loginuid是登录会话初始 UID) - 加条件
and proc.aname[2] in (sudo, su, pkexec)限定父进程名,减少误报 - 避免只依赖
proc.cmdline,它只是 argv[0] 的字符串快照,不含真实执行上下文
真正难处理的是 setuid 二进制文件(如 /usr/bin/passwd)——它们不带明显关键字,必须靠 proc.euid > proc.uid 这类数值比较才能发现。











