Falco
Falco is an open-source runtime security tool that monitors system calls and container behavior to detect threats in real-time. It’s like having a security guard watching every system call your containers make, alerting you when something suspicious happens.
What is Falco?
Falco uses the Linux kernel’s audit subsystem and eBPF to monitor:
- System calls made by containers
- File system access
- Network activity
- Process execution
- Privilege escalations
When Falco detects behavior matching its rules, it generates alerts that can be sent to various destinations.
How Falco Works
flowchart TD
A[Container Process] --> B[Makes System Call]
B --> C[Linux Kernel]
C --> D[Falco Engine]
D --> E{Matches Rule?}
E -->|Yes| F[Generate Alert]
E -->|No| G[Continue Monitoring]
F --> H[Send to Output]
H --> I[SIEM/Logging/Webhook]
style A fill:#e1f5ff
style D fill:#fff4e1
style F fill:#ffebee
style I fill:#e8f5e9
Installing Falco
Using Helm
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm repo update
helm install falco falcosecurity/falco
Using Falco Operator
kubectl create namespace falco-system
kubectl apply -f https://raw.githubusercontent.com/falcosecurity/falco-operator/main/deploy/falco-operator.yaml
DaemonSet Installation
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: falco
namespace: falco
spec:
selector:
matchLabels:
app: falco
template:
metadata:
labels:
app: falco
spec:
hostNetwork: true
hostPID: true
containers:
- name: falco
image: docker.io/falcosecurity/falco:latest
securityContext:
privileged: true
volumeMounts:
- name: falco-config
mountPath: /etc/falco
- name: sys
mountPath: /host/sys
readOnly: true
volumes:
- name: falco-config
configMap:
name: falco-config
- name: sys
hostPath:
path: /sys
Falco Rules
Falco uses YAML-based rules to define what constitutes suspicious behavior.
Basic Rule Structure
- rule: Shell Spawned in Container
desc: Detect shell execution in containers
condition: >
spawned_process and container and
shell_procs and proc.tty != 0 and
not container_entrypoint
output: >
Shell spawned in container (user=%user.name %container.info
shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline)
priority: WARNING
tags: [container, shell, mitre_execution]
Common Falco Rules
Detect Shell in Container
- rule: Detect shell spawned in container
desc: Alert when a shell is executed in a container
condition: >
spawned_process and container and
shell_procs and proc.tty != 0
output: >
Shell spawned in container (user=%user.name container=%container.name
shell=%proc.name parent=%proc.pname)
priority: WARNING
Detect File Modification
- rule: Write below binary dir
desc: Detect writes to binary directories
condition: >
bin_dir and evt.type = write and
container and not exe_running_docker_save
output: >
File below a known binary directory opened for writing
(user=%user.name command=%proc.cmdline file=%fd.name
container=%container.name)
priority: ERROR
Detect Network Anomaly
- rule: Outbound connection to suspicious port
desc: Detect connections to suspicious ports
condition: >
outbound and container and
fd.sport in (4444, 5555, 6666)
output: >
Outbound connection to suspicious port
(user=%user.name container=%container.name
connection=%fd.name)
priority: WARNING
Custom Rules
Create custom rules for your environment:
# custom-rules.yaml
- rule: Unauthorized database access
desc: Detect database access from unexpected containers
condition: >
spawned_process and container and
proc.name in (mysql, psql, mongosh) and
not container.name in (db-client, admin-tool)
output: >
Unauthorized database access
(user=%user.name container=%container.name
process=%proc.name)
priority: ERROR
Load custom rules:
apiVersion: v1
kind: ConfigMap
metadata:
name: falco-custom-rules
namespace: falco
data:
custom_rules.yaml: |
- rule: Unauthorized database access
desc: Detect database access from unexpected containers
condition: >
spawned_process and container and
proc.name in (mysql, psql, mongosh) and
not container.name in (db-client, admin-tool)
output: >
Unauthorized database access
(user=%user.name container=%container.name
process=%proc.name)
priority: ERROR
Falco Outputs
Falco can send alerts to multiple destinations:
File Output
file_output:
enabled: true
keep_alive: false
filename: /var/log/falco_events.log
Syslog Output
syslog_output:
enabled: true
HTTP Output
http_output:
enabled: true
url: "http://webhook.example.com/falco"
Kubernetes Audit Logs
k8s_audit_endpoint: "http://localhost:8080/audit"
Integration Examples
Send to Slack
program_output:
enabled: true
program: "jq '{text: .output}' | curl -X POST -H 'Content-Type: application/json' -d @- https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
Send to Elasticsearch
json_output: true
json_include_output_property: true
json_include_tags: true
program_output:
enabled: true
program: "curl -X POST http://elasticsearch:9200/falco/_doc -H 'Content-Type: application/json' -d @-"
Best Practices
- Start with default rules - Use Falco’s built-in rules first
- Tune for your environment - Adjust rules to reduce false positives
- Use appropriate priorities - ERROR for critical, WARNING for suspicious
- Integrate with SIEM - Send alerts to your security operations center
- Regular rule updates - Keep Falco rules current with latest threats
- Monitor performance - Ensure Falco doesn’t impact workload performance
Troubleshooting
Check Falco Status
kubectl get pods -n falco
kubectl logs -n falco -l app=falco
Test Rules
# Trigger a test event
kubectl run test-pod --image=alpine --rm -it -- sh
# Inside the container, run a command that should trigger a rule
/bin/sh
View Falco Events
# If using file output
kubectl exec -n falco falco-<pod-name> -- tail -f /var/log/falco_events.log
See Also
- Runtime Security - Overview of runtime security
- KubeArmor - Policy-based runtime protection
- eBPF-based Security - eBPF security solutions