Firefox 37 hat ein neues Feature: Opertunistic Encryption, oder auch „TLS for http://“. Die Idee ist einfach: Wir versuchen einfach mal, die Seite über HTTPS zu laden, auch wenn das Zertifikat nicht nicht stimmt, behaupten aber auch nicht, die Seite wäre sicher. Einfach, aber wirkungsvoll. Ich finde es aktuell schrecklich, das es entweder verschlüsselt und authentifiziert mit teurem Zertifikat, oder völlig unverschlüsselt gibt. Sollte nicht viel mehr der Unterschied verschlüsselt und nicht authentifiziert (http) oder verschlüsselt und authentifiziert (https) sein?
Natürlich ist es ein leichtes, die Verschlüsselung auszuhebeln, wenn man ein aktiver Angreifer/MITM ist. Aber es hilft gegen passives Belauschen. Und das muss nicht mal die NSA sein, es geht auch um Sachen wie FireSheep. Auf jeden Fall ist die Idee das man so, wenn möglich, ein verschlüsselte Verbindung bekommt, aber da man ja nicht weiß, mit wem man redet, behauptet niemand, das die Verbindung sicher sei.
Natürlich gibt es auch Gegenstimmen, die sagen, auf diese Weise wird z.B. auch Caching beim ISP gestört, und das kann im schlimmsten Fall dazu führen, dass aktive Angriffe, die eben den entsprechenden Header unterdrücken, Standard werden, was natürlich noch schlimmer wäre. Ich denke jedenfalls, die Idee im Hintergrund völlig transparent, opportunistisch zu verschlüsseln ist keine schlechte Idee. Man darf nur nicht denken oder gar behaupten, es wäre sicherer als unverschlüsselt!
EDIT: Inzwischen hat Mozilla Firefox 37.0.1 veröffentlicht, die genau dieses Feature wieder abschaltet, weil man damit Zertifikatswarnungen bei HTTPS-Verbindungen manipulieren konnte. Um es weiterhin zu benutzten, müssen in der about:config die Keys network.http.altsvc.enabled und network.http.altsvc.oe auf true geändert werden, evtl. auch noch die (Typo?) Varianten mit atsvc statt altsvc.
So, genug der grauen Theorie, wie kann ich das Feature auf meinem Server aktivieren? Gleich vorneweg: Ich würde es noch nicht im Produktiveinsatz benutzen, dafür ist das doch noch zu frickelig. Daher beschreibe ich es unten für Ubuntu 14.04, das dürfte eine gerne genutzte Umgebung für Entwickler sein.
Zu aller erst müssen wir überhaupt eine SSL Verbindung aufbauen können, in der Default-Konfiguration lauscht Apache nicht mal auf Port 443. Das ist aber schnell geändert:
sudo apt-get install ssl-cert #Self-signed "Snakeoil Ltd." Zertifikat installieren sudo a2enmod ssl sudo a2ensite defaul-ssl sudo service apache2 restart
Jetzt sollte der Server über HTTPS erreichbar sein. Tipp1: Zertifikat nicht dauerhaft speichern, wir wollen ja sehen, ob es auch ohne klappt! Tipp2: Nicht vergessen, den Port 443 ggf. in der Firewall freizugeben oder über SSH zu tunneln 😉
Weiter geht’s. Opertunistic Encryption läuft über HTTP Alternate Services, und das ist ein Feature von HTTP 2.0. Leider kann Apache das aber nicht 🙁 Ein Modul dafür gibt es auch noch nicht, aber zumindest gibt es mod_spdy, und auf Spdy (von Google) basiert ja HTTP 2.0, daher reicht das auch.
Der Rest der Anleitung basiert ein wenig auf diesem schönen Tutorial, mit ziemlich viel Try&Error von mir (und den entsprechenden Erklärungen dazu)
Los geht’s. Mod_spdy gibt es zwar als fertiges Paket (wenn auch nicht in den Standard-Quellen, soweit ich weiß) aber nur für Apache 2.2, und Ubuntu ist ja schon auf 2.4 umgestiegen. Also müssen wir selber kompilieren, was aber auch kein Hexenwerk ist:
sudo apt-get install git g++ apache2 libapr1-dev libaprutil1-dev patch binutils make devscripts #Was man so braucht git clone https://github.com/eousphoros/mod-spdy.git #Sourcen hohlen cd mod-spdy/ git checkout origin/apache-2.4.7 #Branch auschecken cd src/ ./build_modssl_with_npn.sh #Gepatchtes mod_ssl Modul bauen chmod +x ./build/gyp_chromium #Nicht vergessen! make BUILDTYPE=Release #mod_spdy bauen
Hier gibt es nicht groß Überraschendes. Leider hat Apache’s normaler mod_ssl ein Feature nicht, das mod_spdy braucht, daher wird hier ein gepatchte Version gebaut. Wir checken vorher einen bestimmten Branch aus, weil HEAD nicht mehr mit der (etwas älteren Version) von Ubuntu funktioniert. Ggf mit apache2 -version nachsehen!
cd /usr/lib/apache2/modules/ sudo mv mod_ssl.so mod_ssl.so.orig #Altes Modul sichern sudo cp ~/mod-spdy/src/mod_ssl.so . #Neues hierher kopieren sudo cp ~/mod-spdy/src/out/Release/libmod_spdy.so ./mod_spdy.so #mod_spdy hierher kopieren
Nun brauchen wir noch Konfigurationsdateien: /etc/apache2/mods-available/spdy.conf
<IfModule spdy_module> # Turn on mod_spdy. To completely disable mod_spdy, you can set # this to "off". SpdyEnabled on # In order to support concurrent multiplexing of requests over a # single connection, mod_spdy maintains its own thread pool in # each Apache child process for processing requests. The default # size of this thread pool is very conservative; you can override # it with a larger value (as below) to increase concurrency, at # the possible cost of increased memory usage. # #SpdyMaxThreadsPerProcess 30 # Memory usage can also be affected by the maximum number of # simultaneously open SPDY streams permitted for each client # connection. Ideally, this limit should be set as high as # possible, but you can tweak it as necessary to limit memory # consumption. # #SpdyMaxStreamsPerConnection 100 # Turns on automatic generation of X-Associated-Content headers # for server push based on HTTPS request patterns. This is a # highly experimental feature and off by default. # #SpdyServerPushDiscoveryEnabled off #SpdyDebugServerPushDiscoverySendDebugHeaders off </IfModule>
und /etc/apache2/mods-available/spdy.load
LoadModule spdy_module /usr/lib/apache2/modules/mod_spdy.so
Nun können wir das Modul aktivieren:
sudo a2enmod spdy sudo service apache2 restart
Noch schnell ein AddOn installieren, das anzeigt, wenn eine Seite SPDY unterstützt, und die (HTTPS!-)Seite neuladen. Sieht gut aus! BTW: Nach ein paar Tagen mit dem AddOn: Erstaunlich, wie viele Seiten SPDY schon nutzen, obwohl es noch keine „offiziellen“ Module für Apache gibt!
So, jetzt aber weiter mit der Oppertunistic Encryption. Wie in dem Blogeintrag, den ich oben verlinkt hatte steht, müssen wir dafür einen extra Header setzen, der sagt, das dieser Ressource auch über einen anderen Kanal erreichbar ist. Das hier kommt in die /etc/apache2/sites-available/000-default.conf:
Header set Alt-Svc 'spdy/3.1=":443"'
Würden wir „richtiges“ HTTP 2.0 nutzen, würden wir statt spdy/3.1 dort h2 schreiben. Der Port muss natürlich der sein, wo die SSL-Seite drüber erreichbar ist 😉
Damit das ganze funktioniert, kann es nicht schaden, das Modul headers auch zu aktivieren 😉 Tipp: Ich meine, bei Apache 2.2 ist die Syntax von mod_headers anders, falls ihr das unter einer Distro ausprobiert, die noch bei Apache 2.2 hängt.
sudo a2enmod headers sudo service apache2 restart
Und siehe da: Es geht! Der erste Request wird noch an Port 80 gestellt, der Header kommt an. Alle weiteren Anfragen (also nach dem Neuladen, theoretisch aber auch schon Bilder in der Seite usw.) gehen an Port 443 und haben den Header Alt-Used in der Anfrage gesetzt. Firefox merkt sich das ein Weile, ab sofort gehen also alle Anfragen nur noch ein Port 443. Gelegentlich scheint sich hier auch noch was zu verklemmen, Firefox neu zu starten scheint zu helfen (dann geht die Anfrage erst Mal wieder an Port 80). Man beachte, wie Firefox das selbst-signierte Zertifikat schluckt, aber auch nirgends behauptet, die Verbindung sei sicher!
Und eigentlich wären wir hier fertig. Wäre da nicht … PHP
Leider ist mod_spdy nicht mit mod_php kompatibel, bzw. PHP ist einfach nicht threadsicher. Da zumindest ich PHP brauche, hier die Anleitung, wie man PHP von mod_php auf FCGI umstellt (was auch generell schneller usw. sein soll). Basis war diese Anleitung.
sudo apache2ctl -M #Nachsehen, ob php5_module gelistet. sudo a2dismod php5 #Weg damit sudo aptitude install libapache2-mod-fastcgi php5-fpm #mod_fastcgi und php-fpm installieren sudo cp /usr/share/php5/php.ini-development /etc/php5/fpm/php.ini #development php.ini benutzen (evtl. eigene!) sudo a2enmod actions #mod_actions brauchen wir gleich
Leider ist die Geschichte mit FCGI nicht ganz so einfach wie mit mod_php… (Installiert, lauft 😉 ) Aber ich habe es auch zum Laufen bekommen. Fast CGI ist erst mal nur eine Schnittstelle, über die Apache externe Programme anspricht. Die Schnittstelle steckt in mod_fastcgi (oder mod_fcgid, aber der wollte bei mir nicht); das externe Programm ist php-fpm. Wie jede PHP-Version hat auch diese eine eigene php.ini (die unter /etc/php5/fpm liegt, die „alte“ unter /apache, die Konsolen-Version unter /cgi). Oben kopiere ich einfach die Development-Version da hin, wenn ihr viel angepasst habt, könnt ihr vielleicht auch einfach die alter als /apache benutzen. Ein Diff kann helfen (auch, alten Kram rauszuwerfen 😉 )
Nun passen wir noch die Config entwas an:
/etc/apache2/mods-enabled/fastcgi.conf
<IfModule mod_fastcgi.c> AddType application/x-httpd-fastphp5 .php Action application/x-httpd-fastphp5 /php5-fcgi Alias /php5-fcgi /usr/lib/cgi-bin/php5-fcgi FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi -socket /var/run/php5-fpm.sock -pass-header Authorization <Directory /usr/lib/cgi-bin> Require all granted </Directory> </IfModule>
Erklärung: Gib alle .php Dateien einen komischen MIMI-Typ. Alle Request mit komischem MIMI-Typ an /php5-fcgi umleiten. /php5-fcgi an /usr/lib/cgi-bin/php5-fcgi umleiten (gibt es nicht, ist egal). Diesen, nicht existenten Pfad nicht selber ausliefern, sondern an das Socket von PHP-FPM weiterleiten. In dem Ordner /usr/lib/cgi-bin alle Zugriffe zulassen (sonst ist es allen verboten).
Danach noch ein Neustart von Apache, und es sollte wieder alles laufen! Tipp: Da PHP jetzt als eigener Prozess läuft, muss es bei einer Änderung der php.ini oder so auch neugestartet werden: sudo service php restart.
Das ist jetzt natürlich nur eine sehr knappe Skizze, die auf meinen Notizen basiert, ich hoffe, ich habe an alles gedacht. Zumindest läuft es bei mir jetzt. Auf unseren Prod-Server werde ich es wohl erst mal nicht bringen, dafür war mir das zu viel Gebastel. Aber generell funktioniert es, und wenn es erst offizielle Pakete dafür gibt, dürfte das auch viel einfach werden… Happy Encryption 😉
Wegen Spams sind die Kommentare für diesen Beitrag vorerst deaktiviert, bei Bedarf bitte per Mail melden!