Apache-Webserver und MySQL unter Ubuntu verschlüsseln

Es kommt immer wieder vor, dass sensible Webanwendungen verschlüsselt werden sollen. Man kann entweder die Dateien einzeln verschlüsseln und die Datenbanktabellen verschlüsseln oder man verschiebt den Apache-Webserver und die MySQL-Datenbanken auf eine verschlüsselte Festplatte. Im ersten Schritt wird logischerweise eine Festplatte verschlüsselt. Wie das funktioniert habe ich schon einmal in einem vorherigen Blog-Eintrag beschrieben: Festplattenverschlüsselung unter Linux mit LUKS.

Wenn die Festplatte verschlüsselt wurde, kann es auch schon los gehen. Als Basis für dieses Tutorial dient uns ein vorhandener Ubuntu-Server mit dazugehörigen LAMP-Server. Für ein schnelles Arbeiten auf der Konsole melden wir uns als Superuser an (sudo -s).

Apache verschlüsseln

Als erstes verschlüsseln wir die Daten auf dem Webserver. Also alle Dateien welche auf dem Webserver bereitgestellt werden. Das sind beispielsweise Bilder, CSS, HTML und PHP-Dateien.
Wir binden die verschlüsselte Festplatte / Partition auf “/mnt/crypt/” ein. Im gemounteten Verzeichnis legen wir einen neuen Ordner “webserver” und einen Unterordner “htdocs” an:

# Ordner webserver anlegen, welche alle relevanten Daten 
# fuer den Webserver bereitstellt
mkdir /mnt/crypt/webserver/

# Unterordner htdocs anlegen. Dieses Verzeichnis dient als Dokumentenroot
mkdir /mnt/crypt/webserver/htdocs

Als nächstes legen wir einen Ordner im Verzeichnis “/var/www/” an, welcher als verschlüsselter Dokumentenroot für unseren Webserver dient:

# Dokumentenroot anlegen
mkdir /var/www/htdocs_crypt

Danach setzen wir die Benutzer- und Gruppenrechte:

# Benutzer- und Gruppenrechte setzen
chown www-data:www-data /var/www/htdocs_crypt

# Alle Rechte für den Owner und Ausführ- und Leseberechtigung für Gruppe / Other
chmod 755 /var/www/htdocs_crypt

Im nächsten Schritt verbinden wir das verschlüsselten Verzeichnis mit dem Webserver-Dokumentenroot. Da aus sicherheitstechnischen Gründen ein symbolischer Link ausgeschlossen wird, wird der Ordner mit mount eingehangen:

mount --bind /mnt/crypt/webserver/htdocs/ /var/www/htdocs_crypt

Damit der neue Dokumentenroot benutzt wird, müssen wir die Apache-Konfiguration anpassen:

# Konfigurationsdatei oeffnen
vi /etc/apache2/sites-enabled/000-default

Dort brauchen wir nur die Zeile “DocumentRoot” anpassen und für unser neues Verzeichnis anpassen:

DocumentRoot /var/www/htdocs_crypt

Damit ist nun bei einem “cryptsetup luksClose …” der Webserver in sicherer Verwahrung und keiner hat mehr Zugriff auf die Dateien.

MySQL-Datenbank verschlüsseln

Es ist recht sinnfrei, wenn man ein verschlüsseltes Webverzeichnis hat, aber die Datenbank offen wie ein Scheunentor auf einer unverschlüsselten Festplatte liegt. Um diesen Missstand zu beseitigen, verschlüsseln wir, bzw. verschieben wir alle MySQL-Datenbanken auf die verschlüsselte Festplatte.
Dazu legen wir wieder einen Ordner mit den Namen “mysql” an:

# Ordner fuer die MySQL-Datenbanken anlegen
mkdir /mnt/crypt/mysql

Als nächstes werden wieder die Rechte gesetzt:

# Benutzer- und Gruppenrechte setzen
chown mysql:mysql /mnt/crypt/mysql

# Alle Rechte für den Owner
chmod 700 /mnt/crypt/mysql

Im nächsten Schritt stoppen wir den MySQL-Service, damit wir alle Dateien vom alten Speicherort zum neuen Speicherort transferieren können. Das Standardverzeichnis von MySQL befindet sich unter “/var/lib/mysql/”, welchen wir nun ändern werden. Wir kopieren die Daten auf unsere verschlüsselte Festplatte, optional könnten wir diese Daten auch verschieben.

# Rekursives Kopieren der Dateien und Ordner
# (Es werden alle Dateien und Ordner auch in Unterordnern kopiert)
cp -R /var/lib/mysql/* /mnt/crypt/mysql/

In der MySQL-Konfiguration legen wir den neuen Ort der Datenbanken fest:

# Konfigurationsdatei oeffnen
vi /etc/mysql/my.cnf

# Speicherort festlegen
datadir = /mnt/crypt/mysql

Wenn wir jetzt den MySQL-Service wieder starten würden, bekämen wir folgende Fehlermeldung:

start: Job failed to start

Denn der MySQL-Service hat keinen Zugriff auf den Pfad. Dies wird mit AppArmor realisiert. Wir müssen daher in der AppArmor-Konfiguration die Rechte für MySQL setzen:

# Konfigurationsdatei von AppArmor oeffnen
vi /etc/apparmor.d/usr.sbin.mysqld

# Neuen Ort von MySQL hinzufügen
# Folgende Zeilen vor der geschlossenen geschweichten Klammer einfuegen
/mnt/crypt/mysql/ r,
/mnt/crypt/mysql/** rwk,

Als nächsten Schritt können wir den MySQL-Service wieder starten:

start mysql

Hinweis: Sollte der MySQL-Service folgende Fehlermeldung werfen:

ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)

...hat der der Benutzer mysql keine Zugriffsrechte auf “/mnt/crypt”. Entweder man fügt mysql der Gruppe hinzu, welche Zugriff auf das Verzeichnis hat (Lese und Ausführrechte), oder man gibt dem Verzeichnis Lese- und Ausführrechte für Others (Achtung: Ist eine unsichere Methode).

Automatische Scripte zum Ein- und Ausbinden

Damit nicht jedes Mal die Befehle einzeln ausführen muss, findet ihr für das automatische Einbinden und das Schließen der Verschlüsselung im Anschluss folgende Bash-Scripte. Diese können auch als Verknüpfung auf dem Desktop abgelegt werden.

Entschlüsseln der Festplatte und Einbinden des Webservers

#!/bin/sh
# Verschluesselte Partition einbinden und mounten
# Hier dient als Beispiel die erste Partition der zweiten Festplatte
HDD=sdb1
MAPPERNAME=crypt_hdd
MOUNTPOINT=/mnt/crypt
sudo cryptsetup luksOpen /dev/$HDD $MAPPERNAME
sudo mkdir -p $MOUNTPOINT
sudo mount /dev/mapper/$MAPPERNAME $MOUNTPOINT
echo "Festplatte $HDD wurde unter $MOUNTPOINT eingehaengt!"

# Webserver einbinden
sudo mkdir -p /var/www/htdocs_crypt
sudo chown www-data:www-data /var/www/htdocs_crypt
sudo chmod 755 /var/www/htdocs_crypt
sudo mount --bind /mnt/crypt/webserver/htdocs/ /var/www/htdocs_crypt
echo "Webserver wurde eingebunden"

# Services starten
sudo /etc/init.d/apache2 start
# mysql starten
sudo start mysql
echo "Apache und MySQL wurden gestartet"

Webserver stoppen und schließen der Festplatte

#!/bin/sh
# Services stoppen
sudo /etc/init.d/apache2 stop
sudo stop mysql
echo "Apache und MySQL wurden gestoppt"

# Dokumentenroot entfernen
sudo umount /var/www/htdocs_crypt
sudo rmdir /var/www/htdocs_crypt
echo "Dokumentenroot wurde entfernt!"

# Verschluesselte Partition umounten und schliessen
MAPPERNAME=crypt_hdd
MOUNTPOINT=/mnt/crypt
sudo umount $MOUNTPOINT
sudo rmdir $MOUNTPOINT
sudo cryptsetup luksClose /dev/mapper/$MAPPERNAME
echo "Festplatte $MAPPERNAME wurde gesperrt!"