HOWTO: Deadlocks vermeiden

Vorwort

Ich hatte mal wieder das Vergnügen zu analysieren, warum sich auf einem MSSQL Server drei unterschiedliche Applikationen im Sekundentakt mit Deadlocks blockiert haben. Die Literatur dazu ist vielfältig, hat mir im Speziellen aber wenig geholfen. Daher fasse ich hier mal in einfachen Worten zusammen, wie ich die Deadlocks aufgelöst habe. Das Ganze hat keinen Anspruch auf Vollständigkeit oder korrektes „Wording“.

Voranalyse

Deadlocks können immer auftreten und stellen normalerweise kein Problem dar (fehlertolerante Anwendungen vorausgesetzt). Zu Problemen kommt es bei gehäuften Auftreten. Die Erkennung und Behandlung von Deadlocks kostet einfach Zeit. Im „schlimmsten“ Produktivfall dauerte es über 10 Sekunden bis ein Deadlock in der Anwendung aufschlug.

Wenn gleichzeitig mehrere Deadlocks auftreten, muss man diese nacheinander „auflösen“. Wenn man „Glück“ hat, lösen sich „Folgedeadlocks“ gleich mit auf. Um das „richtige“ Deadlock zu finden unterteile ich die Deadlocks in zwei Klassen:

  • Ablauf-Deadlock: der klassische Fall. Ein Begin Transation und Commit sind nötig. Diese gehe ich meistens erst im zweiten Schritt an.
  • Zugriffs-Deadlock: Diese Deadlocks werden dadurch verursacht wie dar SQL-Server auf die Daten zugreift. Immer wenn ein Entwickler sagt „Der gleiche Code produziert unter Oracle keine Deadlocks“, hat man so einen Kandidaten. Meistens kann man diese ohne größere Eingriffe in die Applikation auflösen.

Zuverlässiger erkennt man diese Zugriffs-Deadlocks jedoch an dem beteiligten QueryPlan. Dazu muss man wissen, dass der SQL-Server jedes Statement mit einer eigenen Transaction „sichert“ um konsistent auf die Datenbestände zuzugreifen. Als Konsequenz daraus folgt: man kann nicht auf Daten zugreifen (Delete, Update, Insert) ohne Locks zu erzeugen. Daraus folgt wiederum, Statements die viele IO-Ops haben (lesen, schreiben), erzeugen auch viele Locks, die Chance auf ein Deadlock steigen.

Konkret: Es wird folgendes Statement ohne explizite Transaktion von mehreren Prozessen konkurrierend ausgeführt.

UPDATE test_table SET date_value= @Date WHERE name= @Name

In der Theorie (und bei Oracle) darf hier nie ein Deadlock auftreten. Im schlimmsten Fall aktualisieren alle Prozesse die gleichen Rows und der „letzte“ Prozess gibt „die neue Warheit“ vor. Unter MS-SQL hagelt es Deadlocks. Das Statement kann nicht in eine atomare Operation umgesetzt werden. Erst müssen die zu verändernden Rows gefunden und anschließend die Änderung durchgeführt werden. Um einen konsistenten Zugriff auf die Daten zu bekommen benutzt der SQL-Server Shared Locks. Wenn die Spalte „name“ nicht indiziert ist, wird es einen FullTableScan geben. Ein SharedLock „wandert“ durch die Tabelle (und in Abhängigkeit des verwendeten Isolationslevels bleiben die Locks bestehen), dort wo die Where-Clause matched gibt es ein UpdateLock und wenn es dumm kommt, blockieren sich dabei zwei Prozesse zu Tode.

Zusammenfassend formuliert: jede IO-Operation erzeugt ein Lock. Damit hat man gleich zwei Gründe diese zu vermeiden. Das bedeutet aber auch, dass die gleichen Maßnahmen zur Zugriffsoptimierung auch bei Deadlock-Problemen helfen können.

Statement tuning

Der erste Ansatz zielt auf die oben beschriebene IO-Ops/Lock-Problematik ab. Man lässt sich via Error Trace die Statements raus, die an den Deadlocks beteiligt sind und ermittelt sich die Kandidaten mit der höchsten IO-Last (entweder über die Cached Plans-Statistik oder über eine einfache Plananalyse). Diese Statements tuned man anschließend mit passenden Indizes.

Dummerweise macht einem der QueryOptimiser bei kleinen Tabellen einen Strich durch die Rechnung. Der Optimizer versucht (vereinfacht gesagt) die IO-Ops runter zu bekommen. Bei kleinen Tabellen kann es sinnvoller sein einen Full Table Scan zu machen, anstatt einen Index-Seek und Key-Lookup zu machen. Das hat mir schon ein paar mal den Tag versaut.

Ein Beispiel: Eine kleine Tabelle (nur eine Page) wird zur Kommunikation zwischen Prozessen benutzt. Ein Index ist so eingerichtet, das jeder Prozess direkt auf die ihm zugeordneten Rows zugreifen kann. Beim Auslesen der „zu verarbeitenden Werte“ müssen alle Spalten selektiert werden. Aus diesem Grund war der QueryOptimizer auf normalem Weg nicht dazu zu bringen, den Index für die Where-Bedingung zu benutzten. Ein Umstellen der Abfrage nach der Art „SELECT PrimaryKey FROM Table WHERE“ mit anschließendem „SELECT * FROM Table WHERE PrimaryKey =“, um die Nutzung des Index „sanft“ zu „erzwingen“, war nicht möglich. Es blieb nur die Möglichkeit der Applikationen eine View unter zu jubeln, die mittels WITH(INDEX ( ))-QueryHint die Nutzung des Index erzwingt. In Folge dieser Optimierung ging die IO-Last um 20% hoch und die Ausführungszeit des Statements stieg auch um wenige MilliSekunden. Der QueryOptimizer hatte also Recht, den Index nicht zu nutzen ist performanter. Mit Index-Nutzung treten jedoch keine Deadlocks mehr auf (vorher gab es mehre Deadlock alle 10 Sekunden), der Gesamtdurchsatz über die Tabelle stieg dadurch um den Faktor 10. Die höhere IO-Last war damit zu ignorieren.

Eine weitere Möglichkeit der Optimierung ist die Separierung der Indizes. Das ganze zielt in die gleich Richtung wie der Ansatz mit dem Index-Erzwingen. Man führt mehr Indizes als eigentlich nötig um zu verhindern das ein Lese-Lock auf einem Index gelegt wird, der für den Schreibzugriff benötigt wird bzw. umgekehrt. Eine Änderung im Clustered-Index/RawTable soll sich nicht auf eine LeseOperation durchschlagen. Das ganze funktioniert nur wenn die beiden konkurrierenden Statements unterschiedliche Where-Clauses verwenden oder man eine Indexnutzung erzwingt.

Zugriffe und Abläufe optimieren.

Auch wenn die Entwickler es gerne leugnen, verneinen, ignorieren und unzählige Frameworks einführen und nutzen um es zu kaschieren, am Ende entscheiden sie mit ihrer Art des Zugriffs, wie gut der Datenzugriff erfolgen kann. Wenn man also alle Scan – Operationen beseitigt hat, Indizes separiert und optimiert hat und immer noch Deadlocks auftreten, ist es an der Zeit mit dem Entwickler zu Reden und die Abläufe und Datenzugriffe in der Applikation zu optimieren.

Relativ einfach aufzulösen sind Konstrukte der folgenden Art: Lese N Einträge aus einer Tabelle, markiere sie, verarbeite sie und quittiere die Verarbeitung. Im schlimmsten Fall alles in einer großen Transaktion. Es kann performanter sein, nur einen Datensatz zu lesen und zu markieren (inklusive COMMIT) und anschließend in einer neuen Transaktion die Verarbeitung durchzuführen und zu Quittieren. Da man immer nur einen Datensatz sperrt, ist die Chance eine Deadlocks geringer und der Durchsatz kann steigen.

In die Kategorie „schwer zu detektieren aber einfach zu lösen“ fällt die Optimierung der Lock-Reihenfolge bzw. in welcher Reihenfolge wird welche Resource blockiert. Dies kann durch einfaches umsortieren der Statements erfolgen oder mit LockHints (UPDLOCK, XLOCK). Es kann sinnvoll sein möglichst früh ein Update- oder Exclusive-Lock zu holen um spätere Verklemmungen oder gar Deadlocks zu verhindern. Einmal gefunden lassen sich diese Änderung meist ohne großen Aufwand in der Applikation umsetzten.

Richtig kompliziert wird es erst bei Zugriffsoptimierung.
Eins vorweg: eine Zugriffs-Optimierung kann man auch ohne Zutun der Entwickler umsetzten. Mittels View oder „QueryPlan-Forcing“ kann man der Applikation immer die Zugriffs-Variante unterschieben, die man für „optimaler“ hält. Allerdings muss man diese Optimierung bei jedem Software-Update erneut vornehmen. Sobald der Entwickler sich dieser Optimierung bewusst ist (und sie auch versteht) laufen die Updates wesentlich entspannter.

Im Kern geht es auch in dieser Kategorie darum den Zugriff auf Daten zu separieren. Dabei unterteilt man Vertikale und Horizontale Partitionierung.

  • Vertikale Partitionierung: Eine große Tabellen (viele Rows) wird in mehre kleine Tabellen zerlegt. Ziel ist, das die Partitionen so angelegt sind, dass die Applikation nur selten mehrere Partitionen selektieren muss. Ein Beispiel für so etwas sind Auftragsdaten. In einem System gibt es meist 3 Arten von Auftragsdaten: Die Vorschau, die aktiven Aufträge und die archivierten Aufträge. Die Vorschau und die aktiven Aufträge halten sich mengenmäßig meist in Grenzen, die Archivdaten explodieren hingegen meistens. Die BuisinessLogic wird aber fast immer nur die aktiven Aufträge selektieren. Selbst der Benutzer wird sich hauptsächlich um die aktiven Aufträge kümmern und nur selten auf die Archivdaten zugreifen. Die Folge: Es existieren unnötige große Indizies, die Datenzugriffe erfolgen über viel zu große Datenmengen, die Latenz geht hoch, die Chance für Deadlocks steigen. Sinniger ist es die Archivdaten von den aktiven Daten zu trennen (zwei oder drei Tabellen) und die Datenbestände ganz bewusst in der BL zu überführen (delete aus der QuellTabelle – Insert in die FolgeTabelle) und nur im Sonderfall alle Daten zu Selektieren.
  • Horizontale Partitionierung: Gerade moderne Frameworks (z.B. das EntityFramework) verleiten dazu Daten aus unterschiedlichen logischen Kontexten physikalisch in einer Entität abzulegen (Schlagwort: Vererbung und Discriminator). Die Folge sind „sehr Breite“ Tabellen.
    Ein Beispiel: Eine (kleine, Hobby) Autovermietung führt in einer Tabelle die Basis-Fahrzeugdaten (Baujahr, Typ, Modell …), Lebensdaten (letzter Kilometerstand, letzte Reparatur, aktueller Benutzer …) als auch (weil es so Fancy ist) die aktuellen Telemetriedaten (GPS – Speed, Coords, …). Das sind eine Reihe von Zugriffen aus unterschiedlichen Kontexten mit vollkommen unterschiedlicher Zugriffs-Art und Frequentierung.

    • Die Basis-Daten werden einmal Geschrieben, defacto nie geändert und maximal gelöscht, dafür aber sehr häufig in großen Blöcken gelesen (Auflistung der Fahrzeuge)
    • Die Lebensdaten werden regelmäßig aktualisiert und gezielt (über Fahrzeugkennung – indiziert) ausgelesen.
    • Die Telemetriedaten werden permanent (scheiß auf Datenvolumen) geschrieben und nur im Sonderfall ausgelesen.

    Das kann man (bei großen Tabellen) kaum unter einen Hut bringen. Sinnvoller ist es die Daten in unterschiedliche Tabellen Auszulagern und über „1 zu 1“-Beziehung zu verknüpfen. So schlagen die häufigen Updates nicht auf die häufigen Reads durch (und umgekehrt).

Einen Nachteil hat die gezielte optimieren jedoch. Man muss aufpassen, dass man eine Seite nicht übervorteilt. Wenn man die Zugriffe einer Applikation stark optimiert hat (über indizies oder Zugriffsanweisungen), kann es passieren, das die konkurrierende Applikation „verhungert“. Also immer beide Seite Betrachten und optimieren.

TSQL Deadlocks tracen lassen

Wer mal wieder beim MSSQL Server Deadlocks nachspüren muss, hat mehrere Möglichkeiten. 0ft wird der SQL Profiler empfohlen. Ich persönlich finde das ErrorTrace des SQLServers sinnvoller. Dazu muss man das Deadlock-Tracing über das folgende Statement aktivieren:

DBCC TRACEON(1204, 1222, -1)

Anschließend wird bei jedem Deadlock im ErrorLog der komplette Deadlock-Graph ausgegeben. Anders als im Profiler stehen hier aber zusätzliche Informationen zur Verfügung. Extrem nützlich dabei ist die Auflistung der beteiligte Indizes und Sperr-Objekte und die Statements die von dem Deadlock betroffen sind. Bei komplexen Statements oder StoredProcedure bekommt man so die „Line of Code“ die die Probleme verursacht.

network-manager speichert Passwort nicht

Eine kleine Unschönheit beim Upgrade hab ich beim NetworkManager unter xubuntu festgestellt.

Ich nutze Zertifikate um mich an meinem WLAN anzumelden (Radius). Diese setzen ein Password vorraus (anders lässt es der NM eigendlich nicht zu). Leider war das NM-Applet partou nicht in der Lage, eine ordentliche Config-File zu erzeugen, bei der das Password so hinterlegt wurde, dass das WLAN noch vor der Anmeldung verbunden werden konnte.

Dem konnte ich nur manuell beikommen. Unter /etc/NetworkManager/sysem-connections/ liegen die Config-Files. Die entsprechende Datei öffnen und manuell den passenden Parameter setzten
private-key-password=SuperSicher;)

HTPC mit Ubuntu 14.04

In den letzten zwei Wochen hab ich alle meine Rechner auf Ubuntu 14.04 umgestellt. Eine richtige Bruchlandung hab ich dabei nur bei meinem HTPC (auf Basis XBMC) erlebt. Hier eine kurze Zusammenfassung.

Da mein HTPC minimal aufgesetzt ist und keine unnötigen Dienste enthält hab ich erst mal versucht ein einfaches Upgrade aus dem System heraus zu machen. Die hätte den Vorteil gehabt, dass ich mir die folgenden 4 Stunden sparen hätte können. Das nvidia-337 Package hat das „zunichte“ gemacht. In den Trusty Sources zieht das gleich eine ganze Gnome Installation nach sich, die mir dann mein NoDM-Setup zerschossen hat und gleichzeitig die Platte gesprengt hat.

Danach folgte eine Neuinstallation. Eine stunde ging für ein fehlerhaft erstelltes USB-Image drauf, geschenkt, das ist Murphey, aber danach wurde es haarig. Unter Trusty fehlen einigen Paketen schlicht Abhängigkeiten. Ich hab 30 Minuten rumgefriemelt bis ich gemerkt habe, dass ein nodm kein xserver mehr mitinstalliert. Fehlende libraries werden auch nicht im Log erwähnt. Wozu auch ?

Hier meine manuell installierten Pakete:

  • xinit – wird von nodm benötigt
  • alsa-base/alsa-utils – für den sound
  • consolekit, pm-utils – für den shutdwon/suspend aus xbmc herraus.

Nachdem ich XBMC am laufen hatte, hat mich dann noch der „Shutdown/Suspend“ geärgert. Zum einen sind die oben erwähnten Pakete nicht installiert zum anderen wurde etwas an der Struktut geändert, so dass die Beispiele auf xbmc.org einfach nicht mehr passen.

Die korrekte polickit file sieht wie folgt aus:

[Actions for some-user]
Identity=unix-user:some-user
Action=org.freedesktop.upower.*;org.freedesktop.consolekit.system.*;org.freedesktop.udisks.*;org.freedesktop.login1.*
ResultAny=yes
ResultInactive=no
ResultActive=yes

Wichtig ist die Angabe org.freedesktop.login1.*. Die kann auf Suspend udn Hibernate auch eingeschränkt werden.

Danach lief mein HTPC wieder wie vor der Migration.

PulseAudio Intel HDA 898 Soundfehler

Bei Nutzung einer  Intel HDA (CODEC Realtek HDA 898) Soundkarte unter Ubuntu (PulseAudio) kommt es häufig zu Knacken im Sound. Dies wird durch zu häufige bzw. bogey JackDetection verursacht. Um der Sache Herr zu werden braucht man aus dem „alsa-tools-gui“ Paket das tool „hdajackretask“.

 

Dort kann man unter „advanced“ die JackDetection einzeln abschalten und hat endlich ordentlichen Sound.

Erste Schritte im neuen Ubuntu 14.04 Server

Seit dieser Woche laufen bei mir die Updates auf das neue Ubuntu 14.04. Den Anfang machte gestern mein Server (nach „langer“ Vorbereitung). Nach diversen Problemen bei den letzten Updates hatte ich diesmal alle Vorbereitungen getroffen um die Ausfallzeit so „unauffallig“ wie möglich zu gestellten.

  • Wichtige Dienste wie Kerberos, Radius usw sind mittlerweile auf eigene Maschinen ausgelagert worden.
  • Der Server läuft mittlerweile auf einer „echten“ Serverhardware, inklusive Remote-Shell um im Fehlerfall eine lokale Anmeldung durchführen zu können.

Das größte Problem stellt der DNS-Server (Bind9) dar, der leider nicht auf einen meiner EdgeMax-Router zum Laufen zu bekommen ist. Fällt er längere Zeit aus, geht in meinem Heimnetzwerk nicht mehr viel.

Die Installationsroutine ist mittlerweile geübt. Manuell den aktiven Root-Raid 1 aufbrechen (Festplatte im laufenden Betrieb ausbauen). Anschließend wird die Platte direkt an eine VM weiter gereicht und das neue OS installiert. Die Installation verlief Problemlos, danach traten jedoch die ersten fehler auf. Wenn GRUB von einem RAD-Device starten soll, wirft er einen Fehler, bootet dann jedoch anstandslos weiter. Nach dem (erfolgreichen) Booten wird jedes „sudo“ von einer „memory leak“-Meldung begleitet. Diese wird durch das lib-pam-smb Paket verursacht. Nach dessen Deinstallation lief alles ohne Probleme weiter.

Einzig die Vergabe der Netzwerk-Interface Namen führte noch etwas zu Verwirrung. P4P1 hab ich so noch nie als Namen gesehen. Dem kann man aber mit einer passenden UDEV-Rule beikommen.

Der Tausch der Platten (diesmal bei ausgeschalteten Server) und der folgende „First Boot“ brauchten keine 5 Minuten. Bind und MySQL verrichtete sofort wieder ihre Dienste. Das mounten der XFS Laufwerke ging hingegen sofort auf die Bretter. Ein Blick ins „dmesg“ verrät, dass die Parameter „sunit“ und „swidth“ jetzt nicht mehr stillschweigend ignoriert werden, sondern der mount einfach abgebrochen wird. 5 Minuten später war das Storage gemountet und NFS (inkl. Kerberos) verrichtete seinen Dienst. Ab hier merkten die Endanwender (Familie) von den Arbeiten nichts mehr. Mit zwei Ausnahmen (Logitech Media server/Samba) liefen alle externen Dienste nach ca. 20 Minuten wieder.

Mehr Aufwand machte nur der neue Apache. Konfigfiles müssen immer auf „.conf“ enden, sonst werden sie ignoriert. Blöd das man das nur indirekt mitgeteilt bekommt. Nach einer Stunde rummbasteln ging mir dann ein Licht auf. Eine weitere Stunde später liefen wieder alle internen Monitoring Sites.

Richtig übel hat mir jedoch der Logitech Media Server mitgespielt. Der war am Abend gar nicht mehr zur Zusammenarbeit zu bewegen. Alle Squeezeboxen mussten manuell auf den Server von Logitech umgestellt werden. Da das Logging des Logitech Media Servers nicht sehr ergibig ist, konnte ich erste nach ein bisschen rumm probieren raus finden, dass die aktuelle Version 7.7.3 einfach nicht auf Ubnntn 14.04 lauf kann (Perl Version). Erst das Installieren des Nightly-Builds brachte Besserung,

Samba verrichtete zwar tadellos seinen dienst, jedoch waren die angeschlossenen Windows-Instanzen nicht mehr dazu zu bewegen sich an der Domäne anzumelden. Genauer gesagt konnte keine „Vertrauensstellung hergestellt werden“. Ein „rummfrickeln“ in den Untiefen der WindowsEinstellungen (regedit und policykit) brachten keine Besserung. Da ein Anmelden (Aufnehmen) in die Domäne klappt und auch ein Zugriff von Windows auf Samba hab ich nach 2 Stunden rumprobieren meine arbeiten eingestellt.

Kurzfazit: Ich hatte mehr „Ärger“ als erwartet. Gefühlt hab ich von 10.04 auf 14.04 aktualisiert. Das lag aber weniger an Ubuntu, als an den verwendeten Software-Paketen, bzw. hat 12.04 damals schon veraltete Pakete verwendet und der Sprung war jetzt merklich. Jetzt muss sich das System im Langzeittest beweisen. Da hab ich nun weniger Bedenken. Mahl sehen ob ich eine Uptime > 6 Monate hinbekomme.

Bullshit made in germany …

oder „Ich hab jetzt endlich auch ein Konto in der Schweiz“

Zu einer Zeit als mobile Endgeräte noch PDA genannt wurden, entschied ich, wegen eben solch eines Endgerätes, dass ich unbedingt einen IMAP fähigen Mail-Server benötige. Leider hatte man zu dieser Zeit nur zwei Möglichkeiten: selber einen Mail Server betreiben oder Geld für mehr Service bezahlen. (Google Mail war gerade erst im kommen).

Seit diesen Tagen bin ich GMX Pro Kunde. Rückblickend eine verdammt lange Zeit. Ich könnte jetzt einen langen Beitrag darüber schreiben, was GMX und United Internet in Zeiten der Mobilen Endgeräte alles verpennt hat, oder was man als „versierter“ Endnutzer eigentlich erwartet aber belassen wir es bei den Basics. Unzufrieden war ich schon lange mit diesem Verein. Ausschlaggebend für meinen Wechsel weg von GMX war jedoch nur ein Grund: Sicherheit

Ich hab mit entsetzten registriert, wie dilettantisch GMX die letzten Monate agiert hat. Da wird mit großen getöße Angekündigt, dass eine Jahrzehnte alter Standard jetzt umgesetzt wird (Verschlüsselung erzwingen) und dann Versagen sie auf ganzer Linie. Für einen Lacher auf dem 30C3 hat es gereicht. Anstatt sich dann um die Sicherheit ihrer Kunden zu kümmern und endlich ihr WebFronted zu überarbeiten, wird lieber eine Kampagne gegen unliebsame Adblocker gefahren. Das Niveau war erschreckend. Weder vor Scaring noch vor FUD wurde zurückgeschreckt.

Gleichzeitig war das WebFronted von GMX ohne Adblocker, Ghostery und co selbst als zahlender Kunde nicht anzusteuern. Von der Aufmachung nach Bildniveau ganz zu schweigen. Dazu kamen so witzige Sachen wie „nicht abschaltbares Bilderladen beim betrachten von Mails“.

Lange rede kurzer Sinn: ich brauchte einen anderen E-Mail Provider. Eigendeich wollte ich mir selbst einen Server hosten. Kurze die Rahmenbedingen überschlagen:

  • Kosten für eine statische IP (über VPN) – Mein Provider will mir keine statische IP schalten.
  • Mir stehen „nur“ 16/1 Mbit zur Verfügung. Sollte für Mailversand reichen, aber schön ist anders…
  •  Ein Mailserver der öffentlich zugänglich ist, ist eine ganz andere Hausnummer. Vom Pflegen der Spamfilter mal ganz zu schweigen.

Danach hab ich das „Eigenhosting“ für weitere 5 Jahre auf Eis gelegt und mich auf die Suche nach passenden Providern gemacht und bin bei einem kleinen Anbieter in der Schweiz fündig geworden: Kolab Systems.

Zum einen bieten sie ihre Groupware als OpenSource an (was Standard in der Branche zu sein scheint, wenn man gegen Outlook bestehen will), zum anderen betreiben sie einen Mail-Service mit eben dieser Groupware, der all das bietet, was man sich von einem modernen Mail-Provider wünscht:

  • Sicherheit:  Nach bekanntwerden des Hearthbleed – GAUs wurden binnen weniger Stunden die Zertifikate getauscht und die User Informiert. Bei GMX warte ich immer noch auf eine Benachrichtigung.
  • Sicherheit: unverschlüsselt wird nichts angeboten und deren Transportverschlüsselung ist „State of the Art“
  • Datenschutz: Es wird stark auf Anonymität und Sicherheit geachtet. Das FAQ und die Service Beschreibung lesen sich als ob Aluhut-Träger die Zielgruppe sind.
  • Terms of Service die man verstehen kann.
  • Ach und nebenbei voller Support von Mobilen Endgeräten OHNE proprietäre APP (via ActiveSync und Card/Cal-DAV)
  • Synchronisation zwischen verschiedenen Usern
  • Achja und keine Werbung

Müsste ich jetzt nicht alle Dienste auf die neue Mail umstellen, wäre ich im siebten Himmel.

ExpireDate von Zertifikat überwachen.

Wer, wie ich, eine eigene (private) CA betreibt, wird irgendwann mal überrascht feststellen, dass auch das Root-Zertifikat ausläuft. Standardmäßig nach 4 Jahren. Wenn plötzlich der Radius keine Clients mehr ins Netz lässt, wenn jede interne HTTPS-Verbindung auf Warnung läuft und man sich plötzlich wieder mit Notfall-Passwörtern anmelden muss, weiß man, dass man vergessen hat, sein Root-Zertifikat rechtzeitig zu erneuern.

Was bei einzelnen Clients noch mit vertretbaren Aufwand zu beheben ist, nervt beim Zwangs erneuern der CA doch ziemlich, besonders wenn man gerade etwas anderes vor hatte.

Für diesen Zweck hab ich mir ein kleines Script gebastelt, das via Munin alle Cert-Restlaufzeiten ermittelt und rechtzeitig Alarm schlägt.

wie immer unter GPL hier zu beziehen: Check Expire Date

IP-Connection-Track erkennt keine stehenden Verbindungen

Wer das Problem hat, dass bei iptables-Rules wie der folgenden keine (oder nur vereinzelt) Verbindungen nach draußen zustande kommen hat das gleiche Problem wie ich es hatte:

iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i eth1 -o pppoe0               -j ACCEPT

Die Regel besagt, alles von „Drinnen“ (eth1) nach „Draußen“ (pppoe0) zuzulassen und alle Pakete der Verbindungstatus als ESTABLISHED oder RELATED erkannt wird zuzulassen. Kurz: eine StateFull-Firewall die alles von drinnen nach draußen routet aber von draußen nur angefragtes rein lässt.

Wer auf etwas „stabilere“ (oder ältere) Software setzt (in Worten: debian squeeze) ist noch mit einem 2.6er Kernel unterwegs. Bei diesem sind die Module fürs ConnectionTracking wohl noch etwas schärfer/unbrauchbarer.

Erst mit folgendem Befehl verhält sich das ConnectionTracking wie man es erwarten würde:

echo 1 > /proc/sys/net/netfilter/nf_conntrack_tcp_be_liberal

Ab Kernel 2.6.22 ist dies nicht mehr notwendig.

Quelle: http://conntrack-tools.netfilter.org/manual.html

OpenVPN – TLS-Server-Check bestehen

OpenVPN liefert gleich eine ganze BuildChain mit um sich Zertifikate zu generieren und zu signieren. Leider hat man meist schon eine Infrastruktur (CA) im Feld mit der man seine Zertifikate signiert und verteilt. Bei mir habe ich das immer über das in Ubuntu mitgelieferte CA.pl Skript gemacht und die so erzeugten Zertifikate funktionieren gerade nicht in OpenVPN. Es kann zwar eine Verbindung aufgebaut werden aber ein TLS-Server-Check schlägt fehl. Um gültige Zertifikate zu erzeugen muss man folgendes machen.

in der /etc/ssl(openssl.cnf muss man eine neue Sektion anlegen. Am besten mit dem Namen „Server“ oder „OpenVPNHost“

[ server ]
basicConstraints=CA:FALSE
nsCertType          = server
nsComment           = "Some comment"
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer:always
extendedKeyUsage=serverAuth
keyUsage = digitalSignature, keyEncipherment

anschließend muss man das certifiacte wie folgt erzeugen:

openssl req -days 365 -nodes -new -keyout newkey.pem -out newreq.pem -extensions server -config /etc/ssl/openssl.cnf
openssl ca -days 1095 -extensions server -in newreq.pem -policy policy_anything -out newcert.pem

Das so erzeugte Zertifikat besteht auch einen TLS-Server-Check