Kommen Container als Basis der Bereitstellung von Anwendungen zum Einsatz, erfordert dies natürlich auch deren Absicherung. Doch Nord-Süd- und Ost-West-Datenströme sorgen dabei für spezielle Herausforderungen. Den Netzwerkzugriff in jeder Richtung besser zu kontrollieren, verspricht Junipers Container-Firewall cSRX. In Docker-Umgebungen gelingt dies tadellos, doch spielt Kubernetes mit, ist der containerisierte Schutz überfordert.
Anwendungen, die in Containern laufen, sind aus vielen Rechenzentren nicht mehr wegzudenken. Angefangen mit der Plattform Docker, die es erlaubt, Container auf einem Rechner laufen zu lassen, kommt heute für komplexere Anwendungen häufig Kubernetes oder eine seiner kommerziellen Varianten wie RedHats OpenShift oder SUSEs Rancher im Rechenzentrum zum Einsatz.
Firewalling im Container als Herausforderung
Da containerisierte Anwendungen nur über das Netzwerk erreichbar sind, ist dies auch der Ort, eine Firewall zu platzieren, um den Verkehr von und zum Container zu kontrollieren und gegebenenfalls auch Funktionen wie Antivirus oder Intrusion Detection umzusetzen. Dieser Datenstrom nennt sich Nord-Süd-Verkehr.
Komplexe Anwendungen bestehen aber in der Regel aus mehreren Diensten, die ebenfalls über das Netzwerk miteinander kommunizieren. Dieser Verkehr bleibt je nach Umsetzung entweder direkt im Container, indem in einem Container mehrere Anwendungen laufen oder mehrere Container kommunizieren über das Overlay-Netzwerk der Container-Plattform miteinander. Dieser Verkehr ist von außen nicht direkt einsehbar und damit auch nicht einfach kontrollierbar. Dieser Datenfluss wird üblicherweise Ost-West-Verkehr genannt.
Anwendungen, die in Containern laufen, sind aus vielen Rechenzentren nicht mehr wegzudenken. Angefangen mit der Plattform Docker, die es erlaubt, Container auf einem Rechner laufen zu lassen, kommt heute für komplexere Anwendungen häufig Kubernetes oder eine seiner kommerziellen Varianten wie RedHats OpenShift oder SUSEs Rancher im Rechenzentrum zum Einsatz.
Firewalling im Container als Herausforderung
Da containerisierte Anwendungen nur über das Netzwerk erreichbar sind, ist dies auch der Ort, eine Firewall zu platzieren, um den Verkehr von und zum Container zu kontrollieren und gegebenenfalls auch Funktionen wie Antivirus oder Intrusion Detection umzusetzen. Dieser Datenstrom nennt sich Nord-Süd-Verkehr.
Komplexe Anwendungen bestehen aber in der Regel aus mehreren Diensten, die ebenfalls über das Netzwerk miteinander kommunizieren. Dieser Verkehr bleibt je nach Umsetzung entweder direkt im Container, indem in einem Container mehrere Anwendungen laufen oder mehrere Container kommunizieren über das Overlay-Netzwerk der Container-Plattform miteinander. Dieser Verkehr ist von außen nicht direkt einsehbar und damit auch nicht einfach kontrollierbar. Dieser Datenfluss wird üblicherweise Ost-West-Verkehr genannt.
Dessen Kontrolle wäre zwar auch bei Docker mit etwas Aufwand über eine außenstehende Firewall möglich, es ist aber einfacher, dieses durch eine Firewall im Container umzusetzen. Kubernetes bietet je nach verwendetem Netzwerk-Backend hier mehr Möglichkeiten. Calico erlaubt etwa Filterregeln in ein Deployment zu packen, die über die Möglichkeiten von Kubernetes selbst hinausgehen. Cilium ermöglicht sogar Filterregeln auf Applikationsebene, gerade bei webbasierenden Diensten lässt sich hier detailliert filtern. Jedoch bedeutet dies auch, diese Regeln selbst zu konfigurieren, ein Abonnement-Service wie er in den IPS-Engines von Firewalls existiert, fehlt hier.
Hier kommen Container-Firewalls zum Einsatz, die eine kommerzielle Firewall in einem Container enthalten und sich so nahtlos in die Container-Infrastruktur einfügen, um sowohl Nord-Süd- als auch Ost-West-Traffic zu überwachen. Dabei geht die Kontrolle über reine Paketfilterung hinaus, da die meisten Produkte auch UTM-Funktionalitäten wie Intrusion Detection, Applikationskontrolle und auch Web Application Firewalling enthalten.
Von den marktführenden Herstellern haben momentan Juniper, Cisco und Palo Alto entsprechende Produkte im Angebot und wir schauen auf Juniper mit seiner cSRX-Firewall. Deren Leistungsfähigkeit betrachten wir sowohl unter dem Einsatz mit Docker als auch in einer Kubernetes-Umgebung. Neben dem grundsätzlichen Firewalling war die Integration in die Infrastruktur ein wesentlicher Testpunkt – wieviel Aufwand ist erforderlich, um die Security-Funktionen umzusetzen, und gibt es eine direkte Verknüpfung etwa mit der Kubernetes-API.
Installation mit unnötigen Hürden
Üblicherweise ziehen IT-Verantwortliche Container direkt aus einer verfügbaren Registry. Mit dem Docker-run-Kommando lässt sich ein Container mit aus einer voreingestellten Registry wie "docker.io" herunterladen, im lokalen Image-Verzeichnis bereitstellen und starten.
Juniper stellt für unser Testprodukt eine Installationsanleitung bereit, die der Hersteller dann noch um das sogenannte "Day One Book" ergänzt. Beides sind How-tos für die cSRX-Firewall, die sich leider in einigen Details unterscheiden beziehungsweise widersprechen. Beide Dokumente beschreiben etwa, wie Admins das Container-Image manuell herunterladen und dann in die lokale Docker-Installation importieren. Auch fanden wir darin Beispiele, wie der cSRX-Container zu starten ist. Dies sollte mit einen Link zu einer Registry von Juniper klappen, die eine Benutzerauthentifizierung fordert.
Im Test folgten wir der Anleitung, luden manuell das Image herunter und importierten es dann mittels docker load -i. Dies funktionierte für einen einzelnen Docker-Host, führt jedoch bei mehreren Hosts oder beim Einsatz unter Kubernetes zu erhöhtem Aufwand. Hier ist es empfehlenswert, das Image zumindest in eine lokale Registry einzuspielen, damit die lokalen Container-Nodes es on demand herunterladen können. Ein Hinweis dazu fehlt allerdings in Junipers Anleitungen. Für den Teil dieses Tests unter Kubernetes legten wir das Image auch in unserer lokale Registry ab.
Nach kleinen Hürden gute Firewall-Integration
Bevor es an den konkreten Test ging, galt es zunächst einmal herauszufinden, welche der verschiedenen Optionen zum Start des Containers, die die Dokumentation vorschlägt, dazu führt, einen funktionierenden Container zu erhalten. Die richtigen Informationen sind zwar in den Dokumenten enthalten, jedoch war etwas Puzzlearbeit notwendig, die richtige Kombination herauszufinden. Dabei ging es um die Umgebungsvariable "CSRX_SIZE", die auf den Wert "large" zu setzen war, und die Variable "CSRX_ROOT_PASSWORD", die wegen einer Sicherheitslücke zu deaktivieren ist. Den Zugriff zur Konsole erlangten wir trotzdem per docker exec -it csrx /bin/bash. Schwieriger war es, den Fehler bei der "SIZE"-Variablen zu finden, da der Container zwar startet, aber die Firewall schlicht nicht funktioniert, obwohl es möglich ist, sie zu konfigurieren. Eine weitere Falle tauchte erst nach dem vollständigen Testaufbau auf – dazu später mehr.
Die Konfiguration der Firewall-Instanz selbst erfolgt über die CLI. Alternativ steht Junipers Security Director dazu bereit und es ist auch möglich, das netconf-Protokoll freizuschalten und damit die Konfiguration einzuspielen. Das Webfrontend der SRX-Firewall fehlt in der Containerversion. Allerdings ist es in einer containerisierten Umgebung nicht üblich, Dienste manuell zu starten und zu konfigurieren. Stattdessen wird auf Automatisierung gesetzt.
Bei Diensten wie Webservern generiert der IT-Verantwortliche die Konfiguration und mountet sie in den Container hinein. Erfreulicherweise funktioniert dies auch bei cSRX. Im Dateisystem der Firewall finden sich die Konfiguration und ihre Backups im Ordner "/config". Dieser lässt sich mit einem Ordner auf dem Hostsystem verbinden. So ist es auch möglich, die Konfiguration über mehrere Container-Starts zu erhalten. Dies ist sehr nützlich und auch im Einsatz mit Kubernetes wäre diese Funktion wichtig. An dieser Stelle fügt sich das System gut in die Container-Welt ein.
Juniper Container-Firewall cSRX
Produkt
Firewall für virtualisierte und Cloudumgebungen mit containerisierten Anwendungen
Damit die Firewall ihre Arbeit tun kann, muss der Traffic sie passieren. Dies setzt in der Regel voraus, dass der Datenverkehr auf einem Firewall-Interface ankommt und sie auf einem anderen verlässt. Dies bedeutet, dass auf dem Docker-Host mehrere Netzwerke erforderlich sind, die auch mit der Firewall verbunden sind. Außerdem muss über die Routing-Tabelle im Container dafür gesorgt werden, dass die aus dem Container gesendeten Pakete durch die Firewall und nicht über den von Docker bereitgestellten Default-Router laufen. Dies lässt sich entweder nach dem Start über docker exec oder von außen über das nsenter-Kommando konfigurieren. Letzteres erlaubt, die Änderungen im Namespace des Containers vorzunehmen.
An dieser Stelle ist die Einbindung leider nicht so ganz cloudnative, auch wenn die notwendigen Änderungen beim Start der Container durch ein Skript automatisch durchgeführt werden können. Nützlicher wäre es, dies direkt in der Infrastrukturdefinition angeben zu können, aber dies ist keine Schwäche der getesteten Software, sondern der gesamten Umgebung.
Alternativ ist es möglich, mit einer Kombination aus "Destination" und "Source NAT" auf der Firewall zu arbeiten, sodass ein Container, der durch die Firewall mit einem anderen Container kommunizieren will, eine Adresse im lokalen Netz anspricht, die die Firewall auf die Adresse im Zielnetz nattet. Source NAT sorgt dafür, dass der empfangende Container eine Verbindung aus dem lokalen Netz sieht und auch für die Antwortpakete keine Routen zu ändern sind. Beim Anlegen der Netzwerke, die die Daten durch die Firewall schleusen, ist darauf zu achten, dass die Option "com.docker.network.bridge.enable_ip_masquerade" auf "True" steht, sofern Address Translation im Einsatz ist.
Für unseren Testaufbau (Bild 1) legten wir drei Netzwerke an: eines für die Verwaltung der Firewall und zwei Netzwerke, die Daten zur Firewall schaufeln. Zusätzlich starteten wir einen Container mit Nginx (im Bild 1 links zu sehen) und einen Alpine-Container (rechts im Bild), in den wir zum Test manuell wechselten, sodass wir von hier aus testen konnten, ob der Zugriff auf den Webserver abhängig von den Firewallregeln funktioniert. Dabei untersuchten wir sowohl die Variante mit der Veränderung der Routing-Tabelle als auch mit der Kombination aus Destination und Source NAT.
Bild 1: Schematischer Aufbau unserer Testumgebung für den Einsatz der cSRX-Firewall für Docker.
Ebenso achteten wir darauf, ob der Zugriff nicht funktioniert, wenn die Regel deaktiviert ist beziehungsweise auf "Deny" steht. Für die Kontrolle des Nord-Süd-Traffics (also von außerhalb der Container-Umgebung auf den Nginx-Container) starteten wir den cSRX-Container mit der Option "-p 8080:8080", sodass Pakete, die den Docker-Host auf Port 8080 erreichten, auf den Firewallport 8080 weitergeleitet wurden und dort bei der Destination-NAT-Regel landeten und schließlich zum Webserver wanderten.
All dies funktionierte wie gewünscht – jedoch erst im zweiten Versuch. Die Firewall leitete bei offener Regel zwar die Pakete weiter, jedoch nahm der Webserver im Nginx-Container sie nicht an (obwohl sie sichtbar waren, wie der tcpdump-Befehl im Container zeigte). Abhilfe schaffte hier der Troubleshooting-Guide des Day One Books, der dazu riet, das TCP Offloading auf dem Docker-Host (der in unserem Labor eine virtuelle Maschine war) mit "ethtool" zu deaktivieren. Dazu lag ein fertiges Skript vor und danach funktionierten die Verbindungen wie gewünscht.
Bild 2: Sind alle Konfigurationshürden genommen, klappt auch der Start des SRX-Containers.
Deutlicher Mehrwert für Docker-Hosts
Zusammengefasst lässt sich zum Einsatz unter Einzelcontainer-Hosts sagen, dass das Deployment – mit etwas Recherche – wie erwartet funktioniert. Hier wäre es bei den zur Verfügung stehenden Informationsquellen wünschenswert, wenn der Hersteller einmal aufräumt und eine alleingültige Dokumentation erstellt, damit Administratoren das Puzzlespiel, durch das wir gelaufen sind, erspart bleibt.
Beim Design ist zu beachten, dass der Verkehr innerhalb der Container auf den richtigen Weg gebracht werden muss, damit die Firewall auch wirken kann. Einfach nur den SRX-Container auf dem Docker-Host laufen zu lassen, ist nicht ausreichend. Wie bei jedem Microsegmentierungsprojekt muss die Architektur ordentlich geplant werden. Ob dieser Aufwand letztendlich notwendig ist, hängt von den individuellen Sicherheitsanforderungen ab.
Trennen beispielsweise Security-Policys normalerweise Frontend-Webserver von Applikationsservern und diese wiederum von Datenbanken und all dies nicht mehr in VMs oder auf Baremetal, sondern in Containern, sind zur Umsetzung mehrere Container-Hosts und eine Firewall in die Mitte notwendig. Mit Junipers Firewall kann dies auf Ebene der virtuellen Netzwerke in einem Docker-Host geschehen (auch wenn sicherlich die Abschirmung von Containern auf demselben Host untereinander schwächer ist als mit echten Maschinen). Die Möglichkeit, Intrusion Detection in den Verkehr zu hängen, ist ebenfalls positiv zu bewerten, und zwar in allen Himmelsrichtungen (Nord/Süd und Ost/West), da hier gerade auf einem einzelnen Docker-Host normalerweise keine Schutzmaßnahmen implementiert sind.
Aktuell für Kubernetes ungeeignet
Die meisten größeren, containerbasierten Installationen laufen auf der Kubernetes-Plattform. Dies kann ein reines Kubernetes sein oder eines der kommerziellen Produkte wie RedHat OpenShift, SUSEs Rancher oder VMWares Tanzu. Kubernetes ist jedoch berüchtigt für seine kurzen Release-Zyklen, die nicht selten API-Kompatibilitäten aufbrechen.
Im Test sollte ein aktuelles Kubernetes 1.28.1 auf Ubuntu 20 zum Einsatz kommen. Ein Blick in die Juniper-Dokumentation zeigte jedoch, dass nur die Versionen 1.16 bis 1.18 unterstützt sind und das letzte Patch-Release von Version 1.18 aus dem Jahr 2021 stammt. Hier hinkt der Hersteller der Entwicklung hinterher, weil selbst konservativ verwaltete Installationen im Jahr 2023 einige Versionen weiter sind.
Nichtsdestotrotz haben wir zumindest versucht, den Container in der Kubernetes-Installation zu starten. Jedoch trat hier das gleiche Verhalten auf wie beim Weglassen der Umgebungsvariable "CSRX_SIZE". Obwohl diese im Container erkennbar gesetzt war, war keine Verbindung zum srxfpe-Prozess möglich, der für die Steuerung der Pakete durch den Kernel zuständig ist.
Zudem fiel uns beim Studium der Dokumentation auf, dass auch hier der Einsatz von Multus notwendig ist, einer Ergänzung des Kubernetes Netzwerk-Backends. Dieses ermöglicht, in klassischer Weise Subnetze anzulegen, die sich an die cSRX-Instanz im Cluster anschließen lassen. Eine Architektur eines Service Meshes, wie Istio dieses mit Sidecars umsetzt, ist nicht vorgesehen, obwohl genau Funktionen wie Intrusion Detection in dieser transparenteren Integration wünschenswert wären.
Sollte der Hersteller im Bereich Kubernetes Fuß fassen wollen, so ist es dringend nötig, die Software auf den aktuellen Stand in der Kompatibilität zu heben. Der Mitbewerber Palo Alto etwa unterstützt Kubernetes bis Version 1.27 und gleichzeitig ebenso mehr Netzwerk-Backends.
Bild 3: Bei der Konfiguration der cSRX-Firewall inklusive NAT muss der Admin keine Routen im Netzwerk anpassen.
Fazit
Die Installation der cSRX-Firewall in einer Docker-Umgebung funktionierte gut, nachdem wir die richtigen Parameter herausgefunden hatten. Je nachdem ob die unter Docker laufenden Anwendungen händisch oder bei komplexeren Anwendungen beispielsweise mit "Docker Compose" implementiert sind, ist es aber notwendig, die Firewall in die Architektur einzubeziehen und damit auch Änderungen am Container-Setup vorzunehmen. Einfach, wie häufig üblich, eine Docker-Compose-Datei aus GitHub ziehen und starten, führt hier in der Regel nicht zum Erfolg beziehungsweise bleibt die Firewall dann außen vor und kann keine Schutzfunktion einbringen.
Die fehlende Kompatibilität zu aktuellen Kubernetes-Versionen war sehr enttäuschend, da sie den praktischen Einsatz in einer modernen Infrastruktur quasi ausschließt. Der leichtgewichtigere Fußabdruck des cSRX-Containers im Vergleich zu einer VM erlaubt es, ihn für Testszenarien schnell auszurollen. Auch ist es durchaus möglich, cSRX als Firewall außerhalb zu verwenden, in dem IT-Verantwortliche die Linux-Bridges, die Docker anlegt, etwa mittels VXLAN-Tunneln mit der realen Infrastruktur verbinden.
(jp)
So urteilt IT-Administrator
Bewertung
Security in Docker
8
Firewalling unter Kubernetes
1
Cloud-Readiness der cSRX
7
Konfiguration der Firewall
6
Dokumentation
6
Dieses Produkt eignet sich
optimal
für Docker-Umgebungen mit einzelnen Container-Hosts und in Testszenarien.
bedingt
in großen Docker-Infrastrukturen mit Docker Swarm.
Nicht
, wenn Container mit Kubernetes orchestriert werden.