Zurück zum Blog
Security
FortgeschrittenFürPlatform EngineersSecurity EngineersSRE
9 min

Falco in Produktion: Runtime-Security ohne Alarm-Flut

Falco zu installieren dauert zehn Minuten. Es nützlich zu machen dauert Monate. Ein praxisnaher Leitfaden für Runtime-Security, die den Produktionsalltag überlebt — Regel-Reifegrade, Rauschen abbauen und worauf man wirklich alarmiert.

falcoruntime securitykubernetes sicherheitebpfalarm müdigkeitcncf
Inhalt

Falco ist in etwa zehn Minuten installiert. Ein Helm-Chart, und binnen einer Minute fließen Alarme.

Dann kommt die zweite Woche, im Kanal stehen viertausend Meldungen, und jemand stellt ihn stumm. Im dritten Monat erinnert sich niemand mehr daran, dass Falco läuft.

Genau diesen Teil überspringen die Einstiegsanleitungen. Runtime-Security auszurollen ist trivial; sie zu betreiben ist die eigentliche Arbeit — und die besteht vor allem darin, zu entscheiden, wovon man nichts hören will.

Falco beobachtet Syscalls zur Laufzeit — die Schicht, die sieht, was nach der Freigabe durch Scanner und Admission Controller passiert.

Was Falco tatsächlich ist

Falco ist ein CNCF-Graduated-Projekt, ursprünglich von Sysdig gebaut. Es liest Linux-Systemaufrufe direkt aus dem Kernel, prüft diesen Strom gegen eine Regel-Engine und alarmiert bei einem Treffer.

Eine Regel sieht so aus (vereinfacht — die ausgelieferte Fassung trägt noch ein paar Schutzbedingungen mehr):

- rule: Terminal shell in container
desc: A shell was used as the entrypoint/exec target in a container
condition: >
spawned_process and container
and shell_procs and proc.tty != 0
output: >
A shell was spawned in a container
(user=%user.name container=%container.name image=%container.image.repository)
priority: NOTICE
tags: [container, shell, mitre_execution]

Falco reichert das rohe Kernel-Ereignis mit Container- und Kubernetes-Metadaten an, sodass der Alarm Pod, Namespace und Image nennt — nicht nur eine PID.

Heute werden zwei Treiber unterstützt: die moderne eBPF-Probe (Standard, auf CO-RE basierend, ohne Kernelmodul) und ein Kernelmodul. Über Syscalls hinaus holt ein Plugin-System weitere Quellen herein — Kubernetes-Audit-Logs, CloudTrail, Okta.

Warum es diese Schicht braucht

Wahrscheinlich hast du bereits Scanner. Falco leistet etwas, das diese strukturell nicht können.

Warum es diese Schicht braucht
Schicht Werkzeug Zeitpunkt Beantwortete Frage
IaC Checkov, tfsec vor dem Deployment ist das schlecht konfiguriert?
Images Trivy, Grype vor dem Deployment steckt eine bekannte CVE drin?
Admission Kyverno, OPA beim Erzeugen darf das überhaupt existieren?
Laufzeit Falco, Tetragon durchgehend was tut es gerade?

Jede Schicht oberhalb der Laufzeit bewertet ein Artefakt. Falco bewertet Verhalten.

Dieser Unterschied zählt, weil eine Workload jedes Gate vor dem Deployment passieren und zur Laufzeit trotzdem kompromittiert werden kann — über eine Schwachstelle ohne Signatur, geleakte Zugangsdaten oder einen Lieferkettenpfad, der beim Scan sauber aussah. Dasselbe Argument habe ich dazu gemacht, warum eine SBOM allein das nächste Log4j nicht stoppt: Zu wissen, was in der Kiste ist, sagt nichts darüber, was die Kiste im Betrieb tut.

Falco ist die Schicht, die bemerkt, dass ein völlig sauberer Container plötzlich eine Binärdatei zieht und ausführt.

Vier Sicherheitsschichten: IaC, Image-Scanning und Admission Control bewerten Artefakte; nur Runtime-Erkennung bewertet Verhalten.

Das Rauschproblem, ehrlich benannt

Hier kommt, was die meisten Beiträge verschweigen und was das Falco-Projekt selbst offen sagt:

„Der Reifegrad der Regeln spiegelt jedoch nicht direkt ihr Potenzial wider, in der Umgebung der Anwender Rauschen zu erzeugen. Das liegt an der einzigartigen und sich ständig verändernden Natur jeder Umgebung, insbesondere in Cloud-Umgebungen, was es schwierig macht, die Wirkung von Regeln genau vorherzusagen.“

Das lohnt ein zweites Lesen, denn es ist der ehrliche Kern des Themas. Niemand kann dir vorab sagen, welche Regeln bei dir laut sein werden. Weder das Projekt noch ein Hersteller noch ein Blogbeitrag. Dein Normalzustand gehört dir allein.

Nimm „Terminal shell in container“ — eine wirklich wertvolle Erkennung. Und nun überlege, was in einem echten Cluster routinemäßig Shells startet:

  • Betreiber, die mit kubectl exec debuggen
  • CI-Jobs mit Debug-Containern
  • Init-Container, deren Entrypoint /bin/sh -c ist
  • Health-Checks als Shell-Skripte
  • Backup-, Migrations- und Cron-Jobs

Die Regel ist nicht falsch. Sie beschreibt etwas allgemein Verdächtiges, das in deinem Cluster völlig gewöhnlich ist. Multipliziere das über Dutzende Standardregeln, und du hast viertausend Meldungen pro Woche.

Das Rauschen ist kein Fehler. Es ist die unvermeidliche Lücke zwischen generischer Erkennungslogik und deiner konkreten Umgebung. Diese Lücke zu schließen ist deine Aufgabe — und genau die kann dir das Werkzeug nicht abnehmen.

Standardregeln beschreiben allgemein verdächtiges Verhalten, das in einem konkreten Cluster oft völlig normal ist — die Lücke musst du schließen.

Das Rules Maturity Framework

Das Projekt liefert eine Einordnung mit, die wirklich hilft, sobald man von ihr weiß.

maturity_stable — der Standardsatz. Breite Erkennungen auf Systemebene, ausgerichtet an MITRE ATT&CK: Remote Code Execution, Container-Ausbrüche, Netzwerk-Pivots, Rechteausweitung, Diebstahl von Zugangsdaten. Hier anfangen, und zunächst nur hier.

maturity_incubating — spezifischere Erkennungen. Im richtigen Kontext wertvoller, deutlich aufwendiger zu bewerten.

maturity_sandbox — experimentell. Breitere oder engere Abdeckung, höchster Engineering-Aufwand.

Der empfohlene Ablauf aus der Dokumentation:

  1. Nur stabile Regeln fahren
  2. Gegen echten Traffic tunen und dabei den Performance-Overhead messen
  3. Erst wenn Fehlalarme niedrig und dauerhaft niedrig sind, Incubating oder Sandbox ergänzen
  4. Früh eigene Regeln für das schreiben, was bei dir einzigartig ist
  5. Plugins prüfen, falls weitere Ereignisquellen zum Ökosystem passen

Beachte, was das Framework nicht behauptet: Reife beschreibt die Einführungsreife, nicht die Ruhe. Auch eine stabile Regel kann dich fluten.

Tunen, ohne blind zu werden

Vier Schritte, nach Wirkung geordnet.

1. Erst beobachten, dann alarmieren

Lass Falco laufen und schicke alles in ein Log — nicht in einen Kanal, den jemand lesen soll. Gib ihm eine volle Woche, inklusive Deployment, Störung und Wochenende.

Du suchst keine Angriffe. Du erstellst ein Inventar deines Normalzustands. Diese Woche Daten ist mehr wert als jede Überlegung, welche Regeln laut sein „müssten“.

2. Ausnahmen schreiben statt Regeln abschalten

Der Reflex bei einer dauerfeuernden Regel ist, sie abzuschalten. So verschwindet Abdeckung stillschweigend.

Falco unterstützt Ausnahmen und Regel-Overrides genau dafür, damit der bekannte Gut-Fall herausgeschnitten wird und die Erkennung für alles andere bestehen bleibt:

# wird NACH der Standard-Regeldatei geladen
- rule: Terminal shell in container
exceptions:
- name: known_debug_images
fields: container.image.repository
comps: in
values: [company/debug-toolkit, company/migration-runner]
override:
exceptions: append

Zwei Details, über die viele stolpern. Der override-Block ist nicht optional — ohne ihn behandelt Falco den Eintrag als vollständige Neudefinition der Regel und bricht ab, weil desc, condition und output fehlen. Und die Ladereihenfolge zählt: Deine eigene Datei muss in rules_files nach falco_rules.yaml stehen, sonst greift das Override auf eine Regel zu, die es noch gar nicht gibt.

Jetzt greift die Regel weiterhin bei einer Shell im Zahlungsdienst. Sie schweigt nur beim Debug-Image, das dein Team bewusst betreibt.

Die Dokumentation bittet zudem darum, spezifisch zu sein — lieber Akteur und Ziel als ein einzelnes breites Feld, damit eine Ausnahme nicht zum Versteck wird. Viele Standardregeln stellen dafür eigene user_known_*-Makros bereit, die genau zum Überschreiben gedacht sind; das ist oft der sauberste Ansatzpunkt.

Die Disziplin dahinter: Jede Ausnahme ist eine dokumentierte Aussage über deine Umgebung. Schreib das Warum dazu, damit die nächste Person nicht raten muss, ob es eine Entscheidung oder ein Versehen war.

3. Nach Schweregrad routen, nicht nach Standard

Alles in einen Slack-Kanal zu schicken ist der schnellste Weg, Falco nutzlos zu machen. Trenne es:

3. Nach Schweregrad routen, nicht nach Standard
Priorität Ziel Beispiel
Critical / Error Pager Container-Ausbruchsversuch, Schreiben nach /etc/shadow
Warning Ticket-Queue unerwartete ausgehende Verbindung
Notice / Info nur Log, durchsuchbar Shell im Container, Paketmanager-Aufruf

falcosidekick existiert genau dafür — es nimmt die Falco-Ausgabe und verteilt sie auf mehr als 50 verschiedene Ziele. Falco selbst schreibt nach stdout, in eine Datei, an Syslog, an ein gestartetes Programm oder an einen HTTP-Endpunkt; die Verteillogik liegt im Forwarder.

Der Test ist simpel: Würdest du dafür jemanden um drei Uhr nachts wecken? Wenn nein, gehört es nicht auf einen Pager. Und wenn nichts jemanden wecken würde, hast du Monitoring, keine Erkennung.

4. Eigene Regeln für die Kronjuwelen

Die Dokumentation empfiehlt das früh, und es ist die Arbeit mit der höchsten Signalqualität.

Generische Regeln beschreiben generische Bedrohungen. Du aber weißt Dinge, die Falco nicht wissen kann: welche Pfade deine Secrets halten, welcher Dienst das Kronjuwel ist, wie dessen Ausführungsmuster an einem normalen Dienstag aussieht.

- rule: Access to payment signing key
desc: Anything reading the payment service signing key outside the signer
condition: >
open_read and fd.name startswith /etc/payments/keys
and not proc.name in (payment-signer)
output: >
Signing key accessed by unexpected process
(proc=%proc.name container=%container.name)
priority: CRITICAL
tags: [custom, crown_jewel]

Eine solche Regel schlägt zwanzig generische. Sie hat nahezu keine Fehlalarme, weil sie Wissen kodiert, das nur du hast — und wenn sie auslöst, stimmt wirklich etwas nicht.

Eine Falle, die man kennen sollte: proc.name wird vom Kernel nach 16 Zeichen abgeschnitten, nicht von Falco. Passt du auf einen längeren Binärnamen, löst die Bedingung stillschweigend nie aus. Bei langen Namen proc.exepath verwenden.

Nach Schweregrad routen: nur wirklich handlungsrelevante Regeln erreichen einen Pager, alles andere geht in ein durchsuchbares Log.

Das Gespräch über Performance

Falco verarbeitet einen Strom von Kernel-Ereignissen, die Kosten skalieren also mit dem Syscall-Volumen. Ein ausgelasteter Node mit Millionen Syscalls pro Sekunde kostet mehr als ein leerer.

Kommt der Agent nicht hinterher, verwirft er Ereignisse — das ist zugleich ein Performance-Symptom und eine Erkennungslücke. Die Dokumentation hat dafür eine eigene Troubleshooting-Seite, was zeigt, wie verbreitet das ist.

Drei praktische Hinweise:

  • An den eigenen Workloads messen. Veröffentlichte Benchmarks beschreiben fremde Cluster.
  • Gezielt erfassen. Du brauchst nicht jeden Syscall, um das Relevante zu erkennen; die Erfassung zu tunen ist meist billiger, als den Node zu vergrößern.
  • Das Budget ernst nehmen. Das Projekt beschreibt Security-Monitoring als praktisch budgetbegrenzt — zu Recht. Ein Agent, der Workloads ausbremst, wird entfernt, und dann hat man gar keine Erkennung mehr.

Wie „fertig“ aussieht

Die Dokumentation beschreibt den vollständigen Betrieb als Alarm-Triage plus vordefinierte Runbooks im Incident-Response-Prozess. Das ist die ehrliche Messlatte, und sie liegt höher als „es kommen Alarme an“.

Eine realistische Definition von funktionierend:

  • Der Alarmstrom ist klein genug, dass ein Mensch ihn auch im dritten Monat noch liest
  • Jede Regel, die jemanden anpiept, hat ein Runbook mit klarer Handlungsanweisung
  • Ausnahmen sind dokumentiert, mit Begründung
  • Jemand prüft regelmäßig, ob die Kette noch durchgängig funktioniert — Falco protokolliert, Transport läuft, Ziel empfängt, Triage greift
  • Für die Assets, um die es dir wirklich geht, existieren eigene Regeln

Der letzte Punkt zur Überprüfung wiegt schwerer, als er klingt. Eine Erkennungskette, die vor drei Monaten still kaputtgegangen ist, sieht exakt aus wie eine ruhige Umgebung.

Die unbequeme Wahrheit

Ein Alarm, den niemand liest, ist schlechter als kein Alarm, weil er die Illusion von Abdeckung erzeugt. Man besteht die Audit-Frage — „habt ihr Runtime-Erkennung?“ — und hat praktisch keine.

Der eigentliche Maßstab ist also nicht, wie viele Regeln aktiviert sind. Sondern ob im Ernstfall jemand innerhalb einer Stunde etwas bemerkt.

Dorthin kommt man, indem man weniger Regeln aktiviert als möglich, härter tunt als es sich nötig anfühlt, und akzeptiert, dass ein ruhiges, vertrauenswürdiges Signal eine vollständige Abdeckung schlägt, die alle ignorieren.

Falco ist ein wirklich gutes Werkzeug, und die Laufzeitschicht deckt fast niemand sonst ab. Es kommt nur nicht fertig — es kommt als rohe Fähigkeit, die deine Umgebung erst formen muss.

Wer die Plattform drumherum baut, findet dasselbe Prinzip in Secure-by-Default-GKE und Platform Engineering auf Kubernetes: Die Kontrolle, die wirkt, ist die, an die niemand denken muss — oder in diesem Fall die, die niemand zu ignorieren lernt.

Das Fazit

Falco sieht, was Scanner und Admission Controller strukturell nicht sehen können: Verhalten, während es passiert. Das macht den Betrieb lohnend.

Aber der Standardregelsatz ist ein Ausgangspunkt, keine Konfiguration. Das Projekt sagt selbst, dass niemand vorhersagen kann, welche Regeln in deiner Umgebung laut sind — die Tuning-Arbeit ist also weder optional noch an einen Leitfaden auslagerbar.

Eine Woche beobachten. Ausnahmen schreiben statt Regeln abschalten. Nach Schweregrad routen, damit der Pager etwas bedeutet. Eigene Regeln für das ergänzen, von dem nur du weißt, dass es zählt.

Ziel ist ein Signal, dem dein Team auch in sechs Monaten noch traut. Das ist das ganze Spiel.

Häufig gestellte Fragen

Was ist Falco und was macht es?

Falco ist ein CNCF-Graduated-Projekt, ursprünglich von Sysdig entwickelt, das Runtime-Security für Hosts, Container, Kubernetes und Cloud-Umgebungen bietet. Es liest Linux-Systemaufrufe direkt aus dem Kernel, prüft diesen Strom gegen eine Regel-Engine und alarmiert, wenn eine Regel greift. Weil es auf Syscall-Ebene arbeitet, sieht es tatsächliches Verhalten statt Konfiguration: eine Shell, die in einem Container startet, ein Prozess, der nach /etc schreibt, eine unerwartete ausgehende Verbindung, ein privilegierter Container. Die Ereignisse werden mit Container- und Kubernetes-Metadaten angereichert, sodass ein Alarm Pod und Namespace nennt. Über Syscalls hinaus kann ein Plugin-System weitere Quellen einbinden, etwa Kubernetes-Audit-Logs, CloudTrail und Okta.

Wie unterscheidet sich Falco von Trivy oder Kyverno?

Sie arbeiten an unterschiedlichen Punkten im Lebenszyklus, und keines ersetzt die anderen. Image-Scanner wie Trivy und IaC-Scanner wie Checkov betrachten Artefakte vor dem Deployment und beantworten die Frage, ob eine bekannte Schwachstelle oder Fehlkonfiguration enthalten ist. Policy-Engines wie Kyverno und OPA greifen beim Admission und beantworten, ob etwas überhaupt erzeugt werden darf. Falco läuft durchgehend und beantwortet, was eine Workload gerade tut. Diese letzte Frage zählt, weil ein Container jede Prüfung vor dem Deployment bestehen und zur Laufzeit trotzdem über eine unbekannte Schwachstelle kompromittiert werden kann. Falco ist die Schicht, die bemerkt, dass ein sauberer Container plötzlich eine Binärdatei lädt und ausführt.

Warum erzeugt Falco so viele Fehlalarme?

Weil die Standardregeln Verhalten beschreiben, das allgemein verdächtig, in konkreten Umgebungen aber völlig normal ist. Eine Regel, die bei einer Shell im Container auslöst, ist sinnvoll — bis man bedenkt, dass die CI Debug-Container fährt, Betreiber kubectl exec nutzen und die Hälfte der Init-Container legitim eine Shell aufruft. Das Falco-Projekt ist dazu deutlich: Der Reifegrad einer Regel spiegelt nicht direkt ihr Potenzial für Rauschen wider, weil jede Umgebung einzigartig und ständig in Veränderung ist, was die Wirkung einer Regel schwer vorhersagbar macht. Das Rauschen ist kein Defekt, sondern die unvermeidliche Lücke zwischen generischer Erkennungslogik und deinem spezifischen Normalzustand.

Was ist das Falco Rules Maturity Framework?

Es ist die projekteigene Einordnung, wie bereit eine Regel für die allgemeine Übernahme ist. Regeln mit maturity_stable bilden den Standardsatz — breite Erkennungen auf Systemebene, ausgerichtet an MITRE ATT&CK, für Dinge wie Remote Code Execution, Container-Ausbrüche, Netzwerk-Pivots, Rechteausweitung und Diebstahl von Zugangsdaten. Regeln mit maturity_incubating oder maturity_sandbox bieten spezifischere oder breitere Erkennung, erfordern aber deutlich mehr Engineering-Aufwand zur Bewertung und Einführung. Der empfohlene Weg ist, zuerst stabile Regeln zu fahren, sie zu tunen, bis Fehlalarme niedrig und der Performance-Overhead akzeptabel sind, und erst danach weniger reife Sätze zu ergänzen. Wichtig: Reife beschreibt die Einführungsreife, nicht den Rauschpegel.

Wie reduziert man Falco-Rauschen, ohne Abdeckung zu verlieren?

In dieser Reihenfolge. Erstens: lange genug im Beobachtungsmodus laufen lassen, um den eigenen Normalzustand zu sehen — eine Woche echter Traffic lehrt mehr als jede Theorie. Zweitens: Ausnahmen schreiben statt Regeln abzuschalten, damit die Erkennung für alles außer dem bekannten Gut-Muster erhalten bleibt. Drittens: nach Schweregrad routen statt alles in einen Kanal zu schicken — nur wirklich handlungsrelevante Regeln gehören auf einen Pager, der Rest in ein durchsuchbares Log. Viertens: eigene Regeln für das ergänzen, was in deiner Umgebung einzigartig ist — deine Secret-Pfade, deine Kronjuwelen-Dienste — denn die haben meist deutlich höhere Signalqualität als generische Regeln. Ziel ist ein Strom, den ein Mensch auch im dritten Monat noch liest.

Bremst Falco das System aus?

Es hat messbare Kosten, und das Projekt behandelt Performance-Tuning als Teil der Einführung, nicht als Nachgedanken. Falco verarbeitet einen Strom von Kernel-Ereignissen, der Overhead skaliert also mit dem Syscall-Volumen: Ein ausgelasteter Node mit Millionen von Syscalls kostet mehr als ein leerer. Kommt der Agent nicht hinterher, verwirft er Ereignisse — das ist zugleich ein Performance-Signal und eine Erkennungslücke, für die die Dokumentation eine eigene Troubleshooting-Seite hat. Praktisch heißt das: an den eigenen Workloads messen, gezielt festlegen, welche Ereignisse erfasst werden, statt alles mitzunehmen, und das Monitoring-Budget als reale Einschränkung behandeln wie bei jedem anderen Agenten auf dem Node.

Aus der Community

Diskussion im Fediverse

Antworten von Mastodon und Bluesky — direkt aus dem offenen Netz, ohne Tracking.

Antworten werden geladen …

ENDE