Categories
Administration / Webmaster German Linux QNAP Wordpress

Backup vom eigenen Server auf einem QNAP NAS zu Hause über OpenVPN am Beispiel WordPress

Der eigene Backupserver mit QNAP

Wir haben also einen Rootserver oder VServer und wollen ein Backup nach zuhause einspielen. Zuerst sollte man sich Gedanken machen, ob die Bandbreite dafür ausreicht. Ich habe eine Leitung mit 1000 MBit Downstream und 50 MBit Upstream. Das sollte auch für größere Belange voll ausreichen, da im Wesentlichen der Downstream zählt. Der zu versorgende VServer hat (leider) nur 100 MBit Downstream und ist damit also voll ausgereizt.

Nun ist zu überlegen, wie man vorgehen will, denn es gibt mehrere Möglichkeiten. Ich persönlich habe mich dafür entschieden von meinem QNAP NAS einen OpenVPN Server aufspannen zu lassen, auf den sich dann der Server verbinden kann. Den Speicher habe ich als NFSv4 freigegeben, sodass der Server hier mounten kann. Aus Sicherheitsgründen sollte man beachten, dass für diesen NAS-Zugang ein eigener Account und ein eigener Freigabeordner erstellt wird. Schließlich gibt es für Backupzwecke keinen guten Grund, warum diese Daten einfach verfügbar sein sollten.

Warnung: Ein NFSv4 sollte niemals ins Internet hinein freigegeben werden, da es bei diesem Protokoll arge Sicherheitsbedenken gibt. Schließlich ist NFSv4 für interne Netzwerke konzipiert und hält hohen Sicherheitsanforderungen nicht stand. Das Tunneln über ein VPN ist daher das Mittel der Wahl.

Bedenkt, dass ihr für folgende Schritte in der Regel eine statische IPv4-Adresse benötigt. Fragt ggf. euren Internetprovider. Bei Unitymedia/Vodafone kann man sich diese auf Anfrage z.B. einfach einrichten lassen, wenn man das Komfort-Paket hat.

OpenVPN auf QNAP einrichten

Wir installieren zuerst die App “QVPN Service” auf unserem QNAP NAS. Dieses konfigurieren wir wie auf dem folgenden Screenshot gezeigt. Wir haben hier als DNS-Server die zensurfreie und offene Variante vom Digitalcourage e.V. (IP 46.182.19.48). Man beachte außerdem, dass die Checkbox “Nutzen Sie diese Verbindung als Standard-Gateway für externe Geräte” deaktiviert ist. Dies ist erforderlich, damit der Server nicht jeglichen Traffic über das QNAP NAS leitet, was wir bei einem Server idr. nicht haben wollen. Stattdessen werden wie später auf dem Server konfigurieren, dass IP-Adressen des lokalen Netzwerks an eben dieses weitergeleitet werden. Alle anderen Einstellungen können so belassen werden. Wir laden uns noch die Konfigurationsdatei herunter (QVPN v1.1 or newer), weil diese diese später für den Server benötigen.

Nun legen wir einen neuen Freigabeordner an. Dazu gehen wir unter SystemsteuerungFreigabeordner auf ErstellenFreigabeordner. Wir geben dem Ordner z.B. den Ordnernamen ServerBackup. Unter Zugangsrechte hat aktuell nur der Benutzer admin Zugriff auf den Freigabeordner. Falls gewünscht, können hier noch weiteren Nutzern der Zugang gewährt werden. Wir werden gleich noch einen separaten Nutzer für unsere Backupzwecke erstellen.

Nun wäre es sinnvoll einen neuen Benutzer mit beschränkten Rechten einzurichten. Für den Fall, dass der Server kompromittiert wird, wäre es sicherlich am Besten den Schaden zu minimieren und nicht das gesamte NAS freizugeben. Ganz nach dem Motto: So wenig Rechte wie möglich, so viele Rechte wie nötig. Gehen wir also unter Benutzer auf ErstellenEinen Benutzer erstellen. Nennen wir den Benutzer beispielsweise serverbackup und vergeben ein Passwort. Als Benutzergruppe wählen wir everyone. Unter Freigabeordnerrecht setzen wir alle Freigabeordner auf Deny und den Ordner ServerBackup auf RW, damit wir Lese- und Schreibrechte erhalten. Erstellen wir nun den Nutzer.

Sofern das noch nicht passiert ist, müssen wir in der Systemsteuerung den NFS-v4-Dienst aktivieren:

Einrichtung auf dem Server

Das OpenVPN einrichten

Wir müssen zunächst OpenVPN installieren:

sudo apt-get install openvpn

Nun konfigurieren wir das VPN. Dazu legen wir zunächst die Datei /etc/openvpn/passwords.conf an, in der wir in der ersten Zeile unseren Benutzernamen und in der zweiten Zeile unser Passwort ablegen:

serverbackup
unserPasswort123

Nun nehmen wir die zuvor als vom QNAP NAS gespeicherte Konfigurationsdatei für das VPN und legen diese als /etc/openvpn/client.conf ab. Wir müssen diese noch so anpassen, dass Benutzername und Passwort aus unserer Datei ausgelesen werden. Ursprünglich ist es so vorgesehen, dass beim Herstellen der VPN-Verbindung per Prompt nach Benutzername und Passwort gefragt werden. Da wir eine automatisierte Lösung benötigen, müssen wir den Benutzernamen und das Passwort natürlich hinterlegen. Das haben wir bereits getan. Also modifizieren wir die client.conf an der Stelle auth-user-pass wie folgt:

auth-user-pass /etc/openvpn/passwords.conf

Die Datei client.conf sollte nun in etwa wie folgt aussehen:

client
dev tun
script-security 3
remote 42.42.42.42 1194
resolv-retry infinite
nobind
auth-nocache
auth-user-pass /etc/openvpn/passwords.conf
remote-cert-tls server
reneg-sec 0
cipher AES-256-CBC
tls-cipher TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256:TLS-DHE-RSA-WITH-AES-256-$
float
proto udp
explicit-exit-notify 1
<ca>
...
</ca>

Eine sinnvolle Methode die VPN Verbindung herzustellen, wäre natürlich beim Systemstart. Daher legen wir nun die Datei /etc/init.d/iproute.sh
für den init-Prozess an:

!/bin/sh
service openvpn@client start
sleep 30s
ip route add 192.168.178/24 dev tun0
sleep 5s
mount -a

Hier wird erst die VPN-Verbindung hergestellt. Zur Sicherheit warten wir 30 Sekunden. Die interne IP-Adresse meines NAS lautet 192.168.178.46. Daher legen wir das Netz 192.168.178.* auf das VPN um, also auf tun0. Wir warten noch mal 5 Sekunden. Dann mounten wir alle Laufwerke, was insbesondere unser NFSv4 einschließt. Den entsprechenden Eintrag für die fstab besprechen wir gleich.

Wir müssen das Skript noch für den Systemstart verlinken. Dies ist für Runlevel 3 (Multi-User Mode mit Netzwerk) und Runlevel 5 (mit GUI) erforderlich, auch wenn für Server im Regelfall Runlevel 3 reichen würde:

ln -s ../init.d/iproute.d /etc/rc3.d/S07iproute.sh
ln -s ../init.d/iproute.d /etc/rc5.d/S07iproute.sh

Leider ist es aus meiner persönlichen Erfahrung so, dass die VPN-Verbindung auch mal abbrechen kann und dann nicht wieder erneut aufgebaut wird. Ich habe mich deshalb dafür entschlossen, das Skript zusätzlich per Cronjob auszuführen und zwar jeweils wenige Minuten bevor das Backup erfolgen soll. Wenn wir das Backup z.B. um kurz nach 3:00 Uhr ausführen möchten, können wir die Cronjobdatei /etc/cron.d/openvpn z.B. wie folgt definieren:

0 3 * * * root /etc/init.d/iproute.sh

NFSv4 Filesystem mounten

Um die nötigen Voraussetzungen zu schaffen, müssen wir zuerst nfs-common installieren:

sudo apt-get install nfs-common

Nun konfigurieren wir /etc/fstab:

192.168.178.46:/ServerBackup /mnt/RemoteServerBackup nfs rw 0 0

Hierbei ist 192.168.178.46 die lokale IP unseres NAS und ServerBackup der Name unseres Freigabeordners, den wir für das Backup konfiguriert haben. Wir mounten das Ganze nach /mnt/RemoveServerBackup und zwar als nfs-Dateisystem mit Lese- und Schreibrechten (rw).

Nicht vergessen, den Mountpoint auch zu erstellen:

mkdir /mnt/RemoteServerBackup

WordPress Backup einrichten

Wir installieren das Plugin BackWPup und erstellen einen neuen Auftrag. Hier wählen wir unter Allgemein “Backup in Verzeichnis” und unter Planen stellen wir z.B. täglich um 3:25 Uhr ein. Unter “Ziel: Verzeichnis” habe ich für meinen Blog z.B. /mnt/RemoteServerBackup/the_digital_native/wordpress/ eingestellt. Da ich noch weitere Backups auf diese Weise erstelle, macht es Sinn einen entsprechenden Unterordner zu wählen.

Konfiguration und Backup testen

Um das Ganze zu testen, stellen wir auf dem Server erst mal testweise die VPN-Verbindung her und mounten das Dateisystem:

service openvpn@client start
ip route add 192.168.178/24 dev tun0
mount -a

Wir gehen nun unter BackWPup in die Liste der Aufträge und wählen für den eben neu erstellten Auftrag Jetzt starten aus. Der Auftrag sollte nun durchlaufen. Nach Abschluss des Auftrags prüfe einfach, ob das entsprechende Backup auf deinem NAS liegt.

So, wir sind fertig! Wir können nun über VPN automatisiert ein WordPress Backup auf unserem QNAP NAS erstellen.

Categories
Administration / Webmaster Datenschutz German IT-Security Linux Wordpress

Sicherheit und Datenschutz mit Content-Security-Policy Header für WordPress

Heute wollen wir uns mit Content Security Policy (CSP) Headern beschäftigen. In erster Linie ist dies ein Sicherheitsfeature, um das Laden von (Java-)Skripten, aber auch Bilder, Fonts, iFrames etc. aus böswilligen Quellen zu unterbinden und so insbesondere Cross-Site-Scripting zu unterbinden. Wikipedia sagt dazu folgendes:

Content Security Policy (CSP) ist ein Sicherheitskonzept, um Cross-Site-Scripting und andere Angriffe durch Einschleusen von Daten in Webseiten zu verhindern.

In der Praxis sind jedoch Cross-Site-Scripting-Schwachstellen sehr verbreitet. Die Content Security Policy erzwingt eine strikte Trennung zwischen Inhaltsdaten im HTML-Code und externen Dateien z.B. mit JavaScript-Code. In der Regel ist der JavaScript-Code statisch und wird nicht dynamisch generiert.

Content Security Policy, Wikipedia

Wir wollen CSP aber für noch mehr benutzen: Wir können damit auch unerwünschte Drittanbieter ausschließen, die uns WordPress quasi aufzwingt. Diese Drittanbieter können die Besucher eurer Webseite möglicherweise (in einigen Fällen sogar ziemlich sicher) tracken. Wer seinen Benutzern gegenüber Datenschutzfreundlich sein möchte, verzichtet nicht nur auf Google Analytics, sondern auch auf andere Drittanbieter. Dennoch möchte ich das Analysieren von Benutzerverhalten nicht gänzlich verteufeln, denn es liefert nützliche Einsichten, welche Reichweite man mit seinem Angebot erzielt und welche Angebote die Besucher womöglich besonders interessieren. Aber dazu gibt es auch Datenschutzfreundliche Alternativen: Matomo ist ein Paradebeispiel, welche ein selbst gehostetes System darstellt und freingranulare Einstellungen im Bezug auf Datenschutz bietet. Aus meiner Sicht ist der wichtigste Punkt, dass die Daten in den eigenen Händen bleiben und nicht z.B. bei Google landen. Ich beschreibe daher hier auch wie Matomo mit CSP funktioniert, wenn dieses auf einer Subdomain wie https://matomo.the-digital-native.de betrieben wird.

Für WordPress ganz übliche Drittanbeiter sind:

  • Gravatar: Verknüpft beim Dienstanbieter hinterlegte Avatare mit der E-Mailadresse. Sammelt möglicherweise Daten und wird ohnehin von nur wenigen Nutzern gebraucht. Damit Benutzer trotzdem Avatare verwenden können, ist es ratsam das Plugin WP User Avatar als Ersatz zu installieren.
  • Google Fonts: Stellt zentral und kostenlos Schriftarten zur Verfügung, die durch Webdesigner einfach als Fremdresource eingebunden werden können. Eine der ärgerlichsten Datenschutzsünden, denn Google erfährt so von jedem Besucher! Außerdem ist es wirklich sehr einfach möglich, Fonts auch auf dem eigenen Server abzulegen und per CSS nachzuladen. Es gibt also nicht mal einen guten Grund auf diesen Service zurück zu greifen.

Basiskonfiguration für WordPress

Folgende Konfiguration habe ich ausführlich getestet und kann im VirtualHost von apache2 so in der Form hinterlegt werden:

Header always set Content-Security-Policy \
  "default-src 'none'; \
  img-src 'self' data: \
  style-src 'self' 'unsafe-inline'; \
  font-src 'self' data:; \
  script-src 'self' 'unsafe-inline' 'unsafe-eval'; \
  frame-src 'self' \
  form-action 'self'; \
  base-uri 'none'; \
  frame-ancestors 'self'"

Was bedeuten diese Optionen nun?

  • default-src wird immer dann angewandt, wenn eine Ressource geladen werden soll, auf die keine andere Regel zutrifft. Es wird hier empfohlen none zu setzen. Wer ein Kontakt-Formular wie Contact Form 7 einsetzt, wird hier leider zumindest self setzen müssen. Theoretisch sollte das auch anders gehen (via Direktive connect-src auf self). Leider funktioniert dies in der Praxis nicht.
  • img-src definiert, woher Bilder per <img>-Tag geladen werden können. self benötigt man hier logischerweise. Die Option data: ermöglicht das Laden von Bildern aus im HTML codierten Bildmaterial. Dies nutzt WordPress ebenfalls. Wer weitere Quellen für Bilder hat, muss diese hier angeben. Hier schließen wir u.a. Gravatar aus. Wer seinen Benutzern trotz allem Gravatar zur Verfügung stellen möchte, muss hier die URL https://secure.gravatar.com hinzufügen.
  • style-css gibt an, woher CSS-Dateien geladen werden können. Leider muss hier die unsichere Option unsafe-inline hinzugefügt werden, weil WordPress mittels <style>-Tag CSS-Attribute in das HTML einbettet. Dies ist ein Sicherheitsdefizit von WordPress. Wir schließen hier insbesondere auch Google Fonts aus, denn darauf kann man bei auch nur etwas Liebe zum Datenschutz wirklich verzichten.
  • font-src gibt Möglichkeiten zum Nachladen von Schriftarten an. Werden nur Systemschriftarten eingesetzt, kann hier none gewählt werden. WordPress lädt aber, je nach Theme, Schriftarten nach. Zum Teil auch eingebettete Schriftarten, sodass data: nötig wird.
  • script-src gibt insbesondere die Quellen für JavaScripte an. Dass wir hier self haben ist ok, jedoch erfordert WordPress auch unsafe-inline und unsafe-eval, was ein besonderes Sicherheitsrisiko darstellt. Letzteres ermöglicht das Ausführen von JavaScript-Code mit der so genannten eval()-Funktion und gibt als typischer Punkt, um Schadcode einzuschleusen. Die Entwickler von WordPress sollten hier dringend nachbessern und auch ohne unsafe-eval auskommen.
  • frame-src ermöglicht das Laden von Webseiten in <frame> oder <iframe> Elementen. Sollte aus Sicherheitsgründen auf self beschränkt bleiben, falls möglich.
  • form-action beschränkt die Webseiten, die durch das Absenden eines Formulars erreicht werden können. Für Funktionen wie Kontaktformulare, Newsletteranmeldung (lokal) etc. sollte hier self genügen.
  • Setzt man base-uri auf none, muss jede verlinkte Ressource mit einem vollständigen Pfad angegeben werden. Damit wäre z.B. <img src="my_picture.png"> nicht zulässig, sehr wohl aber <img src="https://the-digital-native.de/my_picture.png">. Erfreulicherweise setzt Wodpress dieses Sicherheitsfeature um!
  • frame-ancestors erlaubt bzw. verbietet, dass die eigene Webseite in andere Webseiten eingebunden werden kann, z.B. per iframe. Die Option self verhindert möglicherweise Missbrauch des eigenen Contents durch andere Webseitenbetreiber.

Konfiguration von Matomo

Ich empfehle Matomo auf der eigenen Domain zu hosten, z.B. als Subdomain. In dem Fall muss Matomo in img-src sowie script-src hinzugefügt werden. Wenn man die Opt-Out-Box von Matomo z.B. in die Datenschutzerklärung einbinden möchte, muss Matomo auch als frame-src zulassen, da es mittels iFrame eingebunden wird.

Header always set Content-Security-Policy \
  "default-src 'none'; \
  img-src 'self' data:  https://matomo.the-digital-native.de; \
  style-src 'self' 'unsafe-inline'; \
  font-src 'self' data:; \
  script-src 'self' https://matomo.the-digital-native.de 'unsafe-inline' 'unsafe-eval'; \
  frame-src 'self' https://matomo.the-digital-native.de; \
  form-action 'self'; \
  base-uri 'none'; \
  frame-ancestors 'self'"

Konfiguration für WordPress Administration

Die WordPress-Administration benötigt etwas mehr Rechte, um korrekt zu funktionieren. Da ich die Rechte für die Benutzerspezifischen Seiten nicht unnötig ausweiten möchte, habe ich in apache2 eine Location-Direktive erstellt, die auf das Unterverzeichnis wp-admin abzielt.

<Location ~ "/wp-admin">
Header always set Content-Security-Policy \
  "default-src 'self'; \
  img-src 'self' data: https://ps.w.org https://s.w.org; \
  style-src 'self' 'unsafe-inline'; \
  font-src 'self' data:; \
  script-src 'self' 'unsafe-inline' 'unsafe-eval'; \
  form-action 'self'; \
  base-uri 'none'; \
  frame-ancestors 'self'"
</Location>

Konfiguration von Matomo

Auch hier braucht eine Matomo Instanz ein paar extra-Regeln, um die Einbettung in das Adminmenü zu ermöglichen. Eine Konfiguration kann wie folgt aussehen:

<Location ~ "/wp-admin">
Header always set Content-Security-Policy \
  "default-src 'self'  https://matomo.the-digital-native.de; \
  img-src 'self' data: https://ps.w.org https://s.w.org  https://matomo.the-digital-native.de; \
  style-src 'self' 'unsafe-inline'; \
  font-src 'self' data:; \
  script-src 'self' https://matomo.the-digital-native.de 'unsafe-inline' 'unsafe-eval'; \
  form-action 'self'; \
  base-uri 'none'; \
  frame-ancestors 'self'"
</Location>

Weitere Plugins

Wer das Plugin Yoast zur SEO-Optimierung benutzt, muss unter default-src den Eintrag https://yoast.com hinzufügen.

Generell gilt, dass ihr bei weiteren Plugins immer überprüfen solltet, ob diese auch funktionieren. Unter F12 gibt es in Firefox & Chrome die Console, wo durch CSP geblockte Inhalte angezeigt werden. Surft damit durch eure Webseite und auch das Admin-Menü. Fügt, falls nötig, weitere Webseiten zu den einzelnen Policies hinzu. Bedenkt aber: Lokale Lösungen sind Drittanbietern aus Datenschutzsicht immer vorzuziehen! Verwendet z.B. einen eigenen Captcha-Generator statt Googles ReCaptcha. Ja, es gibt viele Dienste, die euren Benutzern tolle Funktionalitäten bieten, aber wägt immer zwischen Datenschutz und Nice-To-Have Features ab!

Qualität der CSPs testen

Dafür gibt es das Mozilla Obversatory. Trotz dass wir das Maximum rausgeholt haben und einige grüne Häkchen sammeln, bekommen wir aktuell leider -20 Punkte. Kaputt macht uns das Ranking unsafe-inline und unsafe-eval. Hier sind die Softwareentwickler von WordPress gefragt, die hier als einziges Abhilfe schaffen können. Es bleibt Verbesserungspotential!

Mozilla Obversatory für https://the-digital-native.de

Garvatar Ersetzen

Fazit

Mit Content Security Policy Headern kann man eine Menge an zusätzlicher Sicherheit und Datenschutz für seine Nutzer erzielen. Eine gut getestete Grundlage für eine WordPress-Basisinstallation sowie eine Matomo Instanz haben wir hier geliefert. Bereits dies war tagelange Ausprobiererei, bis wir das Optimum an CSPs erreicht haben, ohne das die Funktionalität Schaden genommen hat. Komplexere Installationen benötigen hier evtl. nochmals mehr Aufwand.