Kategorien
Blog

(Technische) Bestandsaufnahme

Vor einiger Zeit hatte ich ja schon einmal von meinem Langzeitprojekt erzählt, die ganzen wazong-Dienste auf eine modernere Basis zu stellen. In diesem Artikel werde ich mal versuchen, die alle aufzulisten. Das dient einerseits dazu, dass ich später nichts vergesse und andererseits ist ja vielleicht für den einen oder die andere etwas interessantes dabei, denn viele davon betreibe ich ja als „öffentliche“ Infrastruktur. Also, was läuft alles auf wazong?

Möglicherweise habe ich sogar noch was vergessen, das werde ich dann nachtragen, außerdem gibt es ein paar Kandidaten, die ich mit dem Umzug eventuell einstellen werde. Aber so untereinander hingeschrieben sieht das tatsächlich ganz beeindruckend aus.

Kategorien
Blog

Alles muss hier moderner werden

Gestern ist dieses – zugegebenermaßen im Moment etwas vernachlässigte – Blog 18 Jahre alt geworden. Herzliche Glückwünsche zur Volljährigkeit.

Nicht ganz so alt, aber fast, ist die Infrastruktur, auf der es läuft: das Blog und ein ganzer Strauß weiterer Dienste verteilen sich auf zwei „root-Servern“ bei Hetzner, die ich jetzt schon seit 2009 bzw. 2014 gemietet habe.

Das ist jeweils das „richtige Blech“, und in einem der beiden Server laufen die Festplatten (ja, so richtig mit rotierendem Rost!) seit bald 13 Jahren durchgehend, im anderen ist das mit 8 Jahren auch nicht viel besser.

[…]
SMART Attributes Data Structure revision number: 16
Vendor Specific SMART Attributes with Thresholds:
ID# ATTRIBUTE_NAME          FLAG     VALUE WORST THRESH TYPE      UPDATED  WHEN_FAILED RAW_VALUE
  1 Raw_Read_Error_Rate     0x000f   100   100   051    Pre-fail  Always       -       0
[…]
  9 Power_On_Hours          0x0032   077   077   000    Old_age   Always       -       114123
[…]

Ich habe zwar ordentliche Backups eingerichtet (und auch die Wiederherstellung getestet), und ich bin mir deshalb recht sicher, dass keine Daten verloren gehen würden, wenn doch mal was abraucht (klopft auf die Tischplatte) … aber ich hätte wahrscheinlich einige Tage Arbeit, um einen der Rechner wieder so aufzusetzen, dass alles so läuft wie zuvor.

In der Arbeit hingegen bin ich inzwischen Teil des „Site Realiability Engineering“-Teams, das die Cloud-Infrastruktur betreibt und betreut. Dort benutzen wir Kubernetes auf Virtuellen Maschinen in der Azure Cloud. Die Infrastruktur ist komplett in beschreibem Code abgelegt und kann jederzeit wieder in den definierten Zustand gebracht werden.

Ist so eine VM kaputt, dann wird sie einfach gelöscht und neu angelegt. In der Theorie der Infrastructure as Code wird das als Pets vs. Cattle bezeichnet, und die Idee dahinter ist, dass die einzelnen, spezialisierten und schwer aufzubauenden Server gedanklich wie Haustiere sind, während die kurzlebigen und austauschbaren Cloud-VMs eher wie Nutztiere sind, wo eine Kuh genau so gut ist wie die nächste (sowohl Veganer als auch bayerische Kleinbauern, die die Namen all ihrer Kühe kennen, werden dem Bild nicht ganz zustimmen können, aber die Idee kommt wohl rüber).

Jetzt ist Azure für mich viel zu teuer, da dort jede einzelne VM monatlich schon mehr kostet als alle meine Server zusammen. Doch auch Hetzner bietet inzwischen Cloud-VMs, darum möchte ich alles hier (macht ausholende Handbewegung) auf Kubernetes in der Hetzner Cloud umziehen.

Ein paar weitere Modernisierungen plane ich im Zuge der Umbauten auch gleich zu machen, und ich werde das hier begleiten in einer eher technischen Artikelserie.

Kategorien
Blog

(Klopf klopf) Ist das Ding noch an?

Oh ja, dieses Blog habe ich ziemlich vernachlässigt. Aber immer, wenn ich mich (privat) an den Rechner setze, habe ich eigentlich eher etwas zu basteln. Den Blogumzug auf eine neue Infrastruktur habe ich zum Beispiel ewig vor mir hergeschoben, bis ich ihn gestern endlich angepackt habe (für Neugierige: endlich wieder aktuelles WordPress in Docker auf aktuellem Apache, PHP 7.3, MariaDB 10, alle Tabellen auf InnoDB mit 4-Byte-UTF-8 umgezogen).

Ein paar Dinge sind noch geradezuziehen: die Umleitung auf https funktioniert noch nicht 100%, Uploads sind völlig unzeitgemäß auf 2MB begrenzt, und einige Plugins mussten auch ihr Leben lassen. Aber jetzt! Jetzt kann ich hier wieder mehr schreiben.

Kategorien
Blog

Let’s encrypt! Jetzt aber richtig!

Mehr TLS für alle!

Ich habe endlich angefangen, alle Blogs auf diesem Server auf https-only umzustellen. Das liegt zum Teil daran, dass die Übertragung von Daten über unverschlüsseltes http von den Browsern (zurecht) immer mehr als unsicher gekennzeichnet wird. Und es verringert natürlich die Überwachungsgefahr für alle Besucherinnen und Besucher der Blogs. Ja, wahrscheinlich ist der Besuch dieser Seiten für Geheimdienste, Ermittlungsbehörden und ähnliche Parteien kein interessanter Datenpunkt, aber ich will mir nicht anmaßen, das für andere Leute zu entscheiden.

Deshalb gibt es jetzt schon percanta.de, streifzug.me, freifunk-stuttgart.de  und weitere nur noch über verschlüsselte Verbindungen. Die Zertifikate dafür kommen von Let’s Encrypt, wo sie endlich automatisiert generiert und erneuert werden können, weshalb die ganze Aktion nicht mehr in einem Albtraum an Ablaufterminen enden muss.

Trotzdem steckt noch einiges an Arbeit in der weiteren Einrichtung und der Beseitigung von Mixed-Content-Warnungen. Sollte sich irgendwas seltsam verhalten, dann meldet Euch.

Kategorien
Blog

WordPress-Updates vergessen .htaccess

Nachdem das Social Plugin von Mailchimp, das hier früher so schön die Reaktionen von Facebook und Twitter als Kommentare ins Blog importiert hat, zu funktionieren aufgehört hatte, habe ich mich ein wenig mit IndieWeb beschäftigt. Lange noch nicht tiefgehend genug, aber die Plugins funktionierten erstmal ganz gut und brachten meinem Blog Webmentions bei (wie z.B. hier zu sehen ist).

Doch am vorletzten Wochenende habe ich ein paar Updates installiert (sowohl für WordPress als auch für das Webmentions-Plugin), und am Anfang der letzten Woche kamen dann gar keine Webmentions mehr an. Bei Bridgy fand ich erstmal nur nichtssagende Fehlermeldungen.

Auf meinen frustrierten Tweet meldeten sich aber sofort freundliche Helfer, darunter der Autor des Webmentions-Plugins, und gemeinsam konnten wir der Ursache auf die Spur kommen: tatsächlich hatte Bridgy eine ordentliche Logdatei, aus der hervorging, dass mein Apache einen Serverfehler 500 zurückgibt:

0.1.0.2 - - [30/Jan/2017:00:42:03 -0800] "POST /_ah/queue/propagate HTTP/1.1" 304 1071 "https://brid.gy/retry" "AppEngine-Google; (+http://code.google.com/appengine)"

2017-01-30 08:42:00.032720 D Params: NestedMultiDict([('response_key', u'aglzfmJy...')])
2017-01-30 08:42:00.937850 I Source: Thomas Renger (Facebook) 10153250416376118, http://brid-gy.appspot.com/facebook/10153250416376118
2017-01-30 08:42:01.030590 I Created by this poll: http://brid-gy.appspot.com/log?start_time=1485727919&key=aglzfmJyaWQtZ3lyIwsSDEZhY2Vib29rUGFnZSIRMTAxNTMyNTA0MTYzNzYxMTgM
2017-01-30 08:42:01.130020 I Starting Response like tag:facebook.com,2013:10155005024956118_liked_by_10153108342655662 https://www.facebook.com/10153250416376118/posts/10155005024956118#liked-by-10153108342655662
2017-01-30 08:42:01.729090 I Webmention from https://brid-gy.appspot.com/like/facebook/10153250416376118/10155005024956118/10153108342655662 to https://dentaku.wazong.de/2017/01/29/digitale-albtraeume-teil-2/
2017-01-30 08:42:01.834260 I Using cached webmention endpoint u'W https dentaku.wazong.de': https://dentaku.wazong.de/wp-json/webmention/1.0/endpoint
2017-01-30 08:42:01.845109 I Sending...
2017-01-30 08:42:02.543940 W Error sending to endpoint: {'body': u'<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">\n<html><head>\n<title>500 Internal Server Error</title>\n</head><body>\n<h1>Internal Server Error</h1>\n<p>The server encountered an internal error or\nmisconfiguration and was unable to complete\nyour request.</p>\n<p>Please contact the server administrator,\n [no address given] and inform them of the time the error occurred,\nand anything you might have done that may have\ncaused the error.</p>\n<p>More information about this error may be available\nin the server error log.</p>\n<hr>\n<address>Apache/2.2.22 (Debian) Server at dentaku.wazong.de Port 80</address>\n</body></html>\n', 'code': '...', 'request': u'POST https://dentaku.wazong.de/wp-json/webmention/1.0/endpoint (with source=https://brid-gy.appspot.com/like/facebook/10153250416376118/10155005024956118/10153108342655662, target=https://dentaku.wazong.de/2017/01/29/digitale-albtraeume-teil-2/)', 'http_status': 500}
2017-01-30 08:42:02.544750 W Propagate task failed

Aber vorher war das doch auch gegangen. Was hatte sich also geändert?

Nun, in der neuen Version war der API-Endpunkt für Webmentions in den Namespace der WordPress-REST-API hinein verlegt (wo er auch logisch hin gehört). Nach einigem Experimentieren fanden wir aber heraus, dass die komplette REST-API auf meinem Server nicht funktionierte — und zwar bei allen Blogs. Im Errorlog sah das dann so aus:

[Mon Jan 30 10:09:56 2017] [error] [client 0.0.0.0] Request exceeded the limit of 10 internal redirects due to probable configuration error. Use 'LimitInternalRecursion' to increase the limit if necessary. Use 'LogLevel debug' to get a backtrace.
[Mon Jan 30 10:09:56 2017] [debug] core.c(3116): [client 0.0.0.0] r->uri = /wp-json/webmention/1.0/endpoint
[Mon Jan 30 10:09:56 2017] [debug] core.c(3122): [client 0.0.0.0] redirected from r->uri = /wp-json/webmention/1.0/endpoint
[Mon Jan 30 10:09:56 2017] [debug] core.c(3122): [client 0.0.0.0] redirected from r->uri = /wp-json/webmention/1.0/endpoint
[Mon Jan 30 10:09:56 2017] [debug] core.c(3122): [client 0.0.0.0] redirected from r->uri = /wp-json/webmention/1.0/endpoint
[Mon Jan 30 10:09:56 2017] [debug] core.c(3122): [client 0.0.0.0] redirected from r->uri = /wp-json/webmention/1.0/endpoint
[Mon Jan 30 10:09:56 2017] [debug] core.c(3122): [client 0.0.0.0] redirected from r->uri = /wp-json/webmention/1.0/endpoint
[Mon Jan 30 10:09:56 2017] [debug] core.c(3122): [client 0.0.0.0] redirected from r->uri = /wp-json/webmention/1.0/endpoint
...

Es brauchte einiges an weiterem Debugging um herauszufinden, was meine Installation von anderen unterschied: meine .htaccess-Datei stammte noch von der ursprünglichen WordPress-µ-2.9-Installation, in die ich die Blogs 2009 umgezogen habe. Die Unterschiede, die sich da über die Jahre ergeben haben, sind bei WordPress auch ordentlich dokumentiert, aber da steht leider nicht, dass mit den älteren Varianten einige neue Funktionen gar nicht … äääh … funktionieren.

Nachdem ich die zentralen Rewrite-Regeln von:

# add a trailing slash to /wp-admin
RewriteCond %{REQUEST_URI} ^.*/wp-admin$
RewriteRule ^(.+)$ $1/ [R=301,L]

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule . - [L]
RewriteRule  ^([_0-9a-zA-Z-]+/)?(wp-.*) $2 [L]
RewriteRule  ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]
RewriteRule . index.php [L]

zu:

# add a trailing slash to /wp-admin
RewriteRule ^wp-admin$ wp-admin/ [R=301,L]

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L] 
RewriteRule ^(wp-(content|admin|includes).*) $1 [L] 
RewriteRule ^(.*\.php)$ $1 [L]
RewriteRule . index.php [L] 

„modernisiert“ hatte, funktionierte auch die REST-API. Und schon kamen die Webmentions wieder an.

Also Achtung! Überprüft auch Eure WordPress-Blogs mal, ob die .htaccess-Datei auf dem neuesten Stand ist, denn das Update aktualisiert sie nicht für Euch. Ruft mal ${euerblog}/wp-json/ auf und guckt, ob da ein JSON-String oder eine Fehlermeldung kommt.

Vielen Dank an @pfefferle für die Hilfe beim Debugging.

Kategorien
Blog

Orange Wand

Die Wand ist jetzt Orange, und das kam so:

Letztes Jahr im Herbst bemerkten wir, dass einer der zahlreichen Flecken an der Wand neben dem Esstisch (wer Kinder hat, weiß was ich meine…) in der Lage war, seine Größe zu ändern. Und er war auch gar kein Fettfleck — so wie seine Nachbarn — sondern eher feucht und kühl, und außerdem war er bei schlechtem Wetter mit Regen deutlicher zu sehen.

blättert

Schon kurze Zeit später begann an der Stelle die oberste Schicht Wandfarbe abzublättern. Offensichtlich kam hier irgendwie Feuchtigkeit durch die Mauer.

Genau in der Höhe des Flecks verläuft außen eine Fuge der (denkmalgeschützten) Sandsteinfassade, die hatte ich gleich als Ursache in Verdacht.

Wir informierten die Hausverwaltung, und die schickte einen Maurer zur Begutachtung vorbei. Der Fachmann fand meine Theorie eher unwahrscheinlich und vermutete vielmehr, dass das Wasser durch die Wand hinter dem Putz von weiter oben dort hinlaufe. Man müsse den Putz wohl großflächig abschlagen.

Deshalb montierte ich mal die darüber hängenden Wandregale ab und stapelte die DVDs in der Ecke des Zimmers. Das war Anfang Oktober, und dann passierte erstmal nichts.

nur wenig aufgestemmt

Als es endlich gelungen war, einen weiteren Termin zu vereinbaren, dauerte die lange erwartete Maureraktion nur ungefähr zehn Minuten: nach fünf Meißelschlägen war klar, dass das Wasser eben doch durch die waagerechte Fuge eindrang.

Die nächste Aktion fand außerhalb unserer Wohnung statt: die Fuge wurde von außen abgedichtet. Das Loch in der Wand war ab da trocken, klaffte aber weiterhin. Wobei: mit der Zeit gewöhnt man sich ja an den Anblick.

Nur wenige Monate später wurde die Wand dann aber doch frisch verputzt, und vor etwa drei Wochen war schließlich nur noch der Farbunterschied zwischen grauem Putz und (nicht mehr so richtig) weißer Wand zu sehen. Das Stück Wand musste also neu gestrichen werden. Wie aber, ohne dass es angestückelt wirkt?

so, fertig

Ein Teilanstrich in frischer weißer Wandfarbe hätte sich von der restlichen Wand deutlich abgehoben, und die ganze Wand (oder gar das ganze Zimmer) wollte ich nicht streichen. Deshalb nahmen wir uns eine Kontrastfarbe vor, fuhren am vergangenen Samstag zum Baumarkt, und entschieden uns da für Orange.

Am Sonntag verbrachte ich dann große Teile des Tages damit, die Leiter herauf- und herunterzusteigen um der Fläche drei Anstriche zu verpassen (den Muskelkater spüre ich jetzt noch).

Gestern habe ich noch einmal ein paar Stellen nachgestrichen, an denen die Farbe immernoch nicht ordentlich gedeckt hatte, und heute konnte ich endlich alle Regale wieder anbringen und auch die übrigen Möbel wieder an ihren Platz räumen.

So, fertig. Hübsch geworden, oder?

Kategorien
Photoblog

Malergehilfin

Kategorien
Blog

Ist schon wieder Vollmond?

Ein Tweet war der Auslöser:

anjam_DD: @CucinaCasalinga istschonwiedervollmond.de #allebekloppt

… und ich wollte auch schon immer mal so eine nützliche Single-Purpose-Seite haben. Daher präsentiere ich nach kurzer Bastelei für Euch alle: Ist schon wieder Vollmond?

(hoffentlich funktioniert das jetzt beim nächsten Vollmond auch richtig — der ist glaub‘ ich morgen)

Kategorien
Blog

wazong und Heartbleed

Heartbleed. Der erste Sicherheitsbug mit eigenem Logo und Webseite. Das eigentliche Problem muss ich sicher nicht mehr erklären (wenn noch Unklarheit besteht, hilft wie immer xkcd). Und natürlich war auch wazong betroffen, wenn auch nur ganz kurz.

Bis zum 21. März 2014 hatte ich nämlich noch OpenSSL 0.9.8 im Einsatz und hatte das gerade erst im Zuge der Maßnahmen zur Verbesserung der Sicherheit durch eine von Heartbleed betroffene Version ersetzt. Nun ja.

Die OpenSSL-Version war nach Veröffentlichung des Bugreports schnell ersetzt, aber bisher fehlten mir noch neue Zertifikate. Und mit neuen Zertifikaten allein war es auch nicht getan: sollten die privaten Schlüssel der alten Zertifikate in falsche Hände geraten sein, dann könnte ja jemand meine Serveridentitäten vorspiegeln.

An diesem Punkt rächte sich, dass ich kostenlose Zertifikate einsetze. Denn zum Ausgleich kostet ein Zertifikatrückruf bei StartSSL 24,90 $ (im Moment 18,58 €) pro Zertifikat. Da musste ich wohl in den sauren Apfel beißen und knapp 60 € nach Israel schicken.

Die folgenden Zertifikate sind jetzt also nicht mehr gültig und sollten bei funktionierender Infrastruktur auch nicht mehr von Browser akzeptiert werden:

  • dentaku.wazong.de mit SHA1-Fingerprint CD 5E 27 98 49 DF 09 4E AC 4B 8D 3B 4D 5F 71 D0 29 6A F0 3F
  • mail.wazong.de mit SHA1-Fingerprint B1 0F 3C A4 F8 BA 16 82 FE 4E 82 61 55 B5 45 52 46 9A 24 EE
  • piwik.wazong.de mit SHA1-Fingerprint D1 F0 DF B9 BC AC 89 1D 26 FB 53 9B C4 15 06 CB 4E D5 78 39

Das Zertifikat für prismcamp.de war nicht betroffen, da ich das erst nach der Reparatur erzeugt habe.

Jetzt seid Ihr als meine Benutzer dran: wie @janl in dieser ausführlichen Handreichung auf Kleinerdrei geschrieben hat (Hervorhebung von mir):

[…]

Und selbst dann sind wir noch nicht durch mit dem Thema Heartbleed. Weil potentiell alle unsere Passwörter bekannt sind, müssen wir nun für jeden Dienst, den wir im Internet nutzen unser Passwort ändern, und zwar erst dann, wenn wir von dem Dienst wissen, dass sie mit allen neuen Sicherheitsmaßnahmen durch sind. Solange sich z.B. Twitter nicht dazu äußert, dass sie alle Maßnahmen ergriffen haben, bringt eine Passwortänderung leider noch nichts.

[…]

Ich bin durch, Ihr müsst Eure Passwörter ändern.

Kategorien
Blog

Bugzilla

Ich habe für meine ToDo-Liste ein Bugzilla installiert. Das klingt jetzt vielleicht erstmal ein wenig spleenig, aber ich will die dahinterstehenden Überlegungen erläutern:

Bisher hatte ich meine ToDo-Liste in OmniFocus. Das war eigentlich toll: die Anwendung existiert auf Mac OS und iOS, die Synchronisation zwischen den Installationen läuft über meinen eigenen Server mit WebDAV. Am Arbeitsplatz mit Zwangs-Windows bin ich hingegen leider ausgesperrt, und die iPhone-Version hätte ich jetzt auch bald neu kaufen müssen (wie so oft: ein neuer Name für die iOS-7-Version, bitte noch einmal 17,99€ bezahlen). Was außerdem fehlt, ist jede Unterstützung für Kollaboration — es gibt keine Möglichkeit, andere Personen in die Erledigung der Aufgaben mit einzubeziehen.

Mit Wunderlist wäre das gegangen. Aber da hätte ich meine Daten wieder auf anderer Leute Server liegen, und das will ich doch so weit wie möglich vermeiden.

Da ich sowieso auch für die Dinge, die ich anbiete (z.B. die Dienste unter ironblogger.de, die WordPress-Plugins wie ddate) mal ein Bugtracking-System installieren wollte, und da ich als Entwickler den Umgang mit solchen Systemen gewöhnt bin, habe ich mich entschieden, alle meine Aufgaben da hineinzupacken. Eine ToDo-Liste funktioniert ja auch nur, wenn sie regelmäßig angesehen wird, und dabei ist es sicher nicht hilfreich, sie an möglichst viele Orte oder auf möglichst viele Programme zu verteilen.

Und warum dann Bugilla, das alte Schlachtschiff? Naja, JIRA ist natürlich viel hübscher, wird allerdings recht schnell ziemlich teuer, wenn mehr Leute teilnehmen dürfen sollen (siehe oben). Solche Einschränkungen kennt die OpenSource-Konkurrenz nicht, und so ist der Server absichtlich für alle Einträge offen. Wenn ihr also findet, dass ich irgendwas dringend tun sollte, dann meldet Euch einfach bei meinem Bugzilla an und tragt Eure Wünsche ein.

Jetzt muss ich noch alle Einträge aus den anderen Programmen übernehmen.

Kategorien
Blog

TLS besser machen

Anmerkung: Auch wenn im folgenden ganz viele Dinge irgendwas mit SSL heißen, möchte ich noch einmal ausdrücklich darauf hinweisen, dass diese Bezeichnung seit 15 Jahren(!) veraltet ist. SSL war eine proprietäre Verschlüsselungserweiterung von Netscape (und es gab vergleichbare Technik von Microsoft unter dem Namen PCT). Seit es 1999 von der IETF standardisiert wurde, heißt es TLS.

TLS (https) habe ich auf dieser Seite schon seit einiger Zeit angeboten. Bisher hatte ich dazu ein Zertifikat von CAcert, doch die sind leider auf den meisten Systemen nicht Teil der vorgegebenen vertrauenswürdigen Zertifizierungsstellen (vgl. Kryptographie ist schwierig). Dadurch war die verschlüsselte Verbindung zu meinem Blog außerhalb von Nerdkreisen nicht zu gebrauchen, weil sie je nach Browser mit verschieden drastischen Sicherheitswarnungen verbunden war. Das musste besser werden.

Im SSL Server Test (seufz) schlug sich das dann auch in einer entsprechenden Note nieder:

Overall Rating: F

Ein F (Note 6). Nicht gut.

Kategorien
Blog

Today is Pungenday, the 38th day of Chaos in the YOLD 3180

Einer der wazong-Benutzer trug den Feature-Request an mich heran, dass sein Blog die Datumsangaben bitte gemäß Diskordianischem Kalender anzeigen sollte. Das ist eine Funktion, die ich auch länger schon haben wollte, dafür müsste es doch ein Plugin geben — das hier ist schließlich WordPress.

Leider fand ich nur dieses: Discordian Date. Aber das konnte nur das aktuelle Datum in einem Widget darstellen. Na gut, dann musste ich eben selbst ran.

Ich habe mich also zwei Abende hingesetzt, und nun ist Version 0.1 meines kleinen Plugins fertig geworden. Es unterstützt bisher nur die ausgegebenen Daten an Artikeln und Kommentaren, hier zu sehen auf einer Artikelseite:

Screenshot mit Diskordianischen Daten

Um auch die Archivstruktur nach dem Gesetz der Fünf anzuordnen, muss ich noch tiefer in WordPress eingreifen. Das kommt später. Dafür habe ich mir Mühe gegeben, die Implementation so sauber wie möglich in die API einzufügen, damit das Diskordianische Datum genau so wie das Gregorianische Datum mit PHP-Formatstrings formatiert werden kann.

Für spätere Version habe ich noch folgendes auf der „Roadmap“:

  • Implementierung der noch fehlenden Formatstrings (z.B. Wochennummer, zweistelliges Jahr,…)
  • WordPress-Archive nach Diskordianischem Kalender
  • Apostelfeiertage und Monatsfeiertage
  • Sprachunterstützung (die soll abschaltbar werden, denn manche Leute mögen die Übersetzungen der Monate und Wochentage nicht)

Bis dahin Viel Spaß mit ddate Version 0.1!

Kategorien
Blog

Mail über Tor routen, ein Experiment

Ungestörte Mailkommunikation ist in den letzten Monaten schwierig geworden (d.h. eigentlich war sie das schon vorher aber wir wussten es nicht). Die Inhalte können wir verschlüsseln, aber inzwischen wissen wir, dass die Metadaten für die Überwacher fast genau so interessant sind. Wenn wenigstens beide an einer Kommunikation beteiligte Mailserver TLS nutzen, dann fällt es dem Lauscher schon schwerer, Adressen und Subject:-Zeile mitzulesen, er kann aber immernoch die IP-Verbindung zwischen den beiden Mailservern sehen. Gerade zwischen uns „Power-Usern“ mit eigenen Mailservern lassen sich dadurch praktisch alle persönlichen Verbindungen rekonstruieren.

Was aber, wenn wir diese Verbindung durch Tor schicken? Probieren wir mal aus, ob das überhaupt geht.

Als Ausgangssituation habe ich wie üblich an beiden Enden Debian GNU/Linux-Server mit Postfix als MTA und Tor — alles von Standard-Paketen installiert.

Empfang

Den empfangenden Mailserver als Tor Hidden-Service einzurichten ist einfach. Dazu muss nur ein Verzeichnis angelegt werden:

mkdir hiddenmailserver

… und in der Konfiguration der SMTP-Port freigeschaltet werden:

HiddenServiceDir /var/lib/tor/hiddenmailserver/
HiddenServicePort 25 127.0.0.1:25

Beim nächsten Start des Tor-Dienstes entsteht dann der neue Hidden-Hostname in der Datei hostname im vorher angegebenen Verzeichnis. Nachdem wir den wissen, können wir die Verbindung gleich testen (mit netcat und torsocks, einem Wrapper, der Bibliotheken zur Umleitung der Netzwerkverbindungen über Tor vorlädt):

ponos:~# torsocks nc -t u2bhrnyodeqtmlt2.onion 25
220 nyx.wazong.de ESMTP Postfix (Debian/GNU)
EHLO ich
250-nyx.wazong.de
250-PIPELINING
250-SIZE 102400000
250-VRFY
250-ETRN
250-STARTTLS
250-AUTH PLAIN LOGIN
250-AUTH=PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
QUIT
221 2.0.0 Bye
ponos:~#

Funktioniert.

Versand

Wie auch die meisten anderen Mail Transport Agents ist Postfix in der Lage, abhängig von der Zieladresse den Transportkanal zu wechseln. Der Mechanismus stammt von „früher“, als es aus Kostengründen noch üblich war, bestimmte Domains über einen anderen Weg als SMTP mit Mail zu beliefern (z.B. UUCP). Die einzelnen Transportkanäle sind Programme, die in einem Verzeichnis liegen. Wir erzeugen also ein Skript, das den smtp-Transportkanal mit torsocks aufruft:

#!/bin/bash
torsocks /usr/lib/postfix/smtp $@

… und Tragen es als tor-Transportkanal in der /etc/postfix/master.cf ein:

[...]
smtp      unix  -       -       -       -       -       smtp
tor       unix  -       -       -       -       -       tor
[...]

Dann schalten wir in der /etc/postfix/main.cf den Transport-Auswahlmechanismus ein:

[...]
transport_maps = hash:/etc/postfix/transport
[...]

…, schreiben unsere Tor-Konfiguration in die /etc/postfix/transport:

wazong.de tor:[u2bhrnyodeqtmlt2.onion]

…, und laden sie in den Mailserver:

cd /etc/postfix
postmap transport

Zum Test schicken wir eine Mail. Im Logfile des versendenden Mailservers sieht das so aus:

Nov 25 23:29:02 ponos postfix/smtp[20884]: 002A82A43B6: to=<dentaku@wazong.de>, 
                relay=u2bhrnyodeqtmlt2.onion[127.0.69.0]:25, delay=14,
                delays=0.06/0.09/12/1.5, dsn=2.0.0,
                status=sent (250 2.0.0 Ok: queued as 877A97240DF)

… und in den Headern der empfangenen Mail:

Received: from ponos.wazong.lan (localhost [127.0.0.1])                                   
        by nyx.wazong.de (Postfix) with ESMTP id 877A97240DF                              
        for <dentaku@wazong.de>; Mon, 25 Nov 2013 23:29:01 +0100 (CET)

Funktioniert.

Ausblick

All das ist natürlich im Moment nur im Proof-Of-Concept-Stadium. Es skaliert in dieser Form nämlich überhaupt nicht, weil auf jedem teilnehmenden Server alle anderen über Tor erreichbaren Domains in der Transport-Map stehen müssten. Postfix kann aber den Table-Lookup an ein externes Programm auslagern (Stichwort: tcp_table) — und das könnte wieder in einem verteilten System nachsehen, also z.B. nach einem bestimmten TXT-Record im DNS. Diese Abfrage müsste dann natürlich auch durch Tor gehen, weil wir sonst DNS-Leaks riskieren.

Außerdem eignet sich die Methode nicht für komplett anonymes Mailen, weil Informationen über den vorherigen Weg der Mail noch immer in den Headern stehen. Und sie unterläuft einen Teil der üblichen Anti-Spam-Maßnahmen (z.B. Greylisting oder SPF), weil die IP-Adresse des einliefernden Mailservers ja jetzt nicht mehr bekannt ist.

Es gibt also noch einiges an Hausaufgaben zu erledigen. Trotzdem: wenn Ihr Lust habt, baut die Sache nach und schickt eine Mail an mich über u2bhrnyodeqtmlt2.onion.

Kategorien
Microblog Photoblog

Ich habe einen „Adventskranz“ …

Ich habe einen „Adventskranz“ „gebastelt“. instagram.com/p/hWc0fbpfhs/  #

Kategorien
Blog

Einen eigenen DynDNS-Service betreiben

DynDNS ist eine praktische Sache: der heimischen Internetverbindung wird ein Name zugewiesen, und wenn die IP-Adresse wechselt, dann kann der automatisch aktualisiert werden. Die meisten handelsüblichen Router können das — aber nicht allein, sondern es wird immer ein spezieller DNS-Server benötigt.

Da gab es mit dyndns.org lange Zeit einen gut funktionierenden kostenlosen Dienst, aber der nennt sich inzwischen dyn.com und will verhältnismäßig viel Geld haben (es gibt zwar immernoch eine kostenlose Variante, aber die muss regelmäßig per Klick auf bunt blinkende Mails wieder freigeschaltet werden). Der Wechsel zu irgendeinem der Konkurrenten verbessert die Lage mutmaßlich immer nur vorübergehend. Außerdem möchte zumindest ich meine Infrastruktur so viel wie möglich selbst betreiben.

Die Aufgabe ist also, einen Eintrag im DNS zu ändern. Eigentlich gibt es einen Prima Standard um DNS-Zonen zu aktualisieren, nämlich das Dynamic DNS Update Protocol, wie es in RFC 2136 und RFC 2137 beschrieben ist. Das können die aktuellen DNS-Server ohne zusätzliche Software, und es ist auch schön kryptographisch abgesichert, aber keiner der handelsüblichen Router kann das (diesem Muster werden wir später nochmal begegnen).

Da muss es doch was von GNU geben. Und tatsächlich: genau diese Aufgabe übernimmt GnuDIP. Das wird zwar seit mehr als 10 Jahren nicht mehr weiterentwickelt, funktioniert aber stabil (Ok, die Webseite sieht sehr altbacken aus und möchte gern ein Java-Applet zur Bestimmung der IP-Adresse verwenden — und was ich davon halte ist ja bekannt).

Im Folgenden richten wir unter der Beispieldomain steinhobelgruen.de eine dynamische Domain dyn.steinhobelgruen.de ein.

Installation

Als Basis nehmen wir einen Debian GNU/Linux-Server mit bind9 als DNS-Server und MySQL als Datenbakserver und gehen (zumindest für den mittleren Teil) grob nach dieser Anleitung vor. Leider hat Debian das gnudip-Paket irgendwann aus der Distribution entfernt, wir machen also eine richtig klassische /usr/local-Installation.

Wir laden das Paket runter, entpacken es und „installieren“ die Software:

wget http://gnudip2.sourceforge.net/gnudip-www/src/gnudip-2.3.5.tar.gz
tar zxvf gnudip-2.3.5.tar.gz
mv gnudip-2.3.5/gnudip /usr/local

Dann legen wir die Datenbank an, dazu passen wir in der Datei gnudip-2.3.5/gnudip.mysql eventuell noch Datenbankname und Passwort an und rufen dann MySQL auf:

mysql -uroot -p  < gnudip-2.3.5/gnudip.mysql

In der GnuDIP-Konfiguration unter /usr/local/gnudip/etc/gnudip.conf müssen wir dasselbe Datenbankpasswort  konfigurieren.

Die mitgelieferten cgi-Skripten konfigurieren wir auf dem Webserver; dazu fügen wir die folgenden Zeilen in der Konfiguration des Webservers ein (eventuell in einem bestimmten Virtual Host):

[...]
Alias /gnudip/html/ /usr/local/gnudip/html/

<Location /gnudip/html/>
Options Indexes
ReadmeName .README
HeaderName .HEADER
RemoveHandler .pl
RemoveType .pl
AddType text/plain .pl
</Location>
ScriptAlias /gnudip/cgi-bin/ /usr/local/gnudip/cgi-bin/

DNS Server konfigurieren

Erstmal richten wir einen Schlüssel für DNS-Updates ein. Dazu brauchen wir das dnssec-keygen-Tool aus dem Debian-Paket dnsutils.

dnssec-keygen -a hmac-sha512 -b 512 -n HOST gnudip

Der Aufruf erzeugt zwei Dateien, die zum Beispiel Kgnudip.+165+23314.key und Kgnudip.+165+23314.private heißen.

Wenn der DNS-Server eine Domain dynamisch aktualisieren soll, dann braucht er ein Verzeichnis, in dem er Schreibrechte hat. Wir legen also eins an:

mkdir /etc/bind/dyndns
chown bind:bind /etc/bind/dyndns

In das neue Verzeichnis legen wir eine fast leere DNS-Zonendatei dyn.steinhobelgruen.de:

$ORIGIN dyn.steinhobelgruen.de.
$TTL 86400
@ IN SOA nyx.wazong.de. hostmaster (
      0 ; Serial
   3600 ; Refresh
   1800 ; Retry
 604800 ; Expire
  600 ) ; Negative Cache TTL
@ IN NS nyx.wazong.de.
@ IN MX 0 nyx.wazong.de.
@ IN A 188.40.53.18

Die neue Zone deligieren wir in der Zone steinhobelgruen.de an unseren Nameserver:

$ORIGIN steinhobelgruen.de.
[...]
dyn IN NS nyx.wazong.de.

Den vorhin erzeugten Schlüssel aus der …private-Datei kopieren wir folgendermaßen in die named-Konfiguration  aufgenommen (in einer neuen Datei /etc/bind/gnudip.key ) …

key gnudip-key {
 algorithm hmac-sha512;
 // the TSIG key
 secret "u+/X3NGp1aQxvJedO/8j2xHDxtNgBaSOMgAYMo/OtpbUJXh02Fwfi8+u+yNq/zkIp36m2vY85pw8pgKMk5XSAw==";
 };

… und in der /etc/bind/named.conf.local legen wir die dynamische Zone an und erlauben die Aktualisierung mit dem Schlüssel:

[...]
// include definition of GnuDIP update key
 include "/etc/bind/gnudip.key";
// define GnuDIP dynamic DNS zone
 zone "dyn.steinhobelgruen.de" in {
 type master;
 file "/etc/bind/dyndns/dyn.steinhobelgruen.de";
 allow-query { any; };
 update-policy { grant gnudip-key subdomain dyn.steinhobelgruen.de; };
 };

Wenn alles passt können wir Bind neu starten (bzw. die Konfiguration neu laden).

/etc/init.d/bind9 reload

Die Teile Verbinden

Der Private Schlüssel kommt zur GnuDIP-Installation nach /usr/local/gnudip/etc/ und wird in /usr/local/gnudip/etc/gnudip.conf eingetragen:

[...]
nsupdate = -k /usr/local/gnudip/etc/Kgnudip.+165+23314.private
[...]

Nach dieser Einrichtung sollten wir direkt auf dem Webinterface einen Admin-Benutzer und die Domain anlegen. Danach können wir weitere Benutzer anlegen oder sogar Selbstregistrierung einschalten.

GnuDIP Web Interface

Router anbinden

An dieser Stelle ist GnuDIP jetzt zu sicher um praktisch zu sein: es definiert nämlich ein eigenes Protokoll für die Aktualisierung der Einträge über HTTP, in der das Passwort zusammen mit einem Salt und einem Zeitstempel in einem MD5-Hash und base64-codiert übertragen wird. Genau so sollte so etwas eigentlich auch gemacht werden, aber keiner der handelsüblichen Router kann das.

Grrrrr! Was können die denn überhaupt?

Nun ja, das ist unterschiedlich. Da ich so eine gerade hier habe, werden wir als Beispiel eine Fritz!Box anbinden. Die unterstützt als DynDNS-Anbieter „Benutzerdefiniert“ und kann dann eine selbstgewählte Update-URL eintragen. Was sie dabei übertragen kann steht in dieser Dokumentation bei AVM. Also habe ich in GnuDIP eine zusätzliche und vereinfachte Update-URL eingebaut, die dazu passt.

Um die bei Euch zu installieren, müsst Ihr dieses Archiv mit zwei Dateien herunterladen, sie auspacken und zu Eurer GnuDIP-Installation dazu kopieren.

Damit ergibt sich als neue Update-URL:

https://steinhobelgruen.de/gnudip/cgi-bin/simpleupdt.cgi?user=<username>&pass=<pass>&domn=<domain>&addr=<ipaddr>&reqc=0 (und zwar genau so mit allen Platzhaltern). Die restlichen Parameter werden wie gewohnt konfiguriert (Achtung! Die Domain muss mit dem Benutzernamen anfangen!)

Benutzerdefinierter Service

Durch die Änderung werden jetzt Benutzername und Passwort im Klartext über’s Netz geschickt. Das gleiche Problem hat aber auch die Benutzeroberfläche, so dass auf dem Server vielleicht sowieso besser TLS (https) benutzt werden sollte.

Und siehe da: es funktioniert:

dentaku@nyx:~$ host dentaku.dyn.steinhobelgruen.de
dentaku.dyn.steinhobelgruen.de has address 78.42.203.144
dentaku@nyx:~$

(P.S.: gebt Euch keine Mühe, die Beispieldomain gibt es wirklich, aber die Schlüssel hier im Blogbeitrag sind natürlich nicht die echten — ach ja, und alle Domain- und Hostnamen werden bei Euch andere sein, wenn Ihr der Anleitung folgt)

Kategorien
Microblog Photoblog

Musste für Kind.eins mal was …

Musste für Kind.eins mal was binden. instagram.com/p/clwHzepfhQ/  #

Kategorien
Blog

Da, DaWanda

Ich tippe ja oft auf der Tastatur rum und nenne das dann „basteln“. Das ist natürlich geschwindelt, denn wenn hier im Haushalt jemand richtig bastelt, dann ist das meine Frau. All die kleinen Figuren und Kuscheltiere, die dabei entstehen, lagen bisher nur hier in unserer Wohnung herum und konnten vom Rest der Welt nur in ihrem Blog (lesen!) bewundert werden. Das sah dann zum Beispiel so aus:

Lila Dino einige kleine Hunde

Jetzt endlich können auch alle anderen Menschen diese Dinge bekommen, denn seit ein paar Tagen hat sie einen DaWanda-Shop (kaufen!). Juhuu!

(Bilder: Susanne Renger, alle Rechte vorbehalten)

Kategorien
Blog

IronBlogger Update: Bonn führt

Hier mal ein kurzer Zwischenstand meiner aktuellen Bemühungen um den Aufbau des IronBlogger-Netzwerks:

Nach 144 Mails und unzähligen Tweets existieren jetzt auf diesem Server die Webseiten und Mailinglisten für Bodensee, Bonn und Köln. Mit Karlsruhe, Bern und Rhein/Main bin ich gerade in unterschiedlichen Stufen des Startprozesses. Am weitesten ist eindeutig Köln Bonn: dort steht sogar schon die Teilnehmerliste, die Proberunde startet morgen, und auf der Mailingliste wird schon über’s Logo diskutiert. Da könnten sich die anderen ruhig ein wenig ranhalten…

Auf komplett eigener Infrastruktur haben sich währenddessen noch die IronBlogger Leipzig gegründet.

Jetzt frage ich mich nur noch: was ist eigentlich mit München?

Kategorien
Blog

An die neuen IronBlogger-Gruppen

Damit ich das jetzt nicht für jede Anfrage getrennt in Antwortmails schreibe:

Der Plan von ironblogger.de ist, den technischen Aspekt des Betriebs der Gruppen zu zentralisieren und sie von der Pflicht zu befreien, sich einen Hausnerd (m/w) zu halten.

Es soll Weboberflächen für die Verwaltung der teilnehmenden Blogs, für Urlaub, Entsperrung und die Erfassung von Einzahlungen geben. Aber noch ist nichts davon fertig.

Daher biete ich Euch an, mein bestehendes Setup mitzubenutzen. Das besteht aus einem Mailinglistenserver  und dem schon vielfach erwähnten Schwung an Python-Skripten, die die Feeds abgrasen und die Auswertungen erstellen. Die Auswertungen werden über die XML-RPC-Schnittstelle in ein WordPress-Blog gepostet (theoretisch müsste auch blogger/blogspot gehen, aber das habe ich noch nicht getestet). Das Blog könnt Ihr entweder direkt hier laufen lassen (als Beispiel heute angelegt: bodensee.ironblogger.de) oder, wenn Ihr denn darauf besteht, auf Eurem Server (oder auf wordpress.com), und es kann entweder eine Subdomain von ironblogger.de bekommen oder jede andere Domain, auch wenn ich es hier hoste.

Wenn ihr das also alles haben wollt, dann meldet Euch bei mir und schickt mir Euren Domainwunsch und eine Liste der Startbelegschaft jeweils mit:

  • Name
  • Mailadresse
  • Blogadresse (und RSS-Feed-Adresse, wenn vom Standard abweichend)
  • Twittername, soweit vorhanden

Nur wer unbedingt will, sollte sich die Skripte noch selbst neu aufsetzen.

Kategorien
Microblog Photoblog

Vorsatz für heute

Vorsatz für heute: instagram.com/p/YwqYLApfuh/  #