DNS mit Docker Teil III – dnsdist als Router / Loadbalancer

Wer meine bisherigen Posts zu Docker und DNS verfolgt hat, weiß: Da steht noch was aus (ich komme nur momentan nicht immer ganz zeitnah dazu meine Erfahrungen zusammen zu schreiben.

Was bisher geschah:

Was jetzt noch aussteht ist eine Sache die mit der Microservice-Architektur von PowerDNS im Vergleich zu „klassischen“ Nameservern wie BIND zusammen hängt: BIND ist monolitisch und kümmert sich um jegliche Anfrage die gestellt wird. In PowerDNS hat man diese Dinge wie oben bereits angedeutet aufgetrennt: Einen Spezialisten zum Auflösen von externen Einträgen (Recursor) und einen weiteren Prozess der sich um die Sachen kümmert für die man selbst verantwortlich ist (authorative). Continue reading

Anwendungsfall für MSSQL in Docker unter Linux

Wie in einem meiner letzten Beiträge beschrieben, kann man mittlerweile einen MSSQL-Server auch unter Linux in Docker laufen lassen. Nun gilt es noch die berechtigte Frage zu klären: Weshalb sollte man sowas tun? Gibt es für dieses Konstrukt überhaupt sinnvolle Anwendungsfälle? Für alle die es eilig haben: Ja die gibt es. Wer es im Detail wissen will sollte weiter lesen.

Der Anwendungsfall für mich hängt indirekt auch mit der Jahreszeit zusammen, wie in jedem Jahr fällt mir als Schriftführer unseres Sportvereins die Aufgabe zu, mich um den Versand der Jahreszeitschrift zu kümmern. Man könnte es auch eine Alternative zu Weihnachtskarten nennen. Für die Verwaltung des Vereins haben wir eine fertige Software die leider nicht open source ist, geschweige denn dass sie nativ unter Linux laufen würde. Aus Sicht eines Anwendungsentwicklers ist die Software nicht gerade optimal, aber sie ist nunmal da und die anderen Mitglieder des Vorstands sind damit vertraut. Mal eben etwas zu ändern ist an dieser Stelle nicht drin.

Continue reading

MSSQL-Server mit Docker unter Linux

Der Titel hört sich im ersten Moment etwas schräg an – insbesondere wenn man zu den etwas älteren Semestern gehört, die noch die Anfeindungen Microsofts in Richtung Linux kennen gelernt haben. Unter anderem mit Werbesprüchen wie „ein freies Betriebssystem hat nicht nur Vorteile“ – verbunden mit einem Bild welches Piguine als Repräsentanten von Linux zeigte mit nicht ganz passenden Köpfen. Das war 2001 und geworben wurde für Windows 2000. Die Zeiten haben sich geändert und mittlerweile gibt es sogar offizieller Weise ein „Windows Subsystem for Linux“ (WSL) und auch erfreuliche Entwicklungen hin zu einer deutlich brauchbareren (Power-)Shell als es die altgediente command.com bzw. cmd.exe je waren. Das Ganze kommt nicht ganz von ungefähr – mit der Microsoft Azure Cloud mussten Werkzeuge her mit denen man Systeme vernünftig remote administrieren kann – da ist es durchaus legitim einmal zu schauen was bei anderen Betriebssystemen für den Erfolg mit verantwortlich ist.

Continue reading

DNS mit Docker Teil II – Recusor

Im letzten Post hatte ich den Anfang des Setups eines vollständigen DNS-Servers mit Docker und PowerDNS beschrieben. Nun folgen die nächsten Schritte. Eigentlich wollte ich diesen Post schon geraume Zeit fertig machen aber besser spät als nie.

PowerDNS-Recursor

Wie beschrieben teilt sich PowerDNS in drei Teile auf, im klassischen BIND-Server ist es ein monolitscher Block (bei dem man per Konfiguration ggf. einzelne Teile stillegen kann).
Der Recursor von PowerDNS übernimmt die Aufgabe der Namensauflösung für Anfragen die der Server nicht selbst auflösen kann. Diese Funktion braucht man im ersten Augenblick ür einen reinenNameserver nicht, aber in der Regel laufen auf dem Server ja auch noch andere Prozesse oder der DNS-Server dient für Clients im Netzwerk als Schnittstelle zum Netz. Dabei legt er praktischer Weise auch noch einen Cache an. Etwas ganz ähnliches macht ganz häufig Router für einen mit, wobei dieser die Anfragen initial dann auch nur an den nächst größeren Nameserver (z.B. beim Provider) abfragt. Ein solcher Cache ist auch für andere Serverprozesse sinnvoll, die viele DNS-Abfragen durchführen. Ein klassicher Fall hierfür ist der Mailserver, wenn er Echtzteit-Blacklists verwendet – diese teilen ihre Einschätzung anhand bestimmter DNS-Antworten mit (das ist schneller und effizienter als http(s), da tcp sondern nur eine upd-Verbindung aufgebaut wird.

Der Recursor ist auch recht schnell eingerichtet, das Dockerfile enthält auch hier keine großen Überraschungen bereit


FROM pschiffe/pdns-recursor:alpine
COPY recursor.conf /etc/pdns/recursor.conf
ENTRYPOINT [ "/usr/sbin/pdns_recursor" ]

Wobei das Config-File wie folgt aussieht:


allow-from=127.0.0.0/8,::1/128,2001:db8:ffff:ffff::/64,192.168.1.0/16
any-to-tcp=yes
#api-key=xxxx
#api-readonly=yes
daemon=no
local-address=::,0.0.0.0
local-port=53
lowercase-outgoing=yes
setgid=recursor
setuid=recursor

das einzig spannende an dieser Stelle ist die oberste Zeile „allow-from“ – sie legt fest von welchen Adressen aus überhaupt auf den Server zugegriffen werden kann. Hier führt man natürlich die Localhost-Adressen an, genauso wie die eigene IPv6-Range (ich erlaube es dem gesamten Bereich der mir zugewiesen ist, damit auch andere auf dem Server laufende Prozesse den DNS-Service nutzen können). Zudem erlaube ich dem eigenen Docker-Netzwerk auf IPv4-Basis den Zugriff, das ist aber eher eine Fallback-Möglichkeit. Man sollte sich überlegen einen Recursor generell für jedermann zu öffnen. Der Recursor kann das durchaus ab, aber es besteht leider die Gefahr, dass er missbraucht wird und dann andere Systeme per Denial-of-Service angreift. Hier kann man ggf. mit dem Load-Balancer vornedran die Menge der Requests von extern limitieren, aber selbst dann bekommt man recht bald wahrscheinlich eine Mail vom BSI die auf die Problematik hinweist – ich hatte es beim Aufbauen mit einem Load-Limit auf 10 externe Anfragen pro Minute versucht, aber der Bot der das automatisiert prüft ist etwas stumpfsinnig und prüft nur ob man generell Abfragen für externe Domains an den Port 53 schicken darf.  Wie sinnvoll derartige Prüfungen sind, darf jeder für sich selbst entscheiden.
Auch diese Definition baut man zu einem Image:


docker build -t powerdns-recursor .

Danach startet man den Server ebenfalls im eingerichteten Docker-Netzwerk für die DNS-Services, natürlich auch hier wieder mit einer festen IPv6-Adresse da man auch hier sonst recht schnell ein Henne-Ei-Problem bekommt was die Namensauflösung betrifft.


docker run --ip6 2001:db8:ffff:ffff:ffff:ffff:0053:4 --network dns --name power_dns_recursor -d powerdns-recursor

Es kann natürlich auch als Dokumentation die vergebenen IP-Adressen mit Namen in der eingenen Datenbank in der eingenen DNS-Zone zu hinterlegen z.B. in einem eigenen DNS-Abschnitt wie dns.my.example.com mit sprechenden Namen: primary,secondary,recursor – denn so richtig einprägsam waren schon IPv4-Adressen nur bedingt und mit der zusätzlichen Länge wird das bei Ipv6 nicht besser.


INSERT INTO `records` VALUES (4, 1, 'authorative.my.example.com', 'AAAA', '2001:db8:ffff:ffff:ffff:ffff:0053:3', 3600, 0, NULL, 0, NULL, 1);

INSERT INTO `records` VALUES (4, 1, 'recursor.my.example.com', 'AAAA', '2001:db8:ffff:ffff:ffff:ffff:0053:4', 3600, 0, NULL, 0, NULL, 1);

Den Recursor kann man dann natürlich auch testen und nach beliebigen nicht eigenen Adressen wie www.google.com, www.amazon.de, www.meine-website.org
{{Beispiel mit dig}}


			

Boot-Trick für Linux-Systeme wenn USB per BIOS nicht geht

Da wollte ich nur einen etwas älteren Laptop wieder soweit flott bekommen. Also die eigenen Daten sichern und eine Neuinstallation erzwingen. Leichter gesagt als getan. Backup dank ein wenig Ordnung im System und der Tatsache, dass es ein Linux-System ist war recht flott erledigt. Einfach die betreffenden Home-Verzeichnisse auf ein Backup-Medium (Netzwerk, externe Platte oder Stick) packen und schon ist man so gut wie fertig. Die Einstellungen des Systems waren mir in dem Fall nicht weiter wichtig – die waren ohnehin etwas „verbastelt“, da kam die Neuinstallation ja gerade recht.

Kniffelig wurde es dann aber diesmal beim Neuinstallieren des Betriebssystems: Von wegen einfach USB-Stick einstöpseln – Reboot und gut – leider nicht! Denn das alte Gerät verweigert sich jeglichem Boot-Versucht von einem USB-Stick und auch die SD-Card findet das System nicht beachtenswert wenn es ums Booten geht.

Nächster Versuch: Klassisch eine Boot-CD brennen – scheitert leider daran, dass die meisten Images mittlerweile größer als eine CD mit ihren 700MB sind. Dabei wollte ich schon aus gutem Grund ein ressourcenschonendes Lubuntu installieren (war auch vorher bereits drauf). Älter CD-Images waren auch nicht so ohne weiteres aufzutreiben. DVDs kann das alte optische Laufwerk nach einigen Versuchen nicht lesen (es steht leider auch nichts auf der Laufwerksklappe). Falls jetzt jemand fragt was man mit derart alten Systemen noch anfangen kann: Sie sind als Notbehelf in der ein oder anderen Situation doch ganz nützlich – vor allem wenn die Gefahr besteht, dass man das Gerät im Zweifel nicht wieder sieht oder es irreparabel beschädigt wird (das man auf derartigen Systemen auch keine privaten Daten lagert sollte jedem klar sein).

Jetzt war ich schon fast davor einen PXE-Server zu installieren und dann das System hoffentlich per Netzwerkboot auf die Spur zu bekommen, aber das ist ja doch etwas Umstand. Daher war das der absolut letzte Notnagel den ich gehen wollte. In der Zwischenzeit hatte ich auch irgendwo im Netz noch eine uralte Lubuntu-ISO-Datei gefunden (14.x – steinalt auf gut deutsch). Doch der Download zog sich etwas in die Länge. Mehr als genügend Zeit sich noch mit anderen Optionen zu beschäftigen.

Eigentlich ist die Lösung recht simpel: Was das BIOS nicht kann, kann das OS bzw. der Bootloader vielleicht dann doch. Da auf dem System ja bereits ein Linux samt Grub als Bootloader vorhanden war geht es dann wie folgt, nachdem man aus dem Bootmenü mit „c“ in den Consolen-Modus gewechselt ist.

ls
set root=(hd1)
chainloader +1
boot

Wobei ls einem die möglichen vorhandenen Partitionen listet und man dann bei set root=…. natürlich die passende Partition angeben muss – hier hilft im Zweifel ein wenig ausprobieren. Mehr als nicht booten oder das alte OS booten kann ja nicht schiefgehen. Danke an die hilfreichen Kommentare hier.

Von der Kunst der Vereinfachung

Abstrahieren und vereinfachen liegt in der Natur des Menschen. Wir alle haben es natürlich gerne wenn eine Aufgabe „leicht“ zu bewältigen ist oder ein Sachverhalt „einfach zu begreifen“ ist. Eine grundlegende Eigenschaft dabei ist es, dass wir Dinge „ausblenden“ die für die aktuelle Aufgabe nicht relevant sind oder deren genaue Zusammenhänge wir nicht bis ins Detail verstanden haben müssen um die Aufgabe zu lösen oder den Sachverhalt zu verstehen. Oftmals reicht es auch aus, die Hintergründe einmal umfassend bearbeitet zu haben und dann mit den gewonnenen Erkenntnissen und ggf. auch Erfahrungen weiter zu arbeiten. Jeder der ein Kraftfahrzeug fährt, hat sich (hoffentlich) einmal mit der dahinter stehenden Physik beschäftigt – doppelte Geschwindigkeit vervierfacht die Energie usw. Das alles setzt ein geübter Fahrer zusammen mit ggf. weiteren Erfahrungswerten ein um sein Fahrzeug im Verkehr sicher zu führen.

Wir Menschen sind auch Meister darin immer mehr dieser Denkarbeit zu automatisieren und uns somit das Leben noch leichter zu machen. Waren die ersten Computer noch groß und nur mit dem notwendigen Fachwissen zu bedienen, so benutzen wir heute fast schon wie selbstverständlich ein Smartphone dessen technische Komplexität um mehrere Größenordnungen über den ersten Großrechnern oder gar Heim-PCs liegt. Durch den Einsatz von Technik und entsprechenden Schnittstelle (der Fachmann spricht vom User-Interface) kann heute jeder mit minimalen Vorkenntnissen ein Smartphone zumindest grundlegend bedienen. Natürlich gibt es auch weiterhin die PowerUser bzw. Spezialisten die nochmals mehr aus dem Gerät „herausholen“ bzw. auch bei bestimmten Fehlerbildern Abhilfe schaffen können (oder zumindest einmal wissen wo man nachschlagen kann um ein Problem zu beheben). Continue reading

Domain Name Server mit PowerDNS – Schritt 1 – Konzept, Netzwerk und Authorative Server

Nachdem ich ja schon einiges in der letzten Zeit über DNS und Co geschrieben habe, geht es diesmal um eine konkrete Umsetzung. Lange Zeit habe ich schon einen eigenen DNS-Server betrieben, damals noch mit BIND. Mit den letzten Serverumzügen habe ich das dann der Einfachheit halber meinem Hosting-Anbieter überlassen (das richte ich ein, wenn der Rest läuft …). Wie das mit aufgeschobenen Aufgaben so ist, irgendwann wird der Status Quo zu einen „Dauerorium“ (die verstetigte Version eines Provisoriums).

Nun wollte ich es endlich angehen, und dabei auch einige zusätzliche Funktionen nachzurüsten. Unter anderem einen eigenen Ipv6 fähigen DynDNS-Service. Nach etwas Recherche stand ein grober Plan:

  • PowerDNS mit MySQL Backend
  • MySQL Server (läuft bereits, bekommt nur ein zusätzliches Schema)
  • Ein (Dyn)DNS-Frontend zur einfacheren Verwaltung und als HTTP(s) Schnittstelle zum Updaten
  • Microservice-Ansatz für die Einzelteile mit Docker als Paravirtualisierung
  • soweit möglich alles nativ in IPv6

Continue reading

Grundlagen zum Domain Name Service

Wie ich beim Schreiben meiner Artikel gemerkt habe, ist es sinnvoll gewisse Grundlagen einmal abzuspalten, um darauf verweisen zu können. Ich werde daher immer einmal wieder den ein oder anderen Grundlagen-Artikel hier zusammenschreiben, der im ersten Moment vielleicht etwas aus dem Zusammenhang gerissen scheint, aber ggf. wertvolle Informationen für alle Einsteiger enthält oder auch dem ein oder anderen Erfahrenen als Auffrischung dienen kann. Ich versuche das möglichst prägnant und wo immer möglich an Beispielen zu beschreiben.

In diesem Artikel geht es im um das Domain Name System – das Konstrukt welches zu Arbeit am Rechner etwas leichter macht, da sich das menschliche Gehirn in der Regel Namen besser merken kann als Zahlenfolgen.

Der langjährige Standard für DNS-Server im Unix und Linux-Umfeld ist der BIND-Daemon und so ziemlich jeder der sich schon einmal mit DNS-Namen hat etwas eingehender beschäftigen dürfen (oder müssen), der weiß, dass die Syntax der Config-Files nicht gerade in die Kategorie „leicht verdaulich“ fällt. Zudem war BIND immer mal wieder ein Sorgenkind wenn es um Sicherheitslücken ging. Sehr verständlich, dass sich viele Website-Betreiber da lieber auf einen Hoster verlassen der das schon für sie regeln wird. Für mich auch lange ein valider Weg, aber eben auch einer mit Einschränkungen.

Continue reading

Datenbankversionierung – Vor- und Nachteile bestimmter Praktiken

Gerade hatte ich mal wieder ein Schlüsselerlebnis in meiner Programmierung. In diesem Fall gab es ein Kollision mit YAML (YAML Ain’t Markup Language) – ich spreche explizit von Kollision, denn meine Erfahrung ist für den verwendeten Anwendungsfall einfach nur schlecht bzw. ich sehe leider aktuell einige Nachteile.

Datenbank-Schemata versionieren

Zur Versionierung von Datenbank-Änderungen bzw. um den Weg von einer „leeren“ Datenbank bis hin zum aktuellen Stand der Entwicklung zu beschreiben verwendet man in der Regel entsprechende Tools wie Liquibase oder Flyway. Das Prinzip ist im Prinzip immer das Gleiche – mit ein wenig „Rahmenwerk“ drum herum steuert man die Ausführung der Datenbank-Statements. Dabei kann man auf verschiedene Szenarien eingehen, einer der häufigst genannten ist, dass man ein Produkt mit verschiedenen Datenbank-Servern laufen lassen kann. Das ist beispielsweise wichtig wenn man Software an Firmen (seltener private Anwender) ausliefert, sich aber darauf einstellen muss, dass dort nicht unbedingt die aktuelle Version von MySQL läuft sondern eben im Zweifel auch ein PostgreSQL oder eine andere (kommerzielle) Datenbank wie Oracle. Continue reading

Container und IPv6 – Basics zum Verständnis / Netzwerkzuschnitt

In diesem Beitrag erläutere ich erst einmal die grundlegenden Probleme welche sich beim Einsatz von Container-Lösungen im Netzwerk ergeben und wie man sie sinnvoller Weise technisch lösen kann. Schlüssel hierfür ist die Verwendung von IPv6 anstelle von IPv4. In einem weiteren Artikel beschreibe ich dann die konkrete Umsetzung. Wer sich mit IPv6 und Containern bereits sicher fühlt kann diesen Artikel ggf. überspringen.

Container sind der aktuelle Stand der Technik was die Auslieferung und die Laufzeitumgebung für Serversoftware betrifft. Die Para-Virtualisierung löst einige Probleme die man typischer Weise hatte, unter anderem das Alles-oder-Nichts-Problem, wenn es darum geht Systemsoftware zu aktualisieren. Mit jedem größeren Versionssprung gibt es die Gefahr, dass bestimmte Teile des eigenen Codes nicht mehr laufen. Aktuell gibt es immer noch genügend Projekte und Software welche auf ältere (um nicht zu sagen teilweise uralte) Versionen von PHP angewiesen sind um zu funktionieren. Mit dem Versionssprung von 5.x nach 7.0 sind einige Altlasten und Funktionen über Bord geworfen worden, unter anderem auch der gesamte Stack für die MySQL-Anbindung, was einigen Anwendungen dann doch das Genick bricht. Häufig stand man nun vor dem Problem, für einen Teil des gehosteten Angebots die Version anheben zu wollen, aber die Altlasten müsste man dafür erst einmal auf Stand bringen. Das ist nicht immer ohne weiteres möglich. Mit Containern schafft man sich hier ggf. kleinere Services mit jeweils ihrer maßgeschneiderten Umgebung – inklusive abgeschottetem Datenbankserver, den sich nicht mehr alle Angebote teilen müssen (über die Vor- und Nachteile von Datenbanken in Containern kann man einen eigenen Artikel schreiben).

Continue reading