… und das ist ziemlich dumm. Oder doch nicht? Mal wieder Freitag, ein DynDNS2-Protokoll kompatibler Update Client behauptet, er kann die Antwort vom Server nicht verstehen. Es ist also eine gute Zeit, um sich das mal näher anzusehen.

Ok, DynDNS usw. ist genau genommen egal: Letztendlich ist das eine API die via http bzw. https auf irgendeinen Webserver bzw. Webservice zugreift. Die Daten zur Anfrage werden klassischerweise als GET oder POST übermittelt, die Antwort kommt als irgendein ASCII-Text zurück. Reiner Text, XML, JSON – so irgendwas. Unterm Strich: Das ist eine Anfrage an eine Web-API. Reicht für den Moment, kann also auch weit jenseits von DNS-Servern und wechselnden IP-Adressen passieren.

So, und was passiert denn hier jetzt? Der Client behauptet er versteht die Antwort vom Webserver nicht. Per tcpdump oder wireshark einen trace erstellt erhält man den unten gezeigten Screenshot. Das funktioniert übrigends super da DynDNS2 tatsächlich noch http verwendet. Auch wenn viele Implementationen inzwischen https ebenso können – aber halt nun mal nicht alle. Und das ursprüngliche Protokoll war auf „http“ festgelegt.

ddclient wireshark
Im Screenshot ist ein Testanfrage. Mit „nohost“ als Antwort ist die zwar in einen Fehler gelaufen, macht aber nichts. Deutlich sichtbar ist eine 6 in der Zeile davor, genauso wie eine 0 in der Zeile danach. Der DynDNS-Client erwartet aber direkt „nohost“ und keine Zahl. Also ja, nachvollziehbar.

Wobei, das ganze mal in einem normalen Webbrowser geöffnet und mit F12 in die Entwicklertools gewechselt ergibt Folgendes:

Webdevel DynDNS

Ok, das ist jetzt kein „nohost“ Fehler sondern eine „nochg“ Statusmeldung. Aber egal, der gleiche Server nur ein anderer Client der angefragt hat: Beim Webbrowser fehlen die Zahlen. Richtig spannend: Ein tcpdump von dieser Anfrage: Die Zahlen sind da. Zusammengefasst: Der Webbrowser kommt mit diesen Zahlen zurecht, er schneidet sie heraus bzw. hat sie, wie auch immer, verarbeitet. Der Automat welcher die API kontaktiert hingegen nicht. Seltsam. Oder doch nicht?

Nein, eigentlich nicht. Das ist ein normales Verhalten bei http. Doch der Reihe nach. Da steht als Webserver Apache und dies stimmt auch. Hier passiert folgendes: Wenn man das mod_deflate aktiviert kann der Webserver Inhalte vorm Übertragen komprimieren. Das spart Übertragungsbandbreite, geht allerdings auf CPU-Kosten. Da die letzten Jahre verhältnismäßig gesehen die CPUs immer leistungsfähiger geworden sind gegenüber der verfügbaren Internetbandbreite: Eine leichte Rechnung. Nächster Einschub: Ein Webserver übermittelt im Kopf die Größe der Daten welche er übermittelt. Bei statischen Daten wie zum Beispiel einer ISO-Datei: Einfach im Dateisystem nachgeschaut wie groß die Datei ist und gut. Der Webbrowser dankt es, in dem er beim Download anzeigt, wie viel er bereits übertragen hat. In Relation zur Zeit ergibt das die Downloadgeschwindigkeit, in Relation zu der Datengröße den bereits erreichten Fortschritt in Prozent. Daraus ableiten kann man nun noch die geschätzte Zeit bis zur Fertigstellung des Downloads.

Wie ist das aber bei Inhalten, die dynamisch zur Laufzeit erstellt werden? Da weiß man doch gar nicht, wie groß die letztendlich sind. Den Fall kennt sicherlich auch jeder: Der Browser weiß, wie viel er bereits heruntergeladen hat, nur weiß er nicht wie viel noch kommt und somit auch nicht wie lange dies wohl dauern wird. Wozu die ganze Erklärung? Da der Webserver nicht weiß wie groß die Daten werden hat er als Transfer-Encoding „chunked“ gewählt. Also sehr frei übersetzt „gestückelt“. Als Trenner in Einzelteile nimmt ein Webserver ein ganz einfaches Maß: Er überträgt Textdaten, also betrachtet er das zeilenweise. Die Zeile „nohost“ aus dem Screenshot oben ist nun mal 6 Zeichen lang. Danach folgt noch eine leere Zeile und die ist, oh Wunder, 0 Zeichen lang. Der Webbrowser versteht natürlich chunked encoding und bereitet die Daten bevor er sie anzeigt richtig auf. Ein tcpdump hingegen zeigt die blanken Daten wie sie soeben eben übertragen wurden. Für beide Ansichten gilt somit: Richtig, aus dem jeweiligen Betrachtungswinkel heraus.

Und wie löst man das Ganze? mod_deflate im Apache abschalten? Nein, will man nicht unbedingt. Gibt viele Gründe warum man den behalten sollte. Es gibt allerdings noch einen anderen Weg: chunked encoding kam mit http/1.1, bei http/1.0 gab es das noch nicht. Also folgenden Eintrag in die Apache-Konfig für die API-Datei: „SetEnv downgrade-1.0“. Die Direktive macht genau das was sie einem suggeriert: Egal mit welcher Variante vom http-Protokoll die Anfrage rein kommt: tue intern so, als wäre es eine http/1.0 Anfrage. Und da es hier noch kein chunked encoding gab ist der Spuk vorbei. Der client, in diesem Falle ddclient, kann wieder fehlerfrei mit seiner API.

Zusammenfassend betrachtet: Ein Einzelfall? Sicherlich nicht. Warum sonst sollte der apache Webserver die Möglichkeit besitzen intern einen Downgrade des anfragenden Protokolls vorzunehmen. Ich kenne in der Tat noch einige weitere Fälle in dem man dieses Vorgehen verwendet. Somit alles gut, der Freitag ist gerettet, das Problem ist gelöst.

Moment, stopp. Wirklich? Mal ernsthaft bitte! Schau nochmals in den Screenshot vom tcpdump rein. Wenn, wie in diesem Falle, der Client nicht mit den Varianten von möglichen http/1.1-Antworten klar kommt und stattdessen http/1.0 benötigt: Warum gibt er dann wie in der ersten Zeile sichtbar als verwendetes Protokoll http/1.1 an? Mit einem http/1.0 hätte es dieses Problem doch nie gegeben. Chunked encoding gibt es erst seit http/1.1. Es ist leider nun mal so, dass das Problem des Clients auf dem Server einfacher zu beheben ist wie an dem Ort wo es tatsächlich passiert: Im Server war es eine einzelne Zeile in der Konfig. Beim Client müsste man auf keine Ahnung wie vielen Installationen entsprechend nachbessern. Daraus resultierend ist die weit verbreite Meinung, dass der Server schuld sein muss, wenn er mit dem Client nicht richtig kommunizieren kann. Das mag ab und zu sicherlich richtig sein, aber nun mal eben nicht immer. Also behebt man als Admin mal wieder die Fehler der Anderen, obwohl man selbst bis dahin alles komplett richtig gemacht hätte. Ein Einzelfall? Sicherlich nicht …