Neulich stand ich vor einem Rätsel: Eine erst kürzlich auf dem eigenen Server installierte Web-Anwendung wollte nicht so recht mit dem Reverse Proxy harmonieren. Die Anwendung leitete nicht nur HTTP-Aufrufe, sondern auch solche die bereits mittels HTTPS angefordert wurden, auf HTTPS um. Der Browser quittierte dies unverzüglich mit der Fehlermeldung „too many redirects“ (zu viele Weiterleitungen) um einer Endlosschleife vorzubeugen.
Infrastruktur
Unsere Infrastruktur in der beschriebenen Server-Umgebung bestand zu diesem Zeitpunkt aus der folgenden Konfiguration: Als Web/Applikations-Server kam Apache mit PHP zum Einsatz, für SSL und Load-Balancing verwendeten wir HAProxy als Reverse Proxy.
Der besagten Web-Anwendung, in diesem Falle Active Collab, wurde mittels const ROOT_URL = 'https://www.example.com/';
mitgeteilt, über welchen Hostname und Protokoll sie zu erreichen ist. Weitere Einstellungen waren nicht notwendig, da sich der Router der verwendeten MVC-Architektur selbständig um die Weiterleitung von HTTP auf HTTPS kümmerte.
Analyse
„So weit, so gut“ würde man denken, doch genau an dieser Stelle entsteht das zuvor beschriebene Problem der Endlosschleife: Überlässt man der Web-Anwendung die automatische Erkennung des Protokolls, wird diese in Kombination mit SSL über einen Reverse Proxy immer versuchen auf HTTPS weiterleiten.
Im Detail geschieht folgendes: Apache teilt der Anwendung mittels Umgebungsvariable mit, die Webseite würde aktuell nicht via HTTPS ausgeliefert. Folglich führt die Anwendung eine Weiterleitung auf HTTPS durch. Dies geschieht völlig unabhängig davon, ob in der Adresszeile des Browsers bereits https:// vorangestellt ist, denn Apache weiß ja nicht, dass der Reverse Proxy die Seite entsprechend ausliefert. Daher wird die Weiterleitung quasi immer ausgelöst.
Lösung
Die Lösung des Problems bestand darin, Apache mitzuteilen, dass die Seite mittels HTTPS ausgeliefert wird, sofern der vorangestellte Reverse Proxy dies unterstützt. Dazu muss, sofern noch nicht geschehen, zunächst das Modul mod_sentenvif
mittels a2enmod setenvif
geladen und Apache mittels apache2ctl restart
neugestartet werden.
Danach wird die folgende Anweisung entweder im VirtualHost oder in der .htaccess hinterlegt, bei der die Umgebungsvariable HTTPS
gesetzt wird, sollte der Request Header X-Forwarded-Proto
den Wert https enthalten.
<IfModule mod_setenvif.c> |
SetEnvIf X-Forwarded-Proto "https" HTTPS=on |
</IfModule> |
Fazit
Für Entwickler: Wenn ihr eine eigene Web-Anwendung entwickelt, empfiehlt es sich, die Weiterleitung auf HTTPS nicht selbst in die Hand zu nehmen, sondern dies dem Webserver zu überlassen. Spricht aus Gründen der Benutzerfreundlichkeit oder Portabilität etwas dagegen, so stellt zumindest einen entsprechenden Hinweis bereit, der auf dieses Verhalten aufmerksam macht.
Für Administratoren: Konfiguriert den Web-Server, in Kombination mit einem Reverse Proxy der sich um SSL kümmert, stets so das Apache auch weiß, dass HTTPS verfügbar ist – auch wenn die Anwendung dies eventuell gar nicht benötigt.