pixel
Seite wählen

NETWAYS Blog

Detector OSS IDS: How to Shellscript Your Own Little Free Intrusion Detection System

Today I’ll show you a side project I’ve been working on the past month to defend my personal systems and practice shell-scripting and forwarding logs. It is just a proof-of-concept that is work in progress. I have decided to share my project, because Open Source = Open World! You can find detector here on Github.

This small project follows 3 basic goals: a) minimal b) trustable c) modular & customizable:

  • Required Binaries for Checks: AWK, SED & GREP (en masse), Inotify-Tools, Tracee, TS, USBGuard, SocketStats, Dialog, (Nethogs)
  • Just run the ./install.sh or ./uninstall.sh
  • Comment or uncomment the execution of the scripts/modules in the central/privacy directories as you like

How it basically works:

– Runner: Create a 1) Systemd service with a timer, calling a 2) Watchdog with a timer, 3) calling a main (separating Operating Systems and module choices), 4) calling the modules

– Modules: 5) run checks 6) grep for exit codes  6) append a time-stamp 7) append a module tag (with a possible KV – filter for Logstash-Pipelines) ->> write to detecor-logfile | Optional:  9) output to Elastic (via Filebeat -> Logstash-Pipelines) 10) output to Icinga 2 (via passive-checks for more logic & free alerting)

Detector currently (2022/08/01) covers:

Dropping & tracking honeypots via inotifywait:

Tracking USBGuard:

Checking Camera & Microphone Activation:

Tracking Shells and Sub-Shells:

Tracking Established and Listening Sockets with their relevant Programs and PIDs, plus provided DNS-Servers and Wireguard:

Using Tracee from Aquasecurity with 4 cool flags: TRC-2 Anti-Debugging , TRC-6 kernel module loading, TRC-7 LD_PRELOAD, TRC-15 Hooking system calls:

Tracking Kernel-Symbol counters for changes on module export tables:

Now we can be happy, but why not send it to Elastic and do some more magic there?

Or add even more logic and alerting via Icinga 2! (All we have to do is create a template for a passive check, apply the passive check over a (Linux)-hostgroup and set up an API-User with the “actions/process-check-result”. Our icinga-pumper.sh POC Code gets automatically executed in the $central directory, and we save ourselves the Icinga 2 agent installation, while Icinga 2 authentication happens over a certificate deployed via Nextcloud or the likes. :

TrippleCross and badbpf are some very cool offensive projects with eBPF implants I’ll try to understand and study until the next blogpost. See you by then!

If you want to learn from the people that tought me to pull such a side-project off, mostly Dirk and Thomas, then come and join us!

Patrick Dolinic
Patrick Dolinic
Junior Consultant

Nachdem Patrick sein Psychologiestudium abgeschlossen hat, ist er 2020 zu NETWAYS, wo er nun sein Hobby zum Beruf macht: Endlich kann er sich voll und ganz der Linux-Welt widmen und sein Faible für Computersicherheit ausleben. Wenn er nicht gerade arbeitet, arbeitet oder zockt er. Nebenbei versucht er beim Joggen 8 km zu reißen, schafft aktuell aber nicht mal die ersten 7.

DockerCon 2022: Wie geht Containersecurity?

Buzzwords wie Software Supply Chain, Container Security Scanning oder Software Bill of Materials (SBOM) sind in den vergangenen zwei Jahren vermehrt in aller Munde, nicht zuletzt aufgrund des anhaltenden Trends zur Containerisierung vormals monolithischer Anwendungen und deren Betrieb als sog. Microservices. Allerdings kann nach wie vor nicht jeder, der auf die ein oder andere Weise mit Docker oder Containern im Allgemeinen zu tun hat, etwas mit diesen Begriffen anfangen. Aus diesem Grund habe ich den Fokus meines virtuellen Besuchs der diesjährigen DockerCon auf genau diesen Themebereich – Containersecurity – gelegt und möglichst viele Best Practices für Dich zusammengefasst.

 

Die Ausgangslage

Die großen Sicherheitslücken der vergangenen zwei Jahre, sei es der Solarwinds-Breach oder die Log4J/Log4Shell-Exploits haben einmal mehr schmerzlich bewusst gemacht: In fast jedem Softwareprodukt, egal ob proprietär oder Open Source, befinden sich zahlreiche mehr oder weniger gut gepflegte Abhängigkeiten verschiedenster Maintainer – in vielen Applikationen stecken bis zu 80% Open Source Code, die es “auf dem Schirm” zu behalten gilt. Dies gilt natürlich auch für Container(-images), die letzten Endes nichts anderes tun, als die Applikation zu bündeln und (weitestgehend) losgelöst vom ausführenden Hostsystem ausführbar zu machen.

Dennoch gelten Container paradoxerweise oft als besonders sicher, sei es aufgrund der von außen wahrgenommenen “Kapselung” oder der geringen Größe – soviel potentiell vulnerable oder bösartige Software kann da doch gar nicht drinstecken, oder? Mögen diese Wahrnehmungen in der Theorie und im Bestfall auch stimmen, sieht die Praxis in den allermeisten Fällen anders aus, wie die ein oder andere Keynote im Rahmen der DockerCon gezeigt hat.

Laut SysDig, einem Spezialisten für Cloudsecurity, laufen 58% der in den einschlägigen Containerregistries (DockerHub, Google, Github, etc.) verfügbaren Containerimages als root, anstatt einen geeigneteren, unprivilegierten Nutzer zu verwenden. Außerdem beinhalten selbst die offiziellen, von den Registries kuratierten Containerimages beliebter Frameworks oder Distributionen dutzende detektierbare Schwachstellen.

Offensichtlich gibt es also zum Einen ein falsches Gefühl von Sicherheit innerhalb der Nutzergemeinschaft von Containern, zum Anderen aber schlichtweg keine Blaupause oder “OneFitsAll”-Lösung, die für beliebige Container(-images) absolute Sicherheit verspricht. Nur eine Sache ist klar: “Hinten” anzufangen, ist nicht rentabel – Container einfach zu deployen und dann im Betrieb nach Sicherheitslücken zu suchen, ist teuer, erzeugt vermeidbaren zusätzlichen Aufwand und nimmt Flexibilität. Die Absicherung der Container muss “nach links” geschoben werden, möglichst an den Beginn der Containerisierung. Doch wo ansetzen?

 

Die Möglichkeiten

Um den Ursprung für Schwachstellen in Container(-images) und damit einhergehend mögliche Ansatzpunkte zur Absicherung zu identifizieren, muss man die “Lebensphasen” eines Container(-images) verstehen. Diese lassen sich kurz und bündig wie folgt darstellen:

 

  • Bau des Images (lokal oder via CI/CD)
  • Distribution des Images – Push in eine Registry (Self-hosted oder bei einem Anbieter), Pull von Usern/Programmen
  • Deployment des Images (Openshift, (Managed) Kubernetes, etc.) und Betrieb des Containers

 

An dieser Stelle wird hoffentlich klar, warum ich permanent “Container(-image)” schreibe – abhängig von der betrachteten Lebensphase haben wir es beim Thema Containersicherheit entweder mit einem erstellten Image oder mit einem laufenden Container, quasi einer Instanziierung dieses Images zu tun. Mit dieser Aufschlüsselung in verschiedene Abschnitte können wir uns nun mögliche Schritte zur Absicherung unserer Container anschauen.

Containerimages werden entweder lokal von Entwickler:innen, DevOps-Engineers, etc. auf Grundlage eines sog. Dockerfiles gebaut – alternativ lässt sich dieser Vorgang aber auch von CI/CD Pipelines umsetzen, wenn man den Dockerfile und andere benötigten Ressourcen bspw. in GitLab eincheckt. Die meisten Möglichkeiten zur Absicherung des späteren Container(-images) ergeben sich bereits in diesem ersten Schritt – der Quellcode der zu containerisierenden Applikation liegt vor, ebenso die Definition des Containers selbst, und auch möglicherweise vulnerable oder bösartige Abhängigkeiten wurden noch nicht in das spätere Containerimage eingebettet.

Ist das Containerimage lokal oder in einer Pipeline gebaut worden, muss man es zur späteren Nutzung in Produktion in eine Containerregistry übertragen. Diese kann entweder selbst gehosted werden, als private, aber gemanagte Instanz in der Cloud laufen oder öffentlich von jedem beliebigen Nutzer einsehbar sein. Auch bei diesem Vorgang gibt es Möglichkeiten, die Supply Chain zwischen Entwickler und Endnutzer abzusichern.

Auch wenn im Dockerfile gewisse Best Practices befolgt werden, kann der Container diese in vielen Fällen beim Deployment überschreiben – das letzte Wort haben hierbei immer Kubernetes, Openshift, Docker Desktop und Konsorten. Aus diesem Grund müssen einige der Überlegungen, die in der Build-Phase des Containerimages stattgefunden haben, auch hier noch einmal herangezogen, betrachtet und evaluiert werden, um die für die konkrete Nutzung besten Einstellungen und Kompromisse zu finden.

Ist der Container erst einmal deployed, gibt es nicht mehr viele Möglichkeiten, ihn “von innen” weiter abzusichern. Dennoch kann und sollte man sich fortlaufend Gedanken bspw. um die Erreichbarkeit innerhalb des Clusters, des Netzwerkes, der Cloud etc. machen, Regeln nachziehen wo nötig und natürlich auch Update- und Backupstrategien im Hinterkopf behalten. Am Ende des Tages merkt man spätestens jetzt: Nach dem Deployment eines Containers seine Sicherheit zu überprüfen und zu garantieren, ist nicht sinnvoll – wir brauchen einen Left Shift.

 

Die Umsetzung

Buildphase

Nach viel Theorie und Konjunktiv können wir uns jetzt konkrete Umsetzungsmöglichkeiten der besprochenen Ansätze anschauen. Beginnen werden wir “ganz links” beim Bau der Containerimages. Vieles lässt sich hier über verschiedene Direktiven im genutzten Dockerfile festlegen – Docker listet alle möglichen Direktiven sowie sinnvolle Best Practices und Caveats in der Docker Dokumentation auf. Für uns besonders interessant sind die Direktiven ADD, COPY und USER. Wie eingangs erwähnt, nutzen mehr als die Hälfte aller Containerimages per Default den root Nutzer innerhalb des Containers, obwohl das in vielen Fällen gar nicht notwendig wäre – auf einem klassischen Server läuft ein Apache2 Webserver schließlich auch als User apache, warum sollte/müsste das innerhalb eines Containers bspw. auf Debian-Basis anders sein?

Die anderen beiden erwähnten Direktiven beziehen sich auf die Abwägung, ob man gewisse Verzeichnisse und Dateien aus seiner Entwicklungsumgebung denn tatsächlich im endgültigen Container braucht – oder ob man die Applikation direkt lokal baut, und lediglich die fertige Binary via COPY in das Containerimage überträgt. In diesem Fall muss man natürlich darauf achten, dass etwaige zur Laufzeit benötigte Tools (ich meine dich, curl) und Bibliotheken sich auch im endgültigen Containerimage befinden. Alternativ kann man innerhalb eines Dockerfiles eine build und eine run Umgebung schaffen – auf diese Weise kann man die Applikation innerhalb des Containers bauen und im Anschluss lediglich die benötigten binären Artefakte und andere benötigten Ressourcen in das Lauzeitimage kopieren. Für diese Vorgehensweise würde es sich anbieten, das Entwicklungsrepository via ADD in die build Umgebung des Containerimages zu übertragen.

Diese Vorgehensweise bringt uns direkt zur nächsten “beliebten” Unsicherheit in Container(-images): Lokal hinterlegte Credentials, Entwicklertokens, Cloudzugänge etc. Es gibt vermutlich keine Art von geheimen Daten, die nicht bereits versehentlich in Containerimages “vergessen” wurde. Das kann schnell passieren – ein Entwickler nutzt ein Shellscript mit Zugangsdaten, um von seiner Entwicklungsumgebung in ein Testcluster zu deployen, eine .yaml-Datei, um Daten aus einer Entwicklerdatenbank zu lesen etc. Im “schlimmsten Fall” überträgt er wissentlich eine Datei mit Zugangsdaten, die die containerisierte Applikation später in Produktion nutzen soll, oder hinterlegt sensible Daten im Containerimage als Umgebungsvariable mittels ENV.

Zur Bewältigung dieser Problematik gibt es die Möglichkeit, ähnlich wie eine .gitignore Datei für Git-Repositories eine .dockerignore Datei für den Buildvorgang eines Containerimages zu hinterlegen. Alle in dieser Datei aufgeführten Dateien und Verzeichnisse werden vom Dockerdaemon bei der Verarbeitung des Build-Contexts, von ADD und von COPY Direktiven ignoriert und finden sich somit zu keinem Zeitpunkt im Containerimage wieder. Dringend benötigte Umgebungsvariablen zur Konfiguration der containerisierten Applikation können auch zum Zeitpunkt des Deployments noch übergeben werden, bspw. mittels des Parameters -e via Docker-CLI oder dem Einlesen von Secrets als Umgebungsvariablen in Kubernetes.

Grundlegende Maßnahmen wie die Nutzung eines passenden Base-Images in der FROM Direktive (es muss nicht immer debian:buster oder ubuntu:20.04 sein), das Vermeiden der Öffnung unbenötigter Ports via EXPOSE sowie der Nutzung sog. Kannibalen-Tags (latest zeigt nach jedem Imageupdate auf eine neue Version) sollten darüber hinaus natürlich immer befolgt und beachtet werden.

Distributionsphase

Haben wir nun lokal oder in der Pipeline ein in sich möglichst sicheres Containerimage gebaut, muss es auf die eine oder andere Art und Weise seinen Weg in eine Containerregistry finden, um von anderen Nutzern heruntergeladen und deployed werden zu können. Für diese Vorgänge werden einem von den meisten Containerregistries Werkzeuge an die Hand gegeben, mit deren Hilfe wir den Prozess des Up-/Downloads von Containerimages absichern können.

Letzten Endes sind Containerregistries nichts anderes als APIs mit der Fähigkeit, Nutzer zu authentifizieren und zu authorisieren, Containerimages in Empfang zu nehmen, zu speichern und deren Versionierung im Blick zu behalten. Wie immer, wenn man über das Internet mit einer API spricht, gilt: HTTPS ist Pflicht! Darüber hinaus bieten Registries verschiedene Möglichkeiten, zusätzliche Maßnahmen gegen die Verbreitung unsicherer Images oder die Manipulation vorhandener Containerimages zu treffen. So können Imageregistries oftmals alle verwalteten Containerimages auf bekannte Schwachstellen scannen und den Download solcher Images durch Endnutzer untersagen. Auch die digitale Signierung von verwalteten Containerimages ist oftmals möglich, z.B. mittels sigstore und cosign.

Deploymentphase

Wird unser Containerimage nun im Rahmen eines Kubernetes-Deployments oder Docker-CLI-Befehls aus der Registry gepulled und deployed, haben wir einmal mehr die Möglichkeit, Sicherheit zu forcieren: Wie bereits erwähnt, können wir zum Einen die Voreinstellungen in Hinblick auf Umgebungsvariablen, User- und Gruppenkontext uvm. überschreiben, zum Anderen bietet natürlich auch die Absicherung der ausführenden Infrastruktur selbst die Möglichkeit, dass Deployment so sicher wie möglich zu gestalten.

Hierzu zählen z.B. die Nutzung sog. rootless Container, die von einem Container Runtime Interface (CRI) wie Docker oder containerd ausgeführt werden, die selbst nicht im root Kontext laufen. Auch die Nutzung restriktiver Netzwerk- und Firewallpolicies kann dabei helfen, die Risiken durch möglicherweise vulnerable oder bösartige Container zu minimieren. Konfiguration und Forcierung dieser Maßnahmen innerhalb eines Clusters können schnell zur Sisyphusarbeit werden – hier kann ein gemanagtes Kubernetes-Cluster von Vorteil sein, bspw. Managed Kubernetes von NETWAYS Web Services. Darüber hinaus sollte man eine nachhaltige Update-Strategie für seine Containerimages verfolgen: Es gilt, einen guten Kompromiss zwischen regelmäßigen Updates zu finden, aber nicht sofort jede neue Version (und deren evtl. neu eingeführte Schwachstellen) in Produktion zu deployen.

 

Das Fazit

Container(-images) sicher zu erstellen, zu verwalten und zu deployen ist ein langer Weg voller Stolpersteine. Wie so oft beim Thema Sicherheit wird man die 100% aller Voraussicht nach nicht erreichen – Nichtexistenz von Sicherheitslücken lässt sich nun einmal nicht beweisen. Dennoch habe ich Dich hoffentlich für das Thema und die teils falschen, gängigen Annahmen und Praktiken sensibilisieren können und nebenbei einige Best Practices an die Hand gegeben, die das Risiko durch vulnerable Container deutlich verringern.

Solltest Du nun mehr über den Vorgang des Imagebaus, den Betrieb von Containern in Kubernetes oder Containerisierung im Allgemeinen erfahren wollen, schau Dir doch einmal unser Kubernetes Schulungsangebot von NETWAYS an. In diesem eintägigen Workshop vermittle ich Dir praxisnah und einsteigerfreundlich alles, was Du für die ersten eigenen Schritte mit Docker und Kubernetes wissen musst. Ich freue mich auf Dich!

Daniel Bodky
Daniel Bodky
Consultant

Daniel kam nach Abschluss seines Studiums im Oktober 2021 zu NETWAYS und berät nun Kunden zu den Themen Icinga2 und Kubernetes. Nebenher schreibt er in seiner Freizeit kleinere Tools für verschiedenste Einsatzgebiete, nimmt öfters mal ein Buch in die Hand oder widmet sich seinem viel zu großen Berg Lego. In der wärmeren Jahreszeit findet man ihn außerdem oft auf dem Fahrrad oder beim Wandern.

OpenBugBounty.org – was ist das?

So wie es heise und anderen auch schon passiert ist, hatten wir kürzlich zwei Mails von openbugbounty.org im Postfach.

Im ersten Moment wunderten wir uns, was das denn für ein Laden sein könnte, aber am Ende gestaltete sich das ganze jedoch positiv.

 

Kommt erstmal überraschend

Über die nicht-kommerzielle Plattform haben uns unabhängig voneinander zwei IT-Security Spezis kontaktiert. Beide hatten unterschiedliche Lücken auf einer unserer WordPress-Installationen entdeckt und anstatt diese auszunutzen (sehr niedriger Impact) oder zu verkaufen (so sie denn Käufer:innen gefunden hätten), wählten sie den Weg des Responsible Disclosure mit einer Frist von 90 Tagen. Dieses Verhalten ist vergleichbar zum bekannteren Google Project Zero.

Responsible Disclosure wird oft kritisiert

Im Grunde gibt dieses Vorgehen den Betroffenen Zeit, den Fehler zu beheben, bevor dieser öffentlich gemacht wird und somit vielleicht auch einen größeren Schaden allein durch die Reichweite anrichten kann. Sobald der Fehler behoben ist, wird der Report veröffentlicht, damit auch andere Betroffene entsprechende Maßnahmen ergreifen können.

Einschub: oft wird Responsible Disclosure kritisiert, gerne auch Bug Bounty allgemein. Zum einen nimmt man den Betroffenen aus der Pflicht sofort zu handeln, wobei je nach Schwere der Lücke Zeit ein durchaus entscheidender Faktor sein kann. Und es ist ja auch nicht gesagt, dass nur exakt eine wohlmeinende Person diese Lücke findet und kein Schindluder damit treibt. Zudem könnte sich eine gewisse Laxigkeit im Bezug auf Datensicherheit einstellen, wenn ja eh ein zusätzlicher Feedbackkanal zur eigenen verhunzten Installation zur Verfügung steht. Und solange von der Seite kein Input kommt, kann das eigene System ja keine sooo schweren Lücken haben, oder?

Wie reagieren?

Wir standen am Anfang auch erst vor der Frage „wie reagieren?“, aber NETWAYS-typisch haben wir dann halt einfach mal gemacht. Also via Twitter bei openbugbounty.org eingeloggt (was machen eigentlich Leute ohne Twitter-Account? Solche soll es ja mittlerweile auch in NETWAYS-orange geben) und die Kontaktdaten der Spezln geholt.

Eine kurze Mail später hatten wir die Details, den möglichen Impact und eine Behebung für die Lücke im Postfach. Natürlich wurde das nochmal verifiziert, wobei seitens openbugbounty.org bereits eine Verifikation erfolgt. Die Fehlerbehebung war dann auch schnell erledigt und wir konnten die Lücken auch gleich noch auf unseren anderen WordPress-Installationen überprüfen.

Der längste Teil der Geschichte war am Ende die Entscheidung, was tun wir mit der Meldung, wie belohnen wir die beiden am besten und schreibe ich diesen Blogpost auf deutsch oder englisch.

Die Plattform selbst war bei diesem Prozedere nur als Kontaktvermittlerin involviert und hat von uns exakt nichts außer diesen Blogpost erhalten. Ihre Eigenpräsentation hat das Projekt auch hochgeladen. Unsererseits war die Erfahrung also gut, die Kommunikation war immer schnell und offen und es besteht hier wirklich kein Grund zur Furcht.

Details zu den Lücken

Wer bis hier hin durchgehalten hat, ist sicher auch neugierig, was das denn nun für Lücken waren. Die erste ermöglichte es, via WordPress API alle User unserer Installation abzufragen (nur GET, kein POST). Also im Grunde diese coolen Nasen – das NETWAYS-Team.

In der zweiten hätte die WordPress-RPC Funktion ausgenutzt werden können um bspw. DDoS-Attacken auszuführen. Details zu beiden Lücken finden sich bei openbugbounty.org unter den Meldungen 1777708 und 1814148.

Wenn Du Lust auf weitere solche und ähnliche Geschichten hast, schau bei unseren Trainings oder Events  vorbei. Mindestens in den Pausen werden immer Erlebnisse aus der IT Welt verglichen, manchmal auch die Länge der Pipelines oder Größe der Cluster.

Du willst davor eigene Erfahrungen sammeln? Klick Dir hier Deinen eigenen K8s-ClusterOpenStack oder GitLab-Server.

Wenn Du und Deine offene Fehlerkultur allerdings auch mal via WordPress-API angezogen werden sollen, ist jobs@netways.de der richtige Einstiegspunkt. Wir freuen uns darauf, den nächsten Bug Report mit Dir zusammen zu beheben!

Tim Albert
Tim Albert
Systems Engineer

Tim kommt aus einem kleinen Ort zwischen Nürnberg und Ansbach, an der malerischen B14 gelegen. Er hat in Erlangen Lehramt und in Koblenz Informationsmanagement studiert, wobei seine Tätigkeit als Werkstudent bei IDS Scheer seinen Schwenk von Lehramt zur IT erheblich beeinflusst hat. Neben dem Studium hat Tim sich außerdem noch bei einer Werkskundendienstfirma im User-Support verdingt. Blerim und Sebastian haben ihn Anfang 2016 zu uns ins Managed Services Team geholt, wo er sich nun insbesondere um Infrastrukturthemen kümmert. In seiner Freizeit engagiert sich Tim in der Freiwilligen Feuerwehr - als Maschinist und Atemschutzgeräteträger -, spielt im Laientheater Bauernschwänke und ist...

Die Out of the Box Experience

Hallo!

Ich würde gern ein aktuelles Thema aufgreifen, das in letzter Zeit viele Leute beschäftigt. Da aus aktuellem Anlass viele Leute ins Homeoffice gehen mussten und nun von dort ihre Arbeit verrichten, haben viele neue Monitore, Rechner, Mikros und Software erhalten, um dies zu bewältigen.

Nun gibt es aber die schon oben beschriebene Erfahrung, die aus rein subjektiver Sicht entscheidet, ob man mit dem neuen Produkt zufrieden ist oder es gleich wieder einpacken und zurückschicken will.

Das Feld ‘Videokonferenzen’ will ich hier gar nicht betreten. Da hat jeder andere Präferenzen.

Mir geht es in dem Blogpost eher um die “Experience”, ein tolles Marketing-Buzzword, bei dem sich am liebsten jeder unter der Couch verstecken möchte. Die Erfahrung, die man mit dem jeweiligen Produkt direkt nach dem Auspacken macht, ist sehr variabel.

Nehmen wir mal als Beispiel einen neuen Firmenlaptop. Wir haben ihn aus der Verpackung gepult und drücken auf den Powerknopf und unsere neue Kiste mit SSD und mehr Speicher & CPU Kraft aller Großrechner in den 80zigern dümpelt 5 Minuten in einem Regenbogenfarbenen Waiting Screen von Windows umher in dem uns mitgeteilt wird das wir uns freuen dürfen das ‘now’ etwas für uns passiert.

NOT!!!! Jemanden warten zu lassen ist keine ‘Gute’ Out of the Box Erfahrung. Auch 4-5 Sicherheitsfragen welche sowas lustiges wissen wollen wie “Was war ihr erstes Haustier” … sind eher Anti Security .. Rein statistisch hat man hier schon in den USA mit sowas wie ‘Spot’ einen Treffer um in einen Benutzeraccount rein zu kommen.

Idealerweise sollte man nicht warten müssen . NEVER make your Customer wait.

Das wussten selbst Betriebssysteme aus der prähistorischen Ära. Einschalten, Loslegen. C64 => Einschalten und READY.
Selbst die Amiga Workbench war nach dem Starten direkt verfügbar und auch Atari TOS auf dem ST. Nun sind wir im Jahr 2020 AD.

Aus Sicht eines Endbenutzers ist das keine gute Erfahrung (Warten, abgreifen personenbezogener Daten für Marketing-Zwecke, Sicherheitsexploit-Fragen) und zum goldenen Abschluss, nachdem man die ganze Prozedur hinter sich hat, kommt noch ein haufen Autoupdates, die noch installiert werden müssen, bevor man effektiv anfangen kann zu arbeiten.

Selbst bei Konsolen ist die Out of the Box Erfahrung … inzwischen hundsmiserabel.
Früher: SNES Spiel in die Konsole stecken und läuft. Heute: Mindestens 2 Anmeldungen. Einmal Hersteller spezifisch XBox Account/STEAM Account/PSX Account und dann gegebenenfalls nochmal die des Spieleherstellers und dessen Plattform inkl. Werbung.

Das künstliche Gold der Marketing/Wertschöpfungskette von Daten, die nur um deren Selbstwillen für User Tracking generiert werden, ist bis in das einfachste Produkt vorgedrungen. Selbst meine Bose Wireless Kopfhörer wollen meinen Alex Account Zugriff um mir ‘Mehr Info’ liefern zu können.

Da ich nun sehr abgedriftet bin von der Thematik: Die “Auspack und sofort Loslegen Erfahrung” ist sehr “Simplismus” geprägt, man findet die “Out of the Box” Erfahrung am idealsten, wenn man direkt loslegen kann.
Kein wenn und kein aber.
Zu einem späteren Zeitpunkt können die Settings des Produktes verfeinert werden. Also ggf. einen Account anlegen, höhere Security Settings setzen und andere Einstellungen vornehmen.

Aber die Defaults sollten IMMER zu einem produktiven Ergebnis führen.

Software ist auch ein Werkzeug wie ein Schraubenzieher. Der will auch nicht, dass ich bei ‘Binford’ einen Account anlege. bevor ich die erste Schraube in das Holzbrett drehe. Software & Betriebssysteme sollten allgemein wieder auf Funktionalität ausgelegt werden anstelle von Subscription ‘featureitis’ …

Das baut nur unnötige Hürden und Fehlerquellen auf und dient nur dem Selbstzweck.
Einstecken, Einschalten & Loslegen war mal die Devise – ich hoffe, dass nach all den bitteren Erfahrungen der letzten Zeit wieder auf diese Out of the Box Erfahrung Wert gelegt wird.

In dem Sinne ‘Good Luck and Good Night’

Bis zum nächsten Mal

David

Das Nette Katzenfoto wurde bereitgestellt von

Photo by DNK.PHOTO on Unsplash.

David Okon
David Okon
Senior Systems Engineer

Weltenbummler David hat aus Berlin fast den direkten Weg zu uns nach Nürnberg genommen. Bevor er hier anheuerte, gab es einen kleinen Schlenker nach Irland, England, Frankreich und in die Niederlande. Alles nur, damit er sein Know How als IHK Geprüfter DOSenöffner so sehr vertiefen konnte, dass er vom Apple Consultant den Sprung in unser Professional Services-Team wagen konnte. Er ist stolzer Papa eines Sohnemanns und bei uns mit der Mission unterwegs, unsere Kunden zu glücklichen Menschen zu machen.

Jitsi Best Practice und Skalierung

Seit nun mehr als zwei Wochen wird dort wo es möglich ist von Zu Hause aus gearbeitet. Home-Office für ALLE! Naja mindest für die die es können.

Damit ist auch von einem Tag auf den anderen der Bedarf an Kommunikations-Werkzeugen vor allem für Video-Konferenzen gestiegen.
Hierfür gibt es einige Plattformen welche mittels Jitsi Video- und Audiokommunikation als Service anbieten. Darunter auch NETWAYS Web Services
Jitsi ist eine Freie Software welche auch selbst betrieben werden kann.
Beim Betrieb von Jitsi jedoch zeigt sich das Jitsi sehr schwierig in der Skalierung ist. Es benötigt die richtigen Ressourcen und die richtigen Clients für die Nutzung, um nicht ab einer zweistelligen Zahl von Nutzern in einen reinen Ton- und Bildsalat zu enden. Die technischen Dokumentationen jedoch sind nicht sehr ausgeprägt und durch ihre Zerstreuung sehr schwer zu einem ganzen zusammen zu fügen.

Daher werden wir uns folgend mit den Punkten Anforderungen, Skalierung und Nutzung auseinander setzen.

Empfehlung für einen eigenen Jitsi Server/Videobridge

Nach meinen Tests und der Güte an vorhandenen Quellen zur Hilfe und Dokumentation komme ich zu folgendem Ergebnis:

    • Betriebssystem: Debian 10 oder Ubuntu 18.04.4 LTS
    • Soviel CPU wie geht
      (klingt komisch ist aber so)
      CPU: bei durchschnittlich 10 Teilnehmer pro Konferenz kommen ich mit 2vCPU für die Videobridge ganz gut klar. Mehr zur Skalierung der CPU findet ihr hier:

jitsi-videobridge-performance-evaluation

  • CPU Jitis/Jifico/Prosody: Hier würde auch eine (v)CPU ausreichen, hängt jedoch auch wieder von der Frequentierung ab.
  • RAM: 4-8 GB für beide Server-Varianten
  • Speicherplatz: max. 50 GB SSD für beide Server-Varianten
  • Eine hohe Bandbreite
  • Die Unstable Version von Jitsi:
# install the key
wget -qO - https://download.jitsi.org/jitsi-key.gpg.key | apt-key add -
# add the unstable repo
sh -c "echo 'deb https://download.jitsi.org unstable/' > /etc/apt/sources.list.d/jitsi-unstable.list"
apt update

Eine gute Installations-Anleitung dazu gibt es zum einen von Jan Doberstein auf seinem Blog jalogisch.de
oder auch sehr hilfreich und weiterführend auf der Seite lw1.at guides

Skalierung einer Jitsi Infrastruktur

Ausgangslage

Wir haben einen vollständig installierten Jitsi Server Namens jitsi.example.com auf Basis von Debian. Jetzt wollen wir mehr mehr Ressourcen bereit stellen, so müssen wir weitere jitsi-videobridge Instanzen aufsetzen.
In der vollständigen Installation eines Jitsi-Servers auf Basis von Debian 10 sind folgende Pakete installiert:

ii jitsi-meet 1.0.4314-1 all WebRTC JavaScript video conferences
ii jitsi-meet-prosody 1.0.3914-1 all Prosody configuration for Jitsi Meet
ii jitsi-meet-web 1.0.3914-1 all WebRTC JavaScript video conferences
ii jitsi-meet-web-config 1.0.3914-1 all Configuration for web serving of Jitsi Meet
ii jitsi-videobridge2 1132-1 amd64 WebRTC compatible Selective Forwarding Unit (SFU)

Der Part jitsi-videobridge ist der Teil der den jtisi-meet mit der Video und Audio Übertragung versorgt. Er schließt sich an jitsi-meet und dem verwendeten prosody (XMPP-Server) an.

Anbindung einer Videobridge

Dazu binden wir die die Paketquellen auf dem zweiten Server vb1.example.com ein und installieren die Videobridge:

# install the key
wget -qO - https://download.jitsi.org/jitsi-key.gpg.key | apt-key add -
# add the unstable repo
sh -c "echo 'deb https://download.jitsi.org unstable/' > /etc/apt/sources.list.d/jitsi-unstable.list"
apt update
apt install jitsi-videobridge2

Sollte eine Firewall auf dem Server jitsi.example.com aktiviert sein so müssen wir den Port 5222 für eingehende Kommunikation öffnen.

Auf dem zweiten Server vb1.example.com passen wir jetzt die Datei “/etc/jitsi/videobridge/config” an:

# Jitsi Videobridge settings

# sets the XMPP domain (default: none)
JVB_HOSTNAME=jitsi.example.com

# sets the hostname of the XMPP server (default: domain if set, localhost otherwise)
JVB_HOST=jitsi.example.com
....

Dann kommen wir zu Datei für die SIP-Kommunikation. Diese sollte vom Hauptserver jitsi.example.com übernommen werden und die UUID sollte hierbei auf jedem Server unterschiedlich gesetzt sein.
Die Datei “/etc/jitsi/videobridge/sip-communicator.properties” wird wie folgt eingestellt:

org.jitsi.videobridge.DISABLE_TCP_HARVESTER=true
org.jitsi.videobridge.ENABLE_STATISTICS=true
# Notwendig falls der Server hinter einem NAT steht.
org.ice4j.ice.harvest.NAT_HARVESTER_LOCAL_ADDRESS=local-ip
org.ice4j.ice.harvest.NAT_HARVESTER_PUBLIC_ADDRESS=public-ip
org.jitsi.videobridge.STATISTICS_TRANSPORT=muc
org.jitsi.videobridge.xmpp.user.shard.HOSTNAME=jitsi.example.com
org.jitsi.videobridge.xmpp.user.shard.DOMAIN=auth.jitsi.example.com
org.jitsi.videobridge.xmpp.user.shard.USERNAME=jvb
org.jitsi.videobridge.xmpp.user.shard.PASSWORD=
org.jitsi.videobridge.xmpp.user.shard.MUC_JIDS=JvbBrewery@internal.auth.jitsi.example.com
#UUID am besten mit "uuidgen" neu gernieren muss auf beiden Servern Einzigartig sein.
org.jitsi.videobridge.xmpp.user.shard.MUC_NICKNAME=9a6187f0-6d3f-46df-b1ff-ce7d2d69513a
org.jitsi.videobridge.xmpp.user.shard.DISABLE_CERTIFICATE_VERIFICATION=true

Auf Debian 10 tritt mit Java 11 folgender Fehler auf:

VB 2020-03-21 19:29:23.687 SEVERE: [16] org.jitsi.utils.concurrent.RecurringRunnableExecutor.log() The invocation of the method org.jitsi.videobridge.stats.StatsManager$StatisticsPeriodicRunnable.run() threw an exception.
java.lang.reflect.InaccessibleObjectException: Unable to make public long com.sun.management.internal.OperatingSystemImpl.getTotalPhysicalMemorySize() accessible: module jdk.management does not "opens com.sun.management.internal" to unnamed module @54ca3634
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:340)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:280)
at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:198)
at java.base/java.lang.reflect.Method.setAccessible(Method.java:192)
at org.jitsi.videobridge.stats.OsStatistics.getTotalMemory(OsStatistics.java:138)
at org.jitsi.videobridge.stats.VideobridgeStatistics.generate0(VideobridgeStatistics.java:703)
at org.jitsi.videobridge.stats.VideobridgeStatistics.generate(VideobridgeStatistics.java:450)
at org.jitsi.videobridge.stats.StatsManager$StatisticsPeriodicRunnable.doRun(StatsManager.java:321)
at org.jitsi.utils.concurrent.PeriodicRunnableWithObject.run(PeriodicRunnableWithObject.java:87)
at org.jitsi.utils.concurrent.RecurringRunnableExecutor.run(RecurringRunnableExecutor.java:216)
at org.jitsi.utils.concurrent.RecurringRunnableExecutor.runInThread(RecurringRunnableExecutor.java:292)
at org.jitsi.utils.concurrent.RecurringRunnableExecutor.access$000(RecurringRunnableExecutor.java:36)
at org.jitsi.utils.concurrent.RecurringRunnableExecutor$1.run(RecurringRunnableExecutor.java:328)

Dieser kann beseitigt werden mittels folgender Ergänzung am Ende der Java System Properties in der Datei “/etc/jitsi/videobridge/config”:

JAVA_SYS_PROPS="-Dnet.java.sip.communicator.SC_HOME_DIR_LOCATION=/etc/jitsi -Dnet.java.sip.communicator.SC_HOME_DIR_NAME=videobridge -Dnet.java.sip.communicator.SC_LOG_DIR_LOCATION=/var/log/jitsi -Djava.util.logging.config.file=/etc/jitsi/videobridge/logging.properties --add-opens jdk.management/com.sun.management.internal=ALL-UNNAMED"

Nun können wir die Videobridge starten:

systemctl enable jitsi-videobridge && systemctl start jitsi-videobridge

An der Stelle geht auch ein Dank an Jan Doberstein der mich auf diese Spur gebracht hat und in seinem Blog-Folge Artikel zu Scaling Jitsi

Nutzung

Das Protkoll WebRTC, welches Jitsi nutzt, wird zur Zeit nur sauber von Google Chrome unterstützt. Somit sollte allen Nutzern dieser Browser, für die Anwendung am Notebook empfohlen werden. Für Androide und iOS Geräte gibt es Applikationen den jeweiligen App-Stores. Sehr schöne Zusammenfassung und eine ausführliche Benutzer-Anleitung hierzu gibt es auch auf der Seite des Freifunk München.

Sicherheit

Zum Thema Sicherheit empfiehlt es sich am Besten zuerst die Stunning-Server von Google in der Datei “/etc/jitsi/meet/jitsi.example.com-config.js zu ersetzen. Eine geeignete Stunning-Server Konfiguration kann wie folgt lauten:

stunServers: [
{ urls: 'stun:stun.schlund.de:3478' },
{ urls: 'stun:stun.t-online.de:3478' },
{ urls: 'stun:stun.1und1.de:3478' },
{ urls: 'stun:stun.hosteurope.de:3478' },
{ urls: 'stun:stun.gmx.de:3478' },
],

Zustätzlich wenn Ihr nicht eine gänzlich freie Plattform, sondern eine mit Moderaten oder sogennante Host per Raum gestützte Instanz betreiben wollt, empfiehlt es sich in prosody und jitsi-meet die Benutzerauthentifzierung für das erstellen von Räumen zu aktivieren.
In der Datei für die prosody-Konfiguration “/etc/prosody/conf.avail/jitsi.example.com.cfg.lua”, setzen wir den Wert für “authentication” auf “internal_plain” und fügen einen neuen VirtualHost darunter ein ein:

VirtualHost "jitsi.yourdomain.example"
-- enabled = false -- Remove this line to enable this host
authentication = "internal_plain"
-- Properties below are modified by jitsi-meet-tokens package config
-- and authentication above is switched to "token"
--app_id="example_app_id"
--app_secret="example_app_secret"
-- Assign this host a certificate for TLS, otherwise it would use the one
-- set in the global section (if any).
-- Note that old-style SSL on port 5223 only supports one certificate, and will always
-- use the global one.
ssl = {
key = "/etc/prosody/certs/jitsi.yourdomain.example.key";
certificate = "/etc/prosody/certs/jitsi.yourdomain.example.crt";
}
-- we need bosh
modules_enabled = {
"bosh";
"pubsub";
"ping"; -- Enable mod_ping
}
c2s_require_encryption = false

VirtualHost "guest.jitsi.example.com"
authentication = "anonymous"
c2s_require_encryption = false

In der Datei “/etc/jitsi/meet/jitsi.example.com-config.js” geben wir nun den neuen VirtualHost an:

var config = {
hosts: {
// XMPP domain.
domain: 'jitsi.yourdomain.example',

// When using authentication, domain for guest users.
anonymousdomain: 'guest.jitsi.yourdomain.example',
}
}

Nun müssen wir noch jifico dazu veranlassen auch eine Authentifizierung durchzuführen und die Klasse in der “/etc/jitsi/jicofo/sip-communicator.properties” laden:

org.jitsi.jicofo.auth.URL=XMPP:jitsi.example.com

Danach müssen die Dienste neu gestartet werden:

sudo systemctl restart prosody.service
sudo systemctl restart jicofo.service

Für die Anbindung einer Authentifizierung in Prosody gibt es auch Enterprise fähige Funktionen für LDAP und Co. Die obige Lösung beschreibt es für ein überschaubares Setup, denn die Benutzer hier müssen dann im Anschluss mit der prosodctl generiert werden:

prosodyctl register  jitsi-meet.example.com

Abschließend bleibt zusagen…

Es ist nicht leicht gute Dokumentationen zu Jitsi und dessen Betrieb zu finden, eben so wie für das Scalling. Eine einheitliche Dokumentation gibt es nicht und somit macht es einen Gesamtüberblick nicht sehr leicht.
Neben der Jitis-Community und der Docs auf GitHub gibt es eine paar bereits schon erwähnte Artikel aber auch die sind rah. Daher die Bitte wenn jemand verbesserungen hat, meldet euch gerne!

Wenn Ihr eine Instanz dringend benötigt und euch nicht mit dem Betrieb ausseinandersetzen könnt oder naja vielleicht nicht wollt, dann schaut doch einfach bei unseren Kollengen von NWS vorbei. Dort bekommt Ihr aktuell mit dem Code #StayAtHome eine kostenlose Jitsi-Instanz für drei Monate und das ganz ohne Abo-Falle!

Also bleibt Zuhause und fragt euch gerade in diesen Tagen doch mindestens einmal am Tag:

1. Ist es wahr?
2. Ist es fair für alle Beteiligten?
3. Wird es Freundschaft und guten Willen fördern?
4. Wird es dem Wohl aller Beteiligten dienen?”

(Das sollten wir uns bei allem Fragen, was wir denken, sagen oder tun IMHO!)

Daniel Neuberger
Daniel Neuberger
Senior Consultant

Nach seiner Ausbildung zum Fachinformatiker für Systemintegration und Tätigkeit als Systemadministrator kam er 2012 zum Consulting. Nach nun mehr als 4 Jahren Linux und Open Source Backup Consulting zieht es ihn in die Welt des Monitorings und System Management. Seit April 2017 verstärkt er das NETWAYS Professional Services Team im Consulting rund um die Themen Elastic, Icinga und Bareos. Wenn er gerade mal nicht um anderen zu Helfen durch die Welt tingelt geht er seiner Leidenschaft für die Natur beim Biken und der Imkerei nach und kassiert dabei schon mal einen Stich.