WordPress + Redis + Crowdsec in Docker

Das von uns am häufigsten verwendete Blog- und CMS-System ist WordPress. Dieses lässt sich auch performant als Docker Container betreiben. Redis als object cache beschleunigt die Zugriffe. Für mehr Sicherheit bietet sich die Community Version von Crowdsec an.

Im folgenden Beispiel zeigen wir, wie dies mittel Docker Compose einfach aufgesetzt werden kann.

Zutaten

Vorbereitung

Für die Kommunikation zwischen WordPress und Crowdsec sollte man ein Dockernetzwerk mit festen IPs erstellen. Andernfalls kann es nach einem Neustart der Container passieren, dass diese andere IPs erhalten und die Kommunikation mit dem Bouncer ins Leere läuft.

In den Beispielen wird immer das Verzeichnis /docker/wordpress als Basis verwendet.

Erstellung des Netzwerkes für die Container & der wordpress.ini

In der Shell das Subnet erstellen (“wpnet”). Die Range kann natürlich frei gewählt werden:

				
					docker network create --subnet=172.26.0.0/24 wpnet
				
			

Im nächsten Schritt erstellt man die wordpress.ini, welche wichtige Einstellungen für die Performance erhält:

				
					nano /docker/wordpress/wordpress.ini
				
			

Die Werte innerhalb der wordpress.ini können nach eigenen Vorgaben angepasst werden:

				
					upload_max_filesize = 256M  
post_max_size = 512M  
max_execution_time = 3000  
max_input_time = 3000  
memory_limit = 1024M  
file_uploads= On  
max_input_vars = 15000
				
			

Die docker-compose.yml erstellen

WordPress + MariaDB + Redis + Crowdsec

				
					nano /docker/wordpress/docker-compose.yml
				
			

Inhalt der docker-compose.yml:

				
					version: '3.1'

services:

  wordpress:
    image: wordpress:latest
    container_name: wordpress
    environment:
      WORDPRESS_DB_HOST: wordpress-db
      WORDPRESS_DB_USER: wp-dbuser   
      WORDPRESS_DB_PASSWORD: EinSuperGeheimesPasswort
      WORDPRESS_DB_NAME: wordpress
      WORDPRESS_CONFIG_EXTRA:
        define('WP_POST_REVISIONS', 5);
        define( 'WP_MEMORY_LIMIT' , '1024M' );
        set_time_limit(300);
        define( 'WP_REDIS_HOST', 'wordpress-redis' );
        define( 'WP_REDIS_PORT', 6379 );
        define( 'DISABLE_WP_CRON', true);
    volumes:
      - /docker/wordpress/app:/var/www/html
      - /docker/wordpress/wordpress.ini:/usr/local/etc/php/conf.d/wordpress.ini
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro
    networks:
      wpnet:
        ipv4_address: 172.26.0.10
    ports:
      - 80:80
      - 443:433
    restart: always
    logging:
      driver: "syslog"

  wordpress-db:
    image: mariadb:latest
    container_name: wordpress-db
    environment:
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wp-dbuser    
      MYSQL_PASSWORD: EinSuperGeheimesPasswort
      MYSQL_RANDOM_ROOT_PASSWORD: '1'
    volumes:
      - /docker/wordpress/database:/var/lib/mysql
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro
    networks:
       wpnet:
         ipv4_address: 172.26.0.11
    restart: always

  wordpress-redis:
    image: redis:alpine
    container_name: wordpress-redis
    ports:
    - 6379:6379
    networks:
      wpnet:
        ipv4_address: 172.26.0.12
    restart: always

  crowdsec:
    image: docker.io/crowdsecurity/crowdsec:latest
    container_name: crowdsec
    ports:
     - 49155:8080
    environment:
     - GID=1000
     - COLLECTIONS=crowdsecurity/wordpress crowdsecurity/http-cve crowdsecurity/whitelist-good-actors
    networks:
       wpnet:
         ipv4_address: 172.26.0.13
    volumes:
     - /docker/wordpress/crowdsec/config:/etc/crowdsec:rw
     - /docker/wordpress/crowdsec/data:/var/lib/crowdsec/data:rw
     - /var/log:/var/log/host:ro
    restart: unless-stopped

networks:
  wpnet:
    external: true
				
			

Die Ports von WordPress (80 & 443) können frei gewählt werden. Ebenso sollte die Umgebungsvariablen “MYSQL_PASSWORD:” auf ein eigenes starkes Passwort geändert werden. Für den HTTPS-Zugriff empfiehlt sich der Zugriff via einen der üblichen Proxies (Traefik, NPM, HAProxy, etc.). Die Werte unter “WORDPRESS_CONFIG_EXTRA:” können ebenfalls den eigenen Vorstellungen angepasst werden (konform zur wordpress.ini).

Wichtig sind hier die IPs der einzelnen Container:

  • 172.26.0.10 -> WordPress
  • 172.26.0.11 -> MariaDB
  • 172.26.0.12 -> Redis
  • 172.26.0.13 -> Crowdsec

Erstmaliger Pull & Start der Container

				
					sudo docker compose -f /docker/wordpress/docker-compose.yml up -d
				
			

Die Container werden nach dem Pull im Hintergrund gestartet. Nach dem ersten Start sollte man die Verzeichnisberechtigungen anpassen. Hierfür stoppt man die Container zunächst wieder:

				
					sudo docker compose -f /docker/wordpress/docker-compose.yml down
				
			

und setzt für das Verzeichnis ./app die Berechtigung/Ownership auf den user “www-data”:

				
					sudo chown -R www-data:www-data /docker/wordpress/app
				
			

Die Container anschließend wieder starten und die Ersteinrichtung starten:

				
					sudo docker compose -f /docker/wordpress/docker-compose.yml up -d
				
			

Ersteinrichtung von WordPress

Plugins für Redis + Crowdsec installieren

Nachdem man die Ersteinrichtung erledigt hat (Blogtitel, Sprache, User, E-Mail, Passwort, etc.) installiert man die Plugins “Redis Object Cache” und “Crowdsec”:

Nach der Aktivierung der Plugins klickt man in der oberen Leiste des Dashboards auf “Object Cache” und aktiviert diesen:

Konfiguration von Crowdsec

Zur Absicherung von WordPress konfiguriert man im letzten Schritt Crowdsec. Zunächst erstellt man sich für “cscli” (Crowdsec CLI) einen temporären Alias in der Shell:

				
					alias cscli="docker exec -t crowdsec cscli"
				
			

Bouncer erstellen

Nun erstellt man einen “Bouncer” für WordPress. Wichtig: den API-Key, welcher angezeigt wird, unbedingt notieren/speichern. Dieser wird später in WordPress noch benötigt:

				
					cscli bouncers add wordpress-bouncer
				
			

Die Ausgabe sollte dann so aussehen:

Den Bouncer mit WordPress verbinden

				
					API key for 'wordpress-bouncer':

   nDxCE0eGRCPl77eWqGJVSg

Please keep this key since you will not be able to retrieve it!
				
			

Zurück im Admin-Dashboard von WordPress in das Crowdsec-Menü gehen (Crowdsec -> Crowdsec). Hier tragen wir die Docker-IP mit Port von Crowdsec (172.26.0.13:8080) sowie unseren eben erzeugten API-Key ein und bestätigen die Änderungen:

Dank statischer IP des Bouncers gibt es nach einem Neustart keine Verbindungsfehler

Das Bouncing Level sollte auf “Normal bouncing” stehen. Um auch das Backend/Login abzusichern, sollte der Schieber “Public website only” nicht aktiviert werden.

Mittels “Test bouncing” kann man überprüfen, ob die Kommunikation soweit läuft.

Falls WordPress hinter einem Proxy betrieben wird, muss dessen IP unter Advanced eingetragen werden (im Format X.X.X.X/32):

Crowdsec "pimpen"

Um die Sicherheit via Crowdsec weiter zu erhöhen, können neben den bereits enthaltenen Collections (crowdsecurity/wordpress, crowdsecurity/http-cve, crowdsecurity/whitelist-good-actors) noch weitere Szenarios über die Shell hinzugefügt werden:

Detect WordPress bruteforce

				
					cscli scenarios install crowdsecurity/http-bf-wordpress_bf
				
			

Detect WordPress bruteforce on xmlrpc

				
					cscli scenarios install crowdsecurity/http-bf-wordpress_bf_xmlrpc
				
			

Detect WordPress authors enumeration

				
					cscli scenarios install crowdsecurity/http-wordpress_user-enum
				
			

Detect WordPress probing aorund wp-config.php

				
					cscli scenarios install crowdsecurity/http-wordpress_wpconfig
				
			

CSCLI dauerhaft in der Shell verfügbar machen

Möchte man den Alias CSCLI nicht nach jedem Neustart neu definieren, kann man diesen auch dauerhaft setzen:

				
					nano ~/.bashrc
				
			

Am Ende der Datei diesen Eintrag setzen:

				
					alias cscli='docker exec -t crowdsec cscli'

				
			

Die Datei speichern und bashrc reloaden:

				
					source ~/.bashrc
				
			

Nützliche Kommandos für CSCLI

Alerts abfragen

				
					cscli alerts list
				
			

Collections anzeigen

				
					cscli collections list
				
			
				
					COLLECTIONS
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 Name 📦 Status Version Local Path
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 crowdsecurity/http-cve ✔️ enabled 2.5 /etc/crowdsec/collections/http-cve.yaml
 crowdsecurity/linux ✔️ enabled 0.2 /etc/crowdsec/collections/linux.yaml
 crowdsecurity/sshd ✔️ enabled 0.2 /etc/crowdsec/collections/sshd.yaml
 crowdsecurity/whitelist-good-actors ✔️ enabled 0.1 /etc/crowdsec/collections/whitelist-good-actors.yaml
 crowdsecurity/wordpress ✔️ enabled 0.4 /etc/crowdsec/collections/wordpress.yaml
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────

				
			

Collections, Scenarios & Parser (Hub) abfragen

				
					cscli hub list
				
			
				
					COLLECTIONS
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 Name 📦 Status Version Local Path
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 crowdsecurity/http-cve ✔️ enabled 2.5 /etc/crowdsec/collections/http-cve.yaml
 crowdsecurity/linux ✔️ enabled 0.2 /etc/crowdsec/collections/linux.yaml
 crowdsecurity/sshd ✔️ enabled 0.2 /etc/crowdsec/collections/sshd.yaml
 crowdsecurity/whitelist-good-actors ✔️ enabled 0.1 /etc/crowdsec/collections/whitelist-good-actors.yaml
 crowdsecurity/wordpress ✔️ enabled 0.4 /etc/crowdsec/collections/wordpress.yaml
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────

PARSERS
───────────────────────────────────────────────────────────────────────────────────────────────────────────────
 Name 📦 Status Version Local Path
───────────────────────────────────────────────────────────────────────────────────────────────────────────────
 crowdsecurity/cri-logs ✔️ enabled 0.1 /etc/crowdsec/parsers/s00-raw/cri-logs.yaml
 crowdsecurity/dateparse-enrich ✔️ enabled 0.2 /etc/crowdsec/parsers/s02-enrich/dateparse-enrich.yaml
 crowdsecurity/docker-logs ✔️ enabled 0.1 /etc/crowdsec/parsers/s00-raw/docker-logs.yaml
 crowdsecurity/geoip-enrich ✔️ enabled 0.2 /etc/crowdsec/parsers/s02-enrich/geoip-enrich.yaml
 crowdsecurity/sshd-logs ✔️ enabled 2.2 /etc/crowdsec/parsers/s01-parse/sshd-logs.yaml
 crowdsecurity/syslog-logs ✔️ enabled 0.8 /etc/crowdsec/parsers/s00-raw/syslog-logs.yaml
 crowdsecurity/whitelists ✔️ enabled 0.2 /etc/crowdsec/parsers/s02-enrich/whitelists.yaml
───────────────────────────────────────────────────────────────────────────────────────────────────────────────

SCENARIOS
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 Name 📦 Status Version Local Path
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 crowdsecurity/CVE-2019-18935 ✔️ enabled 0.2 /etc/crowdsec/scenarios/CVE-2019-18935.yaml
 crowdsecurity/CVE-2022-26134 ✔️ enabled 0.2 /etc/crowdsec/scenarios/CVE-2022-26134.yaml
 crowdsecurity/CVE-2022-35914 ✔️ enabled 0.2 /etc/crowdsec/scenarios/CVE-2022-35914.yaml
 crowdsecurity/CVE-2022-37042 ✔️ enabled 0.2 /etc/crowdsec/scenarios/CVE-2022-37042.yaml
 crowdsecurity/CVE-2022-40684 ✔️ enabled 0.3 /etc/crowdsec/scenarios/CVE-2022-40684.yaml
 crowdsecurity/CVE-2022-41082 ✔️ enabled 0.4 /etc/crowdsec/scenarios/CVE-2022-41082.yaml
 crowdsecurity/CVE-2022-41697 ✔️ enabled 0.2 /etc/crowdsec/scenarios/CVE-2022-41697.yaml
 crowdsecurity/CVE-2022-42889 ✔️ enabled 0.3 /etc/crowdsec/scenarios/CVE-2022-42889.yaml
 crowdsecurity/CVE-2022-44877 ✔️ enabled 0.3 /etc/crowdsec/scenarios/CVE-2022-44877.yaml
 crowdsecurity/CVE-2022-46169 ✔️ enabled 0.2 /etc/crowdsec/scenarios/CVE-2022-46169.yaml
 crowdsecurity/CVE-2023-22515 ✔️ enabled 0.1 /etc/crowdsec/scenarios/CVE-2023-22515.yaml
 crowdsecurity/CVE-2023-22518 ✔️ enabled 0.2 /etc/crowdsec/scenarios/CVE-2023-22518.yaml
 crowdsecurity/CVE-2023-49103 ✔️ enabled 0.2 /etc/crowdsec/scenarios/CVE-2023-49103.yaml
 crowdsecurity/apache_log4j2_cve-2021-44228 ✔️ enabled 0.5 /etc/crowdsec/scenarios/apache_log4j2_cve-2021-44228.yaml
 crowdsecurity/f5-big-ip-cve-2020-5902 ✔️ enabled 0.2 /etc/crowdsec/scenarios/f5-big-ip-cve-2020-5902.yaml
 crowdsecurity/fortinet-cve-2018-13379 ✔️ enabled 0.3 /etc/crowdsec/scenarios/fortinet-cve-2018-13379.yaml
 crowdsecurity/grafana-cve-2021-43798 ✔️ enabled 0.2 /etc/crowdsec/scenarios/grafana-cve-2021-43798.yaml
 crowdsecurity/http-bf-wordpress_bf ✔️ enabled 0.5 /etc/crowdsec/scenarios/http-bf-wordpress_bf.yaml
 crowdsecurity/http-bf-wordpress_bf_xmlrpc ✔️ enabled 0.2 /etc/crowdsec/scenarios/http-bf-wordpress_bf_xmlrpc.yaml
 crowdsecurity/http-cve-2021-41773 ✔️ enabled 0.2 /etc/crowdsec/scenarios/http-cve-2021-41773.yaml
 crowdsecurity/http-cve-2021-42013 ✔️ enabled 0.2 /etc/crowdsec/scenarios/http-cve-2021-42013.yaml
 crowdsecurity/http-wordpress_user-enum ✔️ enabled 0.2 /etc/crowdsec/scenarios/http-wordpress_user-enum.yaml
 crowdsecurity/http-wordpress_wpconfig ✔️ enabled 0.2 /etc/crowdsec/scenarios/http-wordpress_wpconfig.yaml
 crowdsecurity/jira_cve-2021-26086 ✔️ enabled 0.2 /etc/crowdsec/scenarios/jira_cve-2021-26086.yaml
 crowdsecurity/netgear_rce ✔️ enabled 0.3 /etc/crowdsec/scenarios/netgear_rce.yaml
 crowdsecurity/pulse-secure-sslvpn-cve-2019-11510 ✔️ enabled 0.3 /etc/crowdsec/scenarios/pulse-secure-sslvpn-cve-2019-11510.yaml
 crowdsecurity/spring4shell_cve-2022-22965 ✔️ enabled 0.3 /etc/crowdsec/scenarios/spring4shell_cve-2022-22965.yaml
 crowdsecurity/ssh-bf ✔️ enabled 0.3 /etc/crowdsec/scenarios/ssh-bf.yaml
 crowdsecurity/ssh-slow-bf ✔️ enabled 0.4 /etc/crowdsec/scenarios/ssh-slow-bf.yaml
 crowdsecurity/thinkphp-cve-2018-20062 ✔️ enabled 0.4 /etc/crowdsec/scenarios/thinkphp-cve-2018-20062.yaml
 crowdsecurity/vmware-cve-2022-22954 ✔️ enabled 0.3 /etc/crowdsec/scenarios/vmware-cve-2022-22954.yaml
 crowdsecurity/vmware-vcenter-vmsa-2021-0027 ✔️ enabled 0.2 /etc/crowdsec/scenarios/vmware-vcenter-vmsa-2021-0027.yaml
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

POSTOVERFLOWS
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 Name 📦 Status Version Local Path
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 crowdsecurity/cdn-whitelist ✔️ enabled 0.4 /etc/crowdsec/postoverflows/s01-whitelist/cdn-whitelist.yaml
 crowdsecurity/rdns ✔️ enabled 0.3 /etc/crowdsec/postoverflows/s00-enrich/rdns.yaml
 crowdsecurity/seo-bots-whitelist ✔️ enabled 0.4 /etc/crowdsec/postoverflows/s01-whitelist/seo-bots-whitelist.yaml
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

				
			
Nach oben scrollen