Collage of Deutsche Bahn captive page and a browser notification that there is no internet.

Was ist eine Captive Page und wie kann ich selbst eine bauen?

Mein Problem: die erwartete Meldung „im Netzwerk anmelden“ erscheint nicht immer automatisch, wenn ich ein öffentliches WLAN benutzen will, das erst nach Login bzw. Akzeptieren der AGB benutzt werden kann, wie das „WiFi on ICE“ in der Deutschen Bahn. Das macht die Arbeit unterwegs auf Reisen oder im Café nicht einfacher.

Die entsprechende Diskussion auf AskUbuntu.com (Cannot reach public WIFI login page in Ubuntu, Captive Portal Issue) hat schon 23000 Views! Wie konnten sich eigentlich so viele Leute diesen Beitrag ansehen, wenn sie doch gar kein Internet haben? 🤔

Screenshot of quoted post on askubuntu.com

Was passiert hier?

Viele Betriebssysteme wie Android, ChromiumOS, Apple MacOS oder Microsoft Windows haben anscheinend eine eingebaute Unterstützung für diese Art von Anmeldung und zeigen eine „Captive Page“ an, beispielsweise captive.apple.com.

Nicht so Ubuntu Linux. Das ist einer der wenigen Nachteile dieses Betriebssystems, das ich ansonsten sehr schätze. Aus technischer Sicht könnten wir allerdings auch sagen, dass die Captive-Portale die Internetverbindung ihrer Nutzer*innen kidnappen, und das funktioniert eben besser auf Windows und Apple-Geräten als auf Linux, wo im Zweifel die Sicherheit Vorrang vor der Bequemlichkeit hat.

Ich wollte verstehen, was konkret passiert und musste feststellen, dass es gar nicht so einfach ist, wie es auf den ersten Blick erscheinen mag. Weiterführende technische Details sind bei Wikipedia und in der Dokumentation von Chromium nachzulesen.

Ein Captive-Portal versucht wohl üblicherweise, den ersten Seitenaufruf im neuen Netzwerk mithilfe des DNS-Servers umzuleiten, und wenn das nicht klappt, bietet der Netzwerk-Manager des Betriebssystems die Anmeldung an, außer wie gesagt bei Linux.

Es gibt kein Internet

Screenshot of Deutsche Bahn WiFi on ICE internet portal page and an error message that there is no internet

Wenn all das nicht funktioniert, dann sehen wir eine retro-mäßig minimalistisch gestaltete Seite, die behauptet, es gäbe kein Internet. Wer, wie ich, die meiste Zeit seines Lebens in Deutschland verbracht hat, wird diese Meldung vermutlich auch schon des öfteren gesehen haben. Abgesehen vom materiellen Wohlstand unseres Landes ist Deutschland in vieler anderer Hinsicht sehr arm dran. Arm in emotionaler Hinsicht, und ganz sicher auch ziemlich arm in technologischer Hinsicht. Deutschland ist berüchtigt für langsame und ungeschickte Einführung neuer Technologien und für die relativ langsame und unzuverlässige Internetanbindung.

Captive Pages und ihre Herausforderungen verstehen

Wikipedia nennt verschiedene Arten von Problemen, an denen der automatische Anmeldeprozess scheitern kann. Wenn der erste Internetzugriff kein neuer Seitenaufruf einer HTTP-URL ist, sondern vom E-Mail-Client, per AJAX aus einer zuvor geladenen Website, oder einfach nur, wie heutzutage nicht unüblich, direkt per HTTPS stattfindet, ist das Verfahren zum Scheitern verurteilt, und es erscheint, wie im obigen Screenshot, die irreführende Fehlermeldung, dass das Internet gerade nicht verfügbar sei – außer das Betriebssystem hat heimlich, und den Datenschutz missachtend, einen Aufruf an seinen eigenen Server gestellt um zu tracken, ob wir uns gerade in ein anmeldepflichtiges Netzwerk eingewählt haben.

Aber was Apple, Google und Microsoft kann, können echte Hacker schon lange:

Wir bauen unsere eigene Captive Page

Wäre es nicht cool, eine eigene captive.localhost or am besten gleich eine öffentlich verfügbare Seite wie https://captive.open-mind-culture.org/ zu haben, die wir einfach selbst bei Bedarf aufrufen können?

Screenshot of Open Mind Culture captive page with network headers shown in the browser's developer tools

Zwar veranstalten die eigentliche Captive-Mechanismen mehr oder weniger komplizierte Dinge wie Zugriffskontrolle und Abfangen des Netzwerkverkehrs, aber alles was uns noch fehlt, ist ja nur eine Webseite, die diesen bestehende Mechanismus auslöst.

Also bedeutet „eine eigene Captive-Page bauen“ letztlich bloß eine Seite zu veröffentlichen, die eine unverschlüsselte HTTP-Verbindung akzeptiert und mit Status-Code 204 oder 200 beantwortet anstelle auf HTTPS weiterzuleiten.

Mit PHP eine einfache Webseite und HTTP-Header ausgeben

Eine Möglichkeit, eine Webseite auszugeben und die gesendeten HTTP-Header zu kontrollieren, ist das ganze in PHP zu schreiben. Das ist auch in vielen Fällen immer noch die einfachste Möglichkeit, nämlich dann, wenn ohnehin schon ein Server mit einer PHP-basierten Anwednung, wie beispielsweise WordPress, vorhanden ist. Ansonsten lässt sich alternativ genau so gut ein Node Server in die Cloud deployen oder ein „serverloser“ Servicde konfigurieren.

Aber nehmen wir mal einen PHP-Server an, dann können wir ein neues Verzeichnis erstellen und eine neue Subdomain konfigurieren, die auf das neue Verzeichnis zeigt, wo wir dann eine Datei namens index.php speichern, die sich um die nötigen Response-Header kümmern wird. Damit können wir dann gleich auch verhindern, dass Browser oder Proxy Server die Seite ungewollt im Cache speichern.

Erfolgsmeldung mithilfe irgendeines 2xx HTTP Status

Wie wir unter anderem an Apple’s Implementation sehen können, müssen wir gar keinen 204 No Content Status senden. Viele Portale, beispielsweise das ICEportal in deutschen Langstreckenzügen, nutzen ihre Captive Page nicht nur, um die Zustimmung zu ihren AGB bestätigen zu lassen, sondern auch zur Werbung für ihre Dienste und Unterhaltungsmedien sowie für die hilfreiche Anzeige der Zugnummer und des nächsten Bahnhofs. Aber wir sollten uns hier nicht unnötig lange mit eigenem Content aufhalten, wenn unsere Seite ja dafür gedacht ist, ein Hijacking durch das eigentliche Captive-Portal des Netzwerkbetreibers auszulösen, dessen Seite unsere ersetzen soll.

<?php

    if (!headers_sent()) {
        header('Status: 200 OK');
        header('Cache-Control: no-cache');
        header('Content-Type: text/html');
    }
?><!DOCTYPE html>
<html lang="en">
<head>
<title>Success</title>
</head>
<body>
More content here...

Nice! Nun wollen wir beweisen, dass sie tatsächlich funktioniert und ihre Aufgabe erfüllt, richtig? Hier ist sie: http://captive.open-mind-culture.org

Alles läuft wie geplant: kein Fehler, kein Redirect, kein https, aber ein HTTP-Header um Caching zu verhindern.

Jetzt müssen wir das ganze nur noch „in freier Wildbahn“ testen, unterwegs mit dem Laptop in einem der Netze, die in der Vergangenheit für ihre Probleme mit Linux-Clients bekannt waren, wie WiFiOnICE oder WiFi@DB.

Englischsprachiger Blogpost: www.open-mind-culture.org/en/2159/there-is-no-internet-creating-a-captive-page-to-sign-into-any-public-network/