SASL DIGEST-MD5 mit slapd bzw. OpenLDAP

SASL DIGEST-MD5 mit slapd bzw. OpenLDAP

Eine kurze Anleitung wie man einem slapd von OpenLDAP dazu bringt Benutzer via SASL mit DIGEST-MD5 anmelden zu lassen. Selten in einem Titel bereits so viele Akronyme gehabt. Deswegen der Reihe nach:

Aber das alles ist unter Umständen ja bereits bekannt - warum sonst solltest Du Dich auf diese Seite verirrt haben? Was mich immer dran geärgert hat ist, dass aus der OpenLDAP Dokumentation zwar hervor geht wie alles funktioniert, ein praktisches Einrichtungsbeispiel aber schlichtweg fehlt. Dies möchte ich an dieser Stelle nach holen.

Und als Beispiel soll an dieser Stelle DIGEST-MD5 auch völlig ausreichen - auf die anderen Möglichkeiten will ich hier in diesem Posting gar nicht weiter eingehen.

Für die ungeduldigen Leser: Ganz unten ist mein Dockerfile angefügt sowie die ldif Datei mit der man cn=config anpassen kann sobald der slapd läuft. Docker bzw. ldapadd usw. ist noch nicht ganz Deins? In der Dockerfile stehen oben in den Kommentaren passende Beispiele wie das laufen könnte.

Docker

Um solche Sachen zu testen nutze ich ganz gern einen Docker Container. Ich mag es einfach, dass ich Dinge testen kann ohne groß irgendwas an Software installieren zu müssen. Und wenn man fertig ist kann man den Container bzw. das Image einfach so löschen und alles ist wieder spurlos verschwunden als ob es nie dagewesen wäre.

Natürlich geht das ganze auch ohne Docker. Dazu einfach die Schritte aus der Dockerfile sinngemäß auf einem beliebigen slapd übernehmen.

Umsetzung

Um rasch einen OpenLDAP Docker Container zu bekommen verwende ich ganz gerne dieses Image: https://hub.docker.com/r/osixia/openldap/. Das ist Debian basiert, klein, schlank und richtet einen grundlegend vorkonfigurierten slapd Server ein. Wenn es schnell gehen muss oder man sich einfach die Arbeit sparen will selbst ein Image anzulegen: Meiner Meinung nach ein gutes Ausgangsimage!

Und was mache ich im Dockerfile? Wie gehabt, diese Schritte kann man ohne Docker sinngemäß auf dem Linux bzw. der Linux VM durchführen.

  1. Ich installiere das Debian-Paket sasl2-bin. Durch dieses Paket werden diverse Hilfstools rund um SASL installiert.
  2. Als Beispiel lege ich einen SASL Benutzer an sasladmin@slpad.ldap.
  3. Der Benutzer unter welchem Debian slapd laufen lässt wird in die sasl Gruppe mit aufgenommen. Eben damit er die sasldb auch tatsächlich lesen kann 😉
  4. Die SASL Konfiguration für OpenLDAP /etc/ldap/sasl2/slapd.conf wird angelegt und entsprechend mit den notwendigen Dateisystemsrechten versehen.
Entgegen dem Eindruck der aus der OpenLDAP Dokumentation entstehen könnte braucht man für DIGEST-MD5 keinen laufenden saslauthd. Das ist auch der Grund warum ich diesen Passus in der SASL Konfiguration übersprungen habe.

slapd.conf bzw. cn=config

Nun fehlen noch Änderungen an der slapd.conf selbst. Wer das alte Konfigschema verwendet muss die entsprechende slapd.conf Datei sinngemäß bearbeiten, für alle mit neuem cn=config Schema liegt die passende ldif Datei mit dabei. Das von mir verwendete Image verwendet bereits cn=config und da das Dockerfile den slapd-Server erst noch konfiguriert läuft dieser nunmal auch noch nicht. Somit ist die ldif über die üblchen Wege im LDAP-Server mit aufzunehmen nach dem der Container am laufen ist.

Und das steht im config.ldif drin:

  1. Zum einen setze ich eine Umschreibe-Regeln von dem SASL Benutzer auf einem LDAP internen Benutzer
  2. Diesen Schritt kann man weglassen, funktioniert auch ohne: Ich habe die Verwendung von sasldb explizit gesetzt.
#
# slapd Dockerfile inkl. SASL DIGEST-MD5
#

# Starten mit:
# docker build -t gmn-ldap --no-cache .
# docker run -p 127.0.0.1:389:389 --rm --name gmn-ldap gmn-ldap

# SASL Konfig in cn=config übernehmen
# ldapadd  -x -Dcn=admin,cn=config -wchangeme -f config.ldif
# ldapsearch -ZZ -Hldap://localhost -YDIGEST-MD5 -U sasladmin@slapd.ldap

# Suche mit:
# ldapsearch -ZZ -Hldap://localhost -x -Dcn=admin,dc=gmn,dc=ldap -wchangeme


FROM osixia/openldap

ENV \
   LDAP_ORGANISATION=gmn \
   LDAP_DOMAIN=gmn.ldap \
   LDAP_ADMIN_PASSWORD=changeme \
   LDAP_CONFIG_PASSWORD=changeme \
   LDAP_TLS_VERIFY_CLIENT=never


# Notwendige Tools installieren
RUN apt-get update && apt-get install -y sasl2-bin && apt-get clean

# sasldb anlegen sowie notwendige Datei-/Gruppenrechte setzen
RUN echo changeme | /usr/sbin/saslpasswd2 -c -u slapd.ldap sasladmin
RUN usermod -a -G sasl openldap
RUN echo "mech_list: EXTERNAL DIGEST-MD5 CRAM-MD5 PLAIN LOGIN" > /etc/ldap/sasl2/slapd.conf
RUN chown openldap.sasl /etc/ldap/sasl2/slapd.conf && chmod 0660 /etc/ldap/sasl2/slapd.conf

 

dn: cn=config
changeType: modify
add: olcAuthzRegexp
olcAuthzRegexp: uid=sasladmin@slapd.ldap,cn=digest-md5,cn=auth cn=admin,dc=gmn,dc=ldap

dn: cn=config
changeType: modify
add: olcSaslAuxprops
olcSaslAuxprops: sasldb

 

Test

Und so sieht es aus wenn man das jetzt testet, an einem einfachen ldapwhoami gezeigt:

$ ldapwhoami -ZZ -Hldap://localhost -x -Dcn=admin,dc=gmn,dc=ldap -W
Enter LDAP Password: 
dn:cn=admin,dc=gmn,dc=ldap

$ ldapwhoami -ZZ -Hldap://localhost -YDIGEST-MD5 -U sasladmin@slapd.ldap
SASL/DIGEST-MD5 authentication started
Please enter your password: 
SASL username: sasladmin@slapd.ldap
SASL SSF: 128
SASL data security layer installed.
dn:cn=admin,dc=gmn,dc=ldap

Im ersten Aufruf ganz normal via simple bind direkt an den LDAP-Server, im zweiten via SASL/DIGEST-MD5. Gut zu sehen ist der Benutzernamen sasladmin@slapd.ldap welcher dank der Umschreibung als cn=admin,dc=gmn,dc=ldap zurück geliefert wird.

stunnel: noch lange nicht ausgepopt

stunnel: noch lange nicht ausgepopt

Wer kennt das nicht? Irgendeine alte Software die betriebsnotwendig ist und schon seit geraumer Zeit keine Updates mehr bekommen hat. Und die dümpelt halt so vor sich hin. So lange alle Clients sich noch verbinden bzw. die Verbindungen zu anderen Servern aufgebaut werden können scheint ja alles wunderbar zu sein. Es scheint so. Bis irgendeiner meint seine TLS-Einstellungen zu aktualisieren...Und das ist gar nicht so unwahrscheinlich wenn man zum Beispiel den Empfehlungen des BSI folgen mag.Von SSL ist da schon lange keine Rede mehr und sogar TLSv1.1 fehlt neuerdings. Weitere Infos dazu siehe hier:

Besonders prekär ist es, wenn die Anwendung noch gegen openssl 0.9.x verlinkt ist. Damit geht maximal TLSv1.0. Ihr seht schon, das Unheil nimmt seinen Lauf sobald diese alte Software versucht verschlüsselte Verbindungen aufzubauen bzw. über verschlüsselte Verbindungen erreicht werden soll. Die Verbindung startet zwar, wird aber gleich wieder beendet. Meist sind die Fehlermeldungen im Log dazu wenig aussagekräftig.

Interesse daran wie man mittels tcpdump und openssl solche Verbindungsprobleme erkennen kann? Schreibt mir einfach (Mail oder Kommentar), dann reiche ich einen passenden Blogeintrag nach.

Und wie kann man das lösen? Ein Update der Software wäre möglich. Nur gibt es leider viele Gründe warum dies noch nicht passiert ist bzw. die nächsten Tage ebenfalls nicht passieren wird. Sind wir ehrlich zueinander: Das Verständnis dafür mag sich als Admin in Grenzen halten. Dennoch kennen wir alle die Situation. Die gibt es oft. Zu oft. Mit zu vielen Gründen.

Also gut, das geht so nicht. Also was tun wenn guter Rat teuer ist? Es gibt da so ein altes Sprichwort: "Wenn der Prophet nicht zum Berg kommt, dann kommt halt der Berg zum Propheten" (frei nach Francis Bacon 1625). Ein Update der Software ist nicht möglich, die Sicherheitseinstellungen der gegenüber liegenden Seite wird man wohl kaum reduzieren wollen. Bleibt also der Weg durch die goldene Mitte: Ein Proxy muss her! Der macht aus Klartext aktuelle Verschlüsselung, aus zu alter Verschlüsselung aktuelle Verschlüsselung oder, und das soll es ebenfalls geben: Aus alter Verschlüsselung gar keine Verschlüsselung. Auch hierfür gibt es Fälle wo das völlig ausreichend ist.

stunnel

Für solche Dinge nehme ich gerne stunnel (https://www.stunnel.org/). Der ist klein und schlank und läuft unter aller gängigen Unix/Linux Systemen als auch unter Windows. Das Tool gibt es bereits seit über 20 Jahren und wird immer noch aktiv entwickelt. Hut ab!

Ok, als ich das erste Mal mit stunnel zu tun hatte waren meine Beweggründe eher anders herum: Viele Webfrontends damals kannten noch gar keine Verschlüsselung. Also fix stunnel davor geschaltet und schon war die Seite via https anstatt http zu erreichen. Die Richtung ist aber genau genommen völlig egal - es gibt ein Grundprinzip welches man bei stunnel immer im Hinterkopf behalten muss: Auf der einen Seite ist verschlüsselt, auf der anderen Seite ist Klartext. Wer aus alter Verschlüsselung neue machen will braucht somit zwei stunnel: Einen der übers Netz alte Verschlüsselung an nimmt und Klartext nach localhost leitet. Auf localhost geht ein stunnel ran der Klartext nach aktueller Verschlüsselung umwandelt. Reicht eine der beiden Richtungen reicht logischerweise auch nur ein stunnel.

alpine

Kein Platz stunnel irgendwo mit drauf zu packen? stunnel kann zwar drauf funktioniert aber nicht wie erhofft da am Installationsort eine völlig veraltete openSSL Bibliothek installiert ist? Für sowas nehme ich ganz gerne alpine Linux. Klein, sehr, sehr schlank und bringt stunnel in den zusätzlichen Paketen mit. Egal ob als Mini-VM oder als Container: läuft 🙂

Infos zu alpine? Gibt es hier: https://alpinelinux.org/

Beispiel 1: pop3 mit STARTTLS

Genug der großen Reden, ein paar Beispiele müssen her! Die Konfig ist simpel: Zuerst ein paar globale Einstellungen und im Anschluss daran die jeweiligen Proxys. Das Format sollte jedem bekannt sein: Ini lässt grüßen.

;debug = info
;foreground = yes
;options = -NO_SSLv3
sslVersion = all
ciphers = ALL

[stls2pop3]
protocol = pop3
client = no
accept = 10110
connect = pop.gehirn-mag.net:110
cert = /etc/stunnel/stunnel.pem

Im globalen Abschnitt kann z.B. stunnel dazu gebracht werden im Vordergrund zu starten. Perfekt für Diagnose. Ansonsten habe ich hier nur sichergestellt, dass alles was "alte" Verschlüsselung ist verbinden darf.

Zum Proxy stls2pop3 selbst: Mir ist einmal eine Software begegnet die konnte POP3 und POP3S. Ok, POP3S ist raus. Nur wurde bei POP3, sobald angeobten, STLS (STARTTLS) verwendet. Logisch, ohne Schalter zum abstellen. Versteht sich. Oder auch nicht.

client auf no gestellt, es sollen eingehende Verbindungen verschlüsselt angenommen werden. Das soll für den Moment reichen, mehr Wissen braucht es zum client Schalter im Moment noch gar nicht. Mit accept wird der Port auf 10110 gestellt. Und via connect wird angegeben wohin stunnel sich bei eingehenden Anfragen letztendlich verbinden soll. In dem Beispiel steht ein ganz normaler Server welcher via POP3 angesprochen werden soll. Nur Moment, damit das funktioniert muss man beachten, dass bei POP3 für STARTTLS nur die Kurzform STLS verwendet werden muss. Das sollte man wissen. Und somit sollte auch stunnel darüber Bescheid wissen. Deswegen noch fix protocol auf pop3 gestellt. In der manpage zu stunnel.conf sind die Protokolle aufgelistet welche stunnel versteht: Eine ordentliche Menge. Die manpage kann hier nachgelesen werden: https://www.stunnel.org/static/stunnel.html#SERVICE-LEVEL-OPTIONS. Im Bereich "Service Level Options" einfach mal nach "protocol" suchen. Infos zum POP3 Protokoll uns STLS: https://de.wikipedia.org/wiki/Post_Office_Protocol#Verschl%C3%BCsselung.

Zu guter Letzt: Das Zertifikat via cert: Bei vielen Distributionen wird beim installieren bereits ein passendes angelegt. Das Zertifikat fehlt oder soll durch ein anderes ersetzt werden? Siehe stunnel HowTo im Abschnitt "Generating the stunnel certificate and private key (pem)": https://www.stunnel.org/howto.html.

Jetzt noch in der Anwendung rasch angegeben, dass der zu erreichende POP3 Server unter der IP-Adresse xxx.xxx.xxx.xxx bzw. folgendem DNS-Namen ... auf Port 10110 erreichbar ist. Und sehe wie die Anwendung über das hoffnungslos veraltete POP3 STARTTLS wieder verbindet. Ok, im Klartext auf das Ziel. Mag Situationen geben wo das reicht. Falls nicht lies einfach im nächsten Abschnitt weiter. In dem wird durch einen zweiten Proxy die Verschlüsselung auf neu getrimmt.

Beispiel 2: Aus https alt mach neu

So, ein Proxy reicht also nicht. Dann halt mit zwei: Aus https alt mach http Klartext welches nur über localhost sich verbindet. Und zwar auf einen zweiten Proxy welcher aus Klartext https neu macht.

;debug = info
;foreground = yes
;options = -NO_SSLv3
sslVersion = all
ciphers = ALL

[https_in]
client = no
accept = 10443
connect = localhost:54321
cert = /etc/stunnel/stunnel.pem

[https_out]
client = yes
accept = localhost:54321
connect = www.gehirn-mag.net:443
cert = /etc/stunnel/stunnel.pem

Das Prinzip Konfig wie gehabt. Zuerst der Kopf und dann der erste Proxy. Hier mit dem Namen https_in. Wie in Lösung 1 beschrieben macht der aus https Klartext http. Und verbindet sich als Ziel auf localhost:54321. An der Adresse lauscht der zweite Proxy https_out. Ein Unterschied gibt es: Hier steht client auf yes. Bei yes geht stunnel der Annahme, dass das Verbindungsziel Verschlüsselung benötigt. Somit ist der eingehende Teil die Klartextseite. Bei no ist das gerade anders herum (siehe manpage). Der Rest, oh Wunder, ist wie gehabt und bereits bekannt.

Noch fix das Ziel in der Anwendung geändert auf die Adresse des Proxyservers mit Port 10443 und schon wird aus https ganz arg alt https ganz arg neu gemacht.

Fazit

Und wieder mal die Welt gerettet. Dank einem kleinen, schlanken Tool. Das trotz seines Alters alles andere als ins Alter gekommen ist. Es ist kein Fehler in einem ruhigen Moment mal die Webseite und die Beispiele etwas genauer zu betrachten. So viele Dinge die man darüber hinaus mit stunnel noch machen kann. Es lohnt sich.

Monitoring nach Remote

Monitoring nach Remote

Monitoring nach Remote

Monitoring kann spannende Dinge überwachen. Funktioniert richtig toll solange das Ziel direkt via Netzwerk vom Monitorring aus erreichbar ist. Ein SMTP Server lauscht üblicherweise auf Port 25 und dort geht - oh Wunder - doch tatsächlich ein SMTP-Server ran. Lässt sich super mit einem Check prüfen welcher SMTP spricht. Nur was ist wenn es keinen Netzwerkdienst zu der überwachenden Komponente gibt? Solche Dinge wie der Füllstand der Festplatte, die Auslastung der CPU? Ein Agent muss auf das Zielsystem. Bleibt die Frage nach dem welchem. Ein kurzer Überblick der Möglichkeiten.

 

Ich beziehe mich in den folgenden Beispielen auf Icinga und Linux Systeme welche überwacht werden sollen. Als Monitoring-Software darf aber alles laufen was Nagios kompatible Checks verwenden kann. Also egal ob Nagios, Shinken, check_mk und wie Sie alle heißen mögen.

Icinga Agent

Wer ohnehin Icinga2 nutzt kann auch gleich den Icinga2 Agent nutzen. Der ist klein, schlank und sicher. Dazu ist er sauber in Icinga integriert. Klar, ist ja schließlich Icinga selbst. Hauptnachteil für mich: Der bläht die Zonenconfig immer so ungemein auf. Für einzelne Rechner wo man überwachen will gleich den großen Aufwand mit Zonen- und Endpoint-Config wagen? Kann man machen. Für alle ohne Icinga: ganz klar, hier muss was anderes her. Oder wechselt zu Icinga. Kann ich wärmstens empfehlen 😉

NRPE

Lange Zeit erstes Mittel der Wahl: NRPE, der Nagios Remote Plugin Executor (https://github.com/NagiosEnterprises/nrpe). Seit 2017 keine Änderung mehr. Wozu auch? Solange es funktioniert ist ja alles gut. Ja, NRPE ist simpel und einfach. Und da liegt vermutlich das Problem. Verschlüsselung gibt es, jedoch keine Authentifizierung. Lediglich das frei schalten von IP-Adressen welche Anfragen stellen dürfen. Dazu noch die tolle Problematik rund um dont_blame_nrpe. Jeder der das Konstrukt kennt weiß was ich meine. Ansonsten einfach mal nach dem Schalter in der Dokumentation suchen. Viel Spaß beim lesen 😉

Zusammengefasst: Kann man machen. Im abgeschlossenen Netzwerk hinter einer Firewall sollte Verschlüsselung und IP Filter reichen. Das Ding ist klein und schlank, die Problematik rund um dont_blame_nrpe haben genau genommen alle Remote Agent Lösungen. Dumm nur, dass bei aktuellen Distributionen wie z.B. SLES 15.1 der Trend dazu geht NRPE nicht mehr mit auszuliefern. Zu lange keine Änderungen an den Paketen heißt es in der Begründung. Dem Trend werden vermutlich weitere Distributionen folgen bzw. sind schon gefolgt. Als NRPE Nutzer sollte man wohl zumindest offen für anderes sein - jenachdem was die Zukunft einem zu bieten hat.

 

 

check_by_ssh

Oder nur by_ssh wie es innerhalb von Icinga heißt. Jemand schon mal bei NRPE das Problem gehabt, dass der Ausgabe Text gekürzt wurde? Weil die maximale Größe für die Ausgaben seitens Quellcode auf 1024 Zeichen beschränkt wurde? Und wie gelöst? By_ssh? Willkommen im Verein 😉

Oder auch anders ausgedrückt: Welches Linux-System hat keinen ssh Server am laufen? Wenn es im Netz steht und man Monitoring darauf ansetzt dürfte es das so gut wie nie geben. Die Problematik der NRPE Installation ist weg, die Sicherheit ist hoch: Verschlüsselung und Authentifizierung ist bei ssh einfach super gelöst. Die dont_blame-Problematik ist hier sinngemäß die Gleiche: Wenn man erlaubt Argumente zu übergeben könnte jemand Blödsinn machen. Könnte. Heißt ja nicht gleich "muss". Oder einfach keine Argumente zu lassen. Problem der Eventualität gelöst. Wo nichts ist kann auch niemand. Klingt super, oder? Naja, ein Problem fällt mir spontan dazu schon ein. Spaßverderber, ich weiß: Ich brauche einen Benutzer der sich via ssh anmelden kann.

Ok, das ist ja jetzt nicht so das Thema. Das Thema ist eher: Checks sind meistens irgendwelche Skripte, der Benutzer fürs Monitoring braucht somit eine Login-Shell. Der Benutzer kann sich also am System anmelden und Dinge tun die er aus Sicht des Monitoring gar nicht braucht. Wenn jetzt irgendjemand das Monitroing-System knackt und dort die Zugangsdaten fürs ssh ausliest oder den hinterlegten key entsprechend weiter verwendet... Ihr seht schon auf was ich raus will. Der Benutzer braucht also so irgendwas wie chroot mit nur den Checks und Bibliotheken drin die er braucht. Und vermutlich noch das proc-System weil da heraus solche Dinge wie Festplattenbelegung usw. heraus gelesen werden. Und was sonst noch alles so fehlt. Puh, ganz schön aufwendig.

Geht auch etwas anders: Für jeden Check einen eigenen Benutzer anlegen und dem via sshd-Config als auszuführendes Programm den entsprechenden Check hinterlegen. Oder die Login-Shell bei dem Benutzer auf den Check ändern. Irgendwas, was keine Anmeldung mehr in Richtung Shell mit der Möglichkeit der eigenen Befehlseingabe erlaubt.

Machbar also. Mit Aufwand. Ein Hoch auf Orchestrierungstools wie ansible, puppet, chef oder wie die alle auch heißen mögen.

SNMP

Ganz anderer Ansatz: SNMP kennt man. Drucker, Netzwerkkomponenten, diverse Appliances. Die alle haben SNMP drauf und das funktioniert doch super. Ok, in Version 2 mit Community-String ist die Sicherheit so naja. Aber spätestens mit v3 wo Authentifizierung und Verschlüsselung gefordert werden kann ist doch alles wunderbar. Und wenn dann der Monitoringbenutzer im SNMP-Baum unter seiner Kennung nur das findet was er fürs Monitoring braucht ist doch alles perfekt. Bleibt die Frage was mit den eigentlichen Checks fürs Monitoring ist.

Also der Reihe mal nach durchgehen: SNMP ist unter Linux rasch installiert. Von Haus aus gibt es bei Icinga bereits die Checks welche via SNMP CPU, RAM, Prozesse, Plattenplatz usw. auswerten können. Grobe Sicht auf das was die Hardware betrifft: Läuft. Und die speziellen Checks welche man ggf. sogar noch selbst programmiert hat? Ja, die laufen auch. Einfach in die Config mit aufnehmen, im Internet nach check_by_snmp suchen und wie analog zu NRPE oder by_ssh verwenden. Läuft ebenfalls (Links finden sich weiter unten).

Ok, braucht man einen snmpd-Dienst. Einen extra Dienst brauchst bei NRPE aber ebenfalls. Die Checks muss man in der Config definieren. Musst bei NRPE ebenfalls und wenn by_ssh "richtig" machen willst ja auch. Von daher tut das eigentlich nicht weh. Ein weiterer Vorteil gefällig? Systeminventarisierung welche via SNMP Systeme ermittelt? Klar, das kannst jetzt ebenfalls machen. Ein spezielles Überwachungstool welches zusätzlich zum Monitoring läuft und ebenfalls SNMP kann? Na logisch doch, kein Problem. Und ich kenn sogar noch eine GroupWare Lösung welche via Webfrontend überwacht werden kann. Oder via AgentX Schnittstelle den lokal installierten SNMP erweitert. Somit ohne speziellen Checks am Monitoring dran. Das macht Laune, weil das funktioniert mit jeglichem Monitoring welches SNMP kann.

Fazit

SNMP ist viel spannender als man zunächst ggf. vermutet hätte. Jeder der das bisher noch nicht nutzt sollte es zumindest mal anschauen. Es lohnt sich!

Und Windows?

Hier gibt es ebenfalls SNMP. Was der so alles kann und ob bzw. wie man den erweitert weiß ich nicht wirklich. Gerne Kommentare dazu her!

Ich selbst nutze dafür bisher eigentlich immer diesen Weg: https://icinga.com/docs/icinga2/latest/doc/07-agent-based-monitoring/#nsclient-on-windows. Dank Icinga Agent ist die Übertragung gesichert und man kann über nscp ohne großen Aufwand alles mögliche Rund um Windows abfragen.

Testen

Ich nehme inzwischen ganz gerne um so etwas zu testen einen Docker Container. Hat den Vorteil, dass ich den Dienst in einem Container starten und falls ich den nicht mehr brauche einfach löschen kann. Ebenso unkompliziert ist es kurzerhand einen zweiten Dienst mit anderer Konifg parallel zu starten falls man was probieren möchte. Geht aber auch ohne Docker. Für alle mit Docker bzw. Docker interessierten füge ich hier mal meine docker-compose und dockerbuild Datei an:

Ginge auch ohne compose - zumal ich mit nur einem Container ausgekommen bin 😉

#
# Gehirn-Mag.Net snmpd
#

version: '3'

services:

   snmpd:
      build:
         context: .
         dockerfile: snmpd.Dockerfile
      ports:
         - "127.0.0.1:161:161/udp"
      volumes:
         - ./volumes/etc_snmp/:/etc/snmp/

 

Mein Docker-Container basiert auf Ubuntu 18.04. Sollte ein Proxy notwendig sein um das Internet zu erreichen einfach die beiden Proxy-Zeilen entsprechend anpassen.

FROM ubuntu:18.04

# Notwendige Software installieren
#ENV http_proxy=http://xxxx:xxxx@10.1.1.1:3128/
#ENV https_proxy=http://xxxx:xxxx@10.1.1.1:3128/
RUN apt-get update && apt-get install -y snmpd snmp-mibs-downloader snmp openssl monitoring-plugins git wget
RUN git clone https://github.com/dnsmichi/manubulon-snmp.git /usr/lib/nagios/plugins/manubulon
RUN wget "https://exchange.nagios.org/components/com_mtree/attachment.php?link_id=3121&cf_id=29" -O /usr/lib/nagios/plugins/check_by_snmp && chmod -v 0755 /usr/lib/nagios/plugins/check_by_snmp
RUN ln -sv /usr/lib/nagios/plugins/manubulon/plugins/*.pl /usr/local/bin
RUN ln -sv /usr/lib/nagios/plugins/check_snmp /usr/local/bin
RUN ln -sv /usr/lib/nagios/plugins/check_by_snmp /usr/local/bin

# snmpd vorbereiten und starten
ENV MIBSDIR=/usr/share/snmp/mibs:/usr/share/snmp/mibs/iana:/usr/share/snmp/mibs/ietf:/usr/share/mibs/site:/usr/share/snmp/mibs:/usr/share/mibs/iana:/usr/share/mibs/ietf:/usr/share/mibs/netsnmp
RUN /bin/mkdir -pv /var/run/agentx
CMD /usr/sbin/snmpd -Lo -u Debian-snmp -g Debian-snmp \\
    -I -smux,mteTrigger,mteTriggerConf -f

Im Container selbst sind dann die Manubulon Checks sowie check_snmp und check_by_snmp nach /usr/local/bin verlinkt. Zum testen also einfach direkt die Checks aufrufen.

Meine Beispiels snmpd.conf. Mit v2 Community "icinga" sowie einem v3 Benutzer "icinga" und Passwort "abcde%12345".

#
# Gehirn-Mag.Net Beispiel snmpd.conf fürs Monitoring
#

#######################################
#
# Allgemeine Einstellungen
#


# Auf *:161 lauschen
agentAddress udp:161

#######################################
#
# Auth: 1x SNMPv3, 2x community
#


# system, interfaces, host, ucdavis, nsExtendObjects
view icinga included .1.3.6.1.2.1.1
view icinga included .1.3.6.1.2.1.2
view icinga included .1.3.6.1.2.1.25
view icinga included .1.3.6.1.4.1.2021
view icinga included .1.3.6.1.4.1.8072.1.3.2


# Die folgende Zeile "createuser..." sollte besser in /var/lib/snmp/snmpd.conf stehen
# Und das Passwort sollte sinnigerweise angepasst werden ;-)
createUser icinga SHA "abcde%12345" AES
rouser icinga default -V icinga
rocommunity icinga default -V icinga


# public darf nur die sysDescr sehen ;-)
view public included .1.3.6.1.2.1.1.1.0
rocommunity public default -V public


#######################################
#
# Build in - ein paar Beispiele
#


# System Informationen
sysLocation GMN-RZ/WDD
sysContact Mein.Gehirn-Mag.Net <mein@gehirn-mag.net>
sysServices 72


# Process Monitoring
proc snmpd


# Disk Monitoring
disk / 20%
includeAllDisks 10%


# System Load
load 12 10 5

#######################################
#
# Erweiterungen
#


extend check_disk /usr/lib/nagios/plugins/check_disk -w 20% -c 10%
extend check_critical /usr/lib/nagios/plugins/check_procs -C gibtesnicht -c 1:

 

In der dritten Registerkarte direkt über diesem Abschnitt findet sich die von mir verwendete snmpd.conf. Diese kann auch ohne Docker als Ausgangsbasis für eigene Tests verwendet werden.

Zum testen ist noch ein v2 Zugang mit icinga als Community String enthalten, ebenso steht der v3 Zugang direkt in dieser Konfigdatei. Diese sollte aber, wie im Kommentar erwähnt entsprechend in die zweite snmpd Konfig verschoben werden. Die vollständige Doku zur Konfig gibt es hier: http://www.net-snmp.org/docs/man/snmpd.conf.html

"Allgemeine" Checks

Für Checks wie CPU, Plattenplatz usw. verwende ich gerne die SNMP-Checks von Manubulon. Diese sind z.B. in Icinga2 bereits enthalten. Ansonsten finden diese sich hier: http://nagios.manubulon.com/. Leider sind diese nicht mehr aktuell gepflegt, deswegen greife ich gerne auf diesen Fork von einem der Icigna Entwickler zurück: https://github.com/dnsmichi/manubulon-snmp. Diese sind ebenfalls im Container installiert und wären nach /usr/local/bin verlinkt.

Ein paar Beispiele dazu:

root@0b99c3febe7b:/# check_snmp_load.pl -H localhost -2c -C icinga -Tnetsl -w 1,1,1 -c 2,2,1.5
Load (CPUs: 4) : 0.56 1.00 1.34 : OK
root@0b99c3febe7b:/# check_snmp_mem.pl -H localhost -2c -C icinga -w 20,20 -c 30,30
Ram : 87%, Swap : 26% : > 30, 30 ; CRITICAL

Das funktioniert schon mal wunderbar 🙂

 

 

 

 

check_by_snmp

Um nun "eigene" Nagios-Checks einzufügen muss man lediglich in der Config einen Eintrag der Form "extend <check_name> <check_command mit args>" aufnehmen. In dem Beispiel von mir finden sich folgende zwei Zeilen:

extend   check_disk     /usr/lib/nagios/plugins/check_disk -w 20% -c 10%
extend   check_critical /usr/lib/nagios/plugins/check_procs -C gibtesnicht -c 1:

Vom Grundsatz her sieht das zu NRPE ja sehr ähnlich aus. Fehlt noch das passende Gegenstück zu check_nrpe bzw. check_by_ssh. Das gibt es hier: https://exchange.nagios.org/directory/Plugins/%2A-Remote-Check-Tunneling/check_by_snmp--2F-check_snmp_extend--2F-check_snmp_exec/details. In dem Beispiel-Container ist das, wie bereits erwähnt, ebenfalls nach /usr/local/bin verlinkt. Also einfach aufrufen. Und so sehen die beiden Beispiele aufgerufen aus:

root@0b99c3febe7b:/# check_by_snmp -H localhost -2 -C icinga -E check_disk
DISK WARNING - free space: / 30394 MB (20% inode=93%);| /=120929MB;127595;143544;0;159494
root@0b99c3febe7b:/# check_by_snmp -H localhost -2 -C icinga -E check_critical
PROCS CRITICAL: 0 processes with command name 'gibtesnicht' | procs=0;;1:;0;

Auch das funktioniert super! Mehrzeilige Ausgaben, der richtige Exit-Code: Kommt alles sauber mit rüber.

 

 

Sonstiges

Das war ja schon mal einiges was man damit tun kann. Es geht aber noch etwas mehr. Ich habe bei den Beispielen mit extend immer einen vollwertigen Nagios-Check aufgerufen. Das darf aber natürlich auch ein ein Skript sein welches zum Beispiel nur einen Integer Wert zurück liefert. Dieser kann dann mit check_snmp abgerufen und entsprechend weiter aufbereitet werden. Die Doku dazu gibt es hier: https://www.monitoring-plugins.org/doc/man/check_snmp.html. Der ist bei vielen Monitoringlösungen bereits mit dabei und ihr ahnt es ja bereits: Innerhalb von Icinga hießt der nur snmp.

Finale

Neben der Zugriffskontrolle die man wie so oft natürlich entsprechend umfangreich aufblähen kann ist der Rest der snmpd.conf jedoch eher kurz und übersichtlich gehalten. Also innerhalb kürzester Zeit machbar. Meiner Meinung nach lohnt es sich also SNMP als Alternative zu NRPE und check_by_ssh auf dem Schirm zu haben.

Icinga2 vs. PNP

Icinga2 vs. PNP

Icinga2 ist eine praktische Sache, darüber braucht es vermeintlich keine Diskussionen. Eine einfache Lösung für die Darstellung von Performance-Daten ist PNP (ehemals PNP4Nagios). Nur ist diese Kombination bei Checks via nrpe oder by_ssh zunächst zickig.

Die dazugehörigen Links:

Wo das Problem dabei liegt? Jeder der diese Kombination am laufen hat wird die Erkenntnis getroffen haben, dass das Template welches PNP verwendet logischerwiese nrpe oder by_ssh lautet. Genau genommen logisch da der ausgeführte Check halt nun mal nrpe oder by_ssh heißt. Ok, dass die beiden so zunächst nur Mittelsmänner für den eigentlichen Check sind ist der Kombi Icinga2 und PNP an der Stelle schlichtweg egal...

Auf zur Lösung

Was kann man also tun? Man kann sich seine eigenen CheckCommands definieren die dann den passenden Namen haben und für diesen ein PNP Template hinterlegen. Das ist aber umständlich und macht zumindest mir wenig Spaß. Und das geht auch besser: Die PNP Templates werden in php geschrieben. Eine Programmiersprache... Also kann da auch Programmiercode mit rein welcher Entscheidungen trifft und nicht nur Layout entwirft...

Also fix ans Werk gemacht: PNP sieht als Check ja nur nrpe bzw. by_ssh. Woran erkenne ich was das für ein Check eigentlich war? Richtig, ein Blick in die zugehörige xml-Datei hilft. Da steht zum Beispiel die Datasource als auch der Name der rrd-Datei drin. Und letztere trägt den Namen des eigentlichen Checks. Bingo, Treffer: Schiff versenkt.

Uns so wird es gelöst: Ein Template namens by_ssh.php oder npre.php mit folgender Logik erstellt:

  • Ermitteln des Check-Namens anhand der verknüpften rrd-Datei
  • Suchen eines Templates mit Namen des Checks an den noch ein .php angefügt wurde
    • Gefunden? Dann dieses Template per php include einfügen und fertig
    • Nicht vorhanden? Dann einfach das Default Template einfügen

Fertig und funktioniert. Den Quellcode gibt es hier: https://gitlab.com/Gehirn-Mag.net/pnp-by_ssh-or-nrpe-template. Oder hier:

<?php

#
# A clever template for PNP which selects the correct template for by_ssh or 
# nrpe. Just rename or link the file to nrpe.php if needed ;-)
#

#
# MIT License
#
# Copyright (c) 2019 Steffen Schoch <mein@gehirn-mag.net>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#


// Adjust these both to your needs
$templatePath = '/etc/pnp4nagios/templates';
$templateDefault = '/usr/share/pnp4nagios/html/templates.dist/default.php'; 

// Check if template for the used rrd file exists
if(preg_match('/([^\\/]+)\\.rrd$/', $RRDFILE[1], $matches)) {
    // Some debug information if needed
    //throw new Kohana_exception(print_r($matches,TRUE));
    $templateFile = $templatePath . '/' . $matches[1] . '.php';
    if(is_file($templateFile)) {
        // template found, so use it
        include($templateFile);
    } else {
        // nothing found, use default template
        include($templateDefault);
    }
}

Einfach im PNP Template Ordner als by_ssh.php oder nrpe.php ablegen. Da eh gleicher Inhalt: Das kann verlinkt werden. Funktioniert logischerweise auch für alle anderen Templates mit gleichem Problem.

Mehr zum Thema Monitoring gefällig? Gibt es zum Beispiel hier: https://gehirn-mag.net/category/monitoring/.

keepalived manual failover

keepalived manual failover

keepalived ist eine einfache Lösung einen HA-Cluster z.B. unter Linux zu betreiben (https://www.keepalived.org/). Jedoch kennt dieser von Haus keinen Weg für einen manuellen failover. Es folgt eine Auflistung verschiedener Möglichkeiten dennoch das Ziel zu erreichen.

1. Dienst anhalten

Wenn man in der keepalived Konfiguration einen Dienst überwacht kann man diesen schlichtweg stoppen. Der Cluster schwenkt logischerweise sinngemäß. Aber halt, das ist nicht ganz ideal wie folgende Beispiele zeigen:

  • Wenn man schwenkt weil man Updates einspielen will hat man ein Problem wenn man den vermeintlich überwachten Dienst für die finalen Tests starten möchte. Das geht zwar, jedoch schwenkt dann keepalived zurück. Der "Test" ist somit die laufende Produktion. So lange alles gut geht: Toi, toi, toi 😉 Falls nicht: Ooops.
  • Ich habe einige Dienste am Laufen die einiges an Zeit brauchen um sich zu beenden. Zuletzt läuft zwar noch der Netzwerkport und der Dienst steht logischerweise auch noch in der Prozesstabelle - aber Anfragen werden nicht mehr beantwortet. In genau dieser Zeitspanne hat man dann also eine Produktionsausfall. Anmerkung dazu: Die meisten keepalived Skripte die ich kenne prüfen schlichtweg auf das vorhanden sein des Programms in der Prozesstabelle und/oder ob am zugehörigen Port jemand lauscht. Ob vernünftige Antworten auf Anfragen kommen wird meistens nicht überwacht. Das ist zugegebener Maßen aber auch nicht wirklich einfach zu überwachen: Was ist wenn der Dienst, warum auch immer, gerade einfach mal etwas länger braucht um die Antwort zu liefern wie sonst? Wie lange soll die Prüfung warten und ab wann schwenken? In der Zeitspanne die hier gewartet wird könnte der Dienst bereits wieder weg sein. Kurzum: Prozess- und Portüberwachung macht Sinn, "sinnvolle" Antworten nur bedingt. Das sollte genau abgewogen sein ob und in wie weit das sinnvoll ist. Das wäre aber ein anderes Thema. Zurück zum Ausgangspunkt: Auch diese Variante ist alles andere als toll.

Zusammengefasst: Als Test mag Dienst stoppen ausreichend sein, wirklich praktikabel für Updates und der gleichen ist das allerdings nicht.

2. keepalived Priorität

Ein anderer Weg ist in der keepalived Konfiguration die Priorität eines Nodes anzupassen. Man muss letztendlich nur dafür Sorge tragen, dass der Node welcher die Rolle übernehmen soll die höchste Prio hat. Aber mal ehrlich: Will man das so? Im keepalived was ändern und diesen neu starten für einen manuellen failover? Nein, das will man sicherlich nicht!

3. Eigenes Skript

Zu guter Letzt könne man ein Skript erstellen welches den weight anpasst. Also Skript starten und z.B. falls die Datei /etc/keepalived.myweight existiert die Wichtung um den in der Datei angegebenen Wert ändern. Ja, das geht. Nur müsste man so ein Skript noch schreiben. Und ob der Aufwand so wirklich lohnt... 😉

dummy-Netzwerkkarte

Es geht aber auch ganz anders ohne großartig irgendwas an Software schreiben zu müssen. Der Kernel bringt hierfür bereits alles passende mit: Die Netzwerkkarte "dummy". Details z.B. per "modinfo dummy" bzw. in der zugehörigen Kerneldokumentation. Sobald das Modul geladen ist kann die Netzwerkkarte dummy0 entsprechend mit einer beliebigen und nirgends sonst wo verwendeten IP belegt werden. Ich habe hier einen SLES am laufen, dort kann das via Yast2 entsprechend erledigt werden. Aber auch bei Debian/Ubuntu kann man dummy-Karten mit den üblichen Werkzeugen anlegen. Einfach mal in die Doku rein schauen, das sollte sich finden lassen.

Zu Letzt muss noch die keepalived.conf angepasst werden:

track_interface {
em1
dummy0
}

Die Liste meiner track_interface Karten wurde einfach um dummy0 erweitert. Jetzt reicht ein einfaches ifdown dummy0 oder ip link set dummy0 down und keepalive schwenkt auf den anderen Node. Ein ifup dummy0 bzw. ip link set dummy0 up und schon kommt er wieder zurück. Ganz ohne irgendwelche zusätzlichen Skripten.

 

Wildes Let’s Encrypt

Wildes Let’s Encrypt

Let’s Encrypt Zertifikate sind inzwischen fürs Webhosting weit verbreitet: Die Akzeptanz ist hervorragend, die Erstellung sowie regelmäßigen Verlängerungen sind gut automatisierbar. Außer bei den inzwischen angebotenen Wildcard-Zertifikaten. Hier ist Handarbeit angesagt. Oder doch nicht? (mehr …)

check_ntp_time Offset unknown

check_ntp_time Offset unknown

Irgendwie kommen Freitags regelmäßig die Kuriositäten des Monitorings bei mir auf den Tisch. Heute zum Thema NTP: Der check_ntp_time aus den nagios-plugins wirft einen Offset unknown Fehler. Obwohl die Uhrzeit richtig wäre. Also mal nachgeschaut was da los ist. (mehr …)

Nextcloud Auto-Update via cli

Nextcloud Auto-Update via cli

Ich habe einige Nextcloud Instanzen am laufen (https://nextcloud.com/). Und es erscheinen ebenso regelmäßig irgendwelche Updates. Das ist ja auch gut so weil zum einen Sicherheitslücken geschlossen werden, zum anderen zum Teils richtig nette Funktionen mit dazu kommen. Sobald in der Testumgebung alles geklappt hat und richtig läuft kommt die Fleißarbeit: Die ganzen Nextcloud Instanzen von Hand updaten. Hier hört der Spaß allerdings ganz schnell auf – bei mir zumindest. (mehr …)