Dokumentation für IP_AUTH_PATCH: Secure Proxy Auth $Revision: 1.1 $ Einführung Die Standardauthetifizierung von Squid verwendet Authentification laut RFC2617. Squid und die meisten Browser unterstützen allerdings davon nur "Authtype Basic", das bedeutet, die Passwörter werden im Klartext (Base64) übertragen. Besonders, wenn diese Passwörter die selben sind, wie sie von Benutzeraccounts verwendet werden (z.B. wenn diese gegen einen NT-Server validiert werden), ist dieser Zustand sehr ungünstig, da mit einem Packetsniffer dann auf einfachste Weise die Benutzerpasswörter gestohlen werden können. Idee Die Passwortauthentifizierung kann man über ein CGI Script machen, das auf einem SSL-fähigen WWW-Server läuft. So kann man dann die IP-Addresse des Clienten "erlauben". Nun muß also vom Proxy nur noch überprüft werden, ob die IP-Addresse authentifiziert ist, und vom Proxy Daten erhalten darf. Ist das nicht der Fall, wird statt der angeforderten Seite ein Anmeldebildschirm präsentiert. Umsetzung Das Verhalten des Squid ist normalerweise so: Ein Browser fordert eine Seite an, bekommt (da kein Username/Passwort angegeben wurde) ein HTTP_AUTHENTICATION_NEEDED als Antwort. Der Browser öffnet ein Fenster, dessen Inhalt dann leider im Klartext übertragen wird. Der kleine Patch ändert das Verhalten an zwei Punkten: einmal wird die IP-Addresse als Name (und das "Token" IP_AUTH als Passwort) verwendet, falls kein Proxy-Auth-Header vorliegt, und zum zweiten wird anstatt HTTP_PROXY_AUTHENTICATION_NEEDED ein HTTP_CACHE_ACCESS_DENIED gesendet, damit der Browser nicht mehr nach einem Usernamen fragt. Dieses Dokument enthält dann auch gleich ein HTML-Formular für die Anmeldedaten, über das ein CGI-Script auf einem SSL-Server gestartet wird. Dieses CGI-Script bekommt in einem versteckten Feld die ursprünglich angeforderte URL mitübertragen, und veranlaßt den Browser, diese URL nach dem Laden des CGI-Scriptes erneut zu holen. Arbeitstiere Squid verwendet nun das authentication_program, um die IP-Addressen überprüfen zu lassen. Beim ersten Zugriff schlägt dieses fehl, da diese IP Addresse ja unbekannt ist. Dadurch wird das Anmeldeformular angezeigt. Nach dem Ausfüllen wird das CGI-Script gestartet. Diese kann nun die übertragenen Benutzer/Passworte überprüfen, z.B. in dem es diese Paaren verwendet, um sich eine Datei bei einem WindowsNT Server zu holen, um zu erkennen, ob dieser NT Account leseberechtigt auf die Datei und damit "surfberechtigt" ist. Ist das erfolgreich, so wird die IP-Addresse, von der diese Verbindung kommt, freigeschaltet, also den authenticate_program bekannt gegeben (im einfachsten Fall einfach über eine named pipe/FIFO). Das CGI-Script erzeugt einen Refresh-Header mit der ursprünglich angeforterten URL, damit der Browser nach der Anmeldung die richtige Seite lädt. Falls eine SSL-Verbindung aufgebaut werden sollte, funktioniert das so nicht, ein möglicher Ausweg ist z.B. die Javascript-Funktion history.go(-1) zu verwenden. Dann fordert der Browser also die originale URL an, wird wiederum vom authenticate_program verifiziert, diesmal ist die IP bekannt (falls die Authentifizierung erfolgreich war), und der Client bekommt die gewünschten Daten. Implementierung Verwendet man einfach Perl-Scripts für das CGI-Programm und das asuthenticate_program, kommt man schnell zum Ziel. Das authenticate_program kennt einen Hash der IP-Addressen, in dem ein Zeitstempel mitverwaltet wird. Das Perlscript verwendet select(2), um die pipe und stdin gleichzeitig überwachen zu können. Liegen Daten an der pipe an, so werden sie gelesen, die IP wird in den Hash gelegt (bzw. nur der Timestamp aktualisiert), oder aus diesem entfernt (falls es ein logout war). Daten, die über stdin kommen, werden gelesen, die IP-Addresse wird im Hash nachgesehen, und akzeptiert, sofern sie nicht zu alt ist, dabei wird der Timestamp aktualisiert. Login/Logout-CGI sind davon sehr unabhänig, nur die IP-Addressen müssen übertragen werden. Verwendet man eine named-pipe, können die IP-Addressen höchsten lokal gefälscht werden, was mit den Berechtigungen der FIFO entsprechend verhindert werden muß. SSL-Server Zwei Scripte sollten über einen SSL-Server gestartet werden können: login.cgi und logout.cgi. Dieser Server muß erreichbar sein, ohne daß der Proxy verwendet wird, da ansonsten keine Authentification möglich wäre. Beim Netscape Navigator und dem Internet Exporer kann man einstellen, daß für bestimmte Hosts kein Proxy verwendet werden soll. Dieser SSL-Server kann auf der gleichen Maschine wie der Proxyserver laufen. Die Verwendung von Apache+mod_ssl bietet sich hierbei natürlich an. Dabei ist es nichteinmal zwingend erforderlich, ein richtiges SSL-Zertifikat zu besitzen, ein Zertifikat einer Dummy-CA oder ein Testzertifikat sind hierbei ausreichend. Installation Wird das RPM Packet installiert, so müssen die benötigten Beispielscripte aus contrib/IP_AUTH an die gewünschten Orte kopiert werden. Diese funktionieren nur, wenn ein WWW-Server auf dem selben Host wie der Proxy läuft. Diese sind dann in der squid.conf einzustellen. Dabei ist zu beachten, daß das authenticate_program nicht parallel funktioniert! Es muß also zwingend "authenticate_children 1" gesetzt sein! Wird von einem Tarball installiert, sind folgende Schritte mindestens notwendig: # tar -xzvf squid-2.3STABLE1.tgz # cd squid-2.3STABLE1 # patch -p0 <../squid-IP_AUTH.patch # ./configure --prefix=/usr/local/squid --enable-ip_auth # make # make install Dann müssen wiederum die Scripte kopiert und konfiguriert werden. Nun müssen die CGI-Scripte konfiguriert und installiert werden. Entweder liegen sie in einem Verzeichnis, das einen Script-Alias besitzt, oder für dieses Verzeichnis sind folgende Optionen in ".htaccess" gesetzt: "Options +ExecCGI" und "AddHandler cgi-script .cgi". Damit können dann CGI-Scripte da gestartet werden, wo sie hingehören. Funktioniert das nicht, so ist zunächst zu prüfen, ob die Scripte von der Kommandozeile aus startbar sind, und ob sie evtl. Fehlermeldungen bringen. Dann ist im Serverlog zu prüfen, welcher Fehler sich ereignet hat, und dieser entsprechend zu korrigieren. In der Regel müssen die Scripte etwas angepaßt werden. Vorallem der Pfadname der FIFO-Datei zur Kommunikation mit dem authenticate_program muß richtig gesetzt sein (die FIFO muß für die Scripte, also in der Regel für den Apache-User "www?????" schreibbar, für den Squid-User lesbar sein). Andere Benutzer dürfen keinen Zugriff auf diese FIFO erhalten, da ansonsten Passwörter gestohlen werden könnten, und das System gestört werden könnte! Natürlich muß auch das authenticate_program dieselbe FIFO verwenden. Bei diesem muß zusätzlich ein Logfile konfiguriert werden. Dabei sollte dieses File überwacht werden, damit es nicht zu groß wird. Es darf dann nicht einfach gelöscht werden, sondern es muß überschrieben werden (z.B. "cp /dev/null $LOGFILE"), ansonsten müßte der Proxy neugestartet werden, damit auch das authenticate_program neu gestartet wird. In der Datei "ERR_CACHE_ACCESS_DENIED" (in /usr/local/squid/etc/errors) muß dann ggf. die URL zum login.cgi CGI-Script angepaßt werden (die IP_AUTH Distribution setzt vorraus, das es auf dem selber Host wie der Proxy läuft, und /login.cgi heißt).