Falco is a runtime security tool that detects anomalous activity on your Linux hosts.
Here’s Falco in action, monitoring a containerized application and flagging a suspicious exec call:
{
"output": "09:03:33.130858875: 1.188497048: Rule 'Command executed in container' triggered",
"priority": "warning",
"rule": "Command executed in container",
"time": "2023-10-27T09:03:33.130858875Z",
"output_fields": {
"container.id": "a1b2c3d4e5f6",
"container.name": "my-app-container",
"fd.name": "/bin/bash",
"proc.cmdline": "/bin/bash -c 'echo hello'",
"proc.name": "bash",
"proc.pid": 12345,
"user.name": "root"
},
"source": "syscall"
}
Falco operates by inspecting kernel system calls (syscalls) and other system events. It compares these events against a set of predefined rules, often referred to as Falco rules. When an event matches a rule, Falco generates an alert. The power of Falco lies in its ability to detect behaviors that deviate from the norm, such as unexpected process executions within containers, file modifications in sensitive directories, or network connections to unusual destinations.
The core components of Falco are:
- Falco Kernel Module (or eBPF Probe): This is the critical piece that intercepts syscalls at the kernel level. You can choose between a loadable kernel module (LKM) or an eBPF probe. eBPF is generally preferred for its security and ease of deployment, as it doesn’t require recompiling kernel modules.
- Falco Daemon: This is the userspace component that receives the event data from the kernel module/probe, parses it, and evaluates it against the loaded rules.
- Falco Rules: These are YAML files that define the detection logic. They specify which events to look for, under what conditions, and what action to take (e.g., log, alert).
To install Falco on a Linux host, you’ll typically use a package manager or a convenience script. For Debian/Ubuntu systems:
sudo apt-get update
sudo apt-get install -y falco
For RHEL/CentOS/Fedora systems:
sudo yum install -y falco # or dnf install -y falco
Alternatively, the official convenience script is a common way to get started:
curl -s https://falco.org/script/install.sh | bash
After installation, Falco will usually start automatically. You can check its status with systemctl status falco.
The rules themselves are highly configurable. You can find the default rules in /etc/falco/falco_rules.yaml and /etc/falco/falco_rules.local.yaml (where you can add your custom rules). A basic rule might look like this:
- rule: Unexpected shell in container
desc: A shell was run inside a container, which might be suspicious.
condition: >
container and proc.name in (sh, bash, zsh, ksh) and proc.args contains "-c"
output: Unexpected shell ({{.proc.name}}) run in container ({{.container.name}}). Cmdline: {{.proc.cmdline}}
priority: warning
source: syscall
This rule triggers if a shell process (sh, bash, zsh, ksh) is executed within a container (container), and the command line arguments contain -c (indicating a command was executed directly, not just an interactive shell). The output field then formats a human-readable message.
The real magic happens when you combine Falco with other tools. For instance, integrating Falco with Kubernetes allows it to enrich alerts with Kubernetes metadata, such as pod names, namespaces, and labels, making it much easier to pinpoint the source of an issue. This is often achieved by running Falco as a DaemonSet in Kubernetes.
The most surprising thing about Falco is how much it can tell you about system activity without needing to instrument every single application. By tapping directly into the kernel’s view of the world, it can uncover threats that might otherwise be invisible, especially in complex, containerized environments where traditional security tools struggle to keep up.
One area that often trips people up is the container.id field. When Falco is running in a containerized environment, like Kubernetes, it needs to correctly identify which container an event originates from. The container.id field will contain the full Docker/OCI container ID. If Falco itself is running in a container (as is common in Kubernetes), it uses its own container ID to distinguish its own events from those it’s monitoring within other containers. Understanding this distinction is key to correctly filtering and attributing alerts.
The next logical step after getting Falco running is to explore advanced rule writing and integrating it with a SIEM for centralized logging and alerting.