Ausgangslage
Im Intranet einer Bildungseinrichtung wird auf dem Web-Server
srv.org.local
die Lernplattform Moodle betrieben.
Interne Web-Browser erreichen Moodle unter der URL
http://srv.org.local/moodle/
im lokalen Netzwerk.
Externe Web-Browser müssen sich zunächst auf dem SSL-Proxy
erfolgreich authentifizieren und können dann über eine verschlüsselte
Verbindung auf Moodle zugreifen. Im vorliegenden Fall würde
sich die URL wie folgt aus dem Namen der beteiligten Server zusammen setzen:
https://prx.sec.inet/go/http://srv.org.local/moodle/
Abbildung der Netzwerkstruktur:
Gegenüber dem Web-Server tritt der SSL-Proxy als Client auf,
gegenüber dem externen Web-Browser vertritt er die Rolle des Web-Servers.
Dabei muss er URLs im HTML-Quelltext der Seiten automatisch angepassen,
da im Internet außerhalb des lokalen Netzwerkes Adressen der Form
http://srv.org.local/...
nicht funktionieren.
Problemsituation
Betrachten wir zwei stark gekürzte Auszüge aus HTML-Quelltexten, zunächst die eines internen Web-Browsers und danach die eines externen Web-Browsers.
1: <html> 2: <head> 3: <script type="text/javascript" src="http://srv.org.local/moodle/..."></script> 4: <link rel="stylesheet" type="text/css" href="http://srv.org.local/moodle/..." /> 5: <script type="text/javascript"> 6: //<![CDATA[ 7: M.yui.loader = {"base":"http:\/\/srv.org.local\/moodle\/..."}; 8: //]]> 9: </script> 10: </head> 11: <body> 12: <form action="http://srv.org.local/moodle/..." method="post"> 13: <input name="url" type="hidden" value="http://srv.org.local/moodle/..." /> 14: <img src="http://srv.org.local/moodle/..." /> 15: </form> 16: </body> 17: </html>
1: <html> 2: <head> 3: <script type="text/javascript" src="http://prx.sec.inet/go/http://srv.org.local/moodle/..."></script> 4: <link rel="stylesheet" type="text/css" href="http://prx.sec.inet/go/http://srv.org.local/moodle/..." /> 5: <script type="text/javascript"> 6: //<![CDATA[ 7: M.yui.loader = {"base":"http:\/\/srv.org.local\/moodle\/..."}; 8: //]]> 9: </script> 10: </head> 11: <body> 12: <form action="http://prx.sec.inet/go/http://srv.org.local/moodle/..." method="post"> 13: <input name="url" type="hidden" value="http://srv.org.local/moodle/..." /> 14: <img src="http://prx.sec.inet/go/http://srv.org.local/moodle/..." /> 15: </form> 16: </body> 17: </html>
Problematisch sind die Zeilen 7 und 13. Hier wurden vom SSL-Proxy die URLs nicht korrekt angepasst. Dass führt dazu, dass beim externen Zugriff der Funktionsumfang von Moodle nur sehr eingeschränkt genutzt werden kann. Vor allem die an den externen Web-Browser ausgelieferten Javascript-Routinen arbeiten wegen unpassender absoluter URLs nicht korrekt.
Problembehebung
Im an den externen Web-Browser ausgelieferten HTML-Quelltext müssen alle URLs angepasst werden, sowohl im Javascript-Code wie in Zeile 7 als auch in besonderen Attributen wie in Zeile 13. Im Prinzip kann die erforderliche Anpassung entweder am SSL-Proxy oder am Web-Server vorgenommen werden. Hier soll der Web-Server angepasst werden.
Schritt 1: Clientidentifizierung
Die Konfiguration des Apache-Servers wird ergänzt,
damit die Verbindungsaufnahme über den SSL-Proxy erkannt werden
kann. Die Erkennung erfolgt anhand der Adresse des Proxy-Servers
im lokalen Netzwerk. Falls der SSL-Proxy als Quasi-Client auftritt,
wird die Umgebungsvariable viaproxy
auf 1 gesetzt.
Der Eintrag kann in der zentralen Konfigurationsdatei
httpd.conf
erfolgen.
<IfModule setenvif_module> SetEnvIfNoCase Remote_Addr "10\.1\.1\.5" viaproxy </IfModule>
Schritt 2: PHP-Script erstellen
Das Problem mit absoluten URL-Pfaden tritt nur in den Seiten auf, die vom PHP-Code der Anwendung Moodle erzeugt werden. Daher stützt sich die Problembehebung ebenfalls auf PHP. Alle absoluten URLs werden angepasst mit Ausnahme solcher, die vom SSL-Proxy ohnehin korrekt gehandhabt werden.
Script auto_prepend.php
<?php // URL-Filterfunktion einrichten function local_sslproxy_callback($buffer1) { static $search1 = array( 'http:\\/\\/srv.org.local\\/', 'http://srv.org.local/' ); static $replace1 = array( 'https:\\/\\/prx.sec.inet\\/go\\/http:\\/\\/srv.org.local\\/', 'https://prx.sec.inet/go/http://srv.org.local/' ); static $search2 = array( 'src="https://prx.sec.inet/go/', 'href="https://prx.sec.inet/go/', 'action="https://prx.sec.inet/go/' ); static $replace2 = array( 'src="', 'href="', 'action="' ); $buffer2 = str_replace($search1, $replace1, $buffer1); return (str_replace($search2, $replace2, $buffer2)); } // URL-Filterfunktion anwenden, wenn Zugriff per SSL-Proxy erfolgt if ( $_SERVER['viaproxy'] ) { define("LOCAL_CALLBACK_FUNCTION", 1); ob_start("local_sslproxy_callback", 2048); } else { define("LOCAL_CALLBACK_FUNCTION", 0); } ?>
Script auto_append.php
<?php // Filtervorgang bei Bedarf abschliessen if ( LOCAL_CALLBACK_FUNCTION ) ob_end_flush(); ?>
Schritt 3: PHP-Script aktivieren
Die Konfiguration des Apache-Servers wird ergänzt, damit die zuvor definierte Filterfunktion auf alle Ausgaben von Moodle angewendet werden.
<Directory "D:/apm/htdocs/moodle"> <IfModule php5_module> php_admin_value auto_append_file "D:\apm\php5\local\auto_append.php" php_admin_value auto_prepend_file "D:\apm\php5\local\auto_prepend.php" </IfModule> </Directory>
Im Anschluss an die Änderungen muss natürlich der HTTP-Server Apache neu gestartet werden.
Die vorgenommenen Änderungen wirken sich auf alle Inhalte aus, die PHP im Rahmen der Lernplattform Moodle erzeugt, also nicht nur auf HTML-Seiten, sondern auch auf Javascript-Code und JSON-Daten.
Schritt 4: Ergebniskontrolle
Im letzten Schritt müssen die vorgenommenen Änderungen auf ihre Wirksamkeit überprüft werden. Zunächst empfiehlt sich ein Blick in den HTML-Quelltext auf einem externen Web-Browser. Die Problemzeilen 7 bzw. 13 sollten jetzt anders aussehen.
... 7: M.yui.loader = {"base":"http:\/\/prx.sec.inet\/go\/http:\/\/srv.org.local\/moodle\/..."}; ... 13: <input name="url" type="hidden" value="http://prx.sec.inet/go/http://srv.org.local/moodle/..." /> ...
Danach sollten die Funktionen von Moodle praktisch ausprobiert werden, z.B. durch einen Datei-Upload. Zuvor sollte der Cache-Speicher des Web-Browsers bereinigt werden, sonst bleiben noch für eine gewisse Zeit die Probleme durch nicht angepasste URLs bestehen. Das gilt entsprechend, wenn der SSL-Proxy ebenfalls Inhalte zwischenspeichern sollte.
Moodle-Optionen
Moodle kann auch so konfiguriert werden, dass die Lernplattform hinter einem Reverse-Proxy bzw. einem SSL-Proxy arbeitet. Dies hilft beim vorliegenden Problem aber nicht weiter, da eine simultane Nutzung der selben Lernplattform sowohl im lokalen Netzwerk als auch im Internet per Proxy-Server in den Konfigurationsoptionen nicht vorgesehen ist.
Apache-Filter
Statt den Ausgabe-Filter mit PHP zu realieren, könnte man diese Aufgabe auch Apache überlassen. In diesem Fall konnte eine auf Proxy-Verbindungen beschränkte Filterung mit dem Apache-Modul mod_ext_filter und dem externen Programm sed nicht störungsfrei zum Laufen gebracht werden.
Links
Server-Software
Moodle-Konfiguration
- Konfigurationsdatei
- Moodle with Apache Proxy
- Moodle und Reverse Proxies
- Reverse proxy frontend for Moodle
- Moodle und absolute URLs
PHP-Konfiguration
- PHP-Direktive
auto-prepend-file
- PHP-Direktive
auto-append-file
- PHP-Funktion
ob_start()
- PHP-Funktion
ob_end_flush()
- PHP konfigurieren per Apache
Apache-Konfiguration
Sonstiges
Anmerkungen
A reverse proxy is a proxy server that is deployed between a remote user outside an intranet
and a target Web server within the intranet. The reverse proxy intercepts and forwards packets
that originate from outside the intranet. An HTTP(S) reverse proxy specifically intercepts
HTTP(S) requests and responses.
Quelle: SonicWall
SSL-Proxy [...] Wegen der Eigenschaften des SSL-Protokols ist es nicht möglich,
die Domains direkt per https://domain.de/ aufzurufen, sondern nur
über den SSL-Proxy: https://ssl.proxydomain.de/domain.de/.
Quelle: TopNetworks