HowTo: multiple Apache2 vhosts mit unterschiedlichen SSL-Zertifikaten

Die Aufgabe: in Apache bei verschiedenen vhosts verschiedene SSL-Zertifikate fuer die Verschluesselung definieren.
Das Problem: mit mod_ssl laesst sich das ganze nicht so einfach realisieren.
Die Ursache: vhosts basieren auf Basis von HTTP-Headers, SSL liegt ein Layer darunter. Die Verbindung wird gesichert bevor HTTP gesprochen wird. Der Server kann bei Verbindungsaufbau nicht wissen welchen vhost er danach bedienen soll, deswegen kann er das richtiger Zertifikat nicht auswaehlen.
Die Loesung: mod_gnutls
HowTo: das ganze unter Debian Lenny

Ich gehe an dieser Stelle davon aus, dass man bereits SSL-Zertifikate generiert hat (blubs).

Als naechstes ist es nun wichtig das Modul zu installieren, anzupassen und zu aktivieren:

aptitude install libapache2-mod-gnutls

Danach die /etc/apache2/mods-available/gnutls.conf anpassen:

<IfModule mod_gnutls.c>
  GnuTLSCache dbm /var/cache/apache2/gnutls_cache
 
  AddType application/x-x509-ca-cert .crt
  AddType application/x-pkcs7-crl    .crl
 
  GnuTLSCacheTimeout 300
  NameVirtualHost *:443
</IfModule>

und das Modul aktivieren:

a2enmod gnutls

Nun noch die Zeile:

Listen 443

zu der /etc/apache2/ports.conf hinzufuegen und dabei darauf achten, dass die Zeile vor der „Listen 80“ steht, da es sonst in der /var/log/apache2/error.log zu den folgenden Zeilen kommen kann:

[Sun Dec 05 14:37:06 2010] [error] [client ::1] GnuTLS: Handshake Failed (-8) 'A record packet with illegal version was received.'

Nun koennen die vhosts entsprechend eingerichtet werden. Hier ein generisches Beispiel fuer einen vhost:

<VirtualHost *:443>
    ServerAdmin webmaster@example.net
    ServerName www.example.net
    ServerAlias example.net
    DocumentRoot /var/www/example.net/
 
    <Directory /var/www/example.net/>
        Options +Indexes
    </Directory>
 
    GnuTLSEnable on
    GnuTLSCertificateFile /etc/ssl/myCA/private/www.example.net-key-cert.pem
    GnuTLSKeyFile /etc/ssl/myCA/private/www.example.net-key-cert.pem
    GnuTLSPriorities SECURE:!MD5
 
    CustomLog /var/log/apache2/example.net-access.log combined
</VirtualHost>

Nach einem Neustart von Apache2 kann nun per https auf den gewuenschten vhost zugegriffen werden, viel Spass beim Einrichten des zweiten und freien wenns klappt!

Howto: Der eigene Weave Minimal Server / Firefox Sync

Vor 1 1/2 Jahren habe ich den Artikel „Firefox Lesezeichen ueberall – Selfmade!“ geschrieben, wo ich beschrieben habe, wie man mit dem Firefoxplugin Foxmarks bzw. spaeter Xmarks und einem Apache Webserver mit mod_dav enabled seine Lesezeichen auf den eigenen Server synct und so die Kontrolle ueber die Daten behaelt.

Mozilla hat vor einiger Zeit das Weave Projekt gegruendet, dass es spaeter in Sync umbenannt hat. Fuer Firefox 3.5 aufwaerts gibts ein Firefoxplugin, ab der Version 4.0 wird die Funktionalitaet direkt in Firefox enthalten sein. Das Plugin kann Lesezeichen, Passwoerter, Einstellungen, Chronik und offene Tabs an einen Server syncen und so an verschiedenen Standorten verfuegbar machen. Grund genug sich das anzugucken und grund  fuer mich, mich von Xmarks zu verabschieden.

Voraussetzung fuer eine Installation ist, dass man einen eigenen Apacheserver irgendwo laufen hat. Wenn ich das richtig ueberblicke benoetigt man die Module

aptitude install libapache2-mod-php5 php5-sqlite

Anschliessend das weave_minimal.tgz aus diesem Blogeintrag vorletzter Absatz (Mirror) herunterladen und in ein Verzeichnis im DocumentRoot entpacken. Ich persoenlich habe mir eine eigene Subdomain gemacht und in Apache einfach fix einen neuen vhost eingerichtet. Wichtig ist nur, dass man anschliessend in der Apacheconfig einen Alias setzt:

Alias /weave /PATH/TO/DOCUMENTROOT//weave/index.php

Wobei der Pfad entsprechend der lokalen gegebenheiten anzupassen ist. Nun einmal den Apache neustarten damit die Aenderungen uebernommen werden. Als naechstes geht man mit seinem Webbrowser auf die URL: http://MYDOMAIN.TLD/weave/1.0/MYUSERNAME/info/collection wobei MYDOMAIN.TLD natuerlich mit dem eigenen Domainnamen und MYUSERNAME ein Benutzername ist. Bei der Aufforderung sich einzuloggen gibt man einfach eirgendwas ein. Die Authentifizierung schlaegt fehl aber die Datenbank wird erzeugt. Danach geht man auf den Server in das Verzeichnis in dem der entpackte Tarball liegt und legt einen Benutzer an mit dem Befehl:

php5 create_user MYUSERNAME

wobei MYUSERNAME wieder durch den gewuenschten Benutzernamen zu ersetzen ist. Weiter waehlt man sein Passwort und bestaetigt dieses. Nun ist man schon fast am Ziel. Falls noch nicht geschehen das Firefox Sync Plugin installieren und den Browser neustarten.

Wenn man nun Firefox Sync ueber den Assistenten einrichtet waehlt man als erstes aus „I Have a Firefox-Sync Account“. In dem zweiten Fenster sagt man „Eigenen Server verwenden“ und gibt die Server URL mit dem anschliessenden /weave/ ein, z.B. http://MYDOMAIN.TLD/weave/ . Der Benutzername und das Passwort sind die, die man bei dem create_user angelegt hat. Nachdem man diesen Punkt mit „Weiter“ bestaetigt hat, wird man aufgefordert seinen Sync Key einzugeben. Zuerst war ich etwas irritiert, aber es ist _nicht_ das Passwort sondern eine random Zeichenkette die die eigenen Daten auf dem Server dann verschluesselt. Ich habe hier einfach ein alternatives Passwort genommen. Mit „Weiter“ und „Fertigstellen“ Bestaetigen und voila…

Tomcat / Java config snippets

Die hier gemachten Angaben basieren alle auf dem Tomcat6 der bei Ubuntu Linux 10.04 LTS mitgeliefert wird.

Tomcat auf Port 80 laufen lassen

Um den Tomcat auf Port 80 laufen zu lassen in der /etc/tomcat6/server.xml den Connector port=“8080″ auf port=“80″ abaendern und in der /etc/default/tomcat6 den Wert AUTHBIND=yes setzen.

Tomcat Manager installieren

Der Tomcat Manager versteckt sich hinter dem Paket

aptitude install tomcat6-admin

Anschliessend in der /etc/tomcat6/tomcat-users.xml im Block <tomcat-users> die folgenden Zeilen einfuegen

<role rolename="manager"/>
<user username="MYUSERNAME" password="MYPASSWORD" roles="manager"/>

Danach kann man den Tomcat Manager unter der gewohnten Adresse http://MYHOSTNAME.TLD/manager/html aufrufen.

Zugriff bei Tomcat Manager auf IP beschraenken

Um den Tomcat Manager nicht fuer alle frei offen im Netz zu haben empfiehlt es sich den Zugriff darauf zu beschraenken. Dafuer in der /etc/tomcat6/Catalina/localhost/manager.xml den Context Eintrag wie folgt abaendern:

<Context path="/manager" docBase="/usr/share/tomcat6-admin/manager"
antiResourceLocking="false" privileged="true">
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="1\.2\.3\.4"/>
</Context>

Password Hashes statt Plain text in der tomcat-users.xml

Um Password Hashes statt Plain text Passwoerter zu verwenden muss der folgende Absatz in die Host section in der /etc/tomcat6/server.xml eingefuegt werden:

<Realm className="org.apache.catalina.realm.MemoryRealm" digest="SHA" />

anschliessend den Hash erzeugen mit:

cd /usr/share/tomcat6/bin/
export JAVA_HOME=/usr/lib/jvm/java-6-sun
./digest.sh -a SHA MYPASSWORD

und dann den Hash anstatt des Plain text Passwortes in der /etc/tomcat6/tomcat-users.xml im Passwortattribut speichern.

Komprimierung im Tomcat aktivieren

Um die Komprimierung der ausgelieferten Daten zu aktivieren in der /etc/tomcat6/server.xml dem Connector Eintrag um die folgenden Attribute erweitern:

compression="on"
compressionMinSize="2048"
noCompressionUserAgents="gozilla, traviata"
compressableMimeType="text/html,text/xml,text/plain,text/css,text/javascript"

Default root auf alternatives webapps Verzeichnis

Um den default root des Tomcat auf ein eigenes webapps Verzeichnis zu legen in der /etc/tomcat6/server.xml innerhalb des <Host> Blocks den folgenden Absatz einfuegen:

<Context path="" docBase="MYWEBAPPSDIR" debug="0" reloadable="true">
</Context>

Access log schreiben

Um eine access.log wie vom Apache gewohnt zu bekommen, muss in der /etc/tomcat6/server.xml den per default auskommentierten AccessLogValve einkommentieren:

<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs"
prefix="MYHOSTNAME_access_log." suffix=".txt" pattern="common"
resolveHosts="false"/>

Die Datei ist anschliessend unter /var/logs/tomcat6/MYHOSTNAME_access.log zu finden.

JMXREMOTE Connector aktivieren

Dafuer in der /etc/default/tomcat6 in den JAVA_OPTS=““ die folgenden Zeilen hinzufuegen:

-Dcom.sun.management.jmxremote='tomcat'
-Dcom.sun.management.jmxremote.port='8086'
-Dcom.sun.management.jmxremote.authenticate='true'
-Dcom.sun.management.jmxremote.password.file='/etc/java-6-sun/management/jmxremote.password'
-Dcom.sun.management.jmxremote.ssl='false'

und in der angegebenen Passwortdatei die Passwoerter definieren, z.B.:

monitorRole MYPASSWORD1
controlRole MYPASSWORD2

Notiz an mich: Diesen Beitrag NUR im HTML Fenster bearbeiten, nicht in der WYSIWIG, sonst werden die Code snippets rausgeschnitten.

Howto: Mobile Webinterface

Ich schrieb ja vor kurzem darueber, dass ich eine kleine Werder Bremen Newsuebersicht erstellt habe. Als ich nun fuer ein paar Tage im Kurzurlaub war und die Seite ueber mein Handy aufrief, fiel mir auf, dass sie ein mobiles Interface gebrauchen koennte. Das Bild war zu gross, und generell haette man wohl auch was bei den Ladezeiten optimieren koennen. Wieder zurueck habe ich mich dann gleich an die Arbeit gemacht. Schnell bin ich auf zwei sehr nette Loesungen gestossen und habe kurzerhand beide miteinander Kombiniert. Die Loesungen findet Ihr auf den beiden Seiten:

Der erste Blogeintrag beschreibt, worauf man achten muss wenn man ein mobile Webseite erstellt, und beinhaltet eine Anleitung um seine eigene Seite mobil-Freundlich mit einer Subdomain zu erstellen. Der Weg ist recht simpel: Man erstellt eine Subdomain, z.B. von www.pregos.info dann mobile.pregos.info und weist der Subdomain den gleichen DocumentRoot zu. Anschliessend erstellt man zwei PHP Dateien und legt diese in den DocumentRoot. Beide PHP-Dateien werden ueber eine .htaccess vor und nach jeder HTML-Seite aufgerufen. Dabei wird ueberprueft ob die mobile.pregos.info Subdomain aufgerufen wurde, und wenn ja der HTML-Quelltext durch verschiedene Filter gejagt, die dann die Seite entsprechend anpassen.

Dieser Weg ist sehr schnell eingerichtet und funktioniert wunderbar. Ich finde ihn aber nicht schoen, denn das Szenario was mir vorschwebt ist eine mobile Seite von http://werder.pregos.info unter der gleichen Domain, da  jetzt noch ne Subdomain ranzuhaengen http://m.werder.pregos.info, nee, zuviel. Ich moechte, dass die Seite je nachdem von welchem Geraet sie aufgerufen wird, entweder als mobile Version oder als normale zu sehen ist.

Ein simpler Weg dieses zu erreichen waere z.B. mittels JavaScript festzustellen wie gross die Bildschirmaufloesung des anzeigenden Browsers ist und dementsprechend die Seite mittels CSS zu layouten. Das bedeutet aber gleichzeitig, dass ich mit JavaScript arbeiten muss und alle Browser das unterstuetzen muessen und Rechenleistung auf dem mobilen Geraet und und und… Ich will EINE Domain, EINE URL und SELBSTERKENNUNG des Servers.

Ueber WURFL (Wireless Universal Ressource File) bin ich dann irgendwie zu dem Projekt Apache Mobile Filter gestossen. Apache Mobile Filter ist eine Apache-Plugin, dass die Funktionen von WURFL direkt in Apache zur Verfuegung stellt. WURFL kennt z.B. alle UserAgents (z.Zt. 8661 verschiedene) und kann auf dieser Basis sagen, ob das gerade aufrufende Geraet ein mobiles Geraet ist oder nicht. Ueberpruefen und sehen was AMF alles so an Variablen zur Verfuegung stellt koennt Ihr unter der Adresse: http://apachemobilefilter.nogoogle.it/php_test.php

Das schoene ist, dass AMF diese Variablen in PHP unter Apache als dessen Server Enviroment Variablen zur Verfuegung stellt. Ich kann also in PHP z.B. mit der Variable $_SERVER[‚AMF_IS_WIRELESS_DEVICE‘] arbeiten. Mit dieser Loesung kann ich nun serverseitig ueberpruefen ob es sich um ein mobiles Endgeraet handelt oder nicht, und dementsprechend die mobile Version der Seite anzeigen lassen oder nicht.

Nur der Weg dahin brauchte noch etwas, der Support von Apache Mobile Filter war aber allererste Sahne, echt super, kann man nicht anders sagen, und fuer die Nachwelt hier nochmal ein Auszug aus meiner .bash_history:

mkdir foo
cd foo
wget http://downloads.sourceforge.net/project/mobilefilter/ApacheMobileFilter/2.21/Apache2-WURFLFilter-2.21.tar.gz?use_mirror=dfn
tar -xzvf Apache2-WURFLFilter-2.21.tar.gz
cd Apache2-WURFLFilter-2.21/
perl Makefile.PL
make install
aptitude install libapache2-mod-perl2 libgd-gd2-perl libgd-tools
a2enmod perl
cpan Apache2::WURFLFilter Apache2::Filter Apache2::RequestRec Apache2::RequestUtil Apache2::Connection Apache2::SubRequest Apache2::Log CGI::Cookie APR::Table CGI::Cookie LWP::Simple Image::Resize IO::Uncompress::Unzip Cache::FileBackend
mkdir /var/www/MobileFilter
chown www-data:www-data /var/www/MobileFilter

Dazu habe ich noch in die /etc/apache2/httpd.conf die folgenden Eintraege hineingeschrieben:

PerlSetEnv MOBILE_HOME /var/www/MobileFilter
PerlSetEnv CacheDirectoryStore /tmp
PerlSetEnv WurflNetDownload true
PerlSetEnv DownloadWurflURL  http://downloads.sourceforge.net/wurfl/wurfl-latest.zip
PerlSetEnv LoadWebPatch true
PerlSetEnv PatchWurflNetDownload true
PerlSetEnv PatchWurflUrl http://wurfl.sourceforge.net/web_browsers_patch.xml
PerlSetEnv CookieCacheSystem true
PerlSetEnv CapabilityList all
PerlModule Apache2::WURFLFilter
PerlTransHandler +Apache2::WURFLFilter
#PerlOutputFilterHandler Apache2::AMFDeviceMonitor

Anschliessend muss der Apache Webserver mit einem /etc/init.d/apache2 restart neu gestartet werden.

Welche Variablen euch dann zur Verfuegung stehen und ob alles funktioniert kann man mit der Test-PHP Seite ueberpruefen die ich oben bereits einmal verlinkt habe. Diese koennt Ihr euch ganz einfach auf euren eigenen Server schmeissen, gibts hier zum Download.

Wenn irgendwelche Fehler auftauchen oder (wie bei mir zu Anfang) die Variablen nicht zur Verfuegung stehen, einfach nochmal ein rm -rf /tmp/wurfl* machen und Apache neustarten.

Ach so… um die mobile Seite jetzt zu implementieren habe ich die bereits beschriebene Loesung mit den PHP-Files und der .htaccess genommen und einfach in der global_prepend.php und die Zeile:

if ($_SERVER['SERVER_NAME'] == 'mobile.myawesomeblog.com') {

ersetzt durch

 if ($_SERVER['AMF_IS_WIRELESS_DEVICE'] == 'true') {

sowie die nachfolgende Zeile mit der URL-Ersetzung von normaler zu mobile-URL einfach weggelassen.