Seit Wochen nervt eine bestimmte Kiste mit Bind, dass die Hints für den Startup von der Realität abweicht. Und erstaunlicherweise hat sie recht.

Das Problem

Oct  2 17:07:27 named[1117]: checkhints: b.root-servers.net/AAAA (2001:500:200::b) extra record in hints
Oct  2 17:07:39 named[1117]: checkhints: b.root-servers.net/AAAA (2001:500:84::b) missing from hints
Oct  2 17:07:39 named[1117]: checkhints: b.root-servers.net/AAAA (2001:500:200::b) extra record in hints
Oct  2 17:08:17 named[1117]: checkhints: b.root-servers.net/AAAA (2001:500:84::b) missing from hints
Oct  2 17:08:17 named[1117]: checkhints: b.root-servers.net/AAAA (2001:500:200::b) extra record in hints

Ich kann den Cache löschen, aber das Problem kommt einige Tage später wieder.

Auch die originale Quelle der Hint-Files bestätigt, dass ich nichts falsch konfiguriert habe.

Der Fehler

Wie immer bei DNS-Problemen schaut man bei DNSviz nach.

b.root-servers.net-2017-10-02-15_17_03-UTC

Alles OK? Nein, da ist doch ein kleines Warndreieck!

2017-10-02-172109_238x422_scrot

Das ist exakt die Beschreibung meines Problems: Es gibt im Internet noch Einträge, die die alte, fehlerhafte IP enthalten.

Die Ankündigung passt auch prima zu dem ersten Auftreten des Problems:

As previously announced, B-Root’s IPv6 addresswas renumbered
to 2001:500:200::b, effective 2017-06-01.
(Or IPv6 address previously was 2001:500:84::b; we will continue to
operate service onthe old address for at least 6 months.)

Problem solved?

Die Lösung

Natürlich ist das Problem nicht gelöst. Es muss jemand benachrichtigt werden, der das Problem fixed. Aber wer?

$ dig ns net +short | while read a; do
   echo -n "$a ";
   dig +nottl +nocl aaaa b.root-servers.net @$a |
     egrep -i '^b.root-servers.net.*AAAA';
 done | sort

a.gtld-servers.net. b.root-servers.net. AAAA    2001:500:84::b
b.gtld-servers.net. b.root-servers.net. AAAA    2001:500:84::b
c.gtld-servers.net. b.root-servers.net. AAAA    2001:500:84::b
d.gtld-servers.net. b.root-servers.net. AAAA    2001:500:84::b
e.gtld-servers.net. b.root-servers.net. AAAA    2001:500:84::b
f.gtld-servers.net. b.root-servers.net. AAAA    2001:500:84::b
g.gtld-servers.net. b.root-servers.net. AAAA    2001:500:84::b
h.gtld-servers.net. b.root-servers.net. AAAA    2001:500:84::b
i.gtld-servers.net. b.root-servers.net. AAAA    2001:500:84::b
j.gtld-servers.net. b.root-servers.net. AAAA    2001:500:84::b
k.gtld-servers.net. b.root-servers.net. AAAA    2001:500:84::b
l.gtld-servers.net. b.root-servers.net. AAAA    2001:500:84::b
m.gtld-servers.net. b.root-servers.net. AAAA    2001:500:84::b

Also alle. Die gesamte Delegation von NET ist kaputt.

Verantwortlich für .net ist Versign. Und die verweisen für die Delegierung auf Verisign (im Auftrag IANA). (Ja, das hatte ich anfangs falsch.)

Domain Name: ROOT-SERVERS.NET
Registry Domain ID: 2751247_DOMAIN_NET-VRSN
Registrar WHOIS Server: whois.networksolutions.com
Registrar URL: http://www.networksolutions.com
Updated Date: 2017-03-05T17:07:51Z
Creation Date: 1995-07-04T04:00:00Z
Registrar Registration Expiration Date: 2020-07-03T04:00:00Z
Registrar: NETWORK SOLUTIONS, LLC.
Registrar IANA ID: 2
Registrar Abuse Contact Email: abuse@web.com
Registrar Abuse Contact Phone: +1.8003337680
Reseller: 
Domain Status: 
Registry Registrant ID: 
Registrant Name: VERISIGN INC.
Registrant Organization: VERISIGN INC.
Registrant Street: 12061 BLUEMONT WAY
Registrant City: RESTON
Registrant State/Province: VA
Registrant Postal Code: 20190-5684
Registrant Country: US
Registrant Phone: +1.7039481212
Registrant Phone Ext: 
Registrant Fax: +1.7039483670
Registrant Fax Ext: 
Registrant Email: noc@verisign.com
Registry Admin ID: 
Admin Name: IANA Root Management, ICANN
Admin Organization: ICANN
Admin Street: 12025 Waterfront Drive #300
Admin City: Los Angeles
Admin State/Province: CA
Admin Postal Code: 90094
Admin Country: US
Admin Phone: +1.13103015800
Admin Phone Ext: 
Admin Fax: +1.13108238649
Admin Fax Ext: 
Admin Email: kim.davies@icann.org

Also schreibe ich die beide mal an.

Beim Erstellen eines Programms, das Daten aus einem Puffer kratzt, stolperte ich über einen sehr seltsamen Fehler in C. Es kostet mich ernstlich Mühe, das Problem auch nur zu verstehen.

Das Programm

Zuerst habe ich das Problem eingedampft auf ein minimales Beispiel:

#include <stdio.h>

int main(void) {
   int len, step;
   char data[5];

   for(len = 27; sizeof(data) < len; len -= step) {
      step = sizeof(data) + 2; 
      printf("len = %3d, taking %d away.\n", len, step);
   }
}

Was tut das Programm?

  • Es gibt einen Puffer mit einer initialen Länge von 27 Byte.
  • Passt die Struktur nicht mehr in den Restpuffer, brich ab.
  • Solange die gesuchte Struktur aber noch rein passt, verarbeite sie (fehlt im Beispiel).
  • Nach der Verarbeitung verkleinere die Rest-Datenmenge um die verarbeitete Struktur plus ein passendes Alignment (hier fest 2).

Der benutzte Puffer, das Verschieben des Arbeitszeigers und die eigentliche Datenverarbeitung sind in dem Beispiel entfallen.

Überraschung

Und hier die Ausgabe:

len =  27, taking 7 away.
len =  20, taking 7 away.
len =  13, taking 7 away.
len =   6, taking 7 away.
len =  -1, taking 7 away.
len =  -8, taking 7 away.
len = -15, taking 7 away.
len = -22, taking 7 away.
len = -29, taking 7 away.
len = -36, taking 7 away.

Wow! Warum beendet sich das Programm denn nicht?

Die Größe der Struktur ist "5". Das ist ganz bestimmt nicht kleiner als "-1", oder etwa doch?

Ganz offensichtlich ist der Vergleich "5" ist kleiner als  "-1" wahr, aber warum?

Evtl. hab' ich ja irgendwelche Warnungen des Compilers übersehen?

$ cc -O2 -Wall -o t t.c
[ ... nichts ... ]
$ cc --version
FreeBSD clang version 3.9.1 (tags/RELEASE_391/final 289601) (based on LLVM 3.9.1)
Target: x86_64-unknown-freebsd11.0
Thread model: posix
InstalledDir: /usr/bin

Nein, auch nicht.

Erklärung

Wenn der C-Compiler den Wert des "signed int" mit dem Namen "len" in einen "unsigned int" verwandeln würde, dann wäre das Ergebnis erklärt. Der Vergleichwert wäre dann also bei mehr als 4 Mrd., also deutlich größer als die Länge der Struktur.

Aber warum sollt der Compiler eine solche Umwandlung durchführen?

Es bleibt nur ein Blick in die Norm:

  • In 6.5.8 "Relational operators" heißt es: If both of the operands have arithmetic type, the usual arithmetic conversions are performed.
  • In 6.3.1.8 "Usual arithmetic conversions" heißt es: If the operand that has unsigned integer type has  rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with  unsigned integer type.
  • In 6.3.1.1 "Boolean, characters, and integers" heißt es: The rank of any unsigned integer type  shall equal the rank of the corresponding signed integer type.

Für den Vergleich zwischen zwei normalen Integer-Typen – der eine mit, der andere ohne Vorzeichen – gilt also, dass beide Operatoren nach unsigned konvertiert werden: In diesem Fall also von -1 auf 4 Mrd.

Voraussetzung für diese Interpretation ist allerdings, dass der sizeof-Operator einen vorzeichenlosen Integer-Typ liefert. Also wieder die Norm lesen:

  • In 6.5.3.4 "The sizeof operator" heißt es: The result is an integer constant. Huch? Keine Aussage zu Vorzeichen?
  • Etwas später liest man: The value of the result is implementation-defined, and its type (an unsigned integer type) is size_t.

Man müsste also das Spiel gewinnen, wenn man die Variable "len" einen größeren Rank verpasst. Leider klappt das weder mit "long" noch mit "long long".

Erst eine beherzter Cast des sizeof-Operators nach "int" löst das Problem:

#include <stdio.h>

int main(void) {
   int len, step;
   char data[5];
   
   for(len = 27; (int)sizeof(data) < len; len -= step) {
      step = sizeof(data) + 2; 
      printf("len = %3d, taking %d away.\n", len, step);
   }
}

Und das ergibt:

len =  27, taking 7 away.
len =  20, taking 7 away.
len =  13, taking 7 away.
len =   6, taking 7 away.

Ende der Geschichte.

Wer mag, kann mal herausbekommen, ob der Umgang des Compilers im Falle von "long" und "long long" standardkonform ist. Ich habe da meine Zweifel.

Heute Nachmittag zeigte eine Kundenmaschine einen spontanen Anstieg der Auslastung. Auf den ersten Blick sah es so aus, dass einfach viel los war, Es gab so viele Anfragen auf die Webseite, dass die Limits erreicht wurden. Diese Grenzen verhindern, dass die Maschine unbenutzbar langsam wird. Dann meldete sich der Kunde und erklärte die Hintergründe.

Lastanstieg

httpd-anfragen

Ein wunderbarer Anstieg an Anfragen zu einem bestimmten Zeitpunkt. Es klingt dann exponentiell ab.

httpd-prozesse

Und er reißt das Limit der kleinen Maschine.

Mehr Prozesse zu starten, würde nur die Bearbeitung der anderen Prozesse noch weiter verlangsamen. Der dadurch entstehende Rückstau aus Datenbank, Platte etc. verschlimmert das Problem nur.

Wenn die Kiste voll beschäftigt ist, nimmt sie keine weiteren Anfragen an. Also meldet sich der Kunde.

Erklärung

Die Webseite sei jetzt genau ganz wichtig, weil man doch einen Projekttag machen würde. Und dazu habe man an sehr viele Schulen in den letzten Wochen Informationen gegeben. Da die Plätze pro Veranstaltung beschränkt sind, habe man sich eine zentrale Anmeldung eingerichtet.

Die Anmeldewebseite sieht so aus:

2017-09-14-190938_777x202_scrot

Wir hatten also eine Menge Schüler, die in einer Menge Schulen darauf warteten, zu einem festen Zeitpunkt auf eine Webseite zu klicken, deren Inhalt aus einer Datenbank generiert wird und dabei komplett fair ACID-Prinzipen ausführen will.

Kurz: Der Kunde hat einen distributed Denial of Service Angriff bestellt und bekommen.

Ich hatte heute ein längeres Gespräch mit einer Journalistin, die fragen zur DDR-Top-level-domain ".dd" hatte. Das Gespräch war lang. Allerdings stellte sich schnell heraus, dass sie zu jung ist, um sich die Realität von vor 30 Jahren vorstellen zu können.

Probleme beim Telefonat

Zuerst kam es zu einem Verständnisproblem der gesellschaftlichen Situation. Sie konnte sich nicht vorstellen, dass man nicht einfach mal in den USA bei Jon Postel anruft, um eine Länderdomain zu registrieren.

Insbesondere gelang es mir nicht, ihr begreiflich zu machen, welche politische Dimension diese Anfrage hat. Ein Mitarbeiter an einer Universität kann nicht im Namen des gesamten Landes sprechen und handeln.

Wesentlich schwerwiegender waren allerdings die inzwischen eingefahrenen Gedankenwege der "Digital Natives". Sie können es sich schlicht nicht vorstellen, ohne Internet und Smartphone zu agieren.

Eine der Fragen war, ob ich ein spontanes Foto hätte, wie ich in der Uni an einem Rechner (es war damals PC-10) sitze. Ganz abgesehen davon, ob diese Aufnahme auf Papier/Film vorliegen könnte, zeigt es das Selbstverständnis eines "Ich dokumentiere mein Leben mit Selfies"-Typs.

Erklärungen im Nachgang

Kurz danach kam eine Liste von Fragen, die es wert sind, halbwegs ernsthaft beantwortet zu werden. Es sind Fragen, die aus der Sicht meiner Kinder gestellt werden könnten. Deswegen veröffentliche ich hier meine Antworten.

Andererseits kann man schon die Frage stellen, ob nicht jemand, der das beruflich macht, mehr vom Telefonat hätte mitnehmen können. Vielleicht sind die Fragen aber auch nur zur Einholung von Zitaten erneut gestellt und pointiert überhöht. Möglicherweise habe ich auch nicht sauber genug erklärt.

Gab es in der DDR bei diesen „internetähnlichen“ Kommunikation auch Dienste, die mit heutiger „GOOGLE“ Suchmaschine zu vergleichen sind? Wenn ja, erklären Sie mir wie und wer dieses Verfahren genutzt hat.

Ja, es gab (und gibt) an den Bibliotheken der Städte, Universitäten und Firmen die Möglichkeit der Katalogrecherche (https://de.wikipedia.org/wiki/Bibliothekskatalog). War die gewünschte Information nicht lokal in der Bibliothek vorrätig, so bediente man sich der Fernleihe (https://de.wikipedia.org/wiki/Fernleihe).

Benennen Sie die drei wichtigsten Gründe, warum die DDR nicht ins World Wide Web gestartet ist und erklären Sie warum.

Der allerwichtigste Grund warum die DDR nicht ins WWW gestartet ist, ist die historische Kausalität. Die DDR ist untergegangen (1990 siehe https://de.wikipedia.org/wiki/Wende_und_friedliche_Revolution_in_der_DDR), bevor das WWW erfunden wurde (1991 siehe https://de.wikipedia.org/wiki/World_Wide_Web). Lediglich die rechtzeitige Erfindung einer Zeitmaschine (https://de.wikipedia.org/wiki/Zeitmaschine) hätte der DDR das WWW bringen können. Dazu ist es aber bis jetzt nicht gekommen.
Der zweite Grund ist, dass für den Betrieb eines Servers (https://de.wikipedia.org/wiki/Server) am Internet eine Standleitung (https://de.wikipedia.org/wiki/Standleitung) benötigt wird, die zu einem anderen Knoten des Internets reicht. Zu dem damaligen Zeitpunkt waren Leitungen (insbesondere Weitverkehrsleitungen) ein sehr rares Gut. Das dauerhafte Belegen einer Telefonwählleitung wurde (und wird) als Fehler behandelt und die Verbindung amtsseitig getrennt. Eine grenzüberschreitende Leitung ins NSW (https://de.wikipedia.org/wiki/Nichtsozialistisches_Wirtschaftsgebiet) stellte eine unüberwindliche politische Hürde da.
Der dritte Grund ist, dass zu dem Zeitpunkt das Internet (https://de.wikipedia.org/wiki/Internet#Ab_1989_Kommerzialisierung_und_das_WWW) als nicht relevant eingestuft wurde. Stattdessen beschäftigten sich die an Netzwerken interessierten Personen mit OSI (https://de.wikipedia.org/wiki/OSI-Modell), i.d.R. also mit X.25 Netzwerken (https://de.wikipedia.org/wiki/X.25). Wer sich mit Internet beschäftigte, war ein akademischer Außenseiter.
Bonus-Info: Zu den ersten deutschen Webseiten *nach der Wende* gehört das Sekteninformationssystem Religio (http://www.religio.de/) aus Thüringen, dass ab 1992 startete.

Beschreiben Sie mir wie sich das  „Surfen“ in Alltag der DDR gestaltete? Was hat man dafür gebraucht und wie funktionierte es. (Sie haben bereits erwähnt, es gab Bastler, die diese Technik zuhause ausgetestet haben).

Da das "Surfen" in der angefragten Zeit noch gar nicht möglich war (mangels WWW), benutzte man andere Formen der elektronischen Kommunikation. Die einzige nennenswerte Verbreitung hatten die Mailbox-Netze (https://de.wikipedia.org/wiki/Mailbox_(Computer)) die nur kurze Telefonverbindungen benötigten. Der Betreiber einer Mailbox musste den Familien-Telefonanschluss (wenn der überhaupt vorhanden war) zweckentfremden. Es war also während der Kommunikation eines Mailboxnutzers oder der Mailbox selbst nicht möglich, das Telefon zu benutzen. Auch musste die Familie lernen, mit dem kurzen Anklingeln durch andere Rechner klar zu kommen. So durfte man nicht sofort ans Telefon gehen, sondern erst, wenn das Klingeln nicht aufhörte.
Daneben gab es erste Internet-Experimente von Enthusiasten in einzelnen Laboren einzelner Universitäten. Dabei wurde höchstens eine Handvoll Rechner lokal zusammen geschaltet. Diese Netze verließen den Laborraum praktisch nicht.

Gibt es offizielle Zahlen, wie viele Bürger damals das „interne“ Internet genutzt haben?

Mangels Internet gab es gar keine Nutzer.

Welche Reaktionen und Folgen hätte das Internet in der DDR, wenn die Domain offiziell genehmigt worden wäre und die Bürger hätten auch „außerhalb“ kommunizieren können?

Die Existenz der Top-Level-Domain ".dd" (https://de.wikipedia.org/wiki/.dd) ist allein durch den reservierten Eintrag in der internationalen Liste der offiziellen Abkürzungen von Ländernamen (https://de.wikipedia.org/wiki/ISO-3166-1-Kodierliste) gerechtfertigt. Die bei einzelnen Experimenten an einzelnen Universitäten benötigten Namen wurden von den Beteiligten durchaus mit dem kanonischen Namen "kiste.uni-xxx.dd" benutzt. Eine über solche Testaufbauten hinaus gehende Verwendung ist nicht bekannt.
Aus der Geschichte der Mailboxnetze vor allem im Zusammenhang mit den Friedensbibliotheken im Vorfeld der Wende zeigt, dass eine aktive Kommunikation aus kleinen Gruppen große Bewegungen machen kann.
Die Kommunikation der DDR-Bürger mit dem Ausland entsprach durchaus den damals üblichen Standards: Es wurden Briefe geschrieben, telefoniert und sich getroffen. Alles natürlich im Rahmen der geltenden Möglichkeiten.

Ein Kunde hat nach einem Umbau am Außenanschluss massive Probleme mit der Stabilität der IPv6 Versorgung. Nach nächtlicher Inaktivität ist am folgenden Morgen keine IPv6 Kommunikation möglich. Beginnt man auf der ASA zu debuggen, verschwindet das Problem sofort.

Heisenbergsches Nichts

Zunächst stellt sich die Frage, was denn so spannendes in der Nacht passiert sein kann. Eigentlich nichts.

Genau das ist das Problem. Es ist nichts passiert. Genau deswegen geht es nicht mehr. Zur Überprüfung lösche ich den IPv6 Nachbarschafts-Cache und das Problem tritt sofort wieder auf. Der IPv6 Nachbarschaftseintrag für das default Gateway will und will nicht wieder kommen.

Pingt man von der ASA aus ein externes Ziel an, verschwindet das Problem instantan. Auch der IPv6 Nachbarschaftseintrag ist wieder vorhanden.

Das Problem kann also kontrolliert ein- und ausgeschaltet werden. Damit ist der Heisenbug in einen Bohrbug verwandelt und die Suche kann beginnen.

Gestörte Nachbarschaft

Zuerst aktiviere ich das Debugging für IPv6 Nachbarschaftskram.

asa# debug ipv6 nd
asa# debug ipv6 icmp
asa# clear ipv6 neighbors
ICMPv6-ND: DELETE -> INCMP: 2001:db8:700:1d::1
ICMPv6-ND: Sending NS for 2001:db8:700:1d::1 on outside
ICMPv6-ND: Sending NS for 2001:db8:700:1d::1 on outside
ICMPv6-ND: Sending NS for 2001:db8:700:1d::1 on outside
ICMPv6-ND: INCMP deleted: 2001:db8:700:1d::1
ICMPv6-ND: INCMP -> DELETE: 2001:db8:700:1d::1
ICMPv6-ND: DELETE -> INCMP: 2001:db8:700:1d::1
ICMPv6-ND: Sending NS for 2001:db8:700:1d::1 on outside
ICMPv6-ND: Sending NS for 2001:db8:700:1d::1 on outside
ICMPv6-ND: Sending NS for 2001:db8:700:1d::1 on outside
ICMPv6-ND: INCMP deleted: 2001:db8:700:1d::1
ICMPv6-ND: INCMP -> DELETE: 2001:db8:700:1d::1
ICMPv6-ND: DELETE -> INCMP: 2001:db8:700:1d::1

Das Spiel wiederholt sich endlos.

Die ASA benötigt den Nachbarschaftseintrag des Default Gatways, der gerade fehlt (DELETE), und versucht dann per Neighbour Solication (NS) wieder die MAC zur IP zu ermitteln (INCoMPlete).

Allerdings bekommt sie keine Antwort zurück.

Also jetzt mal von der ASA aus pingen:

asa# ping 2001:db8::1
ICMPv6: Sending echo request to 2001:db8::1
ICMPv6-ND: INCMP deleted: 2001:db8:700:1d::1
ICMPv6-ND: INCMP -> DELETE: 2001:db8:700:1d::1
ICMPv6-ND: DELETE -> INCMP: 2001:db8:700:1d::1
ICMPv6-ND: Sending NS for 2001:db8:700:1d::1 on outside
ICMPv6-ND: Sending NS for 2001:db8:700:1d::1 on outside
?

Es fehlt nach wie vor die Antwort vom gegenüber liegenden Router. Deswegen schreibt der Ping sein erstes "?" hin.

ICMPv6: Sending echo request to 2001:db8::1
ICMPv6-ND: Sending NS for 2001:db8:700:1d::1 on outside
ICMPv6: Received ICMPv6 packet from 2001:db8:700:1d::1, type 136

Und auf einmal ist die Antwort da!

Sofort macht sich die ASA über die Rückmeldung her:

ICMPv6-ND: Received NA for 2001:db8:700:1d::1 on outside from 2001:db8:700:1d::1
ICMPv6-ND: INCMP -> REACH: 2001:db8:700:1d::1
ICMPv6: Received ICMPv6 packet from 2001:db8::1, type 129
ICMPv6: Received echo reply from 2001:4bd8::1
!

Das Ping Echo ist zurück, es schreibt ein "!" auf die Zeile und alles geht wieder.

Wenn man jetzt mal genau hinschaut, erkennt man deutlich den Unterschied zwischen den unbeantworteten Anfragen und der erfolgreichen Anfrage.

Ganz genau hinschauen! Sieht man's?

Der kleine Unterschied

Genau, da ist kein Unterschied.

Aber es muss etwas geben, was den Effekt auslöst. Also muss man noch genauer hinschauen.

asa(conf)# access-list debug-38594 extended permit icmp6 any6 any6 neighbor-advertisement 
asa(conf)# access-list debug-38594 extended permit icmp6 any6 any6 neighbor-redirect 
asa(conf)# access-list debug-38594 extended permit icmp6 any6 any6 neighbor-solicitation 
asa(conf)# access-list debug-38594 extended permit icmp6 any6 any6 router-advertisement 
asa(conf)# access-list debug-38594 extended permit icmp6 any6 any6 router-renumbering 
asa(conf)# access-list debug-38594 extended permit icmp6 any6 any6 router-solicitation
asa# capture d-38594 access-list debug-38594 packet-length 1500 interface outside circular-buffer

Es werden alle Nachbarschafts- und Router-Nachrichten mitgeschnitten. In voller Länge, damit man auch was sehen kann.

Und nun schauen wir mal nach den fehlenden Details:

asa# show capture d-38594 detail
17: 07:36:17.423180 6412.25e3.e7fd 3333.ff00.0001 0x86dd Length: 86
 fe80::6400:0 > ff02::1:ff00:1: icmp6: neighbor sol:
 who has 2001:db8:700:1d::1(src lladdr: 64:12:25:e3:e7:fd) [class 0xe0] (len 32, hlim255)

18: 07:36:17.433342 203a.0762.b442 6412.25e3.e7fd 0x86dd Length: 86
 2001:db8:700:1d::1 > fe80::6400:0: icmp6: neighbor adv:
 tgt is 2001:db8:700:1d::1(RSO)(tgt lladdr: 20:3a:07:62:b4:42) [class 0xe0] (len 32,hlim 255)

19: 07:36:18.415887 6412.25e3.e7fd 3333.ff00.0001 0x86dd Length: 86
 fe80::6400:0 > ff02::1:ff00:1: icmp6: neighbor sol:
 who has 2001:db8:700:1d::1(src lladdr: 64:12:25:e3:e7:fd) [class 0xe0] (len 32, hlim255)

20: 07:36:18.423211 203a.0762.b442 6412.25e3.e7fd 0x86dd Length: 86
 2001:db8:700:1d::1 > fe80::6400:0: icmp6: neighbor adv:
 tgt is 2001:db8:700:1d::1(RSO)(tgt lladdr: 20:3a:07:62:b4:42) [class 0xe0] (len 32,hlim 255)

21: 07:36:19.415887 6412.25e3.e7fd 3333.ff00.0001 0x86dd Length: 86
 fe80::6400:0 > ff02::1:ff00:1: icmp6: neighbor sol:
 who has 2001:db8:700:1d::1(src lladdr: 64:12:25:e3:e7:fd) [class 0xe0] (len 32, hlim255)

22: 07:36:19.421441 203a.0762.b442 6412.25e3.e7fd 0x86dd Length: 86
 2001:db8:700:1d::1 > fe80::6400:0: icmp6: neighbor adv:
 tgt is 2001:db8:700:1d::1(RSO)(tgt lladdr: 20:3a:07:62:b4:42) [class 0xe0] (len 32,hlim 255)

23: 07:36:20.422921 6412.25e3.e7fd 3333.ff00.0001 0x86dd Length: 86
 fe80::6400:0 > ff02::1:ff00:1: icmp6: neighbor sol:
 who has 2001:db8:700:1d::1(src lladdr: 64:12:25:e3:e7:fd) [class 0xe0] (len 32, hlim255)

24: 07:36:20.428124 203a.0762.b442 6412.25e3.e7fd 0x86dd Length: 86
 2001:db8:700:1d::1 > fe80::6400:0: icmp6: neighbor adv:
 tgt is 2001:db8:700:1d::1(RSO)(tgt lladdr: 20:3a:07:62:b4:42) [class 0xe0] (len 32,hlim 255)

25: 07:36:21.415856 6412.25e3.e7fd 3333.ff00.0001 0x86dd Length: 86
 fe80::6400:0 > ff02::1:ff00:1: icmp6: neighbor sol:
 who has 2001:db8:700:1d::1(src lladdr: 64:12:25:e3:e7:fd) [class 0xe0] (len 32, hlim255)

26: 07:36:21.419350 203a.0762.b442 6412.25e3.e7fd 0x86dd Length: 86
 2001:db8:700:1d::1 > fe80::6400:0: icmp6: neighbor adv:
 tgt is 2001:db8:700:1d::1(RSO)(tgt lladdr: 20:3a:07:62:b4:42) [class 0xe0] (len 32,hlim 255) 

Die ASA (fe80::6400:0) fragt per Link-Local Multicast (ff02::1:ff00:1) nach der MAC zur IP 2001:db8:700:1d::1. Soweit war das im Debug schon zu sehen.

Überraschenderweise antwortet die Zielmaschine (2001:db8:700:1d::1) der ASA (fe80::6400:0) mit den gewünschten Daten.

Das bedeutet, dass trotz Umbaus am Uplink keine Störung dort vorliegt: Die Antworten kommen an!

Und es bedeutet weiter, dass es allein ein Problem der ASA ist, was hier abgeht.

Als nächstes wird ein Ping von der ASA aus probiert:

27: 07:36:22.396021 6412.25e3.e7fd 203a.0762.b442 0x86dd Length: 86
 fe80::6400:0 > fe80::223a:7ff:fe62:b442: icmp6: neighbor sol:
 who has fe80::223a:7ff:fe62:b442(src lladdr: 64:12:25:e3:e7:fd) [class 0xe0] (len 32,hlim 255)

28: 07:36:22.399408 203a.0762.b442 6412.25e3.e7fd 0x86dd Length: 78
 fe80::223a:7ff:fe62:b442 > fe80::6400:0: icmp6: neighbor adv:
 tgt is fe80::223a:7ff:fe62:b442(RS) [class 0xe0] (len 24, hlim 255)

29: 07:36:22.416009 6412.25e3.e7fd 3333.ff00.0001 0x86dd Length: 86
 2001:db8:700:1d::2 > ff02::1:ff00:1: icmp6: neighbor sol:
 who has 2001:db8:700:1d::1(src lladdr: 64:12:25:e3:e7:fd) [class 0xe0] (len 32, hlim255)

30: 07:36:22.425988 203a.0762.b442 6412.25e3.e7fd 0x86dd Length: 86
 2001:db8:700:1d::1 > 2001:1438:700:1d::2: icmp6: neighbor adv:
 tgt is 2001:db8:700:1d::1(RSO)(tgt lladdr: 20:3a:07:62:b4:42) [class 0xe0] (len 32,hlim 255)

Zuerst kommt ein Abgleich der Nachbarschaftsbeziehung zwischen den Link-Local-Adressen selbst. Dieser funktioniert.

Und spontan ist die folgende Antwort für die ASA akzeptabel.

Das Problem besteht darin, dass die ASA für durchgereichten Datenverkehr die ND nach dem Default-GW mit der Quell-IP fe80::xxx macht, und dann die Antwort ignoriert. Wenn Sie dagegen selbst pingt, ist die Quell-IP des ND allerdings 2001:... und dann akzeptiert sie auch die Antwort.

Und wie sieht man das in dem Ausgabewust (der hier gekürzt ist)? Mit sort | uniq -c.

Auf der Zielgeraden

Ich hab' mal mit der link-lokal Adresse als Default-Route gespielt, weil ja offenbar kein Problem besteht, die MAC einer Link-Local Adresse zu ermitteln.

Es tritt das gleiche Problem auf:

5081: 11:22:27.164588 6412.25e3.e7fd 3333.ff62.b442 0x86dd Length: 86
 fe80::6400:0 > ff02::1:ff62:b442: icmp6: neighbor sol:
 who has fe80::223a:7ff:fe62:b442(src lladdr: 64:12:25:e3:e7:fd) [class 0xe0] (len 32,hlim 255)

5082: 11:22:27.167609 203a.0762.b442 6412.25e3.e7fd 0x86dd Length: 86
 fe80::223a:7ff:fe62:b442 > fe80::6400:0: icmp6: neighbor adv:
 tgt is fe80::223a:7ff:fe62:b442(RSO)(tgt lladdr: 20:3a:07:62:b4:42) [class 0xe0] (len32, hlim 255)

5083: 11:22:28.164557 6412.25e3.e7fd 3333.ff62.b442 0x86dd Length: 86
 fe80::6400:0 > ff02::1:ff62:b442: icmp6: neighbor sol:
 who has fe80::223a:7ff:fe62:b442(src lladdr: 64:12:25:e3:e7:fd) [class 0xe0] (len 32,hlim 255)

5084: 11:22:28.165869 203a.0762.b442 6412.25e3.e7fd 0x86dd Length: 86
 fe80::223a:7ff:fe62:b442 > fe80::6400:0: icmp6: neighbor adv:
 tgt is fe80::223a:7ff:fe62:b442(RSO)(tgt lladdr: 20:3a:07:62:b4:42) [class 0xe0] (len32, hlim 255)

5085: 11:22:29.173925 6412.25e3.e7fd 3333.ff62.b442 0x86dd Length: 86
 fe80::6400:0 > ff02::1:ff62:b442: icmp6: neighbor sol:
 who has fe80::223a:7ff:fe62:b442(src lladdr: 64:12:25:e3:e7:fd) [class 0xe0] (len 32,hlim 255)

5086: 11:22:29.180914 203a.0762.b442 6412.25e3.e7fd 0x86dd Length: 86
 fe80::223a:7ff:fe62:b442 > fe80::6400:0: icmp6: neighbor adv:
 tgt is fe80::223a:7ff:fe62:b442(RSO)(tgt lladdr: 20:3a:07:62:b4:42) [class 0xe0] (len32, hlim 255)

Wie bisher: Anfrage von Link-Local wird beantwortet, aber seitens der ASA nicht verarbeitet.

5087: 11:22:30.164664 6412.25e3.e7fd 3333.ff62.b442 0x86dd Length: 86
 2001:db8:700:1d::2 > ff02::1:ff62:b442: icmp6: neighbor sol:
 who has fe80::223a:7ff:fe62:b442(src lladdr: 64:12:25:e3:e7:fd) [class 0xe0] (len 32,hlim 255)

5088: 11:22:30.172262 203a.0762.b442 6412.25e3.e7fd 0x86dd Length: 86
 fe80::223a:7ff:fe62:b442 > 2001:db8:700:1d::2: icmp6: neighbor adv:
 tgt is fe80::223a:7ff:fe62:b442(RSO)(tgt lladdr: 20:3a:07:62:b4:42) [class 0xe0](len 32, hlim 255)

Wenn die ASA aber mit ihrer offiziellen Adresse anfragt, gibt es kein Problem.

Und noch etwas fällt auf:

5089: 11:22:31.194234 203a.0762.b442 6412.25e3.e7fd 0x86dd Length: 86
 fe80::223a:7ff:fe62:b442 > fe80::6400:0: icmp6: neighbor sol:
 who has fe80::6400:0(src lladdr: 20:3a:07:62:b4:42) [class 0xe0] (len 32, hlim 255)

5090: 11:22:32.200871 203a.0762.b442 6412.25e3.e7fd 0x86dd Length: 86
 fe80::223a:7ff:fe62:b442 > fe80::6400:0: icmp6: neighbor sol:
 who has fe80::6400:0(src lladdr: 20:3a:07:62:b4:42) [class 0xe0] (len 32, hlim 255)

5091: 11:22:33.207508 203a.0762.b442 6412.25e3.e7fd 0x86dd Length: 86
 fe80::223a:7ff:fe62:b442 > fe80::6400:0: icmp6: neighbor sol:
 who has fe80::6400:0(src lladdr: 20:3a:07:62:b4:42) [class 0xe0] (len 32, hlim 255)

Umgekehrt mag sie auch nicht auf Anfragen nach ihrer eigenen Link-Local Adresse antworten. Das gilt inbesondere auch dann, wenn das Paket schon an sie selbst adressiert ist.

5092: 11:22:35.178915 203a.0762.b442 6412.25e3.e7fd 0x86dd Length: 86
 fe80::223a:7ff:fe62:b442 > 2001:db8:700:1d::2: icmp6: neighbor sol:
 who has 2001:db8:700:1d::2(src lladdr: 20:3a:07:62:b4:42) [class 0xe0] (len 32,hlim 255)

5093: 11:22:35.179464 6412.25e3.e7fd 203a.0762.b442 0x86dd Length: 78
 2001:db8:700:1d::2 > fe80::223a:7ff:fe62:b442: icmp6: neighbor adv:
 tgt is 2001:db8:700:1d::2(RS) [class 0xe0] (len 24, hlim 255)

Wohl aber antwortet sie auf die Anfrage an ihre offizielle IP nach ihrer offiziellen IP.

Es scheint so, als ob die ASA die eigene Link-Local Adresse nicht mag.

Der Fehler scheint darin zu bestehen, dass die Link-Local Adresse auf der ASA nicht geändert werden darf. Warum auch immer.

Normalerweise habe ich händisch vergebene Link-Local Adressen nach dem Schema fe80::Gerät:Interface, was die Routingtabellen schön lesbar macht.

Also habe ich die Link-Local Adresse auf "system-default" gestellt und es scheint zu gehen. Selbst nach einem Löschen der Nachbarschafts-Caches erholt sich das System binnen Sekundenfrist von allein.

5123: 14:20:32.560914 6412.25e3.e7fd 3333.ff00.0001 0x86dd Length: 86
 fe80::6612:25ff:fee3:e7fd > ff02::1:ff00:1: icmp6: neighbor sol:
 who has 2001:db8:700:1d::1(src lladdr: 64:12:25:e3:e7:fd) [class 0xe0] (len 32, hlim255)

5124: 14:20:32.569077 203a.0762.b442 6412.25e3.e7fd 0x86dd Length: 86
 2001:db8:700:1d::1 > fe80::6612:25ff:fee3:e7fd: icmp6: neighbor adv:
 tgt is 2001:db8:700:1d::1(RSO)(tgt lladdr: 20:3a:07:62:b4:42) [class 0xe0] (len 32,hlim 255) 

Ein schöner Bug, Cisco.

Die Firma Qualys bietet einen populären SSLTest an. Leider scheinen sie in letzter Zeit einen Fehlgriff getan zu haben, indem sie die CAA Tests einführten. Das Problem ist, dass CAA etwas völlig anderes tut, als die Betreiber annehmen.

Warum CAA?

CAA wurde im RFC 6844 standardisiert und vom CA Forum ab 8. September als verpflichtend vereinbart.

Es geht um folgendes (aus dem RFC)

The Certification Authority Authorization (CAA) DNS Resource Record
allows a DNS domain name holder to specify the Certification
Authorities (CAs) authorized to issue certificates for that domain.
Publication of CAA Resource Records allows a public Certification
Authority to implement additional controls to reduce the risk of
unintended certificate mis-issue.

Der Webseitenbetreiber kann also im DNS seiner Webseitenzone angeben, welche CA für den Server Zertifikate ausstellen darf.

Der RFC stellt nochmal explizit klar:

Like the TLSA record defined in DNS-Based Authentication of Named
Entities (DANE) [RFC6698], CAA records are used as a part of a
mechanism for checking PKIX certificate data.  The distinction
between the two specifications is that CAA records specify an
authorization control to be performed by a certificate issuer before
issue of a certificate and TLSA records specify a verification
control to be performed by a relying party after the certificate is
issued.

Die Zielgruppe des CAA Records ist also die CA, die bei der Zertifikatserstellung prüfen kann, ob der Betreiber sich auch an diese CA wenden wollte. Der Gedanke dabei ist, dass eine CA erkennen kann, dass sie von einem Angreifer für eine fehlerhafte Zertifikatserstellung missbraucht wird.

Die Zielgruppe von TLSA Records dagegen sind die Browser, die bei der Zertifikatsvalidierung prüfen können, ob das beim Verbindungsaufbau präsentierte Zertifikat vom echten Webseitenbetreiber stammt. Der Gedanke dabei ist, dass ein Browser erkennen kann, ob ihm ein falsches Zertifikat unter geschoben werden soll.

Wie deutlich der CAA Record auf den Betrieb einer CA ausgerichtet ist, sieht man daran, dass die Autoren von Comodo (einer CA) stammen und als Beispiel angeben, welche Nutzerkennung im Commodo-Portal für die Zertifikatserstellung benutzt werden darf (aus dem RFC):

example.com.  CAA 0 issue "ca.example.net; account=230123"

Böse formuliert kann man den CAA Record als Abwehrmechanismus von Comodo verstehen, wenn wieder mal fälschlich Zertifikate ausgestellt wurden. Die CA könnte dann darauf verweisen, dass der Webseitenbetreiber ja angeben hätte können, dass diese CA gar nicht für ihn arbeiten darf.

Woher bekommt man nun so einen CAA Eintrag, wenn man einen braucht?

  • Auf der Webseite von SSLmate kann man sich die Records erzeugen.
  • Den notwendigen Issuer-String kann man bei einer inoffiziellen Registry nachschlagen.

Interessant ist dabei, welche Issuer-Strings die CAs so anerkennen. Symantec ist es beispielsweise egal, welcher Reseller zum Zuge kommt. Es ist also nicht möglich, "thawte.com" anzugeben und so GeoTrust auszuschließen.

Ebenso interessant ist, dass der RFC vermeidet, der IANA die Pflege der Issuer-Strings aufzuerlegen. Dabei wäre das echt nützlich gewesen. Die referenzierte Registry hat lustigerweise ein "fork me on Gitlab" Banner in der Ecke.

Was SSLabs tut

Zunächst mal hat Qualsys auf die Ankündigung des CA-Forums reagiert, und prüft auf die Existenz des Eintrags. Ist der Eintrag vorhanden, gibt es Zusatzpunkte für einen A+ Status. Das hebt die Motivation natürlich.

Also schauen wir mal. Eintrag vornehmen und testen:

2017-08-23-184740_578x445_scrot

Ist das nicht cool? Das Zertifikat stammt von Symantec, und der Test befindet den CAA Eintrag für gut.

Aber kann er überhaupt einen Eintrag testen, der gar nicht für die Verwendung in einem Browser vorgesehen ist? Schließlich hat der Test ja keinen Zugriff auf die Validierungslogik der CAs.

Also testen wir auch das.

2017-08-23-185026_573x442_scrot

Wie bitte? Ein ganz offensichtlicher Widerspruch wird mit Zusatzpunkten bewertet?

Wenn man versteht, dass CAA ausschließlich für die  CAs da ist, ist das keine Überraschung. Vielleicht soll ja auch das nächste Zertifikat von einer anderen CA ausgestellt werden? Der Betreiber der Webseite benutzt halt nur noch das noch gültige alte Zertifikat weiter. Gründe kann es vieles geben.

Im Kern fällt es auf die Aussage zurück, dass der Zeitpunkt der Auswertung des CAA Records bei der Zertifkatserstellung wichtig ist. Dieser Zeitpunkt unterscheidet sich erheblich von dem der Zertifikatsvalidierung!

Noch viel witziger sind die Ausschlusskriterien für die Verwendung von CAA:

  • Wenn der CAA Test schon zweimal in der Vergangenheit erfolgreich war und das im Certifcate Transparency Log steht.
    Ich darf also die CA nicht wechseln?
  • Wenn die ausstellende Sub-CA dies in ihren Verträgen ausschließt.
    Diese Sub-CAs waren bisher schon immer eine Quelle von Fehlern.
  • Wenn die CA auch Betreiber des DNS ist.
    Die Großen schauen also weg.
  • Wenn die DNS Abfrage fehlschlägt aus Gründen, die nicht die CA zu verantworten hat, die Anfrage aber wenigsten einmal versucht wurde und die Zone nicht komplett bis zur Wurzel DNSSEC validierbar ist.
    Also immer.

Ehrlich gesagt ist das ein Frechheit.

Und nun?

Wer auch immer einen Draht zu Qualys SSLabs hat, er möge den Leuten dort auf die Füße treten:

  • Entfernt die CAA Prüfung!
  • Prüft TLSA!

So, Leute: Es wird ernst. Die Root-Zone ist schon eine ganze Weile signiert und man soll auch dort mal die Schlüssel wechseln. Das ist nicht einfach, weil alle Betreiber rekursiver Resolver daran mitwirken müssen.

Es gibt drei Typen von Betroffenen:

  • Der Resolver macht kein DNSSEC, dann vergesst es.
  • Der Resolver validiert DNSSEC und es interessiert Euch nicht, dann plant einen Paniktag ein.
  • Der Resolver validiert DNSSEC und ihr wollt Panik vermeiden, dann lest und testet.

Worum geht's?

Fragt man die Root-Nameserver nach ihrem Schlüsselmaterial so gibt es folgende Antwort:

;; QUESTION SECTION:
;.                      IN DNSKEY

;; ANSWER SECTION:
.                       DNSKEY  257 3 8 (
                                AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTO
                                ...
                                9555KrUB5qihylGa8subX2Nn6UwNR1AkUTV74bU=
                                ) ; key id = 20326
.                       DNSKEY  257 3 8 (
                                AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQ
                                ...
                                LmqrAmRLKBP1dfwhYB4N7knNnulqQxA+Uk1ihz0=
                                ) ; key id = 19036
.                       DNSKEY  256 3 8 (
                                AwEAAYvxrQOOujKdZz+37P+oL4l7e35/0diH/mZITGjl
                                ...
                                jpi+V7pgh0o1KYXZgDUbiA1s9oLAL1KLSdmoIYM=
                                ) ; key id = 15768
.                       RRSIG   DNSKEY 8 0 172800 20170831000000 (
                                20170810000000 19036 .
                                D2D0oJblRe/C86Eti+vOLIHll7hvI9mN/O6S9gZqKvN2
                                ...
                                fkMFPGKWv4Gi1BlE+r+a9FDFz4ypjwdbvA== )

Die Root-Zone hat also aktuell drei Schlüssel:

  • Einen Arbeitsschlüssel (key id = 15768) und
  • zwei  Hauptschlüssel von denen Ihr bisher den mit der ID 19036 auf der Platte habt.
  • Der Schlüssel mit der ID 20326 ist neu.

Zum 11. Oktober 2017 wird die Root-Zone mit dem neuen Schlüssel unterschrieben. Dann müsst Ihr den neuen Key auf der Platte haben, sonst fällt bei Euch DNS komplett aus.

Ich habe das selbst schon mal hinbekommen, als am 26.12. mir die Signaturen der Nameserver-Records meiner Test-Root ausliefen. Ein Remote-Zugriff klappte nicht mehr, weil die SSH die IPs nicht nachschlagen konnte, die einzelnen Geräte in Panik die Dienste neu starteten und diese schon beim Start keine Gegenstelle mehr erreichen konnten (IPs nachschlagen ging nicht mehr) und sich instantan wieder beendeten.

Manuell konnte ich an der Konsole des rekursiven Nameserver den Fehler beheben. Nach einer frostigen Fahrradtour in die Firma. Ich habe geschwitzt!

Was ist zu tun?

Eure Software sollte also erkennen, dass es einen neuen Schlüssel gibt und den auf die Platte legen.

Nehmen wir an, es sei unbound. Dann findet ihr eine Datei /etc/unbound/root.key (o.ä.)

; autotrust trust anchor file
;;id: . 1
;;last_queried: 1502962961 ;;Thu Aug 17 11:42:41 2017
;;last_success: 1502962961 ;;Thu Aug 17 11:42:41 2017
;;next_probe_time: 1503005390 ;;Thu Aug 17 23:29:50 2017
;;query_failed: 0
;;query_interval: 43200
;;retry_time: 8640
.       172800  IN      DNSKEY  257 3 8 AwEAAaz/t...V74bU= ;{id = 20326 (ksk), size = 2048b}
   ;;state=2 [  VALID  ] ;;count=0 ;;lastchange=1502399011 ;;Thu Aug 10 23:03:31 2017
.       3696    IN      DNSKEY  257 3 8 AwEAAagA...ihz0= ;{id = 19036 (ksk), size = 2048b}
   ;;state=2 [  VALID  ] ;;count=0 ;;lastchange=1291045951 ;;Mon Nov 29 16:52:31 2010

Diese Datei enthält bereits beide Schlüssel und alles ist gut(TM).

Hat man dagegen unbound irgendwann mal aufgesetzt und nie richtig eingerichtet, so schaut die Datei so aus:

;;id: . 1
;;last_queried: 1414101618 ;;Fri Oct 24 00:00:18 2014
;;last_success: 1414101618 ;;Fri Oct 24 00:00:18 2014
;;next_probe_time: 1414143412 ;;Fri Oct 24 11:36:52 2014
;;query_failed: 0
;;query_interval: 43200
;;retry_time: 8640
.       86390   IN      DNSKEY  257 3 8 AwEAA...k1ihz0= ;{id = 19036 (ksk), size = 2048b}
   ;;state=2 [  VALID  ] ;;count=0 ;;lastchange=1291283901 ;;Thu Dec  2 10:58:21 2010sdf 

Wie fixed man das?

Zuerst einmal sollte unbound wissen, dass er die Datei selbst aktualisieren soll:

$ fgrep root.key /etc/unbound/unbound.conf
 auto-trust-anchor-file: "/etc/unbound/root.key"

Klar soweit?

Wenn auch das nicht hilft, kann es sein, dass die Datei nicht die notwendigen Rechte hat.

-rw-r--r-- 1 root root 758 Okt 24  2014 /etc/unbound/root.key
-rw-r--r-- 1 unbound unbound 1250 2017-08-17 11:42 /etc/unbound/root.key 

Das ist doch wohl deutlich, oder? Und natürlich leicht zu fixen.

Und andere Resolver-Software? Im Kern geht es um RFC 5011 Unterstützung. Die findet man bei Bind und anderer Software.

Achja, bitte schaut doch mal nach den Kundensystemen, von denen ihr wisst oder ahnt.

In letzter Zeit kommt es immer wieder vor, dass die Warteschlange der ausgehenden E-Mails gewaltig anwächst. Es handelt sich dabei oft im Spam-Mails mit gefälschtem Absender und aktivierter Empfangsbestätigung. Ein paar trickreiche Sendmail-Kommandos räumen auf.

In der Warteschlangen stehen hunderte von E-Mails, hier exemplarisch zwei herausgenommen:

~# mailq
v7DB2pot018012     2519 Sun Aug 13 13:02 MAILER-DAEMON
                 (Deferred: Connection refused by habacland.com.)
                                         <hulda1tdnap3@habacland.com>
v7DKLjhL019655     2125 Sun Aug 13 22:21 MAILER-DAEMON
                 (Deferred: Connection refused by habacland.com.)
                                         <marien4j06sq@habacland.com>

Zum einen liegen diese E-Mails schon lange in der Warteschlange (es ist ja Donnerstag, der 17. August). Dies lässt die Warteschlange anwachsen.

Zum anderen wird ein vermutlich unschuldiger Server mit Backscatter attackiert. Auch das ist nicht gut.

Also erst einmal dem Kram wegräumen und manuell begutachten:

~# sendmail -Q"strange backscatter" -qR@habacland.com

Alle E-Mails, die an diese Empfängerdomain gehen, werden mit der Meldung "strange backscatter" in Quarantäne geschoben.

Dies bewirkt zweierlei:

  • Erstens versucht der Mailserver nicht mehr die E-Mails zuzustellen.
  • Und zweitens sind die E-Mails nun leicht erkennbar (die Spooldateien beginnen mit einem 'h').

Da die E-Mails nicht mehr in der normalen Warteschlange auftauchen, muss man ein anderes Kommando zur Anzeige bemühen:

# mailq -qQ
v7DKLjhL019655     2125 Sun Aug 13 22:21 MAILER-DAEMON
     QUARANTINE: strange backscatter
                 (Deferred: Connection refused by habacland.com.)
                                         <marien4j06sq@habacland.com>
v7DB2pot018012     2519 Sun Aug 13 13:02 MAILER-DAEMON
     QUARANTINE: strange backscatter
                 (Deferred: Connection refused by habacland.com.)
                                         <hulda1tdnap3@habacland.com>

Es ist schön zu sehen, dass der Quarantänegrund extra genannt wird. Man kann also mehrere Arten von Quarantäne gleichzeitig betreiben und trotzdem voneinander trennen.

Nachdem ich mich davon überzeugt habe, dass all diese E-Mails die gleiche Art Backscatter sind ...

H??Content-Type: multipart/report; report-type=delivery-status;
        boundary="v7..."

... wird die Zustellung dieser E-Mails abgebrochen.

# mailq -qQ |
  sed -n '/^v/s/[    ].*//p' |
  while read a; do
    sendmail -Q -qQ -qI$a
    sendmail -qI$a -O Timeout.queuereturn=now
  done

Dazu wird pro interner Mailkennung (mit sed extrahiert) der Quarantäne-Mails (mit mailq -qQ selektiert)

  • die Mail aus der Quarantäne genommen (mit sendmail -Q) und
  • die individuelle Queue-Verteilzeit auf 0 gesetzt.

Es wäre natürlich auch möglich gewesen, die E-Mails einfach zu löschen. Aber das ist Ansichtssache.

Bleibt die Frage. woher man so etwas lernen kann: Im Sendmail-Contrib-Verzeichnis gibt es ein Tool qtool.pl, dass all diese Dinge kann und leicht zu lesen ist.

Heute lag eine seltsame Abuse-Mail im Posteingang: Ein Kunde habe einen Angriff vorgenommen und sei deswegen von fail2ban geblockt worden. Als Beleg wurden gesperrte HTTP-Zugriffe auf den Webserver angegeben. Das Verhalten ist reproduzierbar.

Dear Sir/Madam,

We have detected abuse from the IP address ( 217.17.197.14 ), which according to a whois lookup is on your network. We would appreciate if you would investigate and take action as appropriate. Any feedback is welcome but not mandatory.

Log lines are given below, but please ask if you require any further information.

(If you are not the correct person to contact about this please accept our apologies - your e-mail address was extracted from the whois record by an automated process. This mail was generated by Fail2Ban.)

IP of the attacker:  217.17.197.14 

You can contact us by using: abuse-reply@<protect-the-hoster>.de

Addresses to send to:
abuse@iks-jena.de

==================== Excerpt from log for 217.17.197.14 ====================
Note: Local timezone is +0200 (CEST)
/home/users/hwburgk/logs/error.log:[Mon Aug 07 10:32:18.498758 2017] [evasive20:error] [pid 11057:tid 139621224589056] [client 217.17.197.14:60994] client denied by server configuration: /home/users/hwburgk/www/j15/templates/rt_terrantribune_j15/images/bottom-menu-bg.png, referer: http://www.<protect-the-customer>.de/templates/rt_terrantribune_j15/css/template_css.css
/home/users/hwburgk/logs/error.log:[Mon Aug 07 10:32:18.499515 2017] [evasive20:error] [pid 11057:tid 139621300123392] [client 217.17.197.14:60988] client denied by server configuration: /home/users/hwburgk/www/j15/templates/rt_terrantribune_j15/images/footer-bl.png, referer: http://<protect-the-customer>/templates/rt_terrantribune_j15/css/template_css.css
/home/users/hwburgk/logs/error.log:[Mon Aug 07 10:32:18.499542 2017] [evasive20:error] [pid 11057:tid 139621241374464] [client 217.17.197.14:60986] client denied by server configuration: /home/users/hwburgk/www/j15/templates/rt_terrantribune_j15/images/footer-bg.png, referer: http://<protect-the-customer>/templates/rt_terrantribune_j15/css/template_css.css
/home/users/hwburgk/logs/error.log:[Mon Aug 07 10:32:18.500119 2017] [evasive20:error] [pid 11057:tid 139621266552576] [client 217.17.197.14:60990] client denied by server configuration: /home/users/hwburgk/www/j15/templates/rt_terrantribune_j15/images/footer-br.png, referer: http://<protect-the-customer>/templates/rt_terrantribune_j15/css/template_css.css
/home/users/hwburgk/logs/error.log:[Mon Aug 07 10:32:25.007673 2017] [evasive20:error] [pid 11057:tid 139621350479616] [client 217.17.197.14:60998] client denied by server configuration: /home/users/hwburgk/www/j15/
/home/users/hwburgk/logs/error.log:[Mon Aug 07 10:32:25.220530 2017] [evasive20:error] [pid 11057:tid 139621350479616] [client 217.17.197.14:60998] client denied by server configuration: /home/users/hwburgk/www/j15/favicon.ico
/home/users/hwburgk/logs/error.log:[Mon Aug 07 10:32:25.260728 2017] [evasive20:error] [pid 11057:tid 139621350479616] [client 217.17.197.14:60998] client denied by server configuration: /home/users/hwburgk/www/j15/favicon.ico

Zunächst ist auffällig, dass als Begründung für die Sperre die letzten Einträge des Logfiles verwendet werden. Dies ist eine gute Idee, denn so weiß der betroffene Abuse-Bearbeiter, was vorgefallen ist.

Allerdings werden die Logs erst nach der Installation der Sperre bei der Erzeugung der Beschwerde-Mail ausgelesen. Sie enthalten also nur noch die Einträge, die aufgrund der Sperre geblockt wurden. Eine Ursachenermittlung ist so nicht möglich.

Beim schnellen Test am Arbeitsplatz wird die Webseite angezeigt. Soweit so gut.

Drückt man aber F5-neu laden einige Male, so erscheint nur noch das folgende Bild:

2017-08-07-121848_881x287_scrot

Tests von verschiedenen anderen Systemen aus zeigten immer das gleiche Verhalten. Sobald man die CSS-Dateien schnell neu läd, erfolgt die Sperre. Es genügt offenbar auch, die /favicon.ico mehrfach schnell neu zu laden. Diese Datei existiert nicht und liefert einen 404.

Bei jedem dieser Versuche geht eine E-Mail an den Abuse-Kontakt des Internet-Providers, den man nutzt. Also Vorsicht!

Zur Klärung des Problems habe ich den Hoster angerufen und mit der Hotline gesprochen. Nach einigen Erklärungen hatte man das Problem verstanden (und vermutlich den Hotline-Rechner gesperrt). Eine Verbindung in die Abuse-Abteilung war aber nicht möglich, da "Die Kollegen Tag und Nacht im Einsatz sind, so dass sie heute erst nach 15 Uhr wieder rein kommen."

Andrew McConachie hat bei ICANN59 einen sehr interessanten Vorschlag eingebracht. Er belauscht den HTTPS Verbindungsaufbau und blockt den Datenverkehr, wenn die übermittelten Schlüssel nicht zu den vorhandenen TLSA Records aus DNSSEC passen. Auf diese Weise schützt er an zentraler Stelle seine Clients.

Vorgehensweise

Im RFC 6698 wird definiert, wie man mittels DNS Einträgen festlegt, welche Zertifikate für die Webserver benutzt werden dürfen. Das Verfahren heißt kurz DANE (DNS-Based Authentication of Named Entities). Mittels DNSSEC lässt es sich gegen Fälschungen schützen.

Die Middleware, z.B. eine Firewall, sieht normalerweise vom verschlüsselten Verkehr gar nichts. Jedoch muss zum Verbindungsaufbau mit einer prinzipiell unbekannten Gegenstelle zuerst Klartext gesprochen werden, bis man sich auf eine Verschlüsselung einigen konnte.

Durch die IPv4-Adressknappheit hat nicht jede Webseite ihre eigene IP-Adresse, sondern der Webserver muss vorab erfahren, welche Webseite der Client abrufen will, damit er das passende Zertifikat für diese Seite präsentieren kann. Dieses Verfahren heißt SNI (Server Name Indication) und ist im RFC 6066 definiert.

Genau an dieser Stelle greift Andrew ein:

  • Er schneidet bei der Client-Anfrage den angeforderten Servernamen mit und extrahiert das vom Webserver gelieferte Zertifikat aus dessen Antwort beim Verbindungsaufbau.
  • Anschließend prüft er mittels DANE und DNSSEC, ob für diesen Servernamen ein TLSA Record existiert und prüft das Zertifikat gegen diesen Record.
  • Fehlt der TLSA Record oder passt er, passiert nichts weiter.
  • Widerspricht allerdings das Zertifikat dem TLSA Record, so fügt er eine Access-Regel ein, die den Datenfluss für diese Verbindung unterbindet.

Im Endergebnis wird bei einem fehlerhaften Zertifikat (nicht zum TLSA passend), der Client daran gehindert, mit einer wahrscheinlich bösartigen Gegenstelle zu reden.

Praktische Umsetzung

Andrew hat auch gleich noch Code für dieses Konzept geschrieben.

Die Software heißt "danish" und kommt trotzdem mit englischer Dokumentation. Sie läuft auf einem OpenWRT oder LEDE-Router. Wer mag kann damit spielen

Von meiner Seite: Beifall! Großartige Sache, Andrew!