Würde sich Sicherheit nach der Anzahl der Module und Methoden bemessen, wäre ein Webserver eine Festung mit Burggraben darum herum, in dem halb verhungerte Krokodile schwimmen. Wer als Admin Apache konfigurieren soll, das verschiedene Authentifizierungsverfahren und SSL beherrscht, hat die Qual der Wahl.
Wer darf was?
Es gibt viele Verfahren, wer sich wem gegenüber wie authenfizieren und autorisieren darf. Sobald Apache ins Spiel kommt, liegt viel Verantwortung in den Händen des Admins - da will das passende Modul gut gewählt sein.
Zunächst gilt es, zwischen Authentifizierung und Autorisation zu unterscheiden: Autorisation regelt den Zugriff auf Bereiche und erteilt die Erlaubnis zu bestimmten Aktionen. Die Autorisation spielt unter Apache eine große Rolle: Dürfen Anwender ein eigenes
cgi-bin-Verzeichnis im ihrem Home-Verzeichnis anlegen und dort CGIs ablegen? Mit welcher Programmiersprache ist das erlaubt? Wer darf auf welche Bereiche einer Website zugreifen? Die Autorisation ist oft mit der Authentifizierung kombiniert, damit der Webserver erlaubte (oder unerwünschte) Benutzer erkennen kann: Man kann eigene Passwort-Dateien mit
htpasswd oder
htdigest anlegen oder Benutzer über LDAP oder Radius authentifizieren. Es gibt sogar Module, die den Zugriff von SMB-Usern abhängig machen. Passwortdateien kann man unterschiedlich sicher in verschiedenen Datenbankformaten von DBM bis diverse SQL-Datenbanken oder
ldap speichern. Dazu braucht es natürlich die passende Datenbank, die dem Apache Zugriff auf sich erlauben muss. In den meisten Datenbanken kann man Passworte mit dem datenbankeigenen
crypt verschlüsselt ablegen; viele unterstützen auch verschiedene Algorithmen zur Verschlüsselung.
Manche dieser Verfahren übertragen das Passwort vom Client (Browser) zum Webserver in Klartext - also benötigt man möglicherweise noch SSL-Support, um via
https Daten zu senden oder muss darauf bauen, dass der Browser bereits mit Digest umgehen kann. Zu guter Letzt dient die Authentifizierung natürlich auch dazu, den Webserver selbst als denjenigen zu authentifizieren, der er vorgibt zu sein.
Einfache Autorisation
Verschiedene Module für den Apache haben dabei verschiedene Aufgaben. Ein ganz einfaches Modul, um Zugriffe über die Autorisation zu regeln, ist
mod_access.
mod_access gehört zu den Base-Modulen - es ist also sowieso vorhanden, es sei dann, man hat es beim Kompilieren des Apache ausgeschaltet.
mod_access regelt auf verschiedene Arten den Zugriff auf verschiedene Bereiche: Man kann damit per Host, Domain und TLD Zugriffe regeln, per IP und per IP-Range, und das sowohl via Netzmaske als auch mit CIDR-Notation (
/24) oder über die Variable, die der Browser als User-Agent setzt. Typische Konfigurationen könnten so aussehen:
<Directory /intranet>
Order Deny,Allow
Deny from all
Allow from 192.168.*
</Directory>
Das
Allow from darf auch so geschrieben werden:
Allow from mydomain.de.
IPv6-Adressen funktionieren ebenfalls.
In der
httpd.conf sind damit die typischen Webserver-Zeichnisse
/htdocs,
/icons und
/manual konfiguriert, denn
mod_access bezieht sich oft auf ein Verzeichnis. Eine Verzeichnis-Direktive
darf natürlich innerhalb eines Virtual Hosts, konfiguriert mit der Direktive
vorkommen.
Ein Beispiel: Um den Zugriff via Browser-Typ zu regeln (siehe auch die Direktive
BrowserMatch), setzt man zunächst eine Variable:
SetEnvIf User-Agent ^Lynx.* just_lynx
und erlaubt dann den Zugriff mit
Allow from env=just_lynx
und schon können nur noch Browser, die als Typ
Lynx senden, auf das Verzeichnis zugreifen. Natürlich kann man mit vielen Browsern oder mit Perls Modul
LWP diese Variable selbst setzen - als Sicherheitssperre ist diese Konfiguration nicht gedacht. Dafür kann man in Abhängigkeit vom Browsertyp unterschiedliche Webseiten senden. Mit dieser Methode kann man natürlich auch andere Variablen des gesendeten HTTP Headers auswerten.
htaccess-Dateien
mod_access reagiert außerdem auf Anweisungen, die in einer
.htaccess-Datei im jeweiligen Verzeichnis stehen. In der
.htaccess-Datei steht, welche Direktiven
mod_access überschreiben soll. In der
httpd.conf wiederum steht für das jeweilige Verzeichnis die Erlaubnis zum Überschreiben der entsprechenden Direktive mit dem Schlüsselwort
AllowOverride. Der Unterschied zwischen den Anweisungen liegt darin, dass die Direktiven der
.htaccess-Datei nur ausgewertet werden, wenn eine Anfrage für das betreffende Verzeichnis eintrifft. Das Apache-Manual weist ausdrücklich darauf hin, dass viele
.htaccess-Dateien aus Performancegründen keine gute Idee sind, weil der Apache die Verzeichnisse nach der
.htaccess durchforstet und das Regelwerk anwenden muss. Die Direktiven der
httpd.conf dagegen lädt der Apache direkt beim Start des Webservers. Zur Kontrolle:
httpd -L zeigt die aktuell aktiven Direktiven an. Mit der Variable
AccessFileName kann man die
.htaccess-Datei umbenennen, wie man möchte.
Basis-Authentifizierung
Eine absolut minimale Basis-Authentifizierung leistet das Base-Modul
mod_auth. Man legt mit
htpasswd eine Passwortdatei an und weist einem User ein Passwort zu. Der User muss nicht innerhalb des Systems selbst existieren - die User der
/etc/passwd und der Apache-Passwortdatei brauchen nichts miteinander zu tun zu haben. In der
httpd.conf oder via
.htaccess wird einem Verzeichnis die entsprechende Passwortdatei mit den enthaltenen Benutzern oder Gruppen zugewiesen. Man kann also z.B. pro
eigene Passwortdateien vorhalten. Will man Zugriff auf das entsprechende Verzeichnis, schickt der Webserver die Aufforderung, sich für diesen Webserverbereich (
Realm) zu authentifizieren. Der Browser poppt das bekannte Fenster auf oder zeigt einen passenden Eingabedialog an. Username und Passwort wird bei dieser Authentifizierungsmethode im Klartext übertragen. Die einfachste Konfiguration sieht also z.B. in der
httpd.conf so aus:
<Directory /usr/local/apache/htdocs/mystuff>
Order Deny,Allow
Deny from all
Allow from localhost #Zum Üben
AllowOverride AuthConfig
</Directory>
In das Verzeichnis
/usr/local/apache/htdocs/mystuff/ legt man eine
.htaccess-Datei mit folgenden Anweisungen:
AuthType Basic
AuthName "Persönlicher Zugriff"
AuthUserFile /usr/local/apache/authentication/passwords
Require user someuser
Natürlich kann man diese Anweisungen genauso gut in die Directory-Direktive direkt eintragen und sich die
.htaccess-Datei sparen. Dann fällt die
AllowOverride-Anweisung weg.
Zum Schluss legt man die Passwortdatei an:
/usr/local/apache/bin/htpasswd -c /usr/local/apache/authentication/passwords someuser
Man wird auf die übliche Art zweimal nach dem Passwort gefragt und dann liegt die Passwort-Datei im einfachsten Format mit verschlüsseltem Passwort im entsprechenden Verzeichnis außerhalb des Documentroot des Apache. Nach dem Neustart des Apache mit
apachectl restart - wie bei jeder Änderung der
httpd.conf - kann man das Einloggen testen. Änderungen in der
.htaccess-Datei erfordern keinen Neustart des Dämon, weil sie zur Laufzeit ausgewertet werden.
Mehr Sicherheit bei Passworten
Mehre Wege existieren, um die Authentifizierung sicherer, effizienter und skalierbarer zu gestalten. Einige Module erlauben, die Passwort- und Userinformationen in Datenbanken zu speichern - andere sorgen für sicherere Übertragung. Egal, in welchem Format man seine Benutzer verwaltet - zunächst kann man konfigurieren, mit welcher Methode der Browser Benutzername und Passwort an den Webserver übertragen soll.
AuthType Basic überträgt diese Daten im Klartext; deswegen kann man alternativ
AuthType Digest setzen - allerdings muss der Browser dieses Verfahren (ausführlich in RFC 2617) unterstützen.
Mod_auth_digest muss man entweder gleich beim Kompilieren des Apache aktivieren oder aber nachträglich mit
/usr/local/apache/bin/apxs -i -c /apachesourcen/mod_auth_digest.c
installieren und dann via
LoadModule auth_digest_module modules/mod_auth_digest.so
in der
httpd.conf laden, bevor weitere Anweisungen für Digest in Directory-Direktiven auftauchen. Die Authentifizierung via Digest konfiguriert sich etwas anders als der
AuthType Basic:
<Directory /usr/local/apache/htdocs/mystuff/>
AuthType Digest
AuthName "Privater Zugriff"
AuthDigestFile /usr/local/apache/authentication/digests
Require user someuser
</Directory>
Weil das Dateiformat für diese Form der Authentifizierung anders ist, liegt dem Apache ein Programm
htdigest bei, mit dem man neue Passwortdateien generiert:
/usr/local/apache/bin/htdigest -c /usr/local/apache/authentication/digests
"Privater Zugriff" someuser
Die Anweisung AuthName entspricht dem Parameter, den
htdigest erhält. Das Ganze kann man auch in eine
.htaccess-Datei eintragen und muss dann natürlich an die Direktive
AllowOverride AuthConfig in der
httpd.conf im passenden
-Abschnitt denken.
Anonymer Zugriff auf gesicherte Bereiche
Wer eine gewisse Kontrolle über Zugriffe auf bestimmte Bereiche behalten möchte, kann einen FTP-ähnlichen Zugriff für den Apache konfigurieren. Der Webserver erwartet ein Login und ein Passwort - beide sind allerdings öffentlich, damit sich jedermann einloggen kann. Als Passwort kann die eMail-Adresse gefordert sein, die man wiederum mitschreiben kann. Der anonyme Zugriff funktioniert mit jedem Browser und erfordert keine Cookies oder merkwürdige Anhängsel an die URL. Der Zugriff heißt
anonym, weil er keine registrierten Anwender erfordert - nicht etwa, weil er wirklich anonym ist. Die Konfiguration erfolgt ähnlich wie mit echter Authentifizierung und für die Installation genügt das obligatorische
apxs -c -i mod_auth_anon.c. Eine Basiskonfiguration kann etwa so aussehen, um das Modul zu laden:
LoadModule auth_anon_module modules/mod_auth_anon.so
Einem Bereich anonymen Zugriff zuweisen, die Eingabe einer eMail erzwingen, aber nicht mitschreiben und den Anwender abweisen, falls er keinen der gültigen Usernamen verwendet, kann man so konfigurieren:
<Location /somewhere>
Order deny,allow
Allow from all
Require valid-user
Anonymous_Authoritative On
Anonymous_NoUserId off
Anonymous_MustGiveEmail on
Anonymous_VerifyEmail on
Anonymous_LogEmail off
Anonymous anonymous guest www test
AuthName "Use 'guest' or 'anonymous' and email adress as password to login"
AuthType basic
</Location>
Durch den
AuthType basic erfolgt die Übertragung des Usernamen und Passworts natürlich unverschlüsselt. Die Direktive
Anonymous_VerifyEmail kontrolliert auch nur, ob die Schreibweise einer Emailadresse entspricht - nicht aber, ob die eMail-Adresse eine gültige Domain u.Ä. enthält.
Viele Nutzer mit Backends verwalten
Wer mit mehr Usern hantiert, als ein einfaches Textfile verarbeitet, kann auf Alternativen wie
mod_authdbm ausweichen. Apache kann verschiedene File-Formate oder Berkeley-DB ansprechen und von dort seine Informationen beziehen. Für sehr viele Benutzer bieten sich externe Module wie
mod_auth_mysql oder
mod_authldap an. Natürlich muss man dazu eine MySQL-DB bzw.
Openldap und Verwandte installieren und dem Apache den Zugriff auf die DBs erlauben.
Die Basiskonfiguration, um die Benutzerinformationen aus anderen Quellen zu beziehen, ersetzt die Direktiven
AuthUserFile oder
AuthGroupFile durch die entsprechende Direktiven für andere Dateiformate, Datenbanken oder LDAP. Der Apache selbst kann zum Beispiel Informationen aus DBM-Dateien beziehen, die man mit
AuthDBMType und
AuthDBMUserFile konfiguriert. Benutzername und Passwort empfängt der Apache weiterhin für den Bereich via
Basic unverschlüsselt oder mit
Digest.
Wer viele Anwender verwalten will, kann mehrere Backends für seine Benutzerverwaltung verwenden: LDAP, Radius oder auch SQL-Datenbanken kann der Apache über externe Module ansprechen. Bei diesen Methoden gilt es allerdings, zwei Authentifizierungsschritte zu unterscheiden: Zunächst muss man den Zugriff vom Apache zum Backend konfigurieren - dazu braucht der User natürlich kein Passwort eingeben, denn dafür muss der Apache auf das Backend zugreifen dürfen. Die Übergabe von Username und Passwort, um im Backend verwaltete Anwender zu authentifizieren, erfordert dann die Eingabe von Username und Passwort entweder über
AuthType oder über ein selbstgeschriebenes Script. Beide Daten reicht der Apache dann an die Datenbank weiter und dort existiert dann (hoffentlich) der passende User.
Userverwaltungen via LDAP und Radius konfiguriert man bequem über den Apache - man muss oft nur Host und Port für den Zugriff angeben. Bei LDAP kommt noch der
dn (Distinguished Name) hinzu. Wer diese Module verwendet, erhält also neue Direktiven für den Apache wie
LDAP_Server,
LDAP_Port oder
Base_DN. Bei Gebrauch des Radius-Moduls kommen Direktiven wie
AddRadiusAuth und
AuthRadiusBindAdress dazu. Beide Module erhalten zur User-Authentifizierung Passwort und Username vom Webserver für den Bereich mit
AuthType Basic oder
Digest durchgereicht
Liebhaber von SQL-Datenbanken können auf Benutzerdaten via Oracle, MySQL oder auch Postgres zurückgreifen. Das Postgres-Modul wird ähnlich wie das LDAP- und Radiusmodul konfiguriert, indem man innerhalb der Directory-Direktive
Host,
Post usw. für den Zugriff auf die DB setzt. Für mySQL gibt es mehrere Module: Eines arbeitet mit einem zwischengeschalteten CGI-Script, dass Username und Passwort via Perl-Script von MySQL abfragt; das zweite ist ein neueres Modul:
mod_authn_dbi ist ein Interface für verschiedene Datenbanken als Backends. Wer mit Perls DBI-Modul vertraut ist, ahnt schon, wie dieses Modul auf Basis der Bibliothek
libdbi arbeitet. Egal, welche Datenbank dahinter liegt, das Modul erhält vom Apache Username und Passwort. Man kann mit diesem Modul außerdem den Digest Handler von Apache für
AuthType Digest gegen den Digest Handler des Moduls austauschen.
Apache mit SSL
Viele Apaches sind unvollständig, ohne die Möglichkeit, den Webserver via HTTPS ansprechen zu können. Der Apache beherrscht schon lange SSL, das bei den meisten Distributoren bereits vorinstalliert ist. Auch OpenSSL, um Keys und Zertifikate zu generieren, liegt den meisten Distributionen bei. Wer einen neuen Apache baut, muss ein, zwei Handgriffe selbst erledigen:
mod_ssl kompilieren und das Modul aktivieren, die passenden Keys und Zertifikate mit OpenSSL generieren und SSL korrekt in der
ssl.conf (optional) des Apache (Direktive:
Include /pfad/apache/conf/ssl.conf) konfigurieren. Wer das erste Mal mit SSL und Zertifikaten hantiert, sollte sich gründlich in die Materie einlesen - die Webseite von Ralf Engelschall, dem Entwickler von
mod_ssl bietet umfangreiche und verständliche Dokumentation. Zum Schluss muss das eigene Zertifikat (im Grunde der Public Key) entweder an eine übergeordnete Zertifizierungsinstanz zum Signieren weitergereicht werden oder das Zertifikat muss selbst signiert werden (
Self Signed) - wem es bloß darum geht, eine verschlüsselte Webstrecke via HTTPS zu erstellen, braucht vielleicht keine
Certificate Authority wie VeriSign, die das Zertifikat bestätigt, sondern fungiert als seine eigene CA. Für Anwender bedeutet dies, dass ein Bestätigungsdialog für das Zertifikat aufpoppt - das ist bei vielen Websites nicht der Fall, wenn deren Zertifikate von einer der CAs signiert wurden, die Browser wie Mozilla oder IE bereits kennen - zum Beispiel VeriSign, AOL, Thawte, RSA oder Visa. Anwender müssen selbst konfigurieren, ob sie bei jedem Zertifikat bestätigen oder ob die vorhandenen Zertifikate automatisch erkannt werden sollen.
Um den eigenen Apache SSL-tauglich zu konfigurieren, geht man als Minimalkonfiguration folgendermaßen vor:
Schritt 1:
Den Private Key für den Host generieren. Der Key kann verschlüsselt sein - dann muss bei jedem Apache-Start die entsprechende Passphrase eingegeben werden.
Das Kommando
openssl genrsa -des3 -out server.key 1024
erledigt diesen Schritt. Wer sich den Key jetzt anschaut, sieht eine PEM-kodierte Datei.
Schritt 2: Einen Certificate Signing Request (CSR) generieren. Normalerweise würde man den CSR an eine CA schicken, die CA signiert den CSR und man erhält das Zertifikat CRT zurück. Ein CSR ist der Public Key mit einem Common Name zugewiesen, der dem späteren Host entspricht und auf den Server (Secret Key) passt. Mit Signatur einer CA wird ein CSR zu einem CRT.
Den CSR erstellt man mit dem Befehl
openssl req -new -key /pfad/keys/server.key -out server.csr
Ein Dialog mit verschiedenen Fragen zu Common Name, Organisational Unit und den anderen Parametern muss für den Host abgewickelt werden, dann ist der CSR generiert. Merke: Bei Apache mit LDAP ist unter anderem der
DN (Distinguished Name) wichtig, bei SSL-Zertifkaten der
CN (Common Name).
Schritt 3
: Weil wir unsere eigene CA sind, braucht man einen Private Key für die CA, den man ebenfalls selbst generieren muss:
Mit dem Befehl
openssl genrsa -des3 -out ca.key 1024
ist das schnell erledigt.
Schritt 4: Von meiner CA generiere ich ein Self Signed Certificate mit dem Kommando
openssl req -new -x509 -days 365 -key ssl.key/ca.key -out ca.crt
Man erstellt also nicht noch einmal einen CSR, sondern gleich ein CRT mit einer Gültigkeitsdauer von 365 Tagen.
Schritt 5:
Mit dem Self Signed Certificate meiner CA signiere ich das CSR meines Hosts und erhalte mein eigenes Zertifikat CRT. Dazu benutzt man der Einfachheit halber das Shell-Script
sign.sh, dass bei den Sourcen des
mod_ssl-Moduls beigefügt ist. Das erzeugt dann eine Datei
server.crt, die in das gewünschte Zertifikateverzeichnis gehört.

Ein Beispiel-SSL-Zertifikat enthält entsprechende Angaben wie cd CN und ein Verfallsdatum.
Schritt 6: Das Ganze in der
ssl.conf des Apache eintragen. Aber Achtung: Mit SSL braucht jeder Virtual Host eine eigene IP! Dabei sind vor allen Dingen die Direktiven
SSLCertificateFile und
SSLCertificateKeyFile wichtig. Natürlich enthält
mod_ssl deutlich mehr Direktiven, mit denen man gezielt einzelne
<Directory>-Abschnitte mehr oder weniger stark absichern kann. Natürlich muss man Direktiven wie
LoadModule ssl_module modules/mod_ssl.o für das Laden des Moduls, die Direktive SSL Engine on für mindestens den
Default-Virtual Host, Listen 443 für den Port und für die Zertifikatsdateien noch
SSLCertificateFile /usr/local/apache/conf/ssl.crt/server.crt
SSLCertificateKeyFile /usr/local/apache/conf/ssl.key/server.key
korrekt aktivieren und die Pfade entsprechend der eigenen Konfiguration anpassen. Jedem Apache liegt eine Beispiel-Konfiguration bei - aufgrund der vielfältigen Direktiven kann man einiges falsch machen und sollte einen Übungsdurchlauf mit der Beispielkonfig durchspielen. Ein typischer Stolperstein ist, manche SSL-Direktiven außerhalb des betreffenden Virtual Hosts global zu konfigurieren.
Schritt 7: Den Apache mit SSL starten: Statt
apachectl start ruft man
apachectl startssl auf und gibt die Passphrase ein. Erst, wenn man sich der Unangreifbarkeit des Hosts absolut sicher ist, kann man die Verschlüsselung vom
server.crt wegnehmen und die Datei unverschlüsselt im Zertifikatsverzeichnis ablegen. Dann braucht es natürlich keine Passphrase beim Starten des Apache mehr.
Wenn alles durchkonfiguriert ist, liefert
openssl einen Parameter mit, mit dem man eine HTTPS-Verbindung per Hand simulieren kann.
openssl s_client -connect yourhost:443 -state -debug
liefert eine Menge Debugging-Output. Wenn etwas nicht auf Anhieb funktioniert, helfen die FAQs und der Userguide unter localhost/manual/ssl weiter.
Zu guter Letzt gilt es noch eines zu berücksichtigen: Ist SSL im Apache aktiv, ist die Strecke vom Browser zum Webserver mit SSL geteert - wer Datenbanken und LDAP als Backend noch hinter dem Apache verwendet, muss eventuell auch diese Strecke mit SSL absichern. Das mag manch einem als kleinkarierter Aufwand erscheinen, wenn die Backends in einem lokalen Netz ohne Zugriff von außen sitzen - aber schließlich könnte ein Angreifer von innen an dieser Stelle die Daten vom Apache zum Backend abfangen.
Links: