Alle Blogs Updaten bei WordPress MU + Domain Mapping

Nach einem WordPress Update muss man ab und an alle Blogs einer Multisite-Installation updaten. An sich kein Problem – wenn man nicht gerade ein SSL-verschlüsseltes Backend hat und zugleich Domain Mapping verwendet. Denn dann versucht das Updater-Script die URL https://meinblog.blognetzwerk.de/ aufzurufen, obwohl das SSL-Zertifikat für https://meinblog.de/ gilt. Der Update-Vorgang schlägt dann fehl. Abgesehen davon wird der Vorgang bei einer größeren Anzahl Blogs sehr, sehr mühselig, weil ein Fehler das ganze abbrechen lässt.

Die Lösung ist ganz einfach: ein kleines Helper-Script. Es ist sicher nicht optimal, da es nicht die WordPress-Umgebung nutzt und man die MySQL-Zugangsdaten selbst eingeben muss, aber es funktioniert recht gut, nimmt einem viel Arbeit ab – und wenn wer mag, kann es wer ja auch gerne verbessern, ich update das Script hier gerne. Hier ist es:

<?php
define(‘DB_NAME’, ‘datenbankname’);

/** Ersetze username_here mit deinem MySQL-Datenbank-Benutzernamen */
define(‘DB_USER’, ‘datenbankuser’);

/** Ersetze password_here mit deinem MySQL-Passwort */
define(‘DB_PASSWORD’, ‘datenbankpasswort’);

/** Ersetze localhost mit der MySQL-Serveradresse */
define(‘DB_HOST’, ‘datenbankhost’);

mysql_connect(DB_HOST, DB_USER, DB_PASSWORD);
mysql_select_db(DB_NAME);

$blog_list = mysql_query(“SELECT blog_id, domain, path FROM prefix_blogs WHERE archived = ’0′ AND mature = ’0′ AND spam = ’0′ AND deleted = ’0′”);
$mapping_list = mysql_query(“SELECT blog_id, domain FROM prefix_domain_mapping WHERE active = 1 ORDER BY id DESC”);

$urls = Array();

while ($line = mysql_fetch_array($mapping_list)) {
$urls[$line['blog_id']] = $line['domain'];
}

while ($line = mysql_fetch_array($blog_list)) {
if (!isset($urls[$line['blog_id']]))
$urls[$line['blog_id']] = $line['domain'];
}

foreach($urls as $blog_url) {
echo(‘Updating ‘ . $blog_url . ‘ … ‘);
$result = file_get_contents(‘https://’ . $blog_url . ‘/wp-admin/upgrade.php?step=1′);
if(strpos($result, ‘Aktualisierung erfolgreich’))
echo(“done.\n”);
else if(strpos($result, ‘Keine Aktualisierung notwendig’))
echo(“not necessary.\n”);
else {
echo(“unknown result.\n”);
echo($result);
}
}

?>

Die ersten Zeilen sind 1:1 aus der wp-config.php kopiert, der Rest ist glaube ich recht selbsterklärend (das prefix bei den Tabellen muss man ggf. noch anpassen). Das Script ruft man am besten über die Konsole auf – in meinem Fall mit

sudo -u wordpress php update-blogs.php

Damit arbeite ich als der Nutzer wordpress und habe den entscheidenden Vorteil, dass das Script nicht irgendwann einfach abbrechen kann und mir die Statusmeldungen zwischendurch auf die Konsole ausgibt.

Vielleicht kann ja irgendwer den Codeschnipsel brauchen. Viel Spaß damit!

Warum ich nicht zu Demos wie #hh2112 gehe und warum das so bleiben wird

Samstag, der 21.12.2013, kurz nach 21 Uhr. Ich reise von Bochum nach Lübeck und steige zu diesem Zeitpunkt um. Obwohl ich die Ziele inhaltlich unterstütze, bin ich bewusst nicht zu der Demo für den Erhalt des linksalternativen Hamburger Kulturzentrums Rote Flora gegangen, weil ich ein sehr ungutes Gefühl bezüglich einem Teil der Teilnehmer hatte. Und leider hat sich dieses Gefühl bestätigt – einmal mehr.

Zunächst aber scrollte ich durch meine Twitter-Timeline und war erschrocken über das, was sich die Hamburger Polizei geleistet hat. Ich habe ein Jahr in Hamburg gelebt und kenne das Umfeld der Roten Flora ein wenig. Eine unpassendere Polizeistrategie wäre kaum zu finden gewesen. Wie sich im Nachhinein herausstellte, hat die Polizei auch noch sichtlich Gründe vorgeschoben, um das zu provozieren, was sie nachher den Demonstranten vorwarf – eine völlig verdrehte Logik, die vermutlich geplant war. Für einen kurzen Moment ärgerte ich mich, dass ich nicht doch mitdemonstriert hatte, so unmöglich empfand ich das Verhalten der Polizei.

Mit mir fuhren einige Demonstranten mit im Regional-Express nach Lübeck. Eine Gruppe von etwa 8 Personen war nur wenige Sitze weiter. Kurz vor Lübeck habe ich so ein Telefonat mithören dürfen, nachdem ich meine Kinnlade erst einmal vom Boden aufsammeln musste. Eine junge Frau telefonierte mit einigen Freunden, welche noch in Hamburg nahe der Roten Flora waren und nun zum Hauptbahnhof und nach Lübeck wollten. “Dann klatscht noch ein paar Bullen auf dem Weg!” forderte sie ihre Freunde auf.

“Dann klatscht doch noch ein paar Bullen!”. In ihrer Stimme war kein Anzeichen dafür, dass sie das als Scherz meinte. Auch nicht in ihrer Mimik. Im Gegenteil: das war für sie ein sichtlich vollkommen selbstverständlicher Teil ihrer Lebensrealität. Und nicht nur für sie, auch ihre um sie stehenden Freunde schienen das für absolut normal zu halten.

“Dann klatscht doch noch ein paar Bullen!”. Wie kalt und unmenschlich kann ein Mensch sein, dass er Gewalt gegen andere Menschen scheinbar als erstrebenswerten Sport bzw. als erstrebenswerte Rache empfindet? Die den Demonstranten gegenüberliegende Seite – das sind Menschen, keine roboterartigen Feinde. Menschen, die zu großen Teilen einfach nur ihren Job machen. Menschen mit Familie, Freunden, Kindern. Menschen wie die Demonstranten auch, nur zufällig auf der anderen Seite.

Und natürlich gibt es dabei auch Polizisten, die es übertreiben. Polizisten, die viel zu viel Gewalt anwenden. Polizisten, die scheinbar ein Vergnügen daran haben, Menschen körperlich und psychisch zu quälen. Aber was für eine Doppelmoral ist es, diese Polizisten zu verurteilen, und dann in den eigenen Reihen Menschen zu haben, für die es kaum etwas erstrebenswerteres gibt, als “Bullen zu klatschen”?

Warum werden Menschen, die mit Knallkörpern anreisen, die Pflastersteine als Wurfgeschosse herausreißen, die Straßenschilder als Waffen nutzen, … warum werden solche Menschen von der Demonstrationsleitung geschützt? Warum von den Mitdemonstranten? Will man nicht für eine bessere, eine sozialere, eine fairere Welt demonstrieren? Was ist an einer Welt besser, in der Menschen sichtlich nur zu einer Demo kommen, um “Bullen zu klatschen”?

An diesem Samstag haben sich meiner Meinung nach beide Seiten der Lächerlichkeit preisgegeben (und führen jetzt auch noch einen albernen Krieg über die Deutungshoheit dieses Desasters). Dieser Samstag hat mir persönlich aber auch gezeigt, warum ich bei derartigen Demonstrationen fehl am Platze bin. Ich habe kein Verständnis.

Das ist schade, denn ich würde die Ziele dieser Demonstration sehr gerne unterstützen. Aber durch die erzwungene Solidarität mit Menschen, die “Bullen klatschen”, bin ich eben nicht vor Ort, um meine Stimme für eine gute Sache zu erheben. Und werde auch weiterhin nicht vor Ort sein. Denn für ein Weltbild, in dem man “Bullen klatschen” geht, stehe ich nicht zur Verfügung.

Speed! Moaar Speed! – WordPress mit Nginx + fastcgi_cache + optional Domain Mapping

WordPress ohne Caching ist langsam – und wer will schon eine langsame Website haben? Nicht nur die Nutzer sind genervt, auch Google, und das ist dann schlecht für die Suchmaschinenplatzierung, also ist es auch Bestandteil von SEO. Also – was tun?

Der klassische Weg ist wohl ganz klar W3 Total Cache oder WP Super Cache. Damit kann man zwar schöne Ladezeiten erreichen, aber es geht noch schneller und mit mehr Features. Dieses Tutorial wird sich zunächst einmal nur das Caching für anonyme Besucher behandeln (und Domain Mapping sowie SSL im Backend beachten, was ein recht perfektes WordPress Setup ergibt), weitere Techniken für das Beschleunigen von WordPress selbst wird es in einem weiteren Post geben. Hier das Ergebnis, lediglich Piwik verhindert, dass dort nicht 98 – 99 % steht:

Pingdom More Speed

Voraussetzungen für dieses Tutorial ist zwingend ein eigener (virtueller) Server, am besten ohne Plesk oder dergleichen. Außerdem sind Linux-Konsolen-Basiskenntnisse sehr hilfreich – aber die braucht man eh als Server Admin. In diesem Tutorial wird Ubuntu 12.04 Server verwendet, in anderen Distributionen müssen die Befehle ggf. entsprechend angepasst werden.

Einrichtung von nginx

Zunächst einmal die Einrichtung von Nginx. Um Caching zu ermöglichen, brauchen wir eine Nginx-Version mit eincompiliertem fastcgi_cache. Dies ist leider nicht bei dem normalen nginx Paket der Fall, jedoch aber bei nginx-naxsi. Dies installieren wir mit sudo apt-get install nginx-naxsi.

Hierzu sind im Wiki dieses äusserst schnellen Webservers vollständige Konfigurationdateien hinterlegt. Zu beachten ist, dass alle rewrite Regeln in der Konfiguration sind, es gibt keine .htaccess bei Nginx. Für Domain Mapping und SSL im Backend müssen wir diese noch ein wenig modifizieren, das sähe dann so aus:

Datei /etc/nginx/nginx.conf

[...]

http {

types_hash_max_size 2048;
# server_tokens off;
map_hash_bucket_size 64;

server_names_hash_bucket_size 64;
client_max_body_size 128M;

[...]

fastcgi_cache_path /var/run/nginx-cache levels=1:2 keys_zone=WORDPRESS:256m max_size=512m inactive=60m;
fastcgi_cache_key “$scheme$request_method$host$request_uri”;
fastcgi_cache_use_stale error timeout invalid_header http_500;

include /etc/nginx/templates/blogid;

}

Bei dieser Konfigurationsdatei habe ich mal alles rausgeworfen was nicht relevant für unsere Aufgabe ist. Einerseits müssen wir die Standard-Werte für Server und Maps erhöhen, das geschieht im ersten Abschnitt. Andererseits definieren wir einen maximal 512 MB großen Cache für WordPress. Die Zeile mit fastcgi_cache_use_stale ist dabei ein sehr spannendes Feature; sie sorgt dafür, dass Nginx bei einem Error 500 z.B. durch ein fehlerhaftes PHP Script in WordPress trotzdem eine Seite ausliefert – die gecachte nämlich, auch dann, wenn der Cache eigentlich veraltet ist. Das ist einer der Zusatzfeatures von fastcgi_cache im Vergleich zu den WordPress-internen Caching-Methoden. Außerdem wird eine Map mit den Blog IDs inkludiert (siehe nächste Datei).

Datei /etc/nginx/templates/blogid

map $http_host $blogid {
default -999;
include /srv/www/wordpress/httpdocs/wp-content/blogs.dir/1/files/nginx-helper/map.conf;
}

Hier wird die abhängig von der Domain die Blog ID zugeordnet. Das ist wichtig für die Auswahl des richtigen Ordners in /wp-content/blogs.dir/ bei einer Installation mit aktivierter Multisite-Funktionalität (und damit wichtig für Domain Mapping). Die Datei /srv/www/wordpress/httpdocs/wp-content/blogs.dir/1/files/nginx-helper/map.conf wird durch das nginx-helper Plugin generiert, auf dieses komme ich später noch zu sprechen.

Datei /etc/nginx/sites-available/org.sectio-aurea

server {
server_name sectio-aurea.org www.sectio-aurea.org;
access_log /var/log/nginx/org.sectio-aurea.access.log;
error_log /var/log/nginx/org.sectio-aurea.error.log;
include /etc/nginx/templates/wordpress;

access_log /var/log/nginx/cache.log cache;
}
server {
server_name sectio-aurea.org;

access_log /var/log/nginx/org.sectio-aurea.access.log;
error_log /var/log/nginx/org.sectio-aurea.error.log;

ssl on;
ssl_certificate /etc/ssl/private/org.sectio-aurea.chain.complete;
ssl_certificate_key /etc/ssl/private/org.sectio-aurea.key;

ssl_session_timeout 5m;

ssl_protocols SSLv3 TLSv1;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP;
ssl_prefer_server_ciphers on;

include /etc/nginx/templates/wordpress-ssl;
}

Diese jeweiligen Parameter dürfte recht selbsterklärend sein. Interessant ist die Funktion include, da wir dort alle nicht domainabhängigen Konfigurationsdateien zentral gespeichert werden können. Das macht insbesondere bei großen WordPress-Setups mit vielen Domains sehr viel Sinn.

Datei /etc/nginx/templates/wordpress

listen 80;

root /srv/www/wordpress/httpdocs;

index index.php;
client_max_body_size 128M;

set $skip_cache 0;

if ($request_method = POST) {
set $skip_cache 1;
}

if ($request_uri ~* “(/wp-admin/|/xmlrpc.php|/wp-(app|cron|login|register|mail).php|wp-.*.php|/feed/|index.php|wp-comments-popup.php|wp-links-opml.php|wp-locations.php|sitemap(_index)?.xml|[a-z0-9_-]+-sitemap([0-9]+)?.xml)”) {
set $skip_cache 1;
}

if ($http_cookie ~* “comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in”) {
set $skip_cache 1;
}

location / {
try_files $uri $uri/ /index.php?q=$uri&$args;
}

location ~ ^/files/(.*)$ {
try_files /wp-content/blogs.dir/$blogid/$uri /wp-includes/ms-files.php?file=$1 ;
access_log off;
log_not_found off;
expires max;
}

location ^~ /wp-content/blogs.dir {
internal;
alias /srv/www/wordpress/httpdocs/wp-content/blogs.dir ;
access_log off;
log_not_found off;
expires max;
}

if (!-e $request_filename) {
rewrite /wp-admin$ $scheme://$host$uri/ permanent;
}

location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
access_log off;
log_not_found off;
expires max;
}

location ~ \.php$ {
location ~ /wp-(admin|login) {
return 301 https://$host$request_uri;
}

try_files $uri = 404;
fastcgi_index index.php;
fastcgi_pass unix:/var/run/php5-wordpress.sock;
include fastcgi_params;

fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;

fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
fastcgi_cache WORDPRESS;
fastcgi_cache_valid 60m;
}

location ~ /purge(/.*) {
fastcgi_cache_purge WORDPRESS “$scheme$request_method$host$1″;
}

location = /favicon.ico {
log_not_found off;
access_log off;
}

location = /robots.txt {
access_log off;
log_not_found off;
}

location ~ /\. {
deny all;
access_log off;
log_not_found off;
}

location ~* /(?:uploads|files)/.*\.php$ {
deny all;
}

Hier sind schon einige Zeilen mit dabei, welche direkt mit dem Caching zu tun haben. Wir definieren am Anfang, dass alles gecached werden soll, und schalten den Cache dann z.B. für den Adminbereich oder bei der Anwesenheit von Cookies ab, weil er dort nichts bringen würde.

Interessant sind auch noch die rewriting Regeln, dort insbesondere try_files /wp-content/blogs.dir/$blogid/$uri /wp-includes/ms-files.php?file=$1 ; . Dort wird schon in der Nginx Konfiguration je nach URL der richtige Ordner im blogs.dir ausgewählt. Die Variable $blogid wurde in /etc/nginx/nginx.conf mit eingebunden.

Ein wichtiges Sicherheitsfeature kommt ganz am Ende noch dazu: es können keine PHP Dateien im upload / blogs.dir ausgeführt werden. Dies sind die einzigen beiden Orte, wo PHP Schreibrechte benötigt. Das heisst: es gibt keine Möglichkeit mehr, wie ein Angreifer Dateien auf den Webserver ablegen und ausführen kann. Entweder hat der Angreifer keine Schreibrechte – oder er kann die Dateien nur downloaden, nicht aber ausführen, womit er dann zusammengenommen wenig Unsinn machen kann (Stichwort: Remote Shell). Dieser Mechanismus ist nur ein Teil eines vernünftigen Sicherheitskonzeptes, aber ein sehr effektiver, da er das Ausnutzen der allermeisten Lücken in Themes oder Plugins unterbindet.

Ein anderes Sicherheitsfeature ist ein verschlüsseltes Backend. Dies realisiere ich mit kostenlosen StartSSL Zertifikaten und alles über eine IP mit SNI. Leider werden sowohl StartSSL als auch SNI nicht von allen Browsern unterstützt, so dass die Seite selbst ohne Verschlüsselung ausgeliefert werden sollte, ansonsten bekommen manche Nutzer hässliche Fehlermeldungen. Dies erfordert an mehreren Punkten Nacharbeit.

Außerdem haben wir noch die /purge/ Zeile, welche wir benötigen, um z.B. bei einem neuen Post den Cache zu löschen.

/etc/nginx/templates/wordpress-ssl

listen 31.172.41.1:443;

root /srv/www/wordpress/httpdocs;

index index.php;
client_max_body_size 128M;

set $skip_cache 0;

if ($request_method = POST) {
set $skip_cache 1;
}

if ($request_uri ~* “(/wp-admin/|/xmlrpc.php|/wp-(app|cron|login|register|mail).php|wp-.*.php|/feed/|index.php|wp-comments-popup.php|wp-links-opml.php|wp-locations.php|sitemap(_index)?.xml|[a-z0-9_-]+-sitemap([0-9]+)?.xml)”) {
set $skip_cache 1;
}

if ($http_cookie ~* “comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in”) {
set $skip_cache 1;
}

location ~ ^/files/(.*)$ {
try_files /wp-content/blogs.dir/$blogid/$uri /wp-includes/ms-files.php?file=$1 ;
access_log off;
log_not_found off;
expires max;
}

location ^~ /blogs.dir {
internal;
alias /srv/www/wordpress/httpdocs/wp-content/blogs.dir ;
access_log off;
log_not_found off;
expires max;
}

if (!-e $request_filename) {
rewrite /wp-admin$ $scheme://$host$uri/ permanent;
}

location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
access_log off;
log_not_found off;
expires max;
}

location ~ /wp-(admin|login|includes|content) {
try_files $uri $uri/ /index.php?q=$uri&$args;
location ~ \.php$ {
try_files $uri = 404;
fastcgi_index index.php;
fastcgi_pass unix:/var/run/php5-wordpress.sock;
include fastcgi_params;

fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;

fastcgi_read_timeout 120;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
fastcgi_cache WORDPRESS;
fastcgi_cache_valid 60m;
}
}

location / {
return 301 http://$host$request_uri;
}

location ~ /purge(/.*) {
fastcgi_cache_purge WORDPRESS “$scheme$request_method$host$1″;
}

location = /favicon.ico {
log_not_found off;
access_log off;
}

location = /robots.txt {
access_log off;
log_not_found off;
}

location ~ /\. {
deny all;
access_log off;
log_not_found off;
}

Diese Zeilen kennen wir bereits weitestgehend aus dem unverschlüsselten Template. Interessant ist hier höchstens noch die Weiterleitung auf die unverschlüsselte Seite, wenn wir uns nicht im Backend befinden.

Einrichten von PHP

Damit wäre Nginx jetzt konfiguriert. Nun brauchen wir noch PHP. Um genau zu sein php-fpm. Durch dieses Setup bekommen wir gleich die Funktionalität, die beim Apache mit suexec bereitgestellt wird – nur komfortabler. Installieren tun wir PHP mit sudo apt-get install php-fpm. Jede Websoftware braucht eine eigene Konfigurastionsdatei, also begeben wir uns in den Ordner /etc/php5/fpm/pool.d mit cd /etc/php5/fpm/pool.d. Dann kopieren wir die default.conf: cp default.conf wordpress.conf. Diese passen wir nun an: Die relevanten Zeilen sind folgende:

[wordpress] #statt [default]

user = wordpress
group = wordpress

listen = /var/run/php5-wordpress.sock

Den Socket /var/run/php5-wordpress.sock kennen wir schon aus der Nginx-Konfiguration. Natürlich braucht es auch einen Systemuser und eine Systemgruppe namens wordpress – und natürlich sollten die Dateien der WordPressinstallation mit Ausnahme vom upload / blogs.dir Ordner nicht dem Systemuser wordpress gehören, damit PHP nirgends Schreibrechte hat wo es das nicht dringend braucht. Das war alles – so leicht ist die PHP-Bereitstellen und die suexec-Funktionalität mit Nginx.

Einrichtung von WordPress

Nun ist alles bereit, um WordPress anzupassen. Ich gehe hier nicht auf die Erstellung eines Blog-Netzwerkes oder die Einrichtung von Domain Mapping ein, dazu gibt es genug Tutorials. Aber WordPress braucht einige kleine Anpassungen, damit es gut mit dem Nginx Caching funktioniert.

Einerseits brauchen wir das nginx-helper Plugin. Dieses liefert uns Unterstützung für das Domain Mapping (Stichwort blogid von weiter oben) und Unterstützung beim Cache leeren. All diese Features aktivieren wir in der Admin-Oberfläche der Netzwerkverwaltung. Das Plugin weist einen darauf hin, wenn Ordner fehlen, Rechte neu zu vergeben sind etc, also genau die Fehlermeldungen lesen!

Das verschlüsselte Backend macht gleich an zwei Stellen Probleme. Einerseits werden die gecachten Dateien nicht immer korrekt gelöscht, da der Löschbefehl ja aus dem verschlüsselten Backend ausgeht. Er versucht also verschlüsselte gecachte Seiten zu löschen – gecached wurden aber unverschlüsselte Seiten. Dies löst man, indem man (aber nur wenn das Admin Interface auch wirklich verschlüsselt ist) in der Datei /wp-content/plugins/nginx-helper/purger.php in Zeile 204 ganz an den Anfang der Funktion purgeUrl folgende zwei Zeilen ergänzen:

if (substr($url, 0, 5) == ‘https’)
$url = ‘http’ . substr($url, 5);

Damit löschen wir immer die unverschlüsselten Seiten. Verschlüsselte Seiten werden ja eh nicht gecached, da nur das Backend verschlüsselt wird – und das wird nicht gecached.

[UPDATE] Den gesamten Cache zu löschen funktioniert leider auch nicht, wenn man WordPress PHP (siehe PHP-FPM Einrichtung) unter einem anderen User laufen lässt wie nginx. Letzterer läuft unter www-data, ersteres unter wordpress, somit kann PHP nicht wie im Plugin nginx-helper geplant auf Dateiebene alle Cahce-Files löschen. Um dies zu beheben, müssen wir manuell alle Purge-Befehle aufrufen. Dies ist in nginx-helper bereits vorbereitet, daher müssen wir die erste Zeile der Funktion function true_purge_all() in derDatei /wp-content/plugins/nginx-helper/purger.php ersetzen durch $this->purge_them_all(); . Voila, purge all funktioniert.[/UPDATE]

Ein zweites nerviges Problem ist, dass der Editor von WordPress im Backend dann bei internen Links bzw. bei Medien wie Bildern auch auf die verschlüsselten Medien verlinkt. Das unterbinden wir durch ein kleines Zusatzplugin, welches ich ssl-url-fix getauft habe und aus einer einzigen PHP-Datei namens /wp-content/plugins/nginx-helper/ssl-url-fix/ssl-url-fix.php besteht:

<?php
/*
Plugin Name: SSL URL Fix
Plugin URI: http://sectio-aurea.org/
Description: SSL URL Fix
Version: 1.0
Author: Ernesto Ruge
Author URI: http://sectio-aurea.org/
*/
function fix_ssl_url_save($content) {
$host = substr(get_site_url(), is_ssl() ? 8 : 7);

$content = str_replace(‘https://’ . $host, ‘http://’ . $host, $content);

return($content);
}
add_filter( ‘content_save_pre’, ‘fix_ssl_url_save’, 999, 1);
function fix_ssl_url_load($content, $uid) {
$host = substr(get_site_url(), is_ssl() ? 8 : 7);

$content = str_replace(‘http://’ . $host, ‘https://’ . $host, $content);

return($content);
}
add_filter( ‘content_edit_pre’, ‘fix_ssl_url_load’, 10, 2 );
?>

Dies hat nichts direkt mit dem Caching zu tun, aber es nervt um so mehr, wenn einige Besucher die Medien nicht sehen können, daher hier die Erwähnung.

Resultat: Highspeed-Wordpress

Ansonsten habe ich eine gute Nachricht: wir sind fertig! Wir haben nun ein Setup, welches wirklich schnell und belastbar ist – in einem kurzen Test habe ich 2000 Requests auf die reine Index-Seite (ohne css / js Dateien) machen können, und die CPU meines eher kleinen virtuellen Servers hat sich dabei weiterhin gelangweilt. Außerdem wird die gecachte Index-Seite in zum Teil in unter 25 ms komplett ausgeliefert. Wir stoßen damit schnell an die Grenzen des Clients, die Website zu rendern – das verursacht bei meinen Seiten die größte Verzögerung im Lade-Wasserfall z.B. von Pingdom (hier ein exemplarisches Beispiel). Ausserdem wird Piwik sehr sehr deutlich sichtbar – aber das wird ja eh erst am Ende der Seite geladen. Die im Wasserfall erst am Ende geladenen Bilder aus der CSS Datei verbleiben auch im Browser Cache, so dass der Nutzer eine extrem schnelle Website vorfinden wird.

Einen Fallstrick gibt es noch, wozu ich aber keine generalisierte Anleitung zu geben kann: das Caching wird nur dann aktiv, wenn keine Cookies gesetzt sind. Manche (aber glücklicherweise sehr wenige) Plugins setzen aber Cookies, meist sinnloserweise. Bei mir war das beim Plugin Awesome Flickr Gallery der Fall. Dies muss man manuell herauspatchen. Um derartige Probleme herauszufinden hilft das Firefox-Plugin Web-Developer.

Ansonsten wünsche ich viel Spaß bei einem extrem schnellen WordPress! Ergänzungen und Korrekturen dieser Anleitung sind natürlich gerne gesehen. Für weitere Informationen kann ich auch noch dieses und dieses und dieses und dieses Tutorial empfehlen, auf diesen basiert in weiten Teilen meine Konfiguration – und da werden einige Details noch deutlich anschaulicher erklärt.

Als letztes noch die Kategorie bekannte Bugs: das Preview beim designen von Themens funktioniert in den meisten Browsern nicht, weil da auf einer verschlüsselten Seite eine unverschlüsselte angezeigt werden soll, was neuere Browser blocken. Wer da eine gute Idee hat wie man DAS lösen kann – immer her damit.

Spam von SEO Spinnern, Episode 456878342

Um die Antwort vorweg zu nehmen: nope. Ihr habt ja wohl n Knall, liebe “Slap Up Media”, und da hilft es auch nicht wenn Ihr Eure spamversendenden Angestellten als “Digital Media Agent”s bezeichnet. Wenn man Werbung macht, dann kennzeichnet man diese als Werbung. Dann ist das für mich absolut ok. Aber dann tretet doch bitte auch als Werber heran. Und fordert nicht redaktionelle Beiträge, die eigentlich Werbung sind.

Und noch ein Tip: Eurer Beispielbeitrag enthält wahllos via Suchmaschine gefundene Bilder. Damit fordert ihr direkt zu einer Urheberrechtsverletzung auf, denn ein “(Images courtesy of andrewjensen_DOT_net, hoklife_DOT_com, watercoolersdirect_DOT_com)” [_DOT_ von mir ergänzt] ist bei einem Bild ohne bekannte Lizenz weiterhin eine Urheberrechtsverletzung – das ist, als würdet ihr dazu auffordern, die Cola aus dem Laden zu klauen, aber nur dann, wenn ihr dem Kassierer Bescheid sagt, dass ihr gerade den Diebstahl begeht.

Hier das ganze (anonymisierte) Anschreiben im Wortlaut:

Einen schönen Guten Tag,

Vorab möchte ich für diese informelle Anrede entschuldigen.

Ich bin auf der Suche nach Webmastern, welche Interesse daran haben, Gastbeiträge auf ihren Seiten zu veröffentlichen und bin bei dieser Suche auf Ihre Seite gestoßen.

Die Beiträge enthalten eine Text Link zu unserem Kunden, welcher in dieser Kampagne ein namenhafter Online Casino Anbieter ist.

Beiträge werden jeweils neu erstellt und auf die veröffentlichende Seite zugeschnitten, damit es ins Konzept passt und für die Leser auch einen Mehrwert hat. Die Artikel sind informativ, unterhaltsam und gut geschrieben, und natürlich würde auch ein Betrag für die Platzierung gezahlt werden. Die Höhe ist unterschiedlich hoch in den verschiedenen Kampagnen, und kann daher manchmal höher oder geringer ausfallen. Wir würden gern langfristige Beziehungen zu Webmastern aufbauen um mit diesen dann auch in Zukunft an anderen Projekten arbeiten zu können.

Damit Sie sich ein Bild von unseren Beiträgen machen können und sehen, wie diese strukturiert sind, habe ich Ihnen hier mal ein Beispiel mitgeschickt. Dieser Beitrag ist bereits anderswo veröffentlicht worden und dient nur als Beispiel. Ich würde mich freuen, wenn Sie vielleicht die Zeit hätten sich diesen Beitrag anzusehen und würde mich über eine Rückmeldung von Ihnen sehr freuen.

Vielen dank und freundliche Grüße,

[Ein Name]

Und dann der sensationelle Beispielpost, Veränderungen meinerseits in eckigen Klammern:

Wieviel Zeit verschwenden Angestellte im Netz?

Es gab schon immer Leute, die Wege gefunden haben um auf der Arbeit etwas Zeit zu vertrödeln. Heute allerdings, mit dem mehr oder minder uneingeschränkten Zugriff auf’s Internet am Arbeitsplatz, gekoppelt mit den weitverbreiteten sozialen Medien, bringt es einige Arbeitgeber dazu, solche Aktivitäten schon als “Zeitraub” zu bezeichnen.

[Bild Link entfernt]

Zeitverschwendung: Die Zahlen

Eine durchgeführte Studie (von Voco Unternehmensberatern) hat erstaunliche Zahlen ans Licht gebracht, bezüglich darauf wie Angestellte ihre Zeit verbringen. Es scheint als werden 25% der Online Zeit für private Zwecke genutzt, und 80% der E-mails welche vom Arbeitsplatz gesendet werden, sind privater Natur. Voco’s Leiter für Netzwerksicherheit, Paul Hortop, gab zu, dass die Linie zwischen striktem persönlichen surfen – zum Beispiel auf Dating Seiten oder die Buchung für den nächsten Urlaub – und die Grenze Arbeit/Privates manchmal nicht so ganz einfach zu unterscheiden ist. Manche Facebook-Aktivität kann ohne weiteres arbeitsbedingt sein, dasselbe könnte man auch über andere soziale Medien wie z.B. Twitter sagen.

[Bild Link entfernt]

Beliebte Seiten

Hortop stellt auch folgende Frage in den Raum; ” Ist es zeiteffizienter, den Angestellten sein Banking online erledigen zu lassen anstelle davon, dass dieser das Büro für eine halbe Stunde verlassen muss um seine Angelegenheiten zu erledigen?” Die meisten Arbeitgeber würden diesem wohl zustimmen, aber es gibt auch einige Sachen, welche nicht gern gesehen werden. Browser-basierende Flash Games zum Beispiel sind sehr populär, und Spiele wie Happy Wheels und Doom fordern einen Großteil an Zeit. Diese Seiten ziehen jeden Tag tausende von Spielern auf Ihre Seiten, welche ein bißchen Abwechslung suchen.

Aber es sind nicht nur die Spiele und soziale Medien, welche den Bossen Sorgen machen. Seiten wie LinkedIn werden häufig von Angestelleten genutzt zum netzwerken und um bessere Jobs zu finden[hier war ein Link zu einer Anzeigenbörse]. Natürlich ist dies ihr gutes Recht, aber sollte man dies wirklich während der Arbeitszeit tun? Dann gibt es da auch noch noch das Problem der Sicherheit. Wenn eine Firma kein Auge darauf hält, welche Seiten von den Angestellten besucht werden, besteht das Risiko, dass das System durch sogenannte Malware oder einen Virus korruptiert wird. Das Herunterladen von illegalen Materialien – Filme, Musik und so weiter – durch Angestellte, kann zu ernormen Klagen für die Firma führen. Mal ganz abgesehen davon, dass all diese Aktivitäten die Bandbreite nutzen für welche der Arbeitgeber zahlt.

[Bild Link entfernt]

Der Mensch braucht eine Pause

Man muss allerdings auch eine gewisse Perspektive behalten. Es ist hochwarscheinlich, dass Arbeitnehmer auch vor der Erfindung des Internets 25% ihrer Zeit mit etwas anderem verbracht haben. Und das Argument, dass dies eine kleine Ablenkung von der täglichen Schinderei ist, ist ein starkes. Man kann von niemandem erwarten, dass er sich geballte 8 Stunden effektive auf ein und dasselbe konzentriert. Vielleicht müssen sich Manager daran gewöhnen, dass es ein gewisses Maß an Zeit gibt, welches abgeschrieben werden muss – und ein Auge auf die wichtigeren Sicherheitsaspekte halten.

 

(Images courtesy of andrewjensen_DOT_net, hoklife_DOT_com, watercoolersdirect_DOT_com)

Howto: Verschlüsselung auf der WordPress-Oberfläche mit limitierten Ressourcen

SSL-Verschlüsselung für die Admin-Oberfläche scheitert oft an zwei drei Problemen:

  1. SSL-Zertifikate kosten viel Geld
  2. Es steht nur eine IP-Adresse zur Verfügung, jeder SSL-Host braucht aber eine eigene
  3. Die Anleitungen zu dem Thema sind oft recht verwirrend

Doch sowohl für Punkt 1 als auch für Punkt 2 gibt es so langsam eine Lösung. Diese möchte ich hier vorstellen, womit ich Punkt 3 löse. Ich werde dabei einen besonderen Fokus auf WordPress legen und nur kurz auf andere Software eingehen.

Als Basis verwende ich einen Debian 6.0 (Squeeze) Server, das Tutorial funktioniert aber identisch auch mit Ubuntu Servern. Für andere Linux-Distributionen muss man manchmal 2, 3 Dinge anpassen. Plesk dürfte bei meinen Lösungen nur Ärger machen, und ich glaube nicht, dass die Lösungen auf normalem Webhosting funktionieren. [UPDATE]Plesk unterstützt SNI offiziell.[/UPDATE]

Punkt 1: Kostenlose SSL Zertifikate

Das Unternehmen StartCOM bietet seit einiger Weile unter dem Markennamen StartSSL kostenlose SSL-Zertifikate für unkommerzielle Seiten an. Diese werden mittlerweile von den meisten modernen Browsern akzeptiert (sogar vom Internet Explorer seit September 2009), auf Wikipedia findet sich eine Liste dazu. Die Zertifikate sind ein Jahr gültig.

Nachdem man sich auf StartCOM registriert hat (der Vorgang ist etwas aufwändiger) validiert man zunächst seine Domains. Danach geht es zum eigentlichen Signier-Vorgang. Man erstellt auf seinem Linux-Server einen privaten SSL Key:

openssl req -new -nodes -keyout meinzertifikat.key -out meinzertifikat.csr -newkey rsa:4096

Statt meinzertifikat sollte man natürlich einen Namen wählen der auf die Domain hinweist. Ich habe mir angewöhnt, den Domainnamen umzudrehen, also z.B. für dieses Blog org.sectio-aurea – aber die Namensgebung ist natürlich jedem selbst überlassen.

Bei den nachfolgenden Fragen gibt man dann seine Daten ein. Es empfiehlt sich, reale Daten anzugeben, die Daten sind nachher für den Website-Besucher öffentlich einsehbar. Beim Common Name muss man seine Domain angeben (incl. Subdomains). Also z.B. piwik.sectio-aurea.org wenn man seine Piwik-Installation in genau dieser Subdomain sichern möchte.

OpenSSL generiert dann zwei Dateien. Die meinzertifikat.key ist der Key, dieser darf niemals öffentlich werden. Die meinzertifikat.csr ist das das Certificate Signing Request, was wir für StartSSL brauchen. Den gesamten Inhalt der Datei kopieren wir also beim Signier-Prozess in das dazu gehörige Feld. StartSSL bietet zwar auch die Möglichkeit, auf der StartSSL Seite einen Key zu generieren – aber da gewöhnen wir uns gleich mal an, dass der Key niemals in fremde Hände gelangen darf, generieren ihn mit dem Befehl oben selbst und überspringen damit diesen Punkt.

Zwischendrin fragt StartSSL noch nach dem zu zertifizierenden Hostname. Wenn man eine Subdomain signieren will, nutzt man diese – also z.B. piwik.sectio-aurea.org. Wenn man sectio-aurea.org selbst signieren wollte trägt man da www ein – eine Subdomain ist Pflicht, www eignet sich da, da das viele Menschen eingeben.

Am Ende des Signierprozesses erhalten wir das Zertifikat, welches wir unter meinzertifikat.crt abspeichern. Außerdem brauchen wir noch das StartSSL Zwischenzertifikat:

wget -O meinzertifikat.chain.ca https://www.startssl.com/certs/sub.class1.server.ca.pem

Alle vier Dateien kopieren wir nun in den privaten Zertifikat-Speicher und passen die Dateirechte an:

sudo mv meinzertifikat.* /etc/ssl/private/
sudo chown root:root /etc/ssl/private/meinzertifikat.*
sudo chmod 400 /etc/ssl/private/meinzertifikat.*

Voila. Wir haben ein signiertes SSL Zertifikat an der richtigen Stelle um es weiterzuverwenden. Das machen wir nun mit jeder Domain und Subdomain, die wir absichern möchten. Ja, das kann verdammt viel Zeit kosten. Viel Spaß.

Punkt 2: Nur eine IP Adresse? Server Name Injection(SNI)!

Üblicherweise benötigt jedes SSL-Zertifikat eine eigene IP-Adresse, da die IP-Adresse als Entscheidungsmerkmal genutzt wurde, welches SSL-Zertifikat ausgeliefert wird vom Webserver. Der Hostname steht üblicherweise zum Zeitpunkt der Auslieferung des Zertifikates nicht zur Verfügung, er wird erst im zweiten Schritt übertragen.

SNI dreht den Abfragevorgang um und sendet erst den Hostname, um danach die Verschlüsselung zu starten. Dadurch ist eine Auslieferung des SSL-Zertifikates abhängig vom Hostname möglich. SNI wird von allen aktuellen Browsern unterstützt, der wohl größte Problemfall ist der Internet Explorer unter Windows XP: leider wird kein Internet Explorer unter Windows XP unterstützt. Ab Windows Vista wird jeder Internet Explorer unterstützt. Der zweite größere Problemfall ist Android 2.x, was leider auch noch recht weit verbreitet ist. Auf Wikipedia stehen Details zur SNI-Unterstützug.

Die Einrichtung beim Apache Webserver erfolgt dann wie bei normalen unverschlüsselten virtuellen Hosts. Dabei muss man aber sehr sauber arbeiten, ansonsten gibt es unerwartete Resultate und merkwürdige Fehlermeldungen.

Zunächst muss man definieren für welche Bereiche man virtuelle namenbasierte Hosts nutzen möchte. Dies geht in /etc/apache2/ports.conf:

NameVirtualHost *:80
NameVirtualHost 217.115.130.175:443
Listen 80
Listen 443

Diese Einträge sorgen dafür, dass man die IP-Adresse 217.115.130.175 für virtuelle namenbasierte Hosts mit SNI nutzt. Außerdem wird der unverschlüsselte Port 80 auf allen IP-Adressen für Virtuelle Hosts bereitgestellt. Um nun zunächst einen virtuellen Host für Port 80 bereitzustellen, erstellt man in /etc/apache2/sites-avaiable/ eine Datei z.B. mit dem Namen unverschluesselt. In diese trägt man dann seinen virtuellen Host ein:

<VirtualHost *:80>
ServerAdmin mail@ernestoruge.de
ServerName sectio-aurea.org
ServerAlias www.sectio-aurea.org
DocumentRoot /var/www/wordpress/httpdocs
ErrorLog /var/log/apache2/wordpress_org.sectio-aurea.error.log
CustomLog /var/log/apache2/wordpress_org.sectio-aurea.access.log combined
[...]
<Directory /var/www/wordpress/httpdocs>
[...]
Options -Indexes
Order Deny,Allow
Allow from All
AllowOverride All
RewriteEngine On
</Directory>
</VirtualHost>

Die Teile der Konfiguration welche etwas mit SuExec zu tun haben habe ich auskommentiert. Wichtig ist vor allem die erste Zeile: *:80 haben wir zuvor für die Verwendung für virtuelle namenbasierte Hosts definiert. Mit a2ensite unverschluesselt können wir nun die Seite aktivieren, mit service apache2 reload ist sie auch abrufbar. Dasselbe machen wir nun auch für die SSL-Hosts, auch hier erstellen wir in /etc/apache2/sites-avaiable eine Datei, nennen wir sie verschluesselt1:

<VirtualHost 217.115.130.175:443>
ServerAdmin mail@ernestoruge.de
ServerName sectio-aurea.org:443
DocumentRoot /var/www/wordpress/httpdocs
ErrorLog /var/log/apache2/wordpress_org.sectio-aurea.error.log
CustomLog /var/log/apache2/wordpress_org.sectio-aurea.access.log combined
[...]
SSLEngine on
SSLCertificateFile /etc/ssl/private/org.sectio-aurea.crt
SSLCertificateKeyFile /etc/ssl/private/org.sectio-aurea.key
SSLCertificateChainFile /etc/ssl/private/org.sectio-aurea.chain.ca
<Directory /var/www/wordpress/httpdocs>
[...]
Options -Indexes
Order Deny,Allow
Allow from all
AllowOverride All
</Directory>
</VirtualHost>

Auch 217.115.130.175:443 haben wir zuvor für die Verwendung als virtuelle namenbasierte Hosts freigegeben. Wichtig ist natürlich auch der korrekte Pfad zu den Dateien des SSL-Zertifikates sowie der Port hinter dem ServerName. Mit a2ensite verschluesselt1 und service apache2 reload wird die Seite abrufbar.

Wir können nun einen zweiten virtuellen namenbasierten Host hinzufügen. Nennen wir ihn verschluesselt2 und erstellen ihn analog zum oben beschriebenen verschluesselt1. Aktivieren wir diesen, haben wir zwei funktionierende SSL Hosts unter derselben IP. Ziel erreicht!

Manch einer wird sich gefragt haben, warum ich durchgängig die IP bei den SSL-Hosts angebe. Ganz einfach: dadurch kann ich weitere verfügbare IPs für normale und damit für mehr Browser zugängliche Seiten nutzen – SNI wird dann nur bei dieser einen IP verwendet. Ein weiterer virtueller nicht namensbasierter Host wäre dann so denkbar:

<VirtualHost 83.169.35.183:443>
ServerAdmin mail@ernestoruge.de
ServerName mail.foej.net
DocumentRoot /srv/www/net.foej.mail/httpsdocs
ErrorLog /var/log/apache2/net.foej.mail.error.log
CustomLog /srv/www/apache2/net.foej.mail.access.log combined
SSLEngine on
SSLCertificateFile /etc/ssl/private/net.foej.mail.crt
SSLCertificateKeyFile /etc/ssl/private/net.foej.mail.key
SSLCertificateChainFile /etc/ssl/private/net.foej.mail.chain.ca
[...]
<Directory /var/www/net.foej.mail/httpsdocs>
[...]
Options -Indexes
Order Deny,Allow
Allow from all
AllowOverride All
</Directory>
</VirtualHost>

Hat man nur eine IP, kann man auch überall mit *:443 statt 217.115.130.175:443 arbeiten. Wichtig ist nur, dass es in sich konsistent ist. Dies ist auch bei allen anderen Sachen wichtig – z.B. sollte man nicht * und *:80 durchmischen, sollte aufpassen, dass man nicht mehrfach für dieselben Hosts geltende NameVirtualHost definiert etc. Sauberes strukturiertes in sich logisches Arbeiten ist hier die halbe Miete.

WordPress: Admin-Oberfläche nur mit SSL

Um die Admin-Oberfläche immer mit SSL zu verschlüsseln müssen wir noch die .htaccess von WordPress ergänzen. Außerdem habe ich mir angewöhnt, überall das www zu entfernen. Folgende Zeilen werden dafür ganz am Anfang der .htaccess von WordPress ergänzt:

# BEGIN custom
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.*)\ HTTP/ [NC]
RewriteCond %{HTTPS} !=on [NC]
RewriteRule ^/?(wp-admin/|wp-login\.php) https://%{HTTP_HOST}%{REQUEST_URI}\?%{QUERY_STRING} [R=301,QSA,L]
# END custom

Die beiden Zeilen RewriteEngine On und RewriteBase / müssen in den darunter liegenden Zeilen der .htaccess entfernt werden. Die erste Kombination von RewriteCond und RewriteRule ist für die Weiterleitung von www.sectio-aurea.org auf sectio-aurea.org (oder jedem beliebigen anderen Host, das geht sogar mit Subdomains, also www.blog.ruhrmobil-e.de wird automatisch zu blog.ruhrmobil-e.de) verantwortlich, die letzten drei Zeilen aus zwei RewriteCond und einer RewriteRule sind für die Weiterleitung auf die verschlüsselte Verbindung bei der wp-login.php und bei dem gesamten wp-admin Bereich verantwortlich. [UPDATE 14.08., 23:30: Bugfix in letzter RewriteRule]

Abschließende Worte

Mit dem obrigen Tutorial habe ich versucht, die Idee hinter kostenloser Verschlüsselung mehrerer Domains zu beschreiben. Es ist kein Copy & Paste Tutorial, da ich es als wichtig empfinde, dass man versteht, was man da tut, wenn man einen Server betreibt. Außerdem sind zu viele Punkte abhängig von Domains und Ähnlichem, so dass ein Copy & Paste Tutorial kaum möglich wäre.

Wenn ein oder mehrere Punkte unverständlich sind schreibt dies bitte im Kommentarbereich, dann ergänze ich gerne.

WordPress Admin-Oberfläche nur noch mit SSL-Verschlüsselung

Oder auch: warum komme ich mit meinem alten Browser nicht mehr auf die WordPress Admin-Oberfläche meiner Website?

Ab dem 13. August 2013 ist auf allen Seiten des sectio-aurea.org Blog-Netzwerkes (also allen von mir gehosteten WordPress-Seiten) im Admin-Bereich SSL-Verschlüsselung zwingend erforderlich. Grund hierfür ist einerseits Sicherheit – ohne SSL Verschlüsselung können Daten abgehorcht werden. Andererseits gab es in den letzten Tagen erhebliche Brute Force Angriffe auf WordPress, um Accounts zu übernehmen. Keiner der Angriffe war erfolgreich, jedoch ging der Server zeitweise sehr in die Knie – dies wird ebenfalls durch SSL reduziert bzw. ganz verhindert.

Leider kann ich nicht für jede Website teure SSL-Zertifikate und die zusätzlich dafür benötigten IP-Adressen kaufen. Somit muss ich auf kostenlose Zertifikate und eine Technik namens SNI zurückgreifen; beides wird nur von verhältnismäßig aktuellen Browsern unterstützt.

Ich kriege eine Fehlermeldung, wenn ich auf die Admin-Oberfläche von WordPress möchte!

Höchstwahrscheinlich setzt Du einen recht alten Browser ein. Dazu gehört: jeder Internet Explorer unter Windows XP, Firefox vor 2.0, Android Browser vor Android 4.0, Safari vor OS-X 10.4 Leopard. Beim Internet Explorer, Safari und Google Chrome müssen zudem alle Windows Updates installiert sein.

Wer eine SSL-Fehlermeldung angezeigt bekommt, sollte sich also dringend um Updates für Browser und Betriebssystem bemühen. Denn nicht nur wegen der Fehlenden SSL-Unterstützung ist derartig alte Software ein Risiko, sondern auch durch Sicherheitslücken, welche bei alter Software noch weit offen sind und so Angriffspunkt für Viren und Trojaner darstellen.

Nächste Schritte: Verschlüsselung beim Mailserver

In Kürze wird zudem der Mailserver so umgestellt, dass er keine unverschlüsselten Verbindungen mehr entgegennimmt. Bitte stellt Euren Mail-CLient (Thunderbird, Outlook, …) auf eine verschlüsselte Verbindung um falls Ihr das nicht eh schon gemacht habt. Für Nutzer der Weboberfläche mail.foej.net ändert sich nichts.

Warum all der Aufwand?

Gerade Prism, Tempora und Co haben gezeigt, dass es sehr wichtig ist, sich mehr um Verschlüsselung und Datensicherheit zu kümmern. Es wäre zudem naiv davon auszugehen, dass andere Staaten dies nicht tun, zudem ist Cyberkriminalität keine Seltenheit. Man schließt am Bahnhof eben auch sein Fahrrad ab – auch wenn in einer idealen Welt dies nicht nötig wäre, so ist dies doch elementar, damit man sein Rad behält. Ebenso verhält es sich mit Verschlüsselung für IT-Systeme.

Verschlüsselung löst dabei selbstverständlich nicht alle Probleme, insbesondere Geheimdienste haben viele Mittel und Wege, doch an Daten zu kommen, wenn vielleicht auch nicht an alle. Geheimdienste benötigen letztlich eine gesellschaftspolitische Lösung, wir als Bürgerinnen und Bürger müssen die Macht der Dienste begrenzen. Verschlüsselung macht es aber allen Angreifern schwerer und lässt vieles wirkungslos abprallen. Ein Fahrradschloss hilft eben auch nicht gegen eine professionelle Metallsäge, trotzdem reicht das Schloss, um die wohl allermeisten Diebe vom Diebstahl abzuhalten.

Sticky Posts auf Category-Listen

Das Sticky-Post-System von WordPress ist ein wenig komisch. Sticky Posts sind Posts, die immer oben gehalten werden auf der Startseite. Eigentlich sollte man erwarten, dass die zentrale Eigenschaft dieser Posts ist, dass sie oben sind. Weit gefehlt.

Die zentrale Eigenschaft dieser Posts ist es, dass sie auf der Startseite oben sind. Sonst gar nichts. In den Category-Listen sind sie dagegen brav einsortiert nach Datum. Wenn man WordPress als Mini-CMS nutzt und die Kategorien nutzt, um auf verschiedenen Bereichen der Seite News anzuzeigen nervt das ganz schön – weil man auf verschiedenen Bereichen der Seite oben gehaltene Posts haben will. Was tun? Ein hässlicher Hack.

Verbunden habe ich dies mit der Eigenschaft der Startseite, nur Posts einer einzigen Kategorie anzuzeigen. So können Inhalte sehr spezifisch dahin gesteuert werden, wo man sie hinhaben möchte. Um die Eigenarten der Sticky Posts zu erläutern zunächst ein paar Beispiele wie es nicht geht. Als Basis fand ich diesen Post.

function my_post_queries( $query ) {
// only homepage and is the main query
if ($query->is_home() && $query->is_main_query()){
// display only posts in category with id=32
$query->set(‘cat’, 32);
// avoid sticky posts
$query->set(‘post__not_in’, get_option( ‘sticky_posts’ ) );
}
}
add_action( ‘pre_get_posts’, ‘my_post_queries’ );

Das erste $query->set sorgt dafür, dass alle Posts mit der Kategorie-ID 32 angezeigt werden – und zusätzlich alle Sticky Posts mit beliebiger Kategorie. Wenn man das zweite $query->set dazunimmt, bekommt man alle Posts mit der Kategorie-ID 32 – ausser die Posts, die Sticky Posts sind. Ich wollte aber alle Posts mit Kategorie 32, egal, ob Sticky Post oder nicht. Und die Sticky Posts sollten dann auch noch oben sein. Das ist mit dem normalen Query-System von WordPress aber schlichtweg nicht möglich. Zeit für einen hässlichen Hack:

add_action(‘pre_get_posts’, ‘modify_main_query’);
function modify_main_query( $query ) {
if ($query->is_main_query()) {
$query->set(‘post__not_in’, get_option( ‘sticky_posts’ ) );
if ($query->is_home()) {
$query->set(‘cat’, 32);
}
else if ($query->is_category()) {

}
}
}

add_action(‘wp’, ‘add_sticky_posts’);
function add_sticky_posts() {
global $wp_query;
$args = array(
‘post__in’ => get_option( ‘sticky_posts’ ),
‘ignore_sticky_posts’ => 1
);
if (is_home())
$args['cat'] = 32;
else if (is_category())
$args['cat'] = $wp_query->query_vars['cat'];
else
return;

$sticky_post_query = new WP_Query($args);
$wp_query->posts = array_merge($sticky_post_query->posts, $wp_query->posts);
}

Was habe ich gemacht? Ich habe zunächst alle Sticky Posts herausgefiltert und auf der Startseite nur nach Kategorie-ID 32 gesucht. Die Sticky Posts habe ich anschließend gesucht – und dabei ihre Eigenschaft als Sticky Posts zwar als Bedingung genommen, aber in der Positionierung ignoriert. Anschliessend habe ich die Sticky Posts einfach vor die anderen Posts eingesetzt.

Das ganze ist ein ziemlich hässlicher Hack, aber er funktioniert und dürfte auch recht stabil sein. Hässlich ist er vor allem deshalb, weil die restlichen Daten im $wp_query Objekt dem ursprünglichen Query entsprechen, dies aber nicht mehr der Realität von $wp_query->posts entspricht.

29c3, Respekt, Flauscheria, Rückzugsräume und Sprache

Feminismus und Nerds. Das konnte ja nur schiefgehen. Meint man. Nun, irgendwas lief auf dem 29c3 auch wirklich schief. Aber fehlender Feminismus – das war nur ein kleiner Teil der Probleme.

Aber bevor ich von den Problemen spreche: die Konferenz war super. Ich hätte nie gedacht, dass eine ehrenamtlich organisierte Konferenz derart reibungslos über die Bühne gehen kann. Dafür ein herzliches Dankeschön, und ebenfalls vielen Dank für die vielen tollen neuen Kontakte, welche ich auf der Konferenz gewinnen durfte. Es gibt wenig Orte, wo so viele Menschen mit so viel Leuchten in den Augen zu finden sind. Wo Menschen trotz (oder vielleicht grade wegen) ihrer zum Teil offensichtlichen sozialen Inkompatibilität noch so viel träumen, so ungeschliffen, so kreativ und so intelligent sind. Danke!

Klarstellung: Meine Perspektive

Feminismus ist mir nicht fremd. Als in einer grünen Umgebung aktiver Mensch mit vielen Kontakten zu anderen Parteien und einer Vorliebe für überparteiliche Arbeit sind mir viele Gender-Themen recht gut bekannt. Nicht so bekannt war mir der 29c3, das war mein erstes Jahr dort. Ich habe eine recht nerdige Vergangenheit, bin kein Hacker und spiele mittlerweile ein bisschen weiträumiger abseits klassicher Nerd-Themen herum. Einerseits ermöglicht mir das natürlich keine historische Betrachtung des 29c3, andererseits dürfte ich dadurch einen Blick von außen / oben haben. Und dabei fällt das eine oder andere auf.

Viel Respekt

Für einen Neuen war dies faszinierend zu beobachten. Denn im Endeffekt war ein Widerspruch zu beobachten. Einerseits hatten viele Teilnehmerinnen und Teilnehmer sichtlich nicht das Interesse und oft auch nicht die Sozialkompetenz, um wirklich emotional zu verstehen, was die jeweils anderen Personen treibt. Trotzdem wurde eine unheimliche Bandbreite von verschiedenen Lebensstile völlig problemlos akzeptiert. Mehr noch: respektiert. Was phänomenal für eine Konferenz dieser Größe ist – auf Veranstaltungen im Bereich der Autoindustrie wo ich ab und an teilnehme ist man z.B. viel schneller unten durch. Von Discos gar nicht erst zu reden. Möglich machte dies vielleicht grade die Tatsache, dass viele Menschen Dinge einfach laufen liessen und soziale Phänomene gar nicht verstehen wollten weil sie das wichtige – die Inhalte – störten. Was ok ist. Dies war aber auch gleichzeitig die Basis für Einzelne, welche diese Freiheit negativ ausgenutzt haben.

Auf Freiheit folgt Flamewar

Wo die moderate gutgläubige Mehrheit schweigt, bekommen Radikale eine laute Stimme. Das war bei dem Hacker-Jeopardy sehr deutlich zu bemerken. Es war ein wildes argumentationsloses Geprügel, denn für respektlose Sprüche (dessen Anti-Feministische Bedeutung nur eine von vielen Folgerungen sein konnten) sind rote Creeper-Move-Karten als Reaktion genauso maßlos übertrieben wie Sprüche über Feminazis. Auf beiden Seiten fühlten sich Menschen emotional verletzt und schlugen wild um sich – und es gab nur wenige, die versucht haben, die Wogen zu glätten – der Rest begriff nicht was da abgeht und / oder resignierte. Ich selbst gehörte auch zu der Mehrheit. Was vielleicht ein Fehler war. Aber wenn eine Situation erst einmal so eskaliert ist gibt es kaum etwas, was das Desaster noch stoppen kann. Die Inhalte – in diesem Fall Feminismus – sind bei einer solchen Eskalation am Ende dabei nur ein Randthema.

Creeper Move Cards – gute Idee, schlechte Umsetzung

Diese Karten sollten die Möglichkeit geben, bei unangemessenem wie sehr angemessenem Verhalten eine wortlose Rückmeldung zu geben. Wortlos, weil man z.B. zu verletzt ist, um dies auszudiskutieren. Doch so gut gemeint die Absicht hinter den Karten auch war, so sehr ging die Durchführung in die Hose. Die Karten wurden inflationär eingesetzt. Nur wenige wussten überhaupt darüber Bescheid, eine Anleitung fehlte weitestgehend. Es wurde wegen Trivialitäten mit roten Karten um sich geschmissen (es gab wohl maximal einen Fall, wo eine rote Karte den Erfindern des Systems zufolge gerechtfertigt war – der Letzte in der Liste - siehe auch). Die Herausgabestelle Flauscheria hatte selbst Zieldefinitionsprobleme (s.u.). Das System funktioniert auf der Def Con gut, aber vor allem deshalb, weil die Orga der Def Con dahintersteht und die nötigen Infos sowie die nötige Gleichverteilung bereitgestellt hat. Auf der OpenMind hat man dies kopiert und die Karten funktionierten recht gut. Auf dem 29c3 dagegen haben sie dem Ziel von mehr Respekt eher geschadet denn genützt – wenn man einmal so ein Kartensystem der Lächerlichkeit preisgegeben hat ist die Idee schwer wieder ins Positive zu drehen. Denn so blöd die Aktion mit der nackten (roten!) Creeper-Card-Frau zunächst wirkt, so sehr hat sie auf den Punkt gebracht, als wie unsinnig die Karten nach aussen wirkten (was auch die Intention der Erschafferin war).

Die Flauscheria – eine Gruppe mit Zielkonflikten

Die Creeper Move Cards waren exemplarisch für die Flauscheria – sehr viel guter Wille, super-tolle Menschen, aber eher verzweifelte denn souveräne Umsetzung ihrer Ideen. Ich war dort lose angegliedert und kannte viele Flauscheria-Mitglieder bislang nur via Twitter, und letztlich habe ich dort eine Gruppe von zum Teil sehr sehr sensiblen Menschen erlebt. Zum Teil Menschen, die verschiedenste Probleme mit der Welt “da draußen” hatten und sehr verletzbar waren. Die Idee der Creeper Move Cards war also in weiteren Teilen (wie ich finde berechtigtes) Eigeninteresse. Genauso wie es die Forderung nach Rückzugräumen war. Aber genau das hat die Position der Flauscheria so schwierig gemacht, sie waren gleichzeitig Betroffene und neutrale Anbieter verschiedener Lösungsvorschläge der Deeskalation für sensible Menschen. Diesen Zielkonflikt aufzulösen war meiner Meinung nach unmöglich, die beiden Ideen – Respekt und echte Rückzugräume – sollten aber noch mehr beachtet werden, um emotional sehr sensiblen Menschen das Leben zu vereinfachen. Obwohl ich den 29c3 was den Respekt angeht bereits für sehr weit positiv fortgeschritten halte wie oben beschrieben, aber es gibt immer Raum für Verbesserung.

Idee: Rückzugräume für alle

Die andere Idee der Flauscheria ist bei all der Diskussion leider allzu sehr untergegangen: Rückzugräume für Menschen, die nicht durchgängig so viel Menschen um sich herum haben können. Das 29c3 war extrem offen, es waren offene Räume mit offenen Tischen, und jeder konnte fast überall hin. Vielleicht wäre als Ergänzung des Kongresses eine Art Silent Privacy Area mit vielen Sichtschutzwänden und viel privatem Raum sinnvoll, um ein neutrales Gebiet zu schaffen, bei dem man auch mal in kleinen Gruppen oder eben ganz alleine sein kann. Aber dies müsste dann von der Orga aus kommen – und eben nicht von einer kleinen Initiative, die mit “Rückzugsgebiet” vor allem “Rückzugsgebiet für sich selbst” meint.

Feminismus und Nerds: Sprachschwierigkeiten

Am Rande des ganzen Streites kam auch noch etwas ganz anderes zu Tage: der Feminismus und Informatik-Vortrag hat gezeigt, wie weit weg einzelne Fachszenen von dem Mainstream sind. Ich habe dort selbst mit meinem Vorwissen als Grüner echte Schwierigkeiten gehabt, dem Fachwort-Staccato zu folgen. Vielen in dem Vortrag dürfte es noch weit schlimmer ergangen sein, ohne die Grünen hätte ich die Fachworte auch nirgends kennengelernt. Im Anschluss habe ich das Experiment gemacht, wie es wohl ist ohne spezifische Nerdsprachenkenntnisse die Konferenz anzuschauen. Beim Durchwandern der Gänge und Projekte wurde mir eins sehr bewusst: ein der Szene Fremder wäre hoffnungslos verloren gewesen, genauso wie die Zuschauer des Gender und Informatik Vortrages verloren gewesen sind. Das durchzog alle Bereiche, und dabei ist mir aufgefallen, dass auch ich selbst mit durchaus ein wenig Nerdsprachwissen bei vielen Anspielungen schlichtweg keine Ahnung hatte, was diese wohl bedeuten mögen. Insider sind cool. Ja. Aber hin und wieder täte es wohl gut zu schauen, ob man nicht doch eine weniger volle und dafür verständlichere Sprache wählen sollte – denn mit dem Wechsel auf eine neue Location gab es viele neue Teilnehmerinnen und Teilnehmer. Und so schön der Kongress auch war, so war er auch ein wenig fremd für mich – bis zum Ende.

Mehr Willkommenskultur, weniger Streit!

Ich bin nicht als CCC Nerd sozialisiert worden. Und dieses Fremde – es hat die Fähigkeit, persönliches Verhalten zu berühren und zu reflektieren. Das ist zunächst einmal sehr gut. Aber es kann auch als Angriff wirken. Denn klar, die Verhaltensweisen sind von einer vor allem männlichen Gruppe geschaffen worden, und das Thema ist nicht neu – wie die Aschenbrennerin treffend schreibt, gibt es die Haecksen nicht ohne Grund. Aber vielleicht sollten wir weniger über agressive Antifeministen reden. Davon gab es auf dem 29c3 kaum welche. Die meisten Vorfälle waren mehr ein Versehen aus dem bestehenden kulturellen Kontext heraus, die es ruhig anzusprechen gilt, aber es bringt keiner Seite etwas, dies gnadenlos zu eskalieren.

Ja – vielleicht sollten wir mehr über Offenheit gegenüber anderen sozialen Gruppen und Willkommenskultur reden. Denn nur so können wir andere Menschen für Hackerkultur begeistern und eine Atmosphäre schaffen, bei der sich noch mehr als jetzt alle willkommen heissen.