Archiv des Autors: Jörg Kastning

Update 2018-05-21: Mit einem Reverse-SSH-Tunnel zum Offsite-Backup

Im heutigen Beitrag aus der Kategorie Wochenend-Projekte geht es darum, wie man mit Hilfe eines Reverse-SSH-Tunnels ein Offsite-Backup für die heimische Datensammlung realisieren kann. Der Beitrag soll mir als Dokumentation und euch als Anregung für ähnliche Projekte dienen.

Anwendungsfall (Use Case)

In meinem Heimnetzwerk gibt es ein NAS, welches der Familie als allgemeines Datengrab dient. Lagen hier anfangs nur Datensicherungen anderer Geräte, verwalten wir heute, neben anderen Daten, unsere Familien- und Urlaubsfotos auf diesem Gerät. Es existiert eine lokale Datensicherung dieser Daten, die vor versehentlichem Löschen schützt.

Nun sind uns einige dieser Daten so wichtig, dass wir sie auch gern gegen Verlust durch z.B. Feuer oder Diebstahl schützen möchten. Dazu möchte ich die betreffenden Daten gern außerhalb der eigenen vier Wände an einem anderen Standort sichern. Diese Form der Datensicherung bezeichne ich im Folgenden auch als Offsite-Backup.

Anforderungen

An das Offsite-Backup stelle ich folgende Anforderungen:

  1. Die Datenübertragung erfolgt über gesicherte Verbindungen
  2. Die Daten werden in einem Format gespeichert, welches das Lesen ohne Abhängigkeit zu bestimmten Programmen ermöglicht
  3. Die Datenübertragung soll manuell angestoßen werden und optional zeitgesteuert ausgeführt werden können
  4. Eine Wiederherstellung der Daten soll über den gleichen Kanal wie die Datensicherung möglich sein
  5. Die Daten sollen nicht bei einem kommerziellen Anbieter gespeichert werden
  6. Die Daten sollen nicht in einem Speicher abgelegt werden, der sich des unmittelbaren Zugriffs entzieht
  7. In den Routern der beteiligten Heimnetzwerke sollen keine eingehenden Portweiterleitungen konfiguriert werden müssen

Alles was ich benötige, um die obigen Anforderungen umzusetzen sind:

  1. Ein Raspberry Pi
  2. Eine externe USB-Festplatte zum Anschluss an den Pi
  3. Einen Linux-Root-Server im Internet
  4. Einen LAN-Port und Stromanschluss im Elternhaus

Zu meinem Glück sind all diese Dinge bereits vorhanden und ich muss nicht erst eine Einkaufstour unternehmen.

Die Lösung

In groben Zügen erklärt, sieht die Lösung wie folgt aus. An den Raspberry Pi wird eine USB-Festplatte angeschlossen, welche als Speicher für die zu sichernden Daten dient. Der Pi wird in meinem Elternhaus an das dortige Heimnetzwerk angeschlossen. Von dort ausgehend baut er einen Reverse-SSH-Tunnel zu meinem Linux-Server auf, welcher bei einem Hoster läuft und auf eingehende SSH-Verbindungen lauscht. So kann ich von dem Linux-Server aus auf den Pi zugreifen, ohne dass im DSL-Router in meinem Elternhaus eine Portweiterleitung eingerichtet werden muss. Darüber hinaus entfällt auch die Notwendigkeit, die Gegenstelle über die sich ändernde dynamische IP-Adresse auf dem Laufenden zu halten.

model of an offsite backup

SSH-Verbindungen über eine Vermittlungsstelle für ein Offsite-Backup

Nun kann ich von dem NAS aus meinem Heimnetzwerk eine SSH-Verbindung über den Linux-Server zum Raspberry Pi in meinem Elternhaus aufbauen und Daten dorthin übertragen. Auch in meinem Heimnetzwerk muss dazu keine Portweiterleitung geschaffen werden.

Konfiguration auf dem Pi

Auf dem Raspberry Pi habe ich das Betriebssystem Raspbian installiert. Anschließend habe ich ein SSH-Schlüsselpaar erstellt und den öffentlichen SSH-Schlüssel auf dem Linux-Server hinzugefügt, um ohne die Eingabe eines Passworts eine SSH-Verbindung herstellen zu können. Für die Verbindung verwende ich normale Linux-Benutzer ohne besondere Privilegien. Nun kann mit dem Befehl ssh -R 22222:localhost:22 user@Linux-Server ein Reverse-SSH-Tunnel zum Raspberry Pi aufgebaut werden. Der Reverse-SSH-Tunnel ermöglicht es, vom Linux-Server aus mit dem Befehl ssh -p22222 localhost eine Verbindung zum Raspberry Pi aufbauen zu können.

Damit der Reverse-SSH-Tunnel nach der Provider-Zwangstrennung automatisch wieder aufgebaut wird, habe ich auf dem Raspberry Pi folgende Service-Unit erstellt:

[Unit]
Description="Reverse ssh tunnel to proxy"
After=network.target

[Service]
User=pusemuckel
ExecStart=/usr/bin/ssh -NTi /home/pusemuckel/.ssh/id_rsa -o ServerAliveInterval=60 -R 22222:localhost:22 user@Linux-Server
RestartSec=73
Restart=always

[Install]
WantedBy=multi-user.target

Die Option RestartSec gibt an, dass bei einem Verbindungsabbruch 73 Sekunden gewartet wird, bevor ein erneuter Verbindungsversuch gestartet wird. Damit möchte ich dem DSL-Router Zeit für die Wiedereinwahl geben.

Konfiguration auf dem NAS

Auf dem NAS erstelle ich im HOME-Verzeichnis des Benutzers, welcher später die Datensicherung ausführen wird, die Datei ~/.ssh/config mit folgendem Inhalt, um auf einfache Weise eine SSH-Verbindung zum Raspberry Pi im entfernten Standort herstellen zu können.

Host raspi
        HostName localhost
        Port 22222
        ProxyCommand ssh -i ~/.ssh/nas_rsa -A -W %h:%p user@linux-server
        IdentityFile ~/.ssh/nas_rsa

ProxyCommand gibt an, dass der Linux-Server als Proxy bzw. Zwischenpunkt der Verbindung dient. In neueren SSH-Versionen kann man statt dessen auch die etwas einfacher zu handhabende Option JumpHost verwenden.

Neben der obigen Datei wurde auf dem NAS ein SSH-Schlüsselpaar erstellt, dessen öffentlicher Schlüssel auf dem Linux-Server und dem Raspberry Pi im entfernten Standort hinterlegt wurde. Dadurch ist für die Durchführung der Datensicherung keine Passworteingabe erforderlich. Da beide Endpunkte der Verbindung in vertrauenswürdigen Netzen liegen, halte ich diese Vorgehensweise für vertretbar.

Probleme

Leider läuft das Ganze noch nicht so rund und störungsarm, wie ich es mir wünsche. Bei der Zwangstrennung reißt die Verbindung ab, ohne dass der Raspberry Pi eine Chance hätte, den Socket auf dem Server zu schließen.

Da der verwendete Port noch auf dem Linux-Server gebunden ist, schlägt eine erneute Einwahl fehl. Erst wenn der Socket nach einem Timeout geschlossen wurde, ist eine erneute Wiederherstellung der Verbindung möglich.

Update 2018-05-21: Danke an Christian F., welcher mich auf die Optionen ClientAliveCountMax und ClientAliveInterval hingewiesen hat. Mit diesen Optionen kann der SSH-Server erkennen, dass die Verbindung zum Client abgerissen ist und den Socket schließen.

Der Standardwert für ClientAliveCountMax beträgt 3. Dabei handelt es sich um client alive messages, welche der Server zum Client sendet. Bleiben alle drei unbeantwortet, baut der Server die Verbindung ab und gibt den Socket frei. Den Wert für ClientAliveInterval habe ich auf 15 gesetzt. Er gibt an, dass nach 15 Sekunden Inaktivität eine client alive message vom Server an den Client gesendet wird, um zu überprüfen, ob der Client noch antwortet.

Antwortet der Client nicht, wird mit der obigen Konfiguration die Verbindung vom Server nach 45 Sekunden abgebaut und der Socket freigegeben. Der Client kann sich anschließend wieder neu verbinden. Auf dem Client habe ich den Parameter RestartSec auf 73 Sekunden gesetzt (einfach weil mir die Zahl so gut gefällt). Nach dem Abriss der Verbindung durch die Zwangstrennung wird der Tunnel nach 73 Sekunden wieder aufgebaut.

Fazit

Mit dieser kleinen Bastellösung kann ich meine Daten über einen gesicherten Kanal in einen entfernten Standort sichern. Das manuelle Offsite-Backup klappt bereits gut, wenn der SSH-Tunnel zwischen Linux-Server und Raspberry Pi steht.

Da das Problem mit der Zwangstrennung nun etwas entschärft werden konnte, steht auch einem zeitgesteuerten Backup grundsätzlich nichts mehr im Wege. Es bleibt lediglich das Restrisiko, dass sich der Zeitpunkt der Zwangstrennung ändert und diese dann das zeitgesteuerte Backup unterbricht. Mit diesem Risiko komme ich jedoch zurecht.

3-D Secure alias Verified by Visa alias SecureCode

Wählt man bei Online-Händlern die Zahlungsweise Kreditkartenzahlung aus, wird man heute in den meisten Fällen mit dem Verfahren 3-D Secure [1] konfrontiert. Je nachdem welche Kreditkarte man verwendet, heißt das Verfahren Verified by Visa oder bei einer Mastercard SecureCode.

Durch das Verfahren sollen Zahlungsausfälle durch Kreditkartenmissbrauch reduziert werden. Teilnehmenden Online-Händlern wird zudem der Zahlungseingang garantiert, wenn sie 3-D Secure einsetzen.

Doch welche Vorteile bietet dieses Verfahren für den Kunden? Auf den ersten Blick gar keine. Statt eines Passwortes muss der Kunde sich nun eine PIN für die Banking-App bzw. für sein mobiles Endgerät merken.

Im Wikipedia-Artikel zu 3-D Secure [1] wird zudem ausgeführt:

Auch im Jahr 2018 gibt es jedoch noch Konstellationen, in denen die Haftungsfrage eindeutig zu Lasten des Kunden ausfällt und die Registrierung zu 3-D Secure ein im Vergleich zu anderen Zahlungswegen für den Kunden außergewöhnlich riskantes Verfahren sein kann, wie folgender Fall verdeutlicht: Die DKB hat vom statischen Sicherheitscode auf einen dynamischen Code per App oder mTAN umgestellt. In ihren Sonderbedingungen für 3-D Secure legt die DKB aktuell einen Haftungsausschluss für den Fall fest, „dass das mobile Endgerät verloren, gestohlen oder weitergegeben wird und dadurch Dritte ggf. Zugriff auf SMS erhalten und diese unberechtigt nutzen können“. Bei einem möglichen gleichzeitigen Verlust von Kreditkarte und Mobilfunkgerät kann ein Finder also beliebige Zahlungen zu Lasten des Besitzers auslösen und verifizieren, vorausgesetzt er bekommt Zugang zum Mobilgerät (etwa durch eine einfache Tastensperre). Für diese missbräuchlichen Zahlungen haftet der Kunde vollständig bis zur Sperrung der Karte, bei einer Zahlung ohne 3-D Secure haftet er dagegen nur bis maximal 50 €. Bei Verlust stellen weder die auf der Karte aufgedruckten Daten, noch das 3-D-Secure-Verfahren eine Hürde für den einfachen Missbrauch dar, sondern lediglich die PIN oder vergleichbare Sicherungsmechanismen des Mobilgeräts. Das Risiko für den Kunden ist in dieser Konstellation höher, als ohne Registrierung zum 3-D-Secure-Verfahren, unabhängig davon, ob der Kunde 3-D Secure überhaupt benutzt.

Diese Aussage ließ mich zunächst zweifeln, ob ich mich überhaupt noch zum dynamischen 3-D Secure Verfahren anmelden sollte. Ich beschloss daher, die Sonderbedingungen für das 3D Secure Verfahren bei Internet-Zahlungen mit der DKB-Kreditkarte [2] genau zu lesen und im Zweifel bei meiner Bank nachzufragen, wie es sich mit der Haftung verhält.

Aus den Sonderbedingungen für das 3D Secure Verfahren bei Internet-Zahlungen mit der DKB-Kreditkarte

Im Folgenden zitiere ich aus den oben genannten Sonderbedingungen [2] und liste die Fragen auf, welche durch die genannten Punkte aufgeworfen wurden.

Sorgfaltspflichten des Karteninhabers

Hier Punkt 1:

1) Der Karteninhaber
a) hat das Risiko eines unberechtigten Zugriffs auf sein mobiles Endgerät u. a. durch geeignete Schutzmaßnahmen zu minimieren (z.B. PIN auf mobiles Endgerät).
b) hat das Betriebssystem des von ihm verwendeten Endgerätes auf dem neuesten Stand zu halten.
c) hat die App nur aus offiziellen App-Stores (iTunes, Google Playstore, Windows Store) herunterzuladen und dafür vorgesehene Updates regelmäßig durchzuführen.

Während Punkt a) noch einleuchtet, wirft Punkt b) bereits erste Fragen auf. Was mache ich, wenn mein Endgerät schon älter ist und der Hersteller keine Updates mehr für das Betriebssystem veröffentlicht? Was ist, wenn ich mir im Handel ein neues Android-Gerät kaufe, welches mit einer älteren Android-Version ausgeliefert wird und vom Hersteller ebenfalls keine Updates mehr für das Betriebssystem erhält? Darf ich in oben genannten Fällen überhaupt noch am 3-D Secure Verfahren teilnehmen? Oder darf die DKB in diesen Fällen bereits die Haftung im Missbrauchsfall ablehnen?

Zu Punkt 3:

Die DKB AG haftet nicht für den Fall, dass das mobile Endgerät verloren, gestohlen oder weitergegeben wird und dadurch Dritte ggf. Zugriff auf SMS erhalten und diese unberechtigt nutzen können.

Dies ist der Punkt, welcher bereits im Wikipedia-Artikel [1] kritisiert wurde. Hier stellt sich die Frage, ob ich mich mit einer Teilnahme an 3-D Secure nicht schlechter stelle.

Verantwortlichkeit und Haftung

Punkt 7 der Sonderbedingungen [2] widmet sich dann konkret der Haftung:

[…] Die DKB AG übernimmt außerdem keine Haftung bei Manipulation des mobilen Endgeräts (z.B. Jailbreaking, Rooting).

Bedeutet dies, dass Nutzer freier bzw. alternativer Betriebssysteme das Verfahren nicht nutzen können? Schließlich sind Jailbreaks und Rooting oftmals Voraussetzung, um ein Custom-ROM auf ein Endgerät aufspielen zu können.

Mit obigen Fragen habe ich mich per E-Mail an die DKB gewendet und um schriftliche Antwort gebeten.

Die Antwort der DKB

Eine Antwort ließ nicht lange auf sich warten. Man bat darum, die Sache zunächst am Telefon zu erörtern. Auf Wunsch bestätigte man mir die wesentlichen Inhalte dann auch schriftlich.

Nach Aussage eines Mitarbeiters aus der Technik wurde die DKB Secure App so entworfen, dass sie den Patchlevel des mobilen Betriebssystems prüfen und erkennen kann, ob das Gerät gerootet bzw. gejailbreakt wurde. Ist letzteres der Fall oder ist der Patchlevel des Endgerätes zu alt, verweigert die App den Start.

Mir wurde bestätigt, dass dies im Umkehrschluss bedeutet, dass wenn die App startet, die Sorgfaltspflicht aus Punkt 1.b) als erfüllt angesehen werden kann.

Die schlechte Nachricht für die Freunde freier Betriebssysteme ist, dass die DKB jegliche Haftung ablehnt, wenn die App nicht aus den offiziellen App Stores bezogen wurde und/oder unter einem Custom-ROM betrieben wird. Der Haftungsausschluss gilt in diesem Fall übrigens auch, wenn man statt der App das mTAN-Verfahren via SMS nutzen möchte.

Steht noch die Antwort zu Punkt 3 aus. Hierzu teilte mir eine Mitarbeiterin aus der Fachabteilung Privatkundenservice mit, dass die Haftung bei Diebstahl des mobilen Endgeräts nur dann ausgeschlossen ist, wenn der Kunde grob fahrlässig gehandelt hat. Unter grobe Fahrlässigkeit fällt dabei zum Beispiel, dass:

  • das Endgerät nicht mit einer Zugangssperre (PIN) versehen ist,
  • oder die PIN des Endgeräts bzw. der App zusammen mit der Kreditkarte oder dem Endgerät aufbewahrt wird.

Die Beweislast, dass grobe Fahrlässigkeit vorliegt, liegt in diesem Fall bei der Bank.

Mein persönliches Fazit

Die DKB hat zeitnah auf meine Fragen reagiert und diese zu meiner Zufriedenheit beantwortet. Dies empfinde ich als positiv.

Dass die Nutzung freier bzw. alternativer Betriebssysteme quasi ausgeschlossen ist, da bei Jailbreak oder Rooting die Haftung komplett ausgeschlossen wird, bedaure ich. Da man mit einem Jailbreak bzw. Rooting jedoch elementare Sicherheitsmechanismen umgehen kann, kann ich den Haftungsausschluss an dieser Stelle nachvollziehen.

Ich selbst habe mein Telefon nun wieder mit einer PIN versehen und meine Kreditkarte registriert.

Ob es bei SecureCode für Mastercard genauso aussieht, kann ich noch nicht sagen. Sobald ich die Bedingungen hierfür gefunden, studiert und eventuelle Fragen geklärt habe, werde ich diesen Artikel aktualisieren.

Quellen und weiterführende Links

[1] Wikipedia: 3-D Secure
[2] Sonderbedingungen für das 3D Secure-Verfahren bei Internet-Zahlungen mit der DKB-Kreditkarte
[3] smsTAN vs. pushTAN vs. chipTAN

Konzept zum Deployment meines Blogs mit Ansible

An dieser Stelle möchte ich ein Konzept erarbeiten, um meinen Blog mit Hilfe von Ansible1 2 auf einem Ubuntu-Server ausbringen zu können.

Dabei hoffe ich auch ein wenig auf eure Unterstützung. Habt ihr Anregungen, konkrete Verbesserungsvorschläge oder auch Fragen, freue ich mich über eure Kommentare. Denn ich selbst bin kein Ansible-Experte und führe dieses Projekt zum Selbststudium und zu Übungszwecken durch.

Die Testumgebung

Die Testumgebung besteht aus der Ansible Control Machine, basierend auf RHEL 73 und dem Zielsystem, basierend auf Ubuntu Bionic Beaver4. Zum Zeitpunkt der Erstellung dieses Artikels nutze ich Ansible in Version 2.4.2.

Zwar wurde bereits die Ansible-Version 2.5 veröffentlicht, in den RHEL-7-Paketquellen ist jedoch noch die Version 2.4.2 enthalten. Ich verwende diese Version auch auf der Arbeit und erhoffe mir so, Erkenntnisse aus diesem Projekt in meine dienstliche Tätigkeit einfließen lassen zu können.

Auf dem Zielsystem existiert ein Benutzer, welcher über volle sudo-Berechtigung verfügt. Dieser Benutzer muss sich mit seinem Passwort authentisieren, wenn er sudo verwendet.

Auf der Ansible Control Machine wird ein SSH-Schlüsselpaar5 generiert, dessen privater Schlüssel nicht mit einer Passphrase geschützt ist. Der öffentliche Schlüssel wird auf dem Zielsystem abgelegt. Damit wird sichergestellt, dass die Ansible Control Machine SSH-Zugriff auf das Zielsystem hat.

Die Konfiguration von Ansible (/etc/ansible/ansible.cfg) wird so angepasst, dass standardmäßig das oben erzeugte SSH-Private-Key-File beim Verbindungsaufbau genutzt wird.

Die Installation der benötigten Betriebssysteme und Ansible sind nicht Gegenstand dieses Artikels.

Geplante Vorgehensweise

Um eine Vorgehensweise zu erarbeiten, orientiere ich mich an dem Artikel Testinstanz für einen WordPress-Blog erstellen. In diesem habe ich bereits beschrieben, wie ein Blog auf einem weiteren System als Testsystem aufgesetzt werden kann. Die Vorgehensweise ist ähnlich, mit dem Unterschied, dass sämtliche Schritte nun durch Ansible orchestriert werden sollen.

Danach ergibt sich folgende (vorläufige) Reihenfolge:

  1. Vom Produktivsystem benötigte Dateien holen
  2. Sicherstellen, das alle benötigten Pakete auf dem Zielsystem installiert sind
  3. VirtualHost erstellen
  4. DocumentRoot aus Backup-Datei erstellen
  5. Datei-Attribute und Zugriffsrechte korrekt setzen
  6. Eine .httpasswd-Datei erzeugen/ausbringen
  7. Datenbank aus Backup wiederherstellen
  8. Datenbankbenutzer erstellen
  9. Troubleshooting

Mit hoher Wahrscheinlichkeit ist die obige Liste noch nicht vollständig. Daher werde ich diese im Laufe des Projekts anpassen, sobald weitere Erkenntnisse vorliegen.

Als Quelldaten für den Blog liegen das DocumentRoot meines Blogs als Tarball6 vor. Von der Datenbank wurde ein logisches Backup7 erstellt. Auf diese Datensicherung wird zurückgegriffen, um den Blog auf einem neuen Ubuntu-Server auszubringen bzw. wiederherzustellen.

Der erste Versuch

Im ersten Anlauf habe ich eine Ansible-Rolle8 mit folgendem Aufbau erstellt:

/etc/ansible/roles/
└── deploy-my-blog
    ├── files
    │   ├── backup-documentroot.tar.bz2
    │   ├── dh_params.pem
    │   ├── db_dump.sql.bz2
    │   ├── my-it-brain.vhost
    │   └── php-fpm-pool.conf
    ├── handlers
    │   └── main.yml
    ├── tasks
    │   └── main.yml
    └── vars
        └── main.yml

5 directories, 8 files

Unterhalb von files wurden Dateien abgelegt, welche vom aktuellen Produktivsystem stammen und für das Deployment auf einem neuen Server benötigt werden.

Im folgenden werde ich zuerst auf die eingesetzten Module eingehen und anschließend das Playbook zum Deployment des Blogs vorstellen.

Verwendete Module

ModulStatusVerwendung
aptstableinterfaceVerwaltet APT-Pakete
unarchivepreviewEntpackt Archiv-Dateien und kopiert sie ggf. vorher auf das Zielsystem
copystableinterfaceKopiert Dateien auf entfernte Rechner
filestableinterfaceErstellt Dateien, Verzeichnisse, symbolische Links und setzt deren Attribute
mysql_dbpreviewHinzufügen von MySQL-Datenbanken (aus Backup)
mysql_userpreviewHinzufügen (und Entfernen) von Benutzern in MySQL-Datenbanken

Die in der Spalte Status angegebenen Werte stableinterface und preview lassen Rückschlüsse auf die Stabilität der Schnittstellen eines Moduls zu.

So garantieren die Entwickler bei einem stableinterface, dass es in Zukunft keine Änderungen geben wird, die nicht abwärtskompatibel sind. Auch wenn sich keine explizite Angabe findet, wie lange diese Garantie gilt, kann man davon ausgehen, dass man seine Playbooks bei Verwendung dieser Module nicht so schnell aufgrund von Updates anpassen muss. Für Module mit dem Status preview wird genau dies hingegen nicht garantiert. Hier kann es von Version zu Version Änderungen geben, welche Anpassungen an Playbooks erforderlich machen, welche diese Module verwenden. Dadurch entsteht ggf. ein erhöhter Testaufwand, bevor man seine Ansible-Installation aktualisieren kann.

Das Playbook

Den Inhalt der Datei /etc/ansible/roles/deploy-my-blog/tasks/main.yml habe ich unter dem Namen deploy-blog-playbook.yml als Gist veröffentlicht. Um es in diesem Artikel anzeigen zu können, müsst ihr JavaScript in eurem Webbrowser aktiveren.

Die Zeilen 2-11 sorgen dafür, dass die benötigten Pakete auf dem Zielsystem installiert werden. Da es sich dabei um einen Ubuntu-Server handelt, verwende ich das Modul apt.

Die Zeilen 13-16 stellen das DocumentRoot und die SSL-Zertifikate aus dem Dateibackup auf dem Zielsystem wieder her.

In meiner aktuellen Konfiguration verwende ich PHP-FPM mit einem eigenen Pool, welcher in meinem VirtualHost referenziert wird. Um diese Konstellation auch auf dem neuen System nutzen zu können, stelle ich entsprechende Konfiguration mit den Zeilen 18-47 her. Vermutlich können die Zeilen 39-47 entfallen, da PHP-FPM das Logfile automatisch erstellt. Weitere Tests müssen dies noch zeigen. Ich habe diese Zeilen während des Troubleshootings eingefügt. Ursache für den Fehler wird vermutlich das fehlende Log-Verzeichnis gewesen sein, welches ich in den Zeilen 29-37 erzeuge.

Der NGINX auf meinem Produktivsystem verwendet die Datei dh_params.pem, welche ich in den Zeilen 49-57 auch auf den neuen Host kopiere. Anschließend wird in den Zeilen 59-66 die vHost-Datei auf das Zielsystem kopiert und durch die Zeilen 68-77 verlinkt und damit aktiviert.

Die letzten Zeilen kümmern sich um die Einrichtung der Datenbank. Zuerst wird die Dump-Datei auf das Zielsystem kopiert und dort anschließend in die neue Datenbank db_my_it_brain eingespielt. Zum Schluss wird noch der benötigte Datenbank-Benutzer erstellt.

In Zeile 94 und 95 habe ich Variablen eingesetzt, welche in vars/main.yml definiert wurden. Dort habe ich auch eine Variable für den Namen der Datenbank definiert, welche ich gern in Zeile 96 genutzt hätte. Leider ist es mir nicht gelungen, da sowohl priv: '"{{ DBNAME }}".*:ALL' als auch priv: "{{ DBNAME }}".*:ALL zu Fehlern führten. Falls hier jemand eine Idee hat, freue ich mich, wenn ihr mir die korrekte Syntax mitteilt.

Erstes Fazit

Das ging leichter als gedacht. Die benötigten Module waren schnell gefunden und ihre Anwendung aufgrund der hinreichend guten Dokumentation nicht schwierig.

Da die aktuell genutzten Variablen sensible Informationen beinhalten, möchte ich diese zukünftig mit Ansible Vault schützen.

Stand heute bin ich jedoch erstmal in der Lage meinen Blog aus der Datensicherung heraus erneut deployen zu können.

Chemnitzer Linux-Tage 2018 — Jeder fängt mal an.

Am 10. und 11. März 2018 finden fanden die Chemnitzer Linux-Tage (#clt2018) statt. Das Motto lautet in diesem Jahr lautete: „Jeder fängt mal an.“


Auch an dieser Stelle nocheinmal vielen Dank an die Veranstalter der #CLT2018 und die Hörer meines Vortrags „Webseiten mit HTTPS bereitstellen und mit HSTS sichern“. Die Folien zum Vortrag findet ihr auf der Seite Artikel und Vorträge sowie hinter diesem Direktlink.

Zum Ende meines Vortrags habe ich auf weitere Maßnahmen hingewiesen, mit denen sich die Angriffsfläche auf HTTPS verkleinern lässt. Weitere Informationen dazu findet ihr auf dieser Seite im Artikel „Über Pinning (HPKP), CAA und Certificate Transparency“.


Die Besucher erwartet in diesem Jahr erneut ein prall gefülltes Vortragsprogramm mit bis zu sieben parallel laufenden Tracks. War ich im vergangenen Jahr als Besucher zu Gast, steuere ich in diesem Jahr den Vortrag „Webseiten mit HTTPS bereitstellen und mit HSTS sichern“ bei. In diesem führe ich in das Thema HTTPS und die Internet-PKI ein und weise auf einige Stolpersteine hin, die auf dem Weg lauern.

Neben vielen interessanten Vorträgen werden an beiden Tagen jeweils sechs Workshops zum Lernen und Mitmachen angeboten. Für die Teilnahme ist eine Anmeldung erforderlich und es sind 5 Euro Teilnahmegebühr zu entrichten. Beeilt euch bei Interesse mit der Anmeldung, denn die Plätze sind begrenzt.

Darüber hinaus erwarten euch auf den CLT2018:

Die Praxis Dr. Tux bietet in ihrer Sprechstunde bei allen Problemen Hilfestellung, die der Anwender nicht alleine lösen kann.

Im Business Forum stellen sich bis zu 15 Open-Source-Firmen kurz vor. Hört entspannt zu, was diese Firmen genau tun, stellt Fragen und beteiligt euch an der Diskussion.

Auf der PGP-Party könnt ihr eure öffentlichen Schlüssel-Dateien signieren lassen. Weitere Informationen zur Vorbereitung und Durchführung findet ihr unter vorstehendem Link.

Retro Gaming wird während der Chemnitzer Linux-Nacht geboten. Ab 19:30 Uhr könnt ihr auf der Atari 2600 zeigen, aus welchem Holz ihr geschnitzt seid!

In der Projektküche präsentieren 15 Personen in jeweils fünf Minuten ihre Open-Source-Projekte. Möchtet ihr selbst euer Projekt vorstellen? Dann Beeilung, Anmeldeschluss ist der 1. März 2018.

Es wird also wieder viel geboten. Und neben den spannenden und interessanten Vorträgen freue ich mich natürlich auch, bekannte Gesichter wiederzusehen und abends über alte Zeiten zu plaudern. Bis neulich.

Ansible: Playbook nur auf Nodes laufen lassen, die gewissen Kriterien genügen

Manchmal möchte man ein Playbook bzw. Plays nur auf Hosts laufen lassen, welche gewissen Kriterien entsprechen. In diesem Beitrag möchte ich zwei Beispiele geben, wie sich dies umsetzen lässt.

Playbook nur auf Hosts mit Red Hat Betriebssystem ausführen

Das Modul group_by [1] wird genutzt, um während des Laufs eines Playbooks dynamisch Gruppen von Hosts zu erstellen, auf welche man später weitere Plays anwendet.

---
- hosts: all

  tasks:
    - name: Group by OS

      group_by: key=os_{{ ansible_distribution }}
      changed_when: False

- hosts: os_RedHat
  roles:
    - common

Zu Beginn eines Playbook-Laufs wird das Modul setup [2] ausgeführt, um Variablen mit nützlichen Informationen über die Nodes zu belegen. Die Variable ansible_distribution enthält dabei ein Schlüsselwort für eine bestimmte Distribution.

In obigen Beispiel wird dabei die Gruppe os_RedHat erstellt. Im Folgenden werden dann alle Nodes dieser Gruppe der Rolle common zugeordnet.

Dieses Verfahren lässt sich natürlich auch für weitere Variablen anwenden. Möchte man sehen, welche Variablen belegt werden und genutzt werden können, kann sich die Rückgabe von setup in der Standardausgabe ansehen, wenn man das Modul manuell auf einigen Nodes ausführt.

Plays nur auf bestimmten Nodes ausführen

Ein weiteres Beispiel habe ich auf ITrig [4] gefunden:

---
- name: install open-vm-tools
  hosts: vmwareclients
  gather_facts: True
  become: true
  become_user: root
  tasks:
- name: debian install open-vm-tools
  apt: name=open-vm-tools state=present
  when: ansible_os_family == "Debian" and ansible_virtualization_type == "VMware"

- name: centos install open-vm-tools
  yum: name=open-vm-tools state=present
  when: ansible_os_family == "RedHat" or ansible_distribution == 'CentOS' and ansible_virtualization_type == "VMware"

Hier werden Ansible Conditionals [3] verwendet, um zu bestimmen, auf welchen Nodes ein Play ausgeführt wird. Auch hier werden wieder Variablen ausgewertet, welche durch das Modul setup [2] belegt wurden.

In obigen Beispiel wird dies genutzt, um die open-vm-tools mit einem Playbook sowohl auf Debian und RedHat/CentOS Systemen zu installieren.

Quellen

  1. group_by – Create Ansible groups based on facts {en}
  2. setup – Gathers facts about remote hosts {en}
  3. Conditionals {en}
  4. Ansible Playbooks auf Servern mit SSH Key Authentifizierung verwenden {de}

Unit-Typ systemd.path kurz vorgestellt

Mit systemd.path lassen sich Dateien und Verzeichnisse auf bestimmte Ereignisse hin überwachen. Tritt ein spezifiziertes Ereignis ein, wird eine Service-Unit ausgeführt, welche üblicherweise den gleichen Namen, wie die Path-Unit trägt.

Wie dies funktioniert, möchte ich an einem sehr einfachen Beispiel zeigen. Das Ziel ist, die Datei testfile auf Änderungen hin zu überwachen. Immer wenn die Datei nach einem Schreibvorgang geschlossen wird, soll ein bestimmtes Skript gestartet werden.

beispiel.path

Im Verzeichnis /etc/systemd/system/ wird die Datei beispiel.path mit folgendem Inhalt erstellt:

[Unit]
Description=Datei auf Änderungen hin überwachen

[Path]
PathChanged=/home/oglattermann/testfile
Unit=beispiel.service

[Install]
WantedBy=multi-user.target

In der Sektion [Path] wird mit PathChanged= der absolute Pfad zu der zu überwachenden Datei spezifiziert, während Unit= angibt, welche Service-Unit ausgeführt werden soll, wenn sich die Datei ändert. Diese Unit soll gestartet werden, wenn sich das System im Multi-User-Mode befindet.

beispiel.service

Wird die Datei testfile geändert (genau: geschrieben und geschlossen), wird folgende Service-Unit aufgerufen, um das darin spezifizierte Skript auszuführen:

[Unit]
Description=Führt Skript aus, wenn eine Datei sich geändert hat.

[Service]
Type=simple
ExecStart=/home/oglattermann/skript.sh

[Install]
WantedBy=multi-user.target

Das Skript skript.sh enthält dabei in diesem Beispiel lediglich folgenden Code:

#!/bin/bash
echo "Datei geändert" >/home/oglattermann/Output.txt

Für einen Test müssen die beiden soeben erstellten Units noch aktiviert werden:

sudo systemctl enable beispiel.path beispiel.service
sudo systemctl start beispiel.path

Schreibt man nun die Datei testfile neu bzw. wird eine Schreiboperation auf diese Datei abgeschlossen, wird die entsprechende Service-Unit ausgeführt und man findet die Datei Output.txt vor.

Anwendungsbeispiele

Die folgende, unvollständige und nicht abschließende Liste führt einige Anwendungsbeispiele auf, wo sich systemd.path sinnvoll nutzen lässt.

  • Ereignisgesteuerte Datenverarbeitung starten
  • Dateien unter /etc überwachen und bei Änderungen Benachrichtigung versenden
  • Import-Ordner auf neue Dateien hin überwachen und Verarbeitung starten

Quellen und weiterführende Links

Wie kann man mit tcpdump HTTP-Traffic eines bestimmten Hosts sniffen?

Diese Frage wurde bereits von Scott in seinem englischsprachigen Blog beantwortet. Ich gebe sie an dieser Stelle wieder, um nicht immer wieder danach suchen zu müssen.

Das Kommando lautet:

tcpdump -c 20 -s 0 -i eth1 -A host 192.168.1.1 and tcp port http

Die Parameter bedeuten:

  • -c 20: Beendet den Vorgang, nachdem 20 Pakete aufgezeichnet wurden.
  • -s 0: Die mitgeschnittenen Nutzdaten sollen ungekürzt wiedergegeben werden.
  • -i eth1: Zeichne nur Pakete an der Netzwerkschnittstelle eth1 auf.
  • -A: Gebe alle Pakete in ASCII aus.
  • host 192.168.1.1: Zeichne nur Pakete auf, die von Host 192.168.1.1 kommen.
  • and tcp port http: Zeichne nur HTTP-Pakete auf.

Ergänzt man den Befehl noch um -w DATEINAME wird die Aufzeichnung in eine Datei statt auf die Standardausgabe geschrieben.

sht21andrasppi

Raspi-SHT21 Version 2 BETA veröffentlicht

Zwei Jahre sind seit dem letzten Release vergangen. Letztes Wochenende fand ich nun endlich die Zeit, mich wieder mit dem Projekt Raspi-SHT21 zu befassen. Herausgekommen ist die BETA der Version 2.

Alle Informationen zur neuen Version gibt es in den Versionsinformationen auf GitHub und in der README-Datei des Projekts.

Bei mir daheim läuft die neue Version bisher stabil. Da ausführliche Tests fehlen, habe ich sie als BETA markiert. Falls ihr Fehler findet, Fragen habt oder der Meinung seid, dass noch etwas fehlt (Code, Doku, Spendenbutton), eröffnet bitte einen GitHub-Issue oder hinterlasst mir hier einen Kommentar.

In Zukunft soll das Projekt um Remote-Messstationen erweitert werden. Der Raspberry Pi dient dabei als Zentrale zur Speicherung und Visualisierung der Messdaten. Diese werden zukünftig nicht mehr nur ausschließlich vom direkt angeschlossenen SHT21-Sensor geliefert, sondern auch von weiteren Sensoren, die ihre Daten per WLAN übertragen. Sobald es etwas zu zeigen gibt, werde ich in diesem Blog darüber berichten.

Verwandte Artikel

  1. Überwachung von Temperatur und Luftfeuchtigkeit mit dem SHT21
  2. Visualisierung von Umweltdaten

Synology NAS: Einzelnen Ordner neu indizieren

Synology Diskstations stellen Anwendungen bereit, um Bilder, Musik und Videos verwalten zu können. Dies sind im einzelnen

  • die Photo Station,
  • die Audio Station und
  • die Video Station.

Damit die Medien in den jeweiligen Anwendungen angezeigt werden können, müssen diese zuvor indiziert werden. Die Indizierung erfolgt automatisch, wenn Medien über die entsprechende Anwendung hinzugefügt werden. Fügt man sie jedoch auf anderem Wege hinzu, z.B. durch rsync, startet die Medienindizierung nicht und die Medien können in der jeweiligen Anwendung nicht wiedergegeben werden.

Die Benutzeroberfläche „DSM“ bietet lediglich die Möglichkeit, ganz allgemein eine Medienindizierung zu starten. Dabei werden jedoch sämtliche Medien neu indiziert und nicht nur die neu hinzugefügten. Je nach Umfang dauert die Indizierung mehrere Stunden bis Tage. Es gibt jedoch eine Möglichkeit, die Indizierung manuell zu starten und dabei auf ein einzelnes Verzeichnis zu beschränken.

Dazu meldet man sich per SSH an der Diskstation an und führt folgendes Kommando aus:
/usr/syno/bin/synoindex -R /Pfad/zum/Verzeichnis/

Damit lässt sich eine Menge (Rechen-)Zeit sparen.

Kommentar: VMware vSphere Web Client – Welch ein Fluch

Es war einmal vor langer Zeit, als einzig und allein der vSphere Client für Windows existierte, um einen ESX-Host bzw. einen vSphere Cluster zu verwalten. Und die vSphere-Admins waren glücklich und froh.

In dieser guten und glücklichen Zeit war der einzige Wermutstropfen, dass der vSphere Client nur für Microsoft Windows existierte und man als Linux-Liebhaber darauf angewiesen war, für die Administration der vSphere-Umgebung ein anderes Betriebssystem zu booten. Doch konnte dies die Freude nicht mindern. Und alle freuten sich und waren froh.

Doch in dieser Welt des Frohsinns und der Glückseligkeit gab es einen Dämon, dem dies alles gar nicht gefiel. Und dieser Dämon beeinflusste die guten Software-Engineers bei VMware und veranlasste sie dazu, den vSphere Web Client auf Basis von Flash zu entwickeln. Dies war der Beginn von dunklen Zeiten, welche bis in die Gegenwart anhalten.

Wer den vSphere Client kennt und sich den Web-Client ansieht, fragt sich vermutlich: „Warum? Warum investiert man Zeit, um so einen Mist zu entwickeln?“

Der vSphere Web Client ist langsam, kann nichts besser als der Fat-Client, bietet keine neuen Funktionen und basiert auf Flash. Letzteres sorgt dafür, dass es für Linux weiterhin keinen nutzbaren Client gibt. Doch den Göttern sei Dank, wir konnten weiterhin den althergebrachten Fat-Client nutzen und das Flash-Gespenst links liegen lassen. Und nachdem wir uns alle von dem Schreck erholten hatten, waren wir wieder glücklich und froh.

Dies gefiel dem Dämon nicht und so lies er verkünden, dass die Entwicklung des guten etablierten vSphere Client eingestellt wird, da man sich in Zukunft auf den Web-Client konzentrieren will. Dachte man anfangs noch an einen Aprilscherz, so wurden die Zeiten nun richtig finster. Denn der vSphere Web Client war immer noch mies und unbenutzbar. Der Unmut vieler Nutzer entlädt sich seit April 2014 in diesem Thread, welcher bis in die aktuelle Zeit Updates erfährt. Denn das Grundproblem ist immer noch nicht gelöst. Der vSphere Web Client ist immer noch nicht zu gebrauchen.

Um es noch einmal zusammenzufassen, der vSphere Web Client:

  • Ist so langsam, dass ich meinen Bart wachsen höre
  • Zwingt mich Flash auf meiner Admin-Workstation zu installieren, um ihn überhaupt nutzen zu können
  • Funktioniert nicht in allen Browsern
  • Funktioniert mal in dem einen, mal in dem anderen Browser (scheint mit der Mondphase zu wechseln)
  • Benötigt für volle Funktionalität das Client Integration Plugin (CIP), welches noch bescheidener funktioniert, als der Rest des Clients

Dieser Drecks-Web-Client raubt mir den letzten Nerv. Warum beschäftige ich mich überhaupt damit? Weil Client-Probleme im Web-Client reproduziert werden müssen, damit der VMware-Support helfen kann. Dies zieht einen Service Request nicht selten in die Länge, da man mit dem Support erstmal den Web-Client zum Laufen bringen muss, bevor man das eigentliche Problem analysieren kann. Eine echte Lösung gab es für den Client nie. Ein Workaround folgte dem Nächsten.

Unter uns, die Arbeit im VMware-Support kann doch auch keinen Spaß machen, wenn man so ein Drecks-Werkzeug supporten muss. Die Aussage eines Supporters dazu: „Ich gehe groß feiern, wenn der HTML5-Client endlich fertig ist.“

Der neue vSphere Client (HTML5) verspricht Licht am Ende des Tunnels. Die Kritik am verhassten vSphere Web Client scheint VMware erreicht zu haben. Doch offensichtlich muss es erst noch einmal schlechter werden, bevor es besser werden kann. Denn mit vSphere 6.5 hat uns VMware eine Version spendiert, in der sich der ausgereifte vSphere Client nicht mehr verwenden lässt, der vSphere Web Client immer noch totaler Mist ist und der vSphere Client (HTML5) noch nicht voll funktionsfähig ist. Super. Ganz toll. Statt eines gut funktionierenden Clients gibt es jetzt einen gammeligen und einen erst teilweise fertiggestellten.

Was bleibt ist die Hoffnung, dass der HTML5-Client in der nächsten vSphere-Version voll funktionsfähig ist und ein würdiger Nachfolger des guten alten Clients wird, welchen VMware so lieblos sterben lies. Und vielleicht kommt das VMware-Marketing auf der Suche nach Innovationen dann ja auf die Idee, einen schnellen, stabilen Fat-Client zu entwickeln. Und damit sind wir Admins wieder glücklich und zufrieden, bis ans Ende unserer (Arbeits-)Tage.

TLDR;

VMware vSphere ist ein gutes Produkt. Auch im Fall von Störungen in der IT-Infrastruktur lässt einen diese Lösung nur selten im Stich. Virtuelle Maschinen werden bis zuletzt korrekt ausgeführt, während der sie umgebene Rest schon am Boden liegt.

Warum das Unternehmen die Admins über die letzten Jahre mit einem vSphere Web Client straft, der einem jeglichen Spaß an der Arbeit nimmt, wird vielleicht für immer ein Rätsel bleiben.

Hoffentlich bekommt das Unternehmen mit dem neuen vSphere Client (HTML5) endlich die Kurve. Denn die Mitbewerber haben bereits aufgeschlossen und sind einen Blick wert, wenn einem bei Nutzung der Client-Anwendung übel wird.

Nun, wo der Frust einmal raus ist, geht es mir schon besser und ich wünsche euch ein schönes und erholsames Wochenende.