E-mail mit DKIM einrichten mit Postfix, OpenDKIM und PowerDNS

Mailserver gelten (zu Recht) mittlerweile als mit die komplexesten und am schwierigsten zu wartenden Systeme. Das liegt unter anderem daran, dass es sich beim „S“ in SMTP leider nicht um „secure“ sondern um „simple“ handelt. SMTP ist das Simple Mail Transfer Protocol, das ist die Sprache nach welcher sich Mailserver untereinander verständigen und e-mails weiter reichen. Als es definiert wurde, war die Welt des Internet noch sehr klein und auch wesentlich friedfertiger. Heute muss man aufpassen wie ein Schießhund, schneller als einem lieb ist hat man mit einem Mailserver sonst Ärger. Free-Relays gibt es mittlerweile dankenswerter Weiser fast gar keine mehr – diese waren ein erster Angriffspunkt für unerwünschte Werbung (SPAM).

Die eigentliche Installation eines Mailservers ist meist gar nicht das Problem, es sind die vielfachen Absicherungen die es benötigt um ihn auch „sicher“ zu betreiben und nicht als SPAM-Schleuder missbraucht zu werden und natürlich auch sich der diversen SPAM-Quellen zu erwehren. Noch dazu kommt, dass man ggf. auch weitere Server-Prozesse benötigt die der Abholung von Mails durch den Benutzer dienen – heute in der Regel per IMAP (Internet Message Access Protocol), eher historisch zu sehen ist POP(3). Hier muss man dann auch noch dafür sorgen, dass die Authentifizierung für die ganzen Server-Prozesse auch noch schön synchron bleibt. Kurzum: Es ist ein System das man häufig unter dem Motto: Never touch a running system betreibt sobald die Konfiguration einmal den Vorstellungen und Bedürfnissen entspricht (von den üblichen Sicherheitsupdates einmal abgesehen).

Es gibt aber auch Weiterentwicklungen, insbesondere im Kampf gegen SPAM, eines der Verfahren dazu nennt sich DKIM (DomainKeys Identified Mail). Das System macht sich DNS (Domain Name System) und asymmetrische Kryptographie zu nutze: Jede e-mail die durch den Server verschickt wird, wird in den Kopfzeilen um eine digitale Signatur ergänzt. Anhand des im DNS hinterlegten öffentlichen Schlüssels kann dann jeder empfangende Mailserver prüfen ob die Mail vom sendenden Server stammt (korrekt signiert wurde). Das Verfahren ist mittlerweile den Kinderschuhen entwachsen und in den letzten Wochen und Monaten bin ich immer wieder einmal auf kleinere Probleme beim Mailversand gestoßen. Allerhöchste Zeit sich einmal den Thema zu widmen. Continue reading

Microservices – ein Wort, viele Deutungen

Microservices, der große Hype! Mit dem Einzug von Docker als sehr leichte Virtualisierung wurde es nochmal ein Stück leichter Projekte als derartige (Software-)Strukturen zu realisieren. Mittlerweile ist der Hype vorüber und Microservices sind eine von mehreren etablierten Architekturen. Wichtig: eine von vielen, ob sie auf das „Problem“ bzw. den Bedarf des „Stakeholders“ passt, steht auf einem anderen Blatt.

Wie ich lernen durfte, verwenden viele Menschen den Begriff des Microservice sehr unterschiedlich. Das sorgt immer wieder für Schwierigkeiten in der Kommunikation, denn wenn der Gesprächspartner ein anderes Bild im Kopf hat als man selbst, dann redet man sehr schnell aneinander vorbei und keiner ist glücklich bzw. fühlt sich missverstanden. Im Folgenden will ich ein wenig Licht ins Dunkel bringen bzw. eine aus meiner Warte wichtige Unterscheidung und Bezeichnungen die ich gerne verwende um Klarheit zu haben.

Aus meiner Erfahrung heraus wird der Begriff „Microservice“ in folgenden „Geschmacksrichtungen“ benutzt:

  • technischer Mikroservice
  • fachlicher Mikroservice

Bevor wir zu den Unterschieden kommen, es gibt selbstverständlich auch Gemeinsamkeiten.

Was Mikroservices eint

Mikro kommt von klein und im besten Falle meint kleiner auch übersichtlicher. Dies ist eine wichtige Gemeinsamkeit – egal ob fachlich oder technisch man beschreibt oder möchte eine Struktur haben die man noch gut überblicken kann. Gerade in der Software heißt das: Wenn man etwas ändert dann muss man nicht gleich Angst haben, dass einem alles auf die Füße fällt, weil die Abhängigkeiten und Querverbindungen so umfangreich sind dass man sich gar nicht erst ausmalen kann was alles den Bach runter geht wenn man eine Änderung durchführt.

Ganz häufig ebenfalls genannt werden hinsichtlich der Gemeinsamkeiten natürlich auch Technologien wie Docker, Podman, Kubernetes um einmal nur die aktuell wichtigsten zu nennen. Wichtig ist hierbei: Das sind typische Hilfsmittel um Microservices zu gestalten, einen absoluten kausalen Zusammenhang gibt es aber nicht zwingend. Man kann auch Mikroservices auf virtuellen Maschinen ausrollen und wenn man die Prozesstrennung auf einem Server genauer anschaut, dann ist das auch schon eine Art Mikroservice, auch wenn man es in der Regel nicht so nennt: Der Webserver hat im Speicherbereich des Datenbankservers nichts verloren, diese Form der Trennung gibt es aber schon sehr lange und sie ist aus gutem Grund sehr erfolgreich.

Wichtig und ebenfalls häufig genannt: Skalierbarkeit. Mikroservices baut man geschickter Weise so auf, dass diese ggf. mehrfach (auf unterschiedlichen Systemen) laufen können. Das Stichwort hier heißt horizontale Skalierung. Wenn der Ansturm ist, verteile ich die Last auf mehrere Schultern. Das wohl bekannteste Beispiel ist die Supermarkt-Kasse: Wenn die Schlange (Last) zu groß wird dann wird eine weitere Kasse aufgemacht, ist wieder weniger los, reduziere ich die Anzahl der offenen Kassen. Das ermöglicht es die Ressourcen effizient einzusetzen – im Supermarkt kann der Mitarbeiter die Zeit die er an der Kasse nicht gebraucht wird z.B. zum Auffüllen von Regalen nutzen.

Der technische Mikroservice

Spricht man unter Entwicklern oder auch DevOps, so ist man sehr nahe an der Technik. Dementsprechend wird der Mikroservice dort sehr häufig (aber eben nicht immer) als technischer Mikroservice betrachtet. Ich habe eine klare Aufgabenteilung: Der Datenbank-Prozess kümmert sich um die Datenhaltung, der Webserver um die Anfragen per HTTP(S) und dazwischen gibt es wahrscheinlich noch ein wenig Applikations-Code (wahlweise in PHP, Java, NodeJS oder was auch immer gerade passt).

Setzt man nun Docker ein, so sollte man pro Prozess einen Container bekommen, die Kommunikation erfolgt über Netzwerk-Sockets. Dabei ist noch nicht einmal gesagt, dass beide Prozesse auf der gleichen Maschine laufen, im Zweifel steht die Datenbank am anderen Ende der Welt (ob das dann sinnvoll ist, ist eine andere Sache). Kommt nun mehr Last dann kann ich in der Regel einfach mehr Container starten (auch wenn es da bei Datenbank natürlich noch das Thema ACID zu beachten gilt, häufig ist aber nicht die Datenbank der Flaschenhals sondern schon der Webserver kommt nicht hinterher). Brauche ich mehr Rechenleistung und die Aufgabe lässt sich parallelisieren kann ich auch hier einfach weitere Container hochfahren und jeder schnappt sich einen Teil der Arbeit (siehe Supermarktkasse). Sinnvoller Weise sollten die Aufgaben dann nicht auf der gleichen Hardware laufen, wenn die schon am Limit ist, dann macht ein zusätzlicher Container die Sache an der Stelle sogar eher schlimmer denn besser.

Merke „technischer Mikroservice“: Wir reden tatsächlich über einzelne Container-Instanzen.

Der fachliche Mikroservice

Meist eine Stufe höher in der Abstraktion findet sich der fachliche Mikroservice. Wie üblich wenn man die Abstraktionspyramide nach oben geht, werden die Element mit denen man es zu tun hat etwas gröber.

Das ist genau der Punkt an dem viele Product-Owner, Abteilungsleiter oder Manager vom Mikro-Service reden. Gemeint ist dabei aber nicht zwingend die Verteilung auf einzelne Prozesse (das wäre zu fein granular), stattdessen geht es um einzelne „Funktionen“ in einem Unternehme. Im E-Commerce hat sich bei entsprechend großen Unternehmen eine Aufteilung in verschiedene Fachgebiete durchgesetzt, z.B. Suche, Warenkorb, Checkout, Payment, Logistics. Ganz wichtig dabei ist: die einzelnen Aufgabenbereiche agieren unabhängig voneinander über definierte Schnittstellen (das können Rest-APIs sein, aber jeder andere Form der Schnittstelle geht fast genauso gut). Ob innerhalb eines Aufgabenbereichs dann noch eine weitere Unterteilung stattfindet und ob diese dann ggf. technische Mikroservices oder doch eher einen monolithischen Ansatz verfolgen ist für den fachlichen Mikroservice unerheblich. Wichtig ist: Die Aufgaben sind für ein Team überschaubar, es geht also nicht darum von der Beschaffung bis zur Auslieferung von Ware oder Leistungen an den Kunden alles zu beherrschen sondern nur einen (An)-Teil. Den sollte man dann aber eben richtig gut machen.

Fazit

Die Welt ist voller Homonyme und der Terminus „Mikroservice“ macht da keine Ausnahme. Es lohnt sich daher immer, einmal genau nachzufragen was denn nun der Gesprächspartner meint. Dabei schließen sich die beiden Konzepte nicht einmal gegenseitig aus – ganz im Gegenteil: technische Mikroservices sind ganz häufig die Grundlage für eine Mikroservice-Architektur auf der organisatorischen Ebene.

Erfahrungsbericht MacBook / MacOS

Ich hatte nunmehr für ca. ein halbes Jahr die Option mich arbeitsseitig einmal mit dem Thema MacBook und MacOS beschäftigen zu dürfen. Dieser Erfahrungsbericht ist somit sicherlich nicht zu 100% aussagekräftig und kann Spuren von Ironie und Frustration enthalten.

Zum Hintergrund: ich arbeite als Software-Entwickler und DevOp und bin seit Jahren bereits die meiste Zeit nativ unter Linux unterwegs und ursprünglich einmal mit DOS und Windows in verschiedenen Stufen „groß geworden“, für mich war es der erste Vollkontakt mit der Apple-Welt, auch beim Smartphone hat es mich bisher nicht wirklich gereizt einmal ein IPhone auszuprobieren. Continue reading

CentOS – „default target masked“ – was zu tun ist

Das hatte ich mir anders vorgestellt: Auf Arbeit gab es ein System das schon einige Jahre auf dem Buckel hat und leider selten Updates gesehen hat. Es läuft dort (noch) ein CentOS 7. Das Update schien eigentlich ganz normal durchgelaufen zu sein:

sudo yum update

Danach ging es wegen des (längst überfälligen) Kernelupdates an den Reboot und dann wurde es weniger lustig… denn die Maschine startet nur noch mit den Meldungen:

default target masked
rescue target masked, freezing

Den exakten Wortlaut habe ich nicht mehr, denn klar: In dem Zustand geht nur noch eine harter Reboot. Immerhin gut, dass die Maschine nicht in irgendeiner Cloud oder einem Rechenzentrum steht.

Continue reading

Docker healthchecks – things to consider

While working on a recent docker project I encountered an issue when it comes to health checks. You may define a health check for a container from within your Dockerfile, such as

HEALTHCHECK --interval=5s --timeout=5s --start-period=20s
         --retries=5 CMD wget --output-document=- 
         --quiet --tries=1 http://127.0.0.1

The syntax is quite simple to understand, you basically define how and when the health check should be executed and which command(s) to use. Breaking things down from the example

  • –interval=5s – run the check every 5 seconds
  • –timeout=5s – maximum time to wait for the health check to complete
  • –start-period=20s – allow some time for the process to be monitored to come to a functioning state, avoids false alarms during startup, in this case we allow 20 seconds
  • –retries=5 – only trigger an alarm after 5 unsuccessful tries (non zero exit code) – this helps avoiding false alarms in case the process is under heavy load
  • After the CMD follows the command to execute, this is done from inside the container, in the given example we check for the webserver to deliver something indicating the server is working properly

However every one should consider on how flexible the health check should be to match as many use cases as possible. This is especially true if you are dealing with web-based endpoints as pointed out in the example.

Continue reading

Why IPv4 is not better compared to IPv6 in terms of security of your home/office network

If you look at the internet at the moment, from a more technical point of view, you will often find users complaining about the „new“ Internet-protocol IPv6. Most of the time the complaints are about issues with the Internet-Service-Provider ISP used.

I will focus on the issue based on my experience in Germany (things might be different in your location, feel free to leave a note in the comments). In fact the technical introduction of IPv6 went unnoticed for most of the average users. This is partly due to the fact, that in the beginning there were not so much services that were accessible via IPv6 (a typical chicken-egg-problem) and most operating systems seamlessly degrade to IPv4 if a service is not available in IPv6.

Continue reading

Microservices: Ende-zu-Ende, IPv6, Docker und HTTPS / TLS / SSL

IPV6, das neue IP-Protokoll kommt, langsam aber sicher. Amazon ist mit seiner AWS-Cloud voran geprescht und verlangt mittlerweile Aufpreis für externe IPv4-Adressen. Diese werden zunehmend knapper und somit sind auch die Kosten verständlich. Auch bei diversen Hosting-Anbietern hat man seit einiger Zeit zumindest einmal Vorbereitungen getroffen entsprechende Kosten an den Kunden dezidiert weitergeben zu können. Unter anderem wird ein IPv6-only-Betrieb vergünstigt angeboten. Leider ist er auch für mich noch keine wirkliche Option, bereits der Blog benötigt um gut erreichbar zu sein immer noch eine externe IPv4-Adresse, ich möchte ja eine möglichst große Reichweite haben und potentielle Leser nicht aufgrund ihrer IP-Version diskriminieren.

Nun habe ich ja mittlerweile auch einige Dinge nach aktuellem Stand der Technik per Docker virtualisiert (genauer gesagt ist es ja nur eine Paravirtualisierung). IPv6 ist in Docker immerhin angekommen, der Support lässt allerdings immer noch deutlich zu wünschen übrig. Halbwegs tragbar ist der Aufwand wenn man eine feste, öffentliche IPv6-Range hat und mit docker compose bzw. eigenen Docker-Netzwerken arbeitet. Man muss sich dann nur mit der Problematik der Netzwerkaufteilung Gedanken machen. Entgegen der häufig gelesenen Aussage ist aber bei /64-Netzwerken nicht Schluss mit dem Subnetting in IPv6. Derartige Ranges bekommt man in der Regel bei den Hosting-Anbietern im Standard-Paket. Für mich selbst haben sich /80er Aufteilungen für Docker-Netzwerke bisher ganz gut bewährt, das kann man aber je nach Bedarf noch größer oder kleiner schneiden. Continue reading

OpenAPI Specification / SwaggerHub – nett gemeint und meistens gut

Fast jeder Entwickler der sich im Web bewegt, wird derzeit früher oder später Kontakt mit der OpenAPI Initiative  machen. Ziel ist es die Spezifikation von (primär REST)-Schnittstellen zu vereinheitlichen und dabei eine Version zu erzeugen die auch maschinenlesbar ist. Damit eröffnen sich viele Möglichkeiten zur Validierung, Dokumentation und wo nötig auch Code-Generierung wenn man entsprechende Frameworks einsetzt und externe Rest-APIs anspricht. Soweit so gut.

Die Spezifikation ist mittlerweile recht umfangreich und beschreibt sehr viele der Use-Cases recht gut. Insbesondere die Methodik zur Beschreibung von Endpunkten ist in meinen Augen wirklich gut gelungen. Nun gilt aber wie immer: Wo Licht ist, ist auch Schatten. Gerade im Umfeld der Schema-Definitionen bin ich auf eine Lästigkeit gestoßen, für die ich noch keine wirklich brauchbare Lösung gefunden habe. Im Wesentlichen geht es dabei um dynamische indizierte Arrays bzw. Objekte. Continue reading

PowerDNS mit Pi-Hole auf RasPi

Eines der etwas länger schon mal angedachten Projekte, welches ich dann aufgrund Zeitmangels und auch etwas Frustration in die Ecke gelegt hatte ist ein eigener, lokaler DNS-Server den man auch schnell aktualisieren kann – wer häufiger in verschiedenen Projekten arbeitet weiß es zu schätzen wenn man den Stall der Entwicklungs-Container nicht per IP-Adresse auswendig lernen muss, sondern ihn per sprechenden Namen ansprechen kann. In diesem Post geht es erst einmal darum die Grundlagen zu schaffen, auch das ist bereits etwas mehr Arbeit als ich gedacht hätte.Wichtige Eckpunkte / Material zum Nachbauen:

  • Raspberry Pi (inklusive Netzteil)
  • als DNS-Server kommt PowerDNS zum Einsatz
  • MySQL/MariaDB als Datenbank für die DNS-Einträge
  • DNS-Dist als Loadbalancer für DNS-Queries
  • PiHole als Resolver mit Blacklist
  • Docker als Virtualisierung für alle Services
  • IPv6 als primäres Netzwerkprotokoll, IPv4 nur als Fallback

Continue reading

MySQL >= 8.x oder MariaDB – RegularExpression Word-Bounderies – Workaround

Ich hatte gerade ein echtes Aha-Erlebnis in Sachen Regular-Expressions. In denen bin ich sonst eigentlich recht fit, aber man lernt ja bekanntlich nie aus.

Folgende Konstrukte sind in einem SQL-Statement fehlgeschlagen, nachdem ich eine aktuelle MariaDB bzw. eine MySQL 8 Datenbank im Einsatz hatte.


[[:<:]]4711[[:>:]]

Selbst mir war diese Syntax in der Form nicht bekannt. Die beiden Pattern beziehen sich auf Word-Bounderies. Mit anderen Worten wir suchen ob in einem String die Folge 4711 enthalten ist, aber nur exakt diese, Folgen wie 47112 sollen nicht gefunden werden. Im konkreten Beispiel ging es um eine kommagetrennte Liste von Zahlen die zu durchsuchen ist. Dabei kann die 4711 aber auch am Anfang oder am Ende stehen. In MySQL 8 und höher ist der Unterstützung für diese Syntax weggefallen, aus welchem Grunde auch immer. Aber es gibt Ersatz:


[^[:word:]]4711[^[:word:]]

Auch hier suchen wir die Ziffernfolge umrandet von etwas was kein Wort ist – das kann ein Zeilenende, Zeilenanfang, oder etwas anderes als alphanumerisch + „_“ sein [:word:] == [:alphanum:_].