Benutzerspezifische Werkzeuge
Sie sind hier: Startseite Support FAQs Virtual Hosting Ich möchte ein Zope mit einem Apache davor der cached und ich möchte das das einloggen der User über SSL gezwungen wird damit keine Passwörter im Klartext über das Netz gehen.
Eine Ebene höher

Frage

Ich möchte ein Zope mit einem Apache davor der cached und ich möchte das das einloggen der User über SSL gezwungen wird damit keine Passwörter im Klartext über das Netz gehen.

Antwort

Konfiguration von Zope, Apache als Chaching Proxy, sicheres Login und PAM Anbindung

Software: Zope 2.6.1, Apache 1.3.27
Letzte Änderung: 29.04.03
Status: Getestet, noch nicht produktiv

Anforderungen:
+ Caching Apache in front
+ Mehrere virtuelle Hosts auf einer Maschine mit einer IP
+ Login per SSL
- Cachen mit unterschiedlichen Einstellungen je nach Objektart



Am Anfang des Setup des Zope-Systems hier beim DESY waren ein paar grundlegende technische Dinge zu klären. Wie setze ich einen Apache als "caching proxy" vor das Zope und wie schaffe ich es das ein Login in das System _immer_ über eine verschlüsselte Kommunikation läuft.

Zuerst müssen Zope und Apache-SSL installiert werden. Das ist anderswo besser dokumentiert als ich es könnte, deshalb gehe ich nicht weiter darauf ein ;)

Da Zope und Apache zum testen auf einer Maschine installiert werden müssen die TCP-Ports entsprechend eingestellt werden.
Apache lauscht auf den Standard HTTP-Port 80 und Zope wird auf 8080 gestellt. Dazu muss die Zeile
<snip>
# Port for HTTP Server. The standard port for HTTP services is 80.
HTTP_PORT=8080
</snip>
in der Datei z2.py eingetragen werden.

In der httpd.conf muss etwas mehr geändert werden...
Die Standardeinstellungen für den "Main Server" können beibehalten werden, er wird nur noch vom localhost erreichbar sein. Alles andere wird über virtuelle Server gehandhabt.

Mit "Listen 80" und "Port 80" lauscht Apache auf den Standardport

Diese Zeilen sorgen einfach dafür das die benötigten Module geladen werden und zur Verfügung stehen.
<snip>
LoadModule rewrite_module libexec/mod_rewrite.so
LoadModule proxy_module libexec/libproxy.so
LoadModule ssl_module libexec/libssl.so
...
AddModule mod_rewrite.c
AddModule mod_proxy.c
AddModule mod_ssl.c
</snip>

Folgend ist der komplette Abschnitt für die Konfig des Proxy von Apache.
Doku zu den einzelnen Zeilen ist SEHR nützlich und findet sich unter http://httpd.apache.org/docs/mod/mod_proxy.html
<snip>
<IfModule mod_proxy.c>
ProxyRequests Off
# Nicht verwirren lassen, wir benutzen den Proxy explizit in der Weiterleitung
# Aus Sicherheitsgründen (wichtig!) wird die globale Proxyfunktion ausgeschaltet

ProxyVia On
# Bringt zwar nicht viel mit "ProxyRequests Off" aber der Vollständigkeit halber

CacheRoot "/MEINVERZEICHNIS.../apache/proxy"
CacheSize 1000
CacheGcInterval 1
CacheMaxExpire 24
CacheLastModifiedFactor 0.1
CacheDefaultExpire 1
CacheForceCompletion 100 # Ist wichtig um das "halbe Bilder cachen" Symptom zu vermeiden
ProxyReceiveBufferSize 0
ProxyDomain .MEINEDOMAIN.de # Der vollständigkeit halber
</IfModule>
</snip>

Jetzt kommt das Herzstück, die Konfiguration der virtuellen Hosts.
Zuerst kommt in die generelle Konfiguration auf welche IP/Port Kombinationen der Server reagieren soll.
(Angenommen 123.123.321.321 ist die IP der Maschine)
<snip>
#
# Use name-based virtual hosting.
#
NameVirtualHost 123.123.321.321:80
NameVirtualHost 123.123.321.321:443
</snip>

Auch der eigentliche Eintrag für einen virtuellen Host ist ziemlich einfach.
Angenommen der Name www.bloe.de ist so eingerichtet das der DNS auf die IP 123.123.321.312 zeigt (Wie passend ;)
<snip>
<VirtualHost 123.123.321.321:80>
ServerName www.bloe.de
ServerAlias bloe.de
ServerAdmin webmistress@bloe.de
RewriteEngine on
RewriteRule ^(.*) http://123.123.321.321:8080/VirtualHostBase/http/www.bloe.de:80/www_bloe_de/VirtualHostRoot$1 [P,L]
</VirtualHost>
</snip>
Wenn ein weiterer Server (www.foo.com) eingerichtet wird, einfach den Abschnitt oben wiederholen und "bloe.de" durch "foo.com" ersetzen.

Des Pudels Kern ist die RewriteRule: Mit der Regel werden alle (^(.*)) Anfragen zu Zope (8080) umgleitet und gleichzeitig werden die VirtualHostBase und das VirtualHostRoot für das VirtualHostMonster (s.u.) in Zope umgeschrieben.
WICHTIG ist das korrekte übernehmen der "/" in der RewriteRule! Es gibt Anleitungen die Kombinationen verwenden die scheinbar funktionieren aber später mit z.B. dem ZMI Probleme machen. Diese hier funktioniert und macht nicht den berüchtigten "//"-Fehler.

Tip vom Sicherheitsfanatiker: Gut ist auch Zope so konfigurieren das es nur auf Anfragen von "localhost" reagiert und dann (nur!) in der RewriteRule 123.123.321.321 durch "localhost" zu ersetzen.

Kommen wir jetzt zur Einrichtung des VirtualHostMonster in Zope. Einfach im Root von Zope ein Objekt vom Typ "Virtual Host Monster" erstellen. Voila! *staun* Ok, ok, es ist noch nicht ganz alles ;)
Im Zope-Root muss dann noch ein Folder für jede einzelne Website erstellt werden, entsprechend dem Eintrag in der RewriteRule in Apache. In unserem Falle würde der Folder "www_bloe_de" heißen. Da liegen dann die Objekte/Seiten für die Website drin.


Die Apache-Konfiguration für die SSL-Verbindung ist auch einfach nur ein weiterer virtueller Host.
<snip>
<VirtualHost 123.123.321.321:443>
ServerName www.bloe.de
ServerAlias bloe.de
ServerAdmin webmistress@bloe.de
SSLEngine on
... # Hier folgt das ganze SSL-Geraffel. Ist hier nicht Thema, am besten unter apache.org schauen
RewriteEngine on
RewriteRule ^(.*) http://123.123.321.321:8080/VirtualHostBase/https/www.bloe.de:443/www.bloe.de/VirtualHostRoot$1 [P,L]
</VirtualHost>
</snip>

Anders ist hier nur das "https" und das ":443", was einfach dafür sorgt, das eine sichere Verbindung bestehen bleibt wenn sie einmal angelinkt wurde.


Jetzt bleibt nur noch den Einlog-Vorgang über SSL zu zwingen, damit keine Passwörter im Klartext über das Netz fliegen.
Dazu brauchen wir zwei Produkte, den "Cookie Crumbler" und "SSLAbsoluteURL" (Muß installiert werden).
Im Root ein Objekt des Typs Cookie Crumbler und die DTML-Dokumente "logged_in", "logged_out" und "login_form" erstellen (die DTML-Dokumente gibt's auf www.zope.org).
Ab jetzt wird jeder Login nicht mehr über das PopUp-Fenster des Browsers gemacht, sondern es gibt ein schönes, anpassbares HTML-Formular das aufgerufen wird.

Das Objekt "login_form" bekommt eine Property, Name "SSL", Typ "Boolean", Wert "An". Damit und dem Produkt "SSLAbsoluteURL" werden Aufrufe von "login_form" über SSL gezwungen.

Eine Anpassung muß aber in der login_form noch gemacht werden:
<snip>
<dtml-let came_from="REQUEST.get('came_from', '')"
action_url="came_from or 'logged_in'">

<!-- <form action="&dtml-action_url;" method="POST"> -->
<form action="logged_in" method="POST">
</snip>
Es wird nur die "form action" hart auf das DTML-Dokument "logged_in" gelinkt.

Warum? Das Formular springt sonst direkt dahin wo der User hergekommen ist. Das ist aber wahrscheinlich noch keine SSL-Übertragung gewesen! Das heißt, der User tippt ihr Passwort auf einer Seite ein die über SSL übertragen wurde aber wenn sie das Formular abschickt würde die Verbindung doch wieder über eine unsichere Verbindung laufen und Schmidtchen Schleicher könnte mithören...

Wenn allerdings auf "logged_in" verlinkt wird, wird das Passwort noch über eine sichere Verbindung übertragen. "logged_in" springt dann seinerseits direkt weiter auf die Seite wo der User herkam. Also für den User ist alles fein und für uns ist alles sicher.

Tip vom Sicherheitsfanatiker: Wir haben jetzt nur verhindert das Passwörter im Klartext über das Netz flitzen. Allerdings könnte immer noch jemand später die Session-Variablen des Users mitlauschen und die Session evtl. "entführen". Das ist recht unwahrscheinlich _aber_ möglich. Um eine Raketensteuerung zu betreiben würde dann nur helfen _alles_ über SSL laufen zu lassen (was jedoch wiederum Performance des Webservers kostet).

Noch ein wichtiges Wort zum Caching. Es ist zwar jetzt ein funktionierender "caching reverse proxy" vor unserem Zope aber was wird denn gecached?
Es gibt eine Reihe von HTTP Headern die das Verhalten von zwischengeschalteten Caches (der Apache, der Cache des Browsers, etc.) steuern.
Objekte vom Typ "image" haben automatisch einen Satz Header der caching erlaubt, andere Objekttypen leider nicht.

Das hat seinen Zweck, denn Caching hat auch Nachteile. In der Zeit in der der Cache die Anfragen beantwortet wird eine dynamische Seite (zum Beispiel ein Newsscript) nicht ausgeführt und somit auch nicht ge-updated!
Bei einem hochdynamischen System wie Zope ist es also sehr wichtig sich gut zu überlegen was, wann, wie lange gecached werden darf.
ACHTUNG: Der "Accellerated HTTP Cache Manager" ist zwar genau für diesen Zweck da hat aber einen Glitch, so dass die Header nicht ordentlich geschrieben werden und das Objekt dann doch nicht gecached wird (Stand 29.4.03). Mann! Hab ich Ewigkeiten gesucht bis ich _das_ gefunden hab!

Im Moment ist die Lösung die Header für jedes Objekt das gecached werden soll selbst zu schreiben. In DTML würde das so aussehen:
<snip>
<dtml-call "RESPONSE.setHeader('Expires',_.DateTime(_.DateTime().timeTime() + 3600).toZone('GMT').rfc822())">
<dtml-call "RESPONSE.setHeader('Last-Modified',bobobase_modification_time().toZone('GMT').rfc822())">
</snip>
Ich denke aber das der AHCM demnächst gefixed wird und mir schweb auch noch eine Erweiterung vor mit der es möglich ist den unterschiedlichen Objekttypen automatisch unterschiedliche Cache-Zeiten zuzuordnen.

Ich denke ich kann dieses Dokument über die Zeit noch deutlich verbessern und erweitern. Wie gesagt am Caching wird noch gearbeitet, eine Userauthentifizierung durch PAM und Lastverteilung mit ZEO kommen sicher auch noch dazu.

Vielleicht hilft meine Beschreibung ja der Einen oder dem Anderen weiter.
Über Feedback und Verbesserungsvorschläge bin ich immer dankbar :)

/Carsten

--
Carsten Germer, Weboffice Tel.: +49 (0) 40 8998 1661
DESY Email: carsten.germer@desy.de
Notkestr. 85 WWW: http://www.desy.de/
D-22607 Hamburg http://www.germer.org/


Letzte Änderung: 30.04.2006 • Autor: ajung