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

  1. Start with default rules - Use Falco’s built-in rules first
  2. Tune for your environment - Adjust rules to reduce false positives
  3. Use appropriate priorities - ERROR for critical, WARNING for suspicious
  4. Integrate with SIEM - Send alerts to your security operations center
  5. Regular rule updates - Keep Falco rules current with latest threats
  6. 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