Posts mit dem Label Technik werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Technik werden angezeigt. Alle Posts anzeigen

Freitag, 13. Juli 2012

Sicheres Passwort Hashing

Nachdem in letzter Zeit immer und immer wieder Webseiten vor allem dadurch auffallen, dass sie Passwörter im Klartext speichern, hier zwei Funktionen aus der User-Klasse eines meiner letzten Projekte...

Übrigens: Wenn Ihr bei Klick auf 'Passwort vergessen' von einer Webseite das Passwort im Klartext per Email zugesendet bekommt, macht man dort genau das falsch. Schaut dann mal in deren AGB oder Datenschutzbestimmung, ob sie dort behaupten die Passwörter zu hashen. Oft sind die nur Copy&Paste. Und bittet sie das Verfahren umzustellen. Oder schreibt Heise.

Der Code

Für die meisten Probleme gibt es Standards, so auch für das Passwort-Hashing. Es gibt also keinen Grund sich selbst mit Funktionen wie (der nicht mehr zu benutzenden) md5() und String-Operationen seine eigene crypt-Funktion zu schreiben.

Hier nun also eine Lösung mit php, weil die grade hier rumlag.

    /* Code Licence: Public Domain
     *
     * $this->pwhash wird in der DB gesichert bzw. daraus gelesen.
     * die Konfiguration in $_CONFIG sieht z.B. so aus:
     *
     * // Hier ist ein zufälliger Wert pro Webseite einzutragen:
     * $_CONFIG["pw_sitekey"]="897a-d21lk.a8q";
     * // Und hier der Hash-Also. sha1, sha512, NICHT md5!
     * $_CONFIG["pw_hashalgo"]="sha512";
     *
     */

    public function setPassword($password){
        global $_CONFIG;
        $site_key=$_CONFIG["pw_sitekey"];
        $algo=$_CONFIG["pw_hashalgo"];
        $nonce=uniqid();
        $hash = hash_hmac($algo, $password . $nonce, $site_key);
        $this->pwhash = $nonce.':'.$hash;
    }

    public function verifyPassword($password){
        global $_CONFIG;
        $site_key=$_CONFIG["pw_sitekey"];
        $algo=$_CONFIG["pw_hashalgo"];
        $nonce= strstr($this->pwhash, ':',TRUE);
        $hash = strstr($this->pwhash, ':',FALSE);
        $chash= ":".hash_hmac($algo, $password . $nonce, $site_key);
        return ($hash == $chash);
    }

Demo

Was kommt da nun also heraus? Dazu eine kleine Demo
        //Passwort
        $password="very secret";

        //Konfiguration:
        $site_key="12345";
        $algo="sha512";

        $nonce=uniqid();
        $hash = hash_hmac($algo, $password . $nonce, $site_key);
        $pwhash = $nonce.':'.$hash;

        //ausgabe zur Kontrolle
        echo "pwhash= $pwhash\n";

        //zu pruefendes Passwort:
        $check_password="very secret";

        $vnonce= strstr($pwhash, ':',TRUE);
        $vhash = strstr($pwhash, ':',FALSE);
        $chash= ":".hash_hmac($algo, $check_password . $vnonce, $site_key);

        if ($vhash == $chash){
            echo "passwords match!\n";
        }

Die Ausgabe bei übereinstimmenden Passwörtern:
pwhash= 50000b502b234:b038dfb61ba609604e7be78f3aa2cd84fb03970031f5e8d6f2eacc10542741dda5b7f41a716f3f78c305f6898d9b82838ce6b9df15dc94d00c37af393cc51de1
passwords match!

Passwort vergessen!

Wie setzt man das nun organisatorisch mit dem 'Passwort vergessen' Link zusamen? Ganz einfach. Wenn die Nutzer ihr Passwort vergessen können sie sich an ihre Emailadresse einen Link zusenden, mit dessen Hilfe sie auf der Webseite ihr Passwort selbst zurücksetzen können. Der Link enthält dabei ein zufällig erzeugtes Token und verliert nach Benutzung (erfolgreiches Ändern des Passworts) seine Gültigkeit.

Nachtrag: Und natürlich sollte der Link wenn er nicht benutzt wurde nach X Tagen ebenfalls invalidiert werden.

Sonntag, 30. Oktober 2011

U-Pad: Mikrofoneingan als Line-In

Wer kennt das nicht, da hat man eine USB-Soundkarte gekauft, weil der Eingang des Notebooks zu nah an der Festplatte vorbei geführt wird (sic!) und dann kann man an der Soundkarte kein Linepegen anlegen.

Nun, für diesen Fall möchte man ein Dämpfungsglied bauen. Ohne zu sehr auf die Details einzugehen, was die Anpassung angeht, hier ein einfacher Schaltplan um ein Mikrofoneingang zu einem Line-In zu machen.

Obacht: Dies ist für XLR, also symmetrische Signale, gedacht.

       ___ 7500
 o)---|___|-----o--------(o 
       R1       |                mit 2x7.5 und 1x150
LINE           | | 150     MIC   ergibt sich ein Teiler
 IN            |_| R3      OUT   verhältnis von 
       ___      |                15000:150 = 100:1 = -40dB
 o)---|___|-----o--------(o      Bitte 
       R2  7500                  Metallschichtwiderstände
                                 verwenden, die Rauschen nicht.

Für asymmetrische Signale sollte ein normaler Spannungsteiler funktionieren:

         ___15000
 o)-----|___|----o-----(o
                 |
                | | 150
IN              |_|          OUT
                 |
 o)--------------o-----(o

Sonntag, 31. Juli 2011

postfix: IP-Adresse des Absenders verbergen

Nach langer Zeit gibt es heute mal wieder einen kleinen Post aus der Sysadmin-Ecke.

Die Ausgangslage

Ein Benutzer liefert seine Emails mit Authentifizierung bei einem durch mich betriebenen Mailserver ein, der für die entsprechende Domain zuständig ist.

In den Headern dieser Mail wird nun die IP-Adresse auftauchen, von der aus die Email eingeliefert wurde. Dies kann die IP zu Hause sein, die von einem Bekannten oder die von einer Institution. Postet derjenige häufiger auf Mailinglisten kann man so schon ein Profil erstellen und bekommt auf jeden Fall heraus, dass er z.B. Emails von der Uni aus sendet, etc.

Dies möchte man nun verhindern - und das funktioniert mit postfix Bordmitteln sogar relativ einfach.

Mehr Information ist am Ende doch weniger

Zunächt müssen wir die entsprechenden Header erkennen können. Da bei allen nicht-authentifizierten Emails die IP-Adresse des einliefernden MTA im Header unverändert erhalten bleiben soll, schon um Spammer identifizieren zu können ohne extra in die Logs schauen zu müssen, brauchen wir einen Weg, die passenden Received:-Header zu erkennen. Dies erreichen wir, indem wir dem postfix sagen, dass er den Benutzernamen des Absenders auf dem Mailserver in den Header einfügen soll. Dies geschieht über die Anweisung smtpd_sasl_authenticated_header = yes in der Datei main.cf des postfix.

Unser header sieht nun ungefähr so aus:

Received: from [192.168.101.150] (guest123.guest.example.org [192.0.43.10])
  (using TLSv1 with cipher DHE-RSA-CAMELLIA256-SHA (256/256 bits))
 (No client certificate requested)
 (Authenticated sender: username)
 by mail.somedomain.tld (Postfix) with ESMTPSA id 32A59B1C032
 for ; Thu, 30 Jun 2011 12:36:07 +0200 (CEST)

Die hervorgehobene Zeile ist neu hinzugekommen und ermöglicht es uns im zweiten Schritt nach genau diesen Headern zu suchen.

pcre ftw!

postfix bietet dafür die Möglichkeit der header_checks. Damit kann man mittels (perl) regular expressions auf den Headern der Email arbeiten und Zeilen einfügen, Zeilen ändern und eigentlich vor allem Aktionen auslösen wie das Aufhalten einer Email, Abweisen, Weiterleiten, etc.

Wir benutzen diese Möglichkeiten, um auf der oben gezeigten Received:-Zeile ein paar Ersetzungen vorzunehmen.

Dazu stellen wir zunächst sicher, dass die main.cf des Postfix auch header checks aktiviert hat:

 smtpd_sasl_authenticated_header = yes
 ...
 header_checks      =  pcre:/etc/postfix/header_checks
 mime_header_checks =  pcre:/etc/postfix/header_checks

Nun koennen wir in der angegebenen Datei header_checks mit folgender Zeile das Umschreiben aktivieren:

/^Received:\ from (.*)\(.*\)(.*)\(Authenticated\ sender:\ .*\)(.*by mail\.somedomain\.tld.*)$/U  REPLACE Received: from $1 (Remote IP hidden) $2(Sender was authenticated on somedomain.tld) $3

Hinweis: Die Zeile ist relativ lang, beim Kopieren aufpassen sie komplett zu erwischen. Wichtig ist die Option U an der Regex, diese schaltet sie auf ungreedy. Siehe man pcre_table.

Der Name des Mailservers taucht hier nochmal auf, damit ich die Original-IP bei extern eingelieferten Emails nicht verwerfe - das kann zum Identifizieren von Spammern helfen, auch wenn die Header oft gefälscht sind.

Im Ergebnis sieht der Header der Email nun aus wie folgt:

Received: from [192.168.101.150]  (Remote IP hidden) 
 (using TLSv1 with cipher DHE-RSA-CAMELLIA256-SHA (256/256 bits))
 (No client certificate requested)
 (Sender was authenticated at somedomain.tld) 
 by mail.somedomain.tld (Postfix) with ESMTPSA id A36241184685
 for ; Fri, 29 Jul 2011 20:23:31 +0200 (CEST)

Wenn man die private IP auch noch entfernen möchte, kann man sich jetzt natürlich einen weiteren Header-check überlegen, der auf '\[.*\].*Remote IP hidden' triggert und diese ersetzt. Das kann im Einzelfall notwendig werden, wenn kaputte Antispam-Maßnahmen anderer Empfänger solche Emails ablehnen.

Wenn man misstrauisch ist fügt man ausserdem noch eine Zeile hinzu, die jedes Vorkommen von '(Authenticated sender: ...)' mit etwas belanglosem ersetzt, falls man unter allen Umständen die internen Nutzernamen geheim halten will.

Sonntag, 28. November 2010

Server mit Migrationshintergrund

Dieser Post soll allen als Warnung dienen, die einen Rootserver gemietet haben. Es kann einem passieren, dass der Provider beschließt, daß die alte Hardware zuviel Strom frisst, und er die Server der Kunden virtualisieren möchte.

Zustimmung des Kunden

Ein normaler Provider würde dann einen Brief schreiben. Oder vielleicht auch eine Email. Dann auf Antwort warten, und wenn der Kunde sein OK gibt und vielleicht noch einen Terminwunsch äussern darf (nicht während der Produktpräsentation z.B.) wird die Migration durchgeführt oder auch nicht.

Alles andere ist eine einseitige Vertragsänderung die unmittelbar Sonderkündigungsrecht des Kunden zur Folge hat.

Handeln ohne Zustimmung?

Bei einem meiner Provider war das leider nicht so. Ich erhielt eine Email, in der man die neue Virtualisierungslösung anpries und dass man wegen Erneuerung von Hardware meinen Server gerne migrieren würde. Das ist für mich Konjunktiv.

Das Problem war nur, dass ich diese Email eine Woche lang nicht zur Kenntnis genommen habe, weil Thunderbird der Meinung war, sie nicht anzeigen zu müssen. Alles halb so schlimm, könnte man meinen, die Nachricht war ja im Konjunktiv, und kein vernünftiger Provider würde einen Kundenserver nehmen, runterfahren, die Festplatte ausbauen, die Daten kopieren, auf ein Storage mit den Daten aller anderen Kunden legen...

Nun, genau das hat dieser Provider aber getan. Er hat nicht auf eine Antwort gewartet und einfach mal so die Festplatte ausgebaut und in einer Stunde Downtime die Daten kopiert.

Gemerkt habe ich es, weil Nagios gemeckert hat, dass der Server down ist.

Als ich nach etwas Suchen dann feststellte, dass mir Thunderbird Mails unterschlägt, fand ich nach einem Index-Rebuild auch die Email, die auf diese Migration "hinwies", bzw. mich eigentlich darauf hinwies, dass man das gerne tun würde, dieses Migrieren

Was ist 'Ausspähen von Daten'?

Auf meine Email hin, dass ich hier einen Fall von "Ausspähen von Daten" sehe und nicht damit einverstanden bin, dass man einfach meine Daten kopiert, erhielt ich dann gegen 16:09 eine Email, in der man mich fragt, ob ich mit einer Rückmigration auf die alte Hardware einverstanden sei. Diesmal war das sogar als Frage formuliert!

Lernresistent? Könnte man meinen.

Ja, nur leider sehe ich im Syslog, dass der Server um 17:05 und 17:10 rebootet. Es wurde wieder keine Antwort abgewartet - diesmal nicht mal eine Stunde lang - und es wurde erneut ohne Absprache mit den Daten hantiert. Die gehosteten Webseiten waren damit mal wieder nicht erreichbar. Und der Nameserver und Mailserver auf der Kiste auch nicht.

Dieser Zustand wurde leider auch 3 Stunden lang nicht besser. Obwohl ssh irgendwann wieder ging. Des Rätsels Lösung: Sie haben beim Rückmigrieren das Routing verbockt. Nach einer Email an die Notfall-Hotline war das aber dann wenigstens in Rekordzeit behoben - unter 10 Minuten.

got root?

Ich habe nach diesem Vorfall unmittelbar einen anderen Hoster gesucht.

Der neue Server war schließlich am Mittwoch einsatzbereit, im Verlauf des Tages habe ich dann einiges an Domains umziehen dürfen, darunter diverse CMS-Systeme, den Mailserver und den Nameserver für eine zweistellige Zahl an Domains und alle Nutzer und Kunden über die neuen IPs bzw. Nameserver informieren müssen, damit sie ihre DNS-Zonen ggf. anpassen.

finally?

Zwischendurch habe ich dann noch Kontakt zu einem Anwalt aufgenommen, um mir die rechtliche Situation mal ein bisschen genauer darlegen zu lassen.

Nun, die Kündigung beim Provider folgt zum 01.12.2010 - der alte Server ist nun endgültig platt. Genullt. Ob der Provider noch eine Kopie der Daten irgenwo im Backup hat - wer weiss....

Montag, 18. Oktober 2010

Mein Dockstar lebt wieder...

So. Es ist wieder einmal passiert. Ich habe mir Hardware zum Spielen gekauft.

Diesmal: Ein FreeAgent DockStar Network Adapter von Seagate.

Das Schätzchen hat 128MB Ram und 256MB Flash on Board, eine nette ARM CPU, Gigabit-Netzwerk und 4 USB-Ports. Details finden sich zu Hauf im Netz.

Was mich besonders interessiert hat, war die in der CPU vorhandene Crypto-Unit, die sha1, md5 und aes in Hardware berechnen kann.

Linuxkernel

Leider ist es mit der Unterstützung dieser Einheit im offiziellen Kernel noch nicht so wahnsinnig weit - bisher wird das ganze nur rudimentär angesprochen (z.B. kein DMA), so dass es nicht wirklich Spaß macht, das ganze zu nutzen. (1-2MB/s Gewinn)

Etwas mehr verspricht hier ein Kernel des Herstellers - und voilá, GPL-sei-dank gibt es da auch was passendes. Oder naja, etwas das man für passend halten kann.

Vorweg: Ja, ich habe den Kernel letztlich übersetzt bekommen, man darf nur nicht so wahnsinnig sein, und an der config großartig Dinge ändern wollen - weil dann knallt es. Und zwar richtig mit Compiler-Fehlern und Syntax-Errors in den Kernelquellen.

Letztlich habe ich jedenfalls 15MB/sec von einer verschlüsselten USB-Platte lesen können statt 6-7 ohne Hardwareunterstützung.

Details zum Kernel folgen, sobald ich einen stabilen build habe und das dokumentieren kann. Ausserdem will ich die LEDs aus dem Kernel heraus ansprechen können, die GPIO-Konfiguration habe ich im Prinzip bereits.

uBoot - der Bootloader

Damit ich dieses System bequemer booten kann, wollte ich dann einen neuen uBoot bauen.

Die Cross-compiler-chain war ja schon von kernel vorhanden - sollte also alles kein Problem sein. Dachte ich.

Die Konfiguration des DockStar unterscheidet sich leider etwas von der des Sheeva-Plugs. So ist nur die Hälfte des Rams vorhanden, ausserdem sind die beiden LEDs an andere GPIO-Pins angeschlossen.

Kaputtgeflasht

Was mir letztlich das Genick brach war aber ein dummer Fehler: Ich habe das uBoot-Binary direkt in den Flash des DockStar gebrannt - statt des kwb-Images, das die Hardwarekonfiguration enthält.

Letztlich habe ich nun 4 verschiedene Jtag-Adapter hier gehabt, davon zwei selbstgebaute. Der letzte, ein wiggler, funktionierte schließlich - wenn auch nur mit 50kHz statt 500. (Kabellänge)

Folgende Fallen begeneten mir dabei:

  • 74HC244 falschrum im Sockel. Gute Heizwirkung, der Chip hats überlebt, mein Zeigefinger auch...
  • Kabel zu lang und zu wenig abgeschirmt
  • Ein funktionierender DockStar hat das JTAG deaktiviert und ist zum Testen ungeeignet!

Vor allem der letzte Punkt mit dem funktionierenden DockStar hat mich etliche Stunden gekostet. Aber wer rechnet schon damit -.-

Ausblick

Die folgenden Posts werden ausführlich das Wiederbeleben des DockStars, die korrekte Konfiguration des Bootloaders für diese Plattform und die Konfiguration des Kernels enthalten.

Der Bootloader kann hier jedenfalls schon die LED's ansprechen, dem Kernel werde ich das wohl auch noch beibringen. TODO's sind aber noch die Konfiguration des Speichers im uBoot.

Freitag, 28. Mai 2010

How to disable AAAA queries for IPv6 / configure your resolver

Today I stumbled upon a very nasty behaviour of glibc - again.

On a host which has no access to IPv6 at all and no module-support in the kernel, it seems the connect() call fails when there is a AAAA record in place for a remote server.

This means I cannot wget a webpage if an AAAA record exists for the page, etc.

You will find many solutions on how to 'disable IPv6' - but they all miss the resolver in glibc, the part that is behind the 'gethostbyname' call.

I like to disable AAAA DNS-queries for IPv6 completely - and the solution is easy:

#cat /etc/resolv.conf 
options no-inet6
nameserver ...
nameserver ...

Just documenting it here, because the manpage does not document the 'no'-Feature and searching for this on google was not helpful at all.

Freitag, 12. März 2010

Unter OpenWRT per DHCP den NTP announcen

Wer sich wundert, warum die Rechner zu Hause den NTP-Server des eigenen Routers einfach nicht benutzen wollen, sollte mal per tcpdump nachsehen, ob die DHCP-Option 42 auch gesendet wird... Wenn nicht muss man auf dem Router in der /etc/config/dhcp das Schlüsselwort dhcp_option benutzen:
config dhcp lan
        option interface        lan
        option start            100        
        option limit            150
        option leasetime        1h
        list dhcp_option '42,10.1.1.1'
Hier wird den Clients im LAN mitgeteilt, dass man 10.1.1.1 als NTP-Server nutzen will...

Donnerstag, 4. März 2010

TU-Berlin: Sicherheitswettbewerb der AG-Rechnersicherheit

Die AG-Rechnersicherheit hat parallel zu ihrer Präsenz auf der CeBit einen Wettbewerb gestartet, an dem nun jeder per Internet teilnehmen kann um sein Wissen im Bereich der IT-Security zu testen... Dabei gibt es neben einfachen Fragen auch einige praktische Knobeleien zu lösen. Wer mitmachem möchte, sollte natürlich die Spielregeln lesen und das Anmeldeformular ausfüllen. Ansonsten sei jedem ein Besuch auf der CeBit am Stand B39 in Halle 9 ans Herz gelegt.

Montag, 9. November 2009

Things you don't want to see when creating a filesystem...

Wo wir schon beim Thema sind. Habe eben ein altes kernel-log auf meinem nas gefunden:
BUG: unable to handle kernel NULL pointer dereference at 00000004
IP: [] mempool_free+0xe/0x97
*pde = 00000000 
Oops: 0000 [#1] PREEMPT 
Modules linked in: xfs raid456 async_xor async_memcpy async_tx xor md_mod dock container video output wmi ohci_hcd nfsd auth_rpcgss exportfs ac battery ipv6 nfs lockd nfs_acl sunrpc loop parport_pc parport floppy pcspkr rtc i2c_i801 i2c_core rng_core button intel_agp agpgart evdev ext3 jbd mbcache cbc dm_crypt crypto_blkcipher dm_mirror dm_snapshot dm_mod ide_generic ide_cd_mod cdrom ide_disk sd_mod usb_storage dc395x 3c59x mii scsi_mod piix ide_core ehci_hcd uhci_hcd usbcore thermal processor fan

Pid: 27646, comm: md0_raid5 Not tainted (2.6.25.1 #3)
EIP: 0060:[] EFLAGS: 00010286 CPU: 0
EIP is at mempool_free+0xe/0x97
EAX: cf5f15a0 EBX: 00000000 ECX: c15f7990 EDX: 00000000
ESI: 00000000 EDI: cf5f15a0 EBP: 00000000 ESP: cf77be20
 DS: 007b ES: 007b FS: 0000 GS: 0000 SS: 0068
Process md0_raid5 (pid: 27646, ti=cf77a000 task=cf484b00 task.ti=cf77a000)
Stack: ...
Call Trace:
 [] return_io+0x2b/0x33 [raid456]
 [] handle_stripe5+0x488/0xdf9 [raid456]
[...]

Der Bug war übrigens reproduzierbar, wenn man versuchte auf einem gerade im Aufbau befindlichen Raid5 einen LUKS-Container anzulegen und darin dann das Filesystem zu erzeugen.

Things you don't want to see when checking a filesystem...

Out of memory: kill process 3641 (xfs_check) score 20034 or a child
Killed process 3642 (xfs_db)
# xfs_check /dev/sda1
Segmentation fault.
*aargh* 1 GB RAM (davon >700MB frei) sollten meiner Meinung nach für ein fsck auf xfs reichen. Und egal wie kaputt das Dateisystem ist, von einem Superblock mit invaliden Daten sollte es keinen Segfault geben.

Sonntag, 30. August 2009

Webseiten automatisch vor Überlast schützen am Beispiel einer MediaWiki-Seite

Das Szenario: Man ist stolzer Betreiber eines eigenen Servers auf dem ein Wiki läuft. Plötzlich berichtet Heise über das eigene Projekt oder man wird von einer anderen der großen Nachrichten-Portale verlinkt und plötzlich geht auf dem Server gar nichts mehr. Selbst der Zugriff per SSH um zu schauen was los ist funktioniert nicht mehr richtig und alle Nagios-Instanzen schlagen Alarm.

Damit es zu diesem Szenario nicht kommt, gibt es natürlich verschiedene Ansätze. Von redundant vorgehaltenen Servern, die per DNS Round-Robin angesprochen werden, über Loadbalancer auf Routingbasis, etc.

Viele dieser Maßnahmen sind aber entweder recht kostspielig oder haben den Nachteil nicht so gut mit soetwas wie einem Wiki zusammenzuarbeiten.

Es gibt aber eine weitere Möglichkeit, die den Dienst http://coralcdn.org benutzt.

Coral Content Distribution Network

Das Coral Content Distribution Network funktioniert transparent durch das Anhängen einer Domain des Dienstes an eine beliebige Webadresse. So wird aus www.google.de ganz schnell die gecachte Version, wenn man statt dessen www.google.de.nyud.net aufruft.

An dieser Stelle vielen Dank an rbu für den Hinweis auf Coral!

Doch wie kann man diesen Dienst benutzen, um ein Wiki bei Überlast des Servers noch einigermassen erreichbar zu halten?

Ein eigener Host für Coral

Zunächst habe ich zum Testen einen weiteren Virtual Host für das Wiki aufgesetzt, so dass ich dort Einstellungen machen kann, ohne das Wiki unbrauchbar zu machen.

Ausserdem hat das den Vorteil, dass ich https-Zugriffe verhindern bzw. umlenken kann, die über Coral natürlich nicht richtig funktionieren.

Und, noch etwas, dieser Virtual Host soll später vielleicht mal auf einen weiteren Rechner umziehen und kann so noch mehr Last abfedern, indem er statische Dateien wie Bilder direkt aus seinem Cache ausliefert.

Dieser VHost hört auf den originellen Namen cache.meinedomain.tld.

Folgende Parameter wurden (zusätzlich) gesetzt:


      #Dies soll ein Proxy werden, also Zugriff auf
      #folgende Seiten per proxy erlauben:

      <Proxy proxy:http://wiki.meinedomain.tld/ >
            Order deny,allow
            Allow from all
      </Proxy>

      ProxyVia On
      ProxyRequests Off

      #Diese Seite liefern wir auf / aus:
      ProxyPass / http://wiki.meinedomain.tld/
      ProxyPassReverse / http://wiki.meinedomain.tld/

      #Ausserdem Cachen wir auf der Festplatte
      CacheRoot /var/cache/apache2
      CacheDirLevels 2
      CacheDirLength 10
      CacheMinFileSize 10
      CacheMaxFileSize 2000000
      CacheEnable disk /
      CacheEnable disk http://wiki.meinedomain.tld/
      CacheEnable disk proxy:http://wiki.meinedomain.tld/

      #Die Cookies wollen wir nicht mit speichern...
      CacheDefaultExpire 3600
      CacheIgnoreHeaders Set-Cookie

      # Bis hier war das nur die (optionale) proxy-Konfiguration
      # kommen wir nun zum LoadBalancer

      RewriteEngine on
      RewriteCond %{HTTP_USER_AGENT} !^CoralWebPrx
      RewriteCond %{QUERY_STRING} !(^|&)coral-no-serve$
      RewriteMap    lb      prg:/var/www/loadbalance.sh
      RewriteCond   ${lb:%{REQUEST_URI}|NULL} !^NULL
      RewriteRule   ^(.*)$ ${lb:$1|%1}           [P,L]

Der zweite Block definiert ein shellscript als Entscheidungshilfe für das Ziel eines Redirects, wenn der Request nicht von dem coral-webproxy kam. Diese Ausnahme müssen wir konfigurieren, da wir sonst den Coral-Server auf sich selbst umlenken würden.

Und dieses Script ist auch schon das Geheimnis.

Das Redirect-Script

Das folgende Script wird vom apache sofort beim Start geforkt und erhält auf stdin fortan die angefragte URL und kann auf stdout dann ausgeben, wohin denn der Request umgelenkt werden soll.

Damit kann man nun nach eigenem Ermessen Paramter suchen, die für einen Redirect sorgen sollen.

Ich nehme hier das maximum von zweien der Load-Werte, so dass bei zuviel Ansturm die Besucher umgelenkt werden und mit Abflauen des Ansturms (die Besucher bleiben dann ja auf dem Proxy) auch wieder neue Besucherrequests angenommen werden.

Ein wenig zusammengehackt und sicherlich nicht die schnellste Implementierung, aber es erfüllt erstmal seinen Zweck, sollte aber durch ein C-Programm ersetzt werden, welches ein _wenig_ effizienter implementiert ist.

#!/bin/bash

loadbalancer="cache.meinedomain.tld.nyud.net";

while read LINE; do
 load="$(awk '{gsub("\\.",""); if ($1>$2){ print $1} else { print $2 }  }'< /proc/loadavg)"
 if [ "$load" -gt "$(cat /var/www/maxload.conf)" ]; then
   logger -t "loadbalance-cache" "redirecting due to load=$load. request: $LINE"
   printf "http://%s/%s\n" "${loadbalancer}" "${LINE}"
 else
   printf "NULL\n"
 fi
done

In der Datei /var/www/maxload.conf habe ich testweise einfach die Zahl 550 eingetragen, so dass ab einer Load größer 5.5 ein Redirect erfolgt.

Konfiguration des Wikis

Bei Zugriffen über den Proxy muss das Wiki read-only arbeiten. Dafür gibt es mehrere Gründe:

Zum Einen sollen nicht die privaten Previews eines Benutzers gecached werden, zum anderen redirecten wir ja wegen hoher Last - und ein Edit eines Artikels wird sicherlich nicht zum Senken der Last beitragen.

Dazu gibt es einen Codeblock in der LocalSettings.php des Wikis:

if ( preg_match( "/^CoralWebPrx/", $_SERVER['HTTP_USER_AGENT']) > 0
    || preg_match( "/coral-no-serve$/", $_SERVER['QUERY_STRING']) > 0) {

 $wgReadOnly="<span style=\"background-color:yellow;\">Das Wiki ist aus Lastgründen read-only. Du greifst daher gerade über ein Cache auf eine gespeicherte Version zu.</span>";
}

Dadurch verlieren wir zwar auch die PageHits-Zählung im Wiki, aber über einen Proxy werden diese ohnhin nicht mehr korrekt gezählt.

Konfiguration des Wiki-Hosts

Nachdem alles getestet ist und funktioniert, können wir bei Überlast alle Requests auf den Wikiserver direkt auf die cache-Variante von Coral lenken. Dies machen wir mit einigen Zeilen in der Definition des Virtual Hosts:

RewriteEngine on
RewriteMap    lbwiki      prg:/var/www/wiki.meinedomain.tld/loadbalance.sh
Folgende Regeln fügen wir nun an die .htaccess des Wikis an. Das muss geschehen, da wir dort noch andere Rewrite-Regeln definiert haben.
# Alle requests des coral-proxies auf den cache lenken,
# requests von unserem Cache nicht auf unser Cache umlenken.
RewriteCond %{REMOTE_ADDR} !^127.0.0.1$
RewriteCond %{REMOTE_ADDR} !^IP.DES.EIGENEN.PROXIES$
RewriteCond %{HTTP_USER_AGENT} ^CoralWebPrx
RewriteRule   ^(.*)$ http://cache.meinedomain.tld/$1           [R,L]

RewriteCond %{REMOTE_ADDR} !^127.0.0.1$
RewriteCond %{REMOTE_ADDR} !^IP_DES_CACHES$
RewriteCond %{QUERY_STRING} (^|&)coral-no-serve$
RewriteRule   ^(.*)$ http://cache.meinedomain.tld/$1           [R,L]


#Folgender Block prueft ob die load zu hoch ist und
#redirected dann auf den gecachten cache...
#RewriteMaps muessen global in der vhost konfig gemacht werden.
RewriteCond %{REMOTE_ADDR} !^127.0.0.1$
RewriteCond %{REMOTE_ADDR} !^IP_DES_CACHES$
RewriteCond %{HTTP_USER_AGENT} !^CoralWebPrx
RewriteCond %{QUERY_STRING} !(^|&)coral-no-serve$
RewriteCond   ${lbwiki:%{REQUEST_URI}|NULL} !^NULL
RewriteRule   ^(.*)$ ${lbwiki:$1|%1}           [R,L]


Wichtig ist hier, dem LoadBalancer einen anderen Namen zu geben.

Wir benutzen für diesen Artikel wieder dasselbe script, so dass direkt auf den Host cache.meinedomain.tld.nyud.net verwiesen wird.

Der erste Block ist eher 'Kosmetik' und verhindert, dass man auf wiki.meinedomain.tld über Coral zugreifen kann.

Samstag, 29. August 2009

easyjet: was kann man alles falsch machen?

Eine Bekannte schrieb mir, beim Buchen von Flügen per easyJet kämen Zertifikatsfehler. Was das denn zu bedeuten habe?

Das Zertifikat für https://www.easyjet.de ist nur für www.easyjet.com gültig. Nungut, kann passieren. Versuchen wir denen das mal zu sagen... Pustekuchen. Ein Kontaktformular haben die auf ihrer Seite gar nicht. Najaah, schauen wir mal im whois, da wird doch - nein, Fehlanzeige, keine Telefonnummern oder Emailadressen im whois. Nur eine Postadresse in London. Hach, raten wir ne mailadresse per telnet auf port 25:
$ dig mx easyjet.de +short
10 mxhost-2.vi.net.
5 mxhost-1.vi.net.
los gehts:
$ nc mxhost-1.vi.net  25
220 mxhost-1.vi.net ESMTP Postfix
HELO mail.xxxxxxxxxxx.net
250 mxhost-1.vi.net
MAIL FROM: <postmaster@xxxxxxxxxxx.net>
250 2.1.0 Ok
RCPT TO: <webmaster@easyjet.de>
554 5.7.1 <webmaster@easyjet.de>: Relay access denied
wat?! Der für die Domain zuständige MTA weigert sich dorthin zu relayen?

Dann kann und will ich ihnen auch nicht mehr helfen...

Die betreiben da unter easyjet.de Flugbuchungen, aber weder ihr SSL-Zertifikat funktioniert, noch ihr Mailsystem?! Super!

Aber das passt zu den Buchungsmails die sie verschicken. Multipart mit text und html-Teil. Aber: Der Text-Teil ist komplett leer, im html-Teil stehen dann die Buchungsdaten.

Mittwoch, 20. Mai 2009

Nur ein kleiner Umbau...

Warum muss Murphy eigentlich so grausam sein?

Ich habe ein externes AIT1 Laufwerk ausgegraben sowie ein AIT2-Laufwerk. Nun dachte ich mir, die Laufwerke sind ja beide gehäusetechnisch kompatibel, sogar die Dipswitches sind an derselben Stelle, also baue ich das AIT2-Laufwerk in das externe Gehäuse ein und hänge es an meinen Fileserver. Weil: Backup ist wichtig!¹

Nachdem der Umbau beendet war wollte ich die Frontblende des Gehäuses wieder einsetzen. Tja, passt nicht, denn bei dem AIT2 Laufwerk handelte es sich wohl um eines, dass in einer Lib zum Einsatz gekommen war, jedenfalls hatte es erstens keine Klappe vor dem Slot und war zweitens etwa 4 mm zu breit. Egal, zum Testen reichts erstmal - jedenfalls wenn man das richtige SCSI-Kabel findet...

Okay, nachdem das Kabel gefunden war (ein internes zwar und bestimmt zu lang, aber egal, denn zum Testen reichts erstmal...) konnte das Laufwerk in Betrieb genommen werden. Ergebnis: läuft

Nächster Schritt: Einbauen

Also heute frisch ans Werk, das Laufwerk gehört in den Server, dann ist es nicht mehr so laut, weil kein eigener Lüfter, und ausserdem ist dann weniger Geraffel und Kabelsalat im Schrank - und das Gehäuse konnte ich ja eh nicht zumachen.

Bei der Gelegenheit wollte ich auch mal schauen welcher RAM im Server verbaut ist - weil das ist definitiv zu wenig im Moment.

Also flux alle Kabel getrennt, Server aus dem Rack gezogen, *uffissderschwer*, aufgemacht, Ram ausgebaut, Riegel verglichen. Natürlich hat man keinen Kompatiblen Riegel hier und es steht auch nicht drauf was für welcher das ist, also nachher mal Google bemühen - Ramriegel neben das Notebook.

Kommen wir zum Laufwerk. Das Gehäuse wird flink zerlegt, Laufwerk raus und zum Server getragen. Nun, das Laufwerk hat zwar die Höhe eines 5 1/4 Laufwerkes, aber nicht die Breite. Gut, Einbauschienen hängen hier auch noch an einer alten SCSI Platte im Schrank, das passt schon - leider erst beim dritten Versuch.

So langsam werde ich leicht genervt, denn jetzt geht das Suchen nach SCSI Kabeln und Adaptern los - intern ist nur noch ein 50 pol. Flachbandstecker am SCSI Controller frei, das Laufwerk hätt aber gerne ein 68 pol. Anschluss. Nach einigem Suchen und dem Auffinden von 10 Stück IDE-Kabeln findet sich schliesslich alles ein.

Also Laufwerk ist eingebaut, Deckel drauf, Klappe zu - Klappe zu?! *arrgh*

Das Laufwerk ist 0,5 cm zu lang, bzw, schaut vorne aus dem Gehäuse raus.. *heul*

Egal zum testen.... also die linke Frontklappe abgebaut, Server ins Rack, und los.

Jetzt noch die Kabel anschliessen, vor allem die USB *AUTSCH*!

Meister, warum is da Saft drauf?

Hmm. Warum bekomme ich am USB-Kabel der externen Festplatte nen Stromschlag?

Mal verifizieren. *AUTSCH* - okay, da ist Strom drauf... Messgerät!

Oh, interessant: 219 Volt, 50 Herz. 20mA gegen Erde, keine Phasenverschiebung. Nur woher kommt das? Die USV ist aus, primär ist ein Schalter in der Steckdosenleiste, der ist aus, dahinter ein Verteiler, ebenfalls mit Schalter, dann die Festplatte. Alles aus. Eigentlich.

Kaltgerätekabel von der USV abgezogen: keine Spannung. Aha, daher weht der Wind?

Also mal das Voltmeter in richtung USV verschoben. An beiden äußeren Pins des Kaltgeräteausgangs liegen 219 Volt gegen Erde. Yay!

Ich hab also mal wieder den Jackpot geknackt: Der Schalter in der Steckdose schaltet also ganz offensichtlich nur einpolig ab - und natürlich, bei einer Chance von 50:50, schaltet der NICHT die Phase ab. Warum auch. Und dann sind da wohl noch irgendwelche Y-Kondensatoren in dem Schaltznetzteil der Festplatte, die sie, mangels Erde weil Eurostecker, wohl gegen die USB-Masse gesetzt haben. *seufz*

Gut, also Stecker um 90 Grad drehen und weitermachen, Zweipoliger Trenner kommt dann morgen.

Also Kabel ran und los.

pieeeeeep

Hmm. Warum piept der jetzt?

Moment, da war doch noch was - aaah, der RAM liegt noch auf dem Schreibtisch.

Ich brauch jetzt erstmal nen Kaffee!

Nach dem Kaffee werde ich wohl das Laufwerk wieder ausbauen, dafür den Ram einbauen, das AIT1 Gehäuse mit einer kleinen Trennscheibe bearbeiten und das Laufwerk da wieder einbauen. *nerv*


¹ Ein Raid ist nett, aber kein Backup, ein Fehler beim mdadm und alles ist weg - wenn man nicht wie ich Glück hat und nur 20 GB verliert, weil man den Rebuild abgebrochen hat. Details vielleicht in einem späteren Post ;)

Mittwoch, 22. April 2009

Internetzensur bei Kabel Deutschland

Das Kabel Deutschland mit zu den Zensurprovidern gehört, war ja klar, wenn man sich ansieht, wer da im Aufsichtsrat sitzt.

Auf meine Anfrage, wie das denn nun mit den Sperren läuft und auf welcher Rechtsgrundlage sie das machen wollen, habe ich nach 3 Wochen immerhin die Antwort, dass sie es an eine andere Abteilung weitergeleitet haben.

Die brauchen also allen Ernstes 3 Wochen für das Weiterleiten einer E-Mail.

Mein Faxgerät funktioniert übrigens immer noch nicht am KD-Anschluss, Telefonate klappen oft auch nur in eine Richtung, häufig ist besetzt, ohne dass der Angerufene telefoniert. Und das obwohl es VoIP mit ihrer Hardware über deren Kabelnetz ist - Bandbreite also nicht das Problem ist.

Übrigens: Die Zweckbindung der Zensur wurde aus dem heute eingebrachten Gesetzesentwurf gestrichen. Das BKA soll also beliebige Seiten auf die Sperrlisten setzen können. Nachprüfen ob die Sperre gerechtfertigt ist ist darf man nicht - weil man sich ja beim Zugriff evtl. schon strafbar macht.

Nachtrag:

Es ist natürlich nicht bei dieser kleinen Änderung geblieben. Laut Heise soll nun auch ermittelt werden, wenn man wiederholt auf die Stoppseite gelangt, und dann nachweisen müssen, dass es ein Versehen war oder eine automatische Weiterleitung. Ich bin gespannt wie das gehen soll.

Und schliesslich sollen die Provider verpflichtet werden 'mindestens' eine 'DNS-Sperre' einzurichten. Man darf gespannt sein, was da in Zukunft also alles versehentlich mit weggefiltert wird.

Samstag, 28. März 2009

'Kinderpornosperre' in 27 Sekunden 'umgehen'

Einfach um zu zeigen wie schwachsinnig die Pläne unserer Regierung sind hat jemand ein kleines Video gedreht. Es zeigt, wie man innerhalb von 27 Sekunden(!) die geforderten Sperren mit Stoppseiten etc. umgehen kann. Viel Spaß: Internetsperre in 27 Sekunden umgehen

Unter Linux geht es natürlich noch schneller:

  $ echo "nameserver 193.254.184.230" > /etc/resolv.conf
oder
  $ sudo bash -c 'echo "nameserver 193.254.184.230" > /etc/resolv.conf'

Montag, 23. März 2009

Bald Internetzensur bei Kabel Deutschland?

Sehr geehrte Damen und Herren,
mit entsetzen musste ich heute eine Meldung zur Kenntnis nehmen, nach der Kabel Deutschland angeblich einer willkürlichen Sperrung von Webseiten anhand einer Liste des BKA zugestimmt haben soll:

"In der Internet-Branche stoßen die Pläne von der Leyens für eine freiwillige Vereinbarung nicht auf allzu große Unterstützung; zuletzt berichtete der "Kölner Stadt-Anzeiger", dass sich mehrere deutsche Internet-Provider gegen den Plan sperrten, kinderpornografische Seiten im Zuge einer solchen Vereinbarung zu blockieren. Die Gespräche mit Vodafone und Kabel Deutschland seien positiv verlaufen, berichtet das Blatt unter Berufung auf einen internen Vermerk des Innenministeriums."

Quelle: http://www.heise.de/newsticker/Bundesregierung-Keine-Internet-Zensur-aber-Web-Sperren-gegen-Kinderporno--/meldung/134976

Bitte teilen Sie mir mit:
  • ob dieser Bericht den Tatsachen entspricht
  • auf welcher Rechtsgrundlage Sie derartige Massnahmen durchführen wollen
  • wie Sie die Sperren technisch realisieren wollen
  • wie Sie die Einhaltung des Datenschutzes in Bezug mit den 'Stopp-Seiten' realisieren wollen
  • ob Sie ausschliessen können, dass auch Inhalte wie 'Glücksspielseiten' und 'Killerspiele' gefiltert werden, wie vermehrt gefordert wurde.
  • Ich weise Sie schon jetzt darauf hin, dass ich vermutlich von meinem Recht einer Vertragskündigung Gebrauch machen werde, sollten Sie diese Massnahmen an meinem Anschluss durchführen. Entweder in Form eines Sonderkündigungsrechts wegen einseitiger Änderung des Vertrages oder wegen Nichterbringung von Leistung.

    Mit freundlichen Grüßen,

    Montag, 2. März 2009

    CeBIT - ich komme...

    So. Nun fahre ich also auch mal zur CeBIT. Der größten Computermesse überhaupt. Da arbeiten bestimmt nur Profis. Die besten der Besten und so...

    Nur leider schaffen es diese Experten nicht, eine RFC-konforme Email zu bauen, das regt mich ja schon wieder auf:

    Im Subject haben sie es ja noch hinbekommen, mit dem Encoding. Nur leider im Body nicht.

    Es könnte natürlich an der Frickelsoftware liegen, die sie da benutzen ;)

    X-Mailer: Microsoft CDO for Exchange 2000
    X-MimeOLE: Produced By Microsoft MimeOLE V6.00.3790.4133
    

    Der Body ist dann jedenfalls latin1, 8bit, ohne Encoding-Angabe:

    Content-Type: text/plain
    Content-Transfer-Encoding: 8bit
    

    Naja, wenigstens kein html...

    Montag, 23. Februar 2009

    Zischen und Zirpen aus den Lautsprechern.

    Ich hatte die letzen Wochen immer wieder ein Problem: Sobald gnome gestartet wurde, war ein ununterbrochenes Zirpen und Zischen aus den Lautsprechern zu hören.

    Sobald man den esd gekillt hatte, wurde es still. Wollte man wieder Musik wiedergeben, fing das Gezische wieder an. Soweit so nervig, vor allem, wenn man Podcasts einer Vorlesung bearbeiten will.

    Was zwischendurch ein paar Mal geholfen hatte, war alsaconfig aufzurufen. Ich habe die Probleme letztlich auf ein Kernelupdate geschoben, und mir nicht soviel weitere Gedanken gemacht.

    Gestern habe ich dann wieder mal ein Kernelupdate gemacht, mit dem Ergebnis, dass die komischen Geräusche der Soundkarte auch mit alsaconfig nicht mehr wegzubekommen waren.

    Schliesslich fand ich per Zufall die Lösung des Rätsels, als ich nach und nach versuchte, die Kernelmodule zu entladen, die ein 'snd' im Namen trugen. Bei zweien davon weigerte sich der kernel beharrlich. Eines davon: snd_pcsp.

    Nachdem ich im Gnome-Lautstärkeregler dann eine Einstellung für eine Basisfrequenz gefunden habe und bei einer Änderung das Gezirpe die Tonhöhe ebenfalls änderte, wusste ich, was mir hier vorgespielt wird...

    Alsa hat seit einiger Zeit eine Emulation zur Soundausgabe über die normalen, alten PC-Speaker. Dummerweise klappt das auf meiner Hardware nicht so besonders, so dass ständig Nebengeräusche entstehen. Aaarghhh

    Hiermit sei derüber gebloggt, eventuell finden andere Opfer dann einen Eintrag per Google, der ihnen hilft ;)

    Technische Daten für die googlesuche:

      00:1b.0 0403: 8086:284b (rev 03)
      00:1b.0 Audio device: Intel Corporation 82801H (ICH8 Family) HD Audio Controller (rev 03)
      snd_intel8x0m,snd_intel8x0,snd_ac97_codec,snd_hda_intel,snd_pcm,snd_timer
    

    Sonntag, 15. Februar 2009

    ddos - Mittäter und Opfer (Update)

    Tja, so kanns gehen. Eben noch rege ich mich darüber auf, dass mein Hoster manitu von einer ddos heimgesucht wird, schon darf ich feststellen, dass einer meiner Nameserver an einer anderen Distributed Denial of Service Attacke munter mitgewirkt hat. grmpf.

    Aufgefallen ist mir das ganze per munin:

    Okay, zwei/drei Anfragen pro Sekunde sind nicht viel, nur sieht man leider dadurch im Graphen den Rest nicht mehr. Ausserdem könnte der Angreifer ja auf die Idee kommen, auch mal mehr Requests zu schicken. Aber was will der eigentlich von mir - und wie ist er auf meinen Server gekommen?! Und zwei Anfragen - wo soll hier der DOS sein? Und warum fragt der ständig nach den Nameservern der '.'-Zone?

    Was soll also der 'Mist'?

    Des Rätsels Lösung: Natürlich bin ich nicht das Opfer, das war mir eigentlich klar, aber es ist fast noch schlimmer: Ich Mein Nameserver ist Mittäter und die scheinbaren Angreifer sind die tatsächlichen Opfer.

    Jemand im Internet schickt gerade an massiv vielen Nameserver diese Anfragen mit gefälschtem Absender. Das Ergebnis: Nameserver die nicht ganz korrekt konfiguriert sind antworten dann freigiebig mit der Liste aller Root-Nameserver.

    Bei wirklich großen Nameservern fallen diese Anfragen vermutlich nicht mal auf, weil sie im Hintergrundrauschen untergehen, so dass nur wenige Admins den Missbrauch ihrer Systeme überhaupt bemerken werden.

    (Die Liste der Root-Nameserver gibt es hier oder beim Nameserver Eures Vertrauens per $ dig . NS @nameserver. )

    Warum ist das nun ein Problem? Ganz einfach: der Angreifer schickt ein paket mit 40 bytes los, das Opfer erhält aber eine Antwort, die um ein vielfaches größer ist. Die Nameserver fungieren also als Verstärker des Angriffs. Schade eigentlich.

    Selbst ein korrekt konfigurierter Nameserver, der die Anfrage ablehnt, antwortet noch mit der Ablehung, trägt also immernoch ein bischen zum DOS bei.

    Gegenmassnahmen?

    Es sind mehrere denkbar:

    Einerseits haben die Anfragen alle denselben Inhalt und sind daher alle 40 byte groß. In 40 byte kann man auch sonst kaum eine sinnvolle Anfrage unterbringen, also kann man alles was per udp auf port 53 ankommt und weniger als 45 byte Größe hat blocken. Damit antwortet man sogar nicht mal mehr mit der Ablehnung und die Anfragen sind aus den logs. Man sollte nur seinen Provider und primäre/sekundäre Nameserver der eigenen Domains whitelisten, für den Fall, dass der Angreifer mal diese als neues Ziel definiert.

    Dann könnte man ein rate-limit per IP einführen, so dass bei mehr als 20 Anfragen in 20 Sekunden der port 53 für diesen Host für einige Zeit gesperrt wird. Auch hier: Whitelisten nicht vergessen.

    Oder man kann regelmässig seine Logs durchgehen, wer denn nun schon wieder soviele Anfragen produziert, und dann diese IP's für port 53 sperren.

    Achja, und ganz wichtig: Das Secure BIND Template umsetzen und die default policy der BIND-Installation unter debian ändern, damit man auf die Anfragen nicht die Liste liefert² ;)

    In dem Template werden übrigens Views für verschiedene Hostgruppen definiert. Sehr schick - und ich habe auch endlich welche in meinen Configs definiert. Wollte ich schon lange machen.

    Damit kann man unterschiedlichen Hostgruppen per acl unterschiedlich antworten. Also z.B. allen hosts aus dem Firmennetz die privaten Adressen und Namen auflösen und mit demselben Nameserver von aussen diese Anfragen nicht erlauben oder eine komplett andere Antwort geben.

    Damit könnte man auch mit einem einzigen Nameserver ein Wlan derart gestalten, dass alle noch nicht authentifizierten Benutzer auf die Anmeldeseite gelangen, wo sie einen vpn-Client herunterladen können und später - ohne Ändern der resolv.conf¹ - mit der IP die sie innerhalb des VPN's haben korrekte Namensauflösung vom Nameserver erhalten. (Aber das ist ein anderes Thema...)


    ¹ Es ist sehr eklig, denn der DHCP-Client im Wlan andere Nameserver einträgt, als der VPN-Tunnel braucht, dann kloppen sich DHCP-Client und VPN-Client nämlich schön darum, wem die resolv.conf gehört. Läuft die DHCP-Lease ab, trägt der DHCP-Client 'seine' DNS-Server ein und man landet wieder nur auf der Startseite für das WLAN mit dem Hinweis, man solle sein VPN aktivieren. Arrrgh.

    ² Einer meiner anderen Nameserver, der auf ein minimales gentoo aufsetzt, hat interessanterweise diese Anfragen von Anfang an refused, obwohl die Konfiguration nicht wesentlich von der auf dem debian abwich. Grummel.


    Nachtrag: Wirksame Gegenmassnahme

    Tja, auf die Einfachsten Dinge kommt man zum Schluss: Offenbar sehen die Anfragen ja immer identisch aus, also kann man einfach die Anfrage als solche blocken:

     iptables -I INPUT -i eth0 -p udp  --destination-port 53 \
           -m string --algo kmp --from 30 --hex-string "|010000010000000000000000020001|" -j DROP
    
    und fertig ist die Laube... Ab Position 30 fängt der eigentliche Query an.
    0100 - standard Query mit Recursion (1)
    0001 - Eine einzelne Frage ist enthalten
    
    Gegen Ende dann:
    0002 - NS wird angefragt
    0001 - Class IN
    

    Mittwoch, 26. November 2008

    HOWTO: eigener primärer DNS mit BIND und Schlund

    Vergangenen Freitag ging durch die einschlägigen Medien die Meldung über eine DDOS-Attacke auf InternetX, die einen Ausfall bzw. die Nicht-Erreichbarkeit ihrer Nameserver zur Folge hatte.

    Die Nameserver vonInternetX werden z.B. von Schlund genutzt um die Domains ihrer Kunden darauf 'abzulegen'.

    Auch ich bin ein Kunde von Schlund, alle meine Domains habe ich über das Webinterface 'gekauft' und bisher auch darüber die Nameserver ns9.schlundtech.de und ns10.schlundtech.de 'konfiguriert', sprich meine RR's dort eingetragen.

    Vergangenen Freitag konnte ich meine Domains dann allesamt nicht mehr auflösen. Etwas Recherche brachte zum Vorschein, dass die Nameserver von Schlund zwar wie DENIC vorschreibt in unterschiedlichen 'Class C-Netzen' liegen, aber in einem gemeinsamen AS.

    Seit der Einführung von CIDR (im Jahr 1993!) existieren aber diese Netzklassen so nicht mehr. Wichtig ist spätestens seit dem, dass die Nameserver in unterschiedlichen autonomen Systemen (AS) liegen, da beim Ausfall des Routings zu einem AS dann immer noch der andere Nameserver erreichbar ist.

    Nun gut, ich habe mich also am Samstag endlich daran gemacht, meinen eigenen BIND aufzusetzen. Alle Schritte, und die Einstellungen im Schlund-Interface, will ich beispielhaft im Folgenden dokumentieren. Ich konfiguriere einen primären und einen sekundären Nameserver und nutze den ns10 von Schlund als weiteren sekundären Nameserver.

    Die 6 Schritte zum eigenen authoritativen Nameserver

    • Namen und IP-Adressen der Nameserver in die Zone eintragen (nur die A-Records)
    • sekundären BIND aufsetzen
    • primären BIND aufsetzen
    • Zonefiles schreiben
    • Testen ob die Zone beim sekundären Nameserver ankommt
    • Schlundtech konfigurieren

    Das Szenario für dieses Beispiel

    Es gibt zwei Server, 192.0.2.101 und 192.0.2.102, die als primärer und sekundärer Nameserver für die Domain example.org eingerichtet werden sollen. Für dieses Beispiel benutzen wir natürlich reservierte Namen und Adressen.

    Namen und IP-Adressen in die Zone eintragen

    DNS ist je nach Kofiguration ein recht träges System. Man weiss auch nie, welche Admins ihre Caches nicht im Griff haben, und auch nach Ablauf der TTL noch veraltete Daten ausliefern. Es ist daher immer gut, Änderungen die man später braucht, möglichst früh einzutragen und, wenn möglich, die TTL zu verringern. Auf das Verringern der TTL und ähnliches verzichten wir hier der Einfachheit aber mal, weil das Webinterface von Schlund da ein wenig unübersichtlich ist. Der von Schlund so genannte SOA-Level bleibt auf 'Empfohlene Einstellungen'.

    Als erstes tragen wir die A-Records für unsere Nameserver ein.

    ns01.example.org.   IN A 192.0.2.101
    ns02.example.org.   IN A 192.0.2.102
    

    Bitte bei Bind auf den Punkt am Ende der Namen achten oder die Domain und den Punkt weglassen. Bei Schlund: Entsprechend der vorhandenen Einträge machen - ich glaube ohne Punkt und ohne Domain ist korrekt.

    Danach sollte man bei seinem Server-Hoster dafür sorgen, dass das Reverse-Lookup der IP-Adresse die oben angegebenen Namen liefert.

    Jetzt können wir gemütlich einen Kaffee trinken gehen...nein, im Ernst, je nachdem wie paranoid man ist sollte man etwas warten, mindestens bis die Zeit für das negative Cachen abgelaufen ist. Da wir aber den ns10 weiter in Betrieb lassen kann es nur zu Verzögerungen beim Auflösen unserer Domain kommen, aber nicht zum Totalausfall, sofern ns10 noch zu erreichen ist.

    Den sekundären BIND aufsetzen

    Wir gehen davon aus, dass nach einem emerge -av net-dns/bind oder einem apt-get install bind9 der BIND installiert ist.

    Die Konfiguration ist eigentlich ganz einfach - leider weichen bei Gentoo und Debian die Pfade ein wenig voneinander ab sowie das Konzept der Konfiguration.

    Während bei Gentoo alles in einer Datei steht, teilt Debian die named.conf mittels include-Anweisungen in drei Dateien auf.

    Wir gehen beim Sekundären mal von Debian aus...

    In der Datei /etc/bind/named.conf müssen wir unter Debian nichts weiter für unser Beispiel einfügen, da diese zwei anderen Dateien inkludiert.

    Man kann aber allerdings darüber nachdenken, den rootservern von .com und .net zu verbieten, nicht-registrierte Domains auf Suchseiten umzulenken:

     zone "com" { type delegation-only; };
     zone "net" { type delegation-only; };
    

    In der Datei

    named.conf.options
    ändern wir am meisten, siehe Komentare in den Zeilen, es sollte selbsterklärend sein. Die folgende Datei ist 'komplett':

    acl myown-servers  {        
            127.0.0.1;        
            # Hinweis: hier alle eigenen Server/Netze eintragen, 
            # die den Server als normalen DNS benutzen dürfen.
            # Kann auch leer sein.
    };
    
    acl secondaries {
            62.116.163.100; # InternetX/Schlund
            62.116.162.121; # InternetX/Schlund
            192.0.2.102;    # unser sekundärer (dieser host selbst)
            127.0.0.1;
    };
    
    options {
            directory "/var/cache/bind";;
            forwarders {
                                 # wenn wir selber auflösen wollen:
                    192.0.2.14;  # erster Nameserver des ISP
                    192.0.2.15;  # zweiter Nameserver des ISP
            };
    
            listen-on-v6 { none; }; # wird hier IPv6 aktiviert, müssen
                                    # in den ACLs die Adressen auch in der
                                    # alternativen Schreibweise erscheinen.
    
            listen-on { 127.0.0.1; 192.0.2.102;}; # logisch...
    
            transfer-source 192.0.2.102; # von dieser Adresse 
                                         # machen wir Zonentransfers
            version "get lost";
            allow-transfer {"none";};
            allow-recursion {myown-servers;}; 
            notify no;
            auth-nxdomain no;    # conform to RFC1035
    };
    
    

    Nun folgen noch die Zonendefinitionen in der Datei named.conf.local:

    zone "example.org" in{
      type slave;
      file "slv/example.org.slave";
      masters {192.0.2.101;};
    };
    

    Danach das slv-Verzeichnis verlinken und eine leere Datei anlegen, in die bind schreiben darf:

      # cd /etc/bind
      # ln -s /var/cache/bind/slv slv
      # touch slv/example.org.slave
      # chown bind:bind slv/example.org.slave
    

    Das slv-Verzeichnis habe ich angelegt, um nicht immer überlegen zu müssen, ob ich auf meinem Debian oder meinem Gentoo-Server eingeloggt bin.

    Damit ist der Sekundäre Nameserver Einsatzbereit und kann so bleiben. Wir laden die Zone nicht neu, das erledigt der Server nachher hoffentlich von alleine, wenn er das Notify von unserem primären Nameserver erhält.

    Bei Hosts mit mehr als einer IP-Adresse sind die Quelladressen anzugeben, weil der primäre Nameserver sonst u.U. keine Zonentransfers erlaubt.

    primären BIND aufsetzen

    Mein primärer Nameserver läuft auf einem aktellen Gentoo, daher hier ein leicht anderer Ansatz, wir schreiben alles in eine Datei und müssen den Symlink für das slv-Verzeichnis nicht anlegen.

    Nach einem emerge -av net-dns/bind editieren wir die /etc/bind/named.conf:

    ACHTUNG: In der Originaldatei sind schon einige Zonen definiert, diese bleiben erhalten, ausserdem hat dieser Server nur eine IP-Adresse, daher müssen wir die Anaben zu den Quelladressen wie bei unserem Secondary oben nicht machen. In der folgenden Konfiguration sind nur Änderungen und Erweiterungen zur Originalversion der Datei aufgeführt:

    acl myown-servers  {        
            127.0.0.1;
            ...;        #hier also wieder alle unseren server 
    };
    acl secondaries {
            62.116.163.100; # InternetX/Schlund
            62.116.162.121; # InternetX/Schlund
            192.0.2.102;    # unser sekundärer
            127.0.0.1;
    };
    options {
            directory "/var/bind";
    
            // uncomment the following lines to turn on DNS forwarding,
            // and change the forwarding ip address(es) :
            forward first;
            forwarders {
                    DNS1;   # erster DNS unseres ISP
                    DNS2;   # zweiter DNS unseres ISP
            };
    
            listen-on-v6 { none; };
            listen-on { 127.0.0.1; 192.0.2.101;};
    
            pid-file "/var/run/named/named.pid";
            max-journal-size 50k;
            version "get lost";
            allow-transfer {"none";};
            allow-recursion {myown-servers;};
    };
    
    zone "COM" { type delegation-only; };
    zone "NET" { type delegation-only; };
    
    zone "example.org" IN {
            type master;
            file "pri/example.org.zone";
            allow-transfer { secondaries; };
            notify yes;  #bei Änderungen die secundaries informieren
    };
    
    

    Wir haben die Konfiguration des Dienstes geschafft, nun müssen wir ihm noch die Daten geben, die er verteilen soll.

    Zonefiles schreiben

    Jetzt kommt der unangenehmste Teil der Arbeit, das manuelle Kopieren aller Einträge aus dem Schlund-Webinterface in eine Zonendatei.

    Das wichtigste zuerst: Bei jeder Änderung der Zone muss die serial hochgezählt werden, sonst wird die Zone nicht auf die sekundären Server kopiert. Ausserdem muss das Retry-Interval größer als 30 Minuten sein, sonst nimmt Schlund die Zone nicht an. Und immer auf die Punkte am Ende der Hostnamen achten, ohne Punkt wird die Domain eingesetzt!

    Wir legen nun im Unterverzeichnis pri das Zonenfile pri/example.org.zone an:

    $ORIGIN example.org.
    $TTL 2d    ; 172800 secs default TTL for zone
    @             IN      SOA   ns01.example.org. hostmaster.example.org. (
                            2008112601 ; se = serial number
                            12h        ; ref = refresh
                            35m        ; ret = update retry
                            3w         ; ex = expiry
                            3h         ; min = minimum
                            )
                  IN      NS      ns01.example.org.
                  IN      NS      ns10.schlundtech.de.
                  IN      NS      ns02.example.org.
                  IN      TXT     "v=spf1 a mx ?all"
                  IN      MX  10  mail1.example.org.
                  IN      MX  20  mail2.example.org.
                  IN      A       192.0.2.100
    ns01          IN      A       192.0.2.101
    ns02          IN      A       192.0.2.102
    www           IN      CNAME   example.org.
    

    Das ORIGIN der ersten Zeile definiert für den Rest der Datei, welche Domain wir da eigentlich vor uns haben. Ab der dritten Zeile findet sich der SOA-Eintrag, in dem der primäre Nameserver angegeben ist und eine Emailadresse des zuständigen Admins. Hier: hostmaster@example.org, das @ wird durch einen Punkt ersetzt. Es folgt die serial number, die bei jeder Änderung erhöht werden muß. Es empfiehlt sich das Datum und einen Zähler mit der Zahl der Änderung an diesem Tag zu nutzen. Die serial darf kein Zeichen länger sein, da sie sonst von Bind nicht angenommen wird.

    Es folgen dann eine ganze Reihe von Timeouts und Intervallen, das Beispiel passt schon so...

    Weiter unten in der Zone sind die Nameserver der Domain angegeben. Das ist wichtig. Bei uns stehen die Nameserver sogar noch in derselben Domain, für die sie auch zuständig sind. Daher müssen wir nachher in das Webinterface bei Schlund noch zusätzlich die IP-Adressen der Server angeben.

    In dieser Zone sind auch gleich Beispiele für einen SPF-Record, Nameserver und einen CNAME für den WWW-Host, der auf den A-Record der Domain zeigt.

    Wir können nun den bind auch beim Systemstart hochfahren lassen und starten:

     # rc-update add named default
     # /etc/init.d/named start
    

    Damit sollte der primäre Nameserver fertig sein

    Testen ob die Zone beim sekundären Nameserver ankommt

    Wir loggen uns nun wieder bei unserem eben konfigurierten Sekundären Nameserver ein und schauen nach, ob die Zonendatei nun Daten enthält.

    Wenn alles gut gegangen ist, hat der primäre Nameserver beim Starten unseren Secondaries ein Notify geschickt und sie zu einem Zonentransfer animiert. Der Server von Schlund ignoriert das Notify, da er unseren primären Nameserver ja noch nicht kennt.

    Sollte die Zone noch leer sein, kann man vom sekundäen Server aus mit dem Utility dig mal einen Zonentransfer versuchen und dabei die Logausgaben des primären Nameservers anschauen.

      dig axfr example.org  @ns01.example.org
    

    Hat man mehrere IP-Adressen hilft -b IP weiter.

    Bei Änderungen an den Zonen muß der BIND nicht neu gestartet werden. Das Kommando rndc hilft weiter:

    rndc reload

    Schlundtech konfigurieren

    Nachdem man die eigenen Server konfiguriert hat und alles funktioniert(!), kann man sich an das Webinterface von Schlund wagen.

    Als Einrichtungsart unter 'DNS-Einstellungen und Weiterleitungen' wählt man 'nur zweiter Nameserver' und auf dem ersten Registerblatt 'Domain-Einstellungen' gibt man bei den Nameservern ein:

     ns01.example.org      192.0.2.101
     ns10.schlundtech.de
     ns02.example.org      192.0.2.102
    

    Bei Nameservern, die in der Domain liegen, die sie auch verwalten, ist die Angabe der IP-Adresse essentiell!

    Sobald man auf 'Domain aktualisieren' klickt, sollte ein Zonentransfer vom primären DNS starten...

    Um Fehlermeldungen zu lesen, die beim Zonentransfer auftreten können, muss man sich vom Webinterface abmelden, neu anmelden und auf der Startseite in der History klicken.

    Der ns10 von Schlund erlaubt übrigens wohl gar keine Transfers.

    Wenn alles gut geganten ist, kann man im whois seine Nameserver bewundern und bei einem dig nach den Nameservern der Domain die Additional-Records sehen, welche die IP-Adressen enthalten. Man sollte beim dig natürlich einen Nameserver vom ISP nehmen, nicht seinen eigenen, der funktioniert ja ;)

    $ dig ns example.org
    [...]
    ;; ANSWER SECTION:
    example.org.  34422 IN NS ns01.example.org.
    example.org.  34422 IN NS ns02.example.org.
    example.org.  34422 IN NS ns10.schlundtech.de.
    
    ;; ADDITIONAL SECTION:
    ns01.example.org. 34265 IN A 192.0.2.101
    ns02.example.org. 34265 IN A 192.0.2.102
    ns10.schlundtech.de. 2167 IN A 62.116.163.100
    

    Bei allem Debugging mit AS'en und Nameservern, etc, ist die Webseite von robtex sehr praktisch, da sie Graphen für AS-Zuordnungen und DNS-Einträge zeichnen kann.