Zufällige Inhalte in einem WordPress-Widget darstellen

Um zufällige Inhalte in einem WordPress-Widget darzustellen, gibt es einige Plugins, welche sich dieser Anforderung annehmen. Allerdings wirken sie in den meisten Fällen leicht überdimensioniert, sodass ich auf der Suche nach einer leichtgewichtigen Lösung war. Herausgekommen ist dabei folgendes Snippet:

<div id="content0" style="display: none;">A</div>
<div id="content1" style="display: none;">B</div>

<script>
  randomIndex = Math.floor(Math.random()*2);
  document.getElementById("content" + randomIndex).style.display = "inline";
</script>

Für jeden zufälligen Inhalt wird ein div-Container angelegt und dieser ist initial nicht sichtbar. Im Skriptteil wird nun zufällig einer dieser div-Container sichtbar geschaltet. Einziger Wermutstropfen ist, dass der Widget-Titel auf diese Art und Weise nicht angepasst werden kann. Durch eine erweitere Version des Skriptes kann dieses Problem beseitigt werden:

<div id="content0" style="display: none;">A</div>
<div id="content1" style="display: none;">B</div>

<script>
  randomIndex = Math.floor(Math.random()*2);
  document.getElementById("content" + randomIndex).style.display = "inline";
  
  const titles = ["A", "B"];
  document.getElementById("custom_html-6").getElementsByClassName("widget-title")[0].textContent=titles[randomIndex];
</script>

In dieser Version werden die Titel in einem Array hinterlegt. Die entsprechende ID des gewünschten Widgets muss vorher einmalig per Hand ermittelt werden und kann dann genutzt werden, um den Titel zu setzen.

WordPress Pseudo-Cronjob-System deaktivieren

WordPress verfügt über ein Pseudo-Cronjob-System, über welches regelmäßige Aufgaben seitens WordPress ausgeführt werden. Hintergrund ist, dass die meisten Webhosting-Pakete über keine echte Cronjob-Funktionalität verfügen. Ausgelöst wird das Pseudo-Cronjob-System durch Besuche der Webseite.

Allerdings führt dies auch zu Problemen; da es so vorkommen kann, das bestimmte Dinge, wie die Veröffentlichung geplanter Artikel, sich verzögern können. Wird WordPress auf einem dedizierten Server ausgeführt, kann hier auf einen echten Cronjob gewechselt werden. Dazu müssen zur Konfigurationsdatei wp-config.php folgende Zeilen hinzugefügt werden:

/* Deaktiviere WordPress Pseudo-Cronjob-System */
define('DISABLE_WP_CRON', true);

Damit die Cronjob-Funktionalität weiterhin funktioniert, muss der Cronjob entsprechend eingetragen werden. Dazu wird die Crontab-Datei im Kontext des Nutzers www-data geöffnet:

sudo -u www-data crontab -e

Dort sollte dann die entsprechende Zeile hinzugefügt werden:

*/1  *    * * *   php /var/www/wordpress/wp-cron.php

Damit werden die Aufgaben, welche WordPress im Rahmen seines Pseudo-Cronjob-System durchführt, nun durch einen echten Cronjob durchgeführt. Damit ist die Zuverlässigkeit des Systems erhöht und geplante Aufgaben, werden immer zeitnah erledigt.

w.org im Seitenquelltext unter WordPress

Auf einer Webseite, welche ich betreibe, fand sich folgende Abhängigkeit im Quelltext der Seite:

<link rel='dns-prefetch' href='//s.w.org' />

Hier wurde ein DNS Prefetch durchgeführt, das bedeutet der Browser angewiesen wird, besagte Domain bereits per DNS aufzulösen, bevor sich eigentlich benötigt wird. Grundsätzlich achte ich darauf das meine Webseiten ohne externe Abhängigkeiten auskommen. Eine Ausnahme ist z.B. der Zählschnipsel der VG Wort, welcher für die Abrechnung entsprechender Texte benötigt wird.

Bei der Ursachenforschung stellte ich fest das WordPress hier Emojis nachlädt, obwohl dies in den Einstellungen in der Sektion Schreiben deaktiviert wurde.

In den Einstellungen kann die automatische Umwandlung von Emojis abgeschaltet werden

Ursächlich für das Problem war ein Unicode-Zeichen, welches in einem Widget der Seite genutzt wurde und dazu führte, dass das entsprechende Zeichen extern als SVG-Datei geladen wird. Die einfachste Lösung ist es das entsprechende Zeichen zu entfernen, allerdings kann dieses Verhalten auch generell abgeschaltet werden. Dazu sind in der Datei functions.php des benutzen Themes folgende Zeilen hinzuzufügen:

add_filter( 'emoji_svg_url', '__return_false' );
remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
remove_action( 'wp_print_styles', 'print_emoji_styles' );

Damit ist die automatische Umwandlung von Emojis abgeschaltet und auch der entsprechende DNS Prefetch sollte nicht mehr im Quelltext auftauchen.

WordPress CLI installieren und nutzen

Für das Content-Management-System WordPress existiert neben dem eigentlichen System auch eine separate Kommandozeile. Die hört auf den Namen WP-CLI und muss im ersten Schritt installiert werden:

curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x wp-cli.phar
mv wp-cli.phar /usr/local/bin/wp

Damit ist die WP-CLI installiert und kann über das Kommando:

wp --info

getestet werden. Um WP-CLI aktuell zu halten, kann das Kommando:

wp cli update

genutzt werden.

Grundsätzlich sollten die Befehle der WP-CLI im Kontext des Webserver-Nutzers ausgeführt werden. In den meisten Fällen ist dies www-data. Eine Ausnahme bilden die Befehle zur Installation und zur Aktualisierung. Wird versucht ein WP-CLI-Befehl unter dem root-Nutzer auszuführen, so erhält der Nutzer folgende Meldung:

Error: YIKES! It looks like you’re running this as root. You probably meant to run this as the user that your WordPress installation exists under.

If you REALLY mean to run this as root, we won’t stop you, but just bear in mind that any code on this site will then have full control of your server, making it quite DANGEROUS.

If you’d like to continue as root, please run this again, adding this flag: –allow-root

If you’d like to run it as the user that this site is under, you can run the following to become the respective user:

sudo -u USER -i — wp

Per sudo mit dem korrekten Nutzer ausgeführt funktioniert das Ganze:

sudo -u www-data wp transient delete --all
Success: 163 transients deleted from the database.

Mittels der WP-CLI lassen sich eine Reihe von Aufgaben bewerkstelligen. So verfügt die CLI über Methoden, um Kommentare zu erzeugen und zu verwalten. Mit dem Befehl:

wp comment delete $(wp comment list --status=spam --format=ids)

können z.B. alle Spam-Kommentare gelöscht werden. Über den core-Namespace können unter anderem WordPress-Updates vorgenommen werden:

wp core update

Vor allem im Zusammenhang mit einer Automation spielt WP-CLI seine Stärken aus. So können neue WordPress-Installationen angelegt werden und entsprechende Plugins automatisch installiert werden. In der Entwickler-Dokumentation von WordPress findet sich eine Referenz der Befehle der WP-CLI.

Entwickelt wird WP-CLI auf Github. Lizenziert ist das CLI unter der MIT-Lizenz und damit freie Software. Die offizielle Seite des Projektes ist unter wp-cli.org zu finden.

Fail2ban für WordPress einrichten

Beim Betrieb eines Servers wird der Nutzer schnell feststellen, dass er nicht der einzige ist, der gerne Zugriff auf den Ser­ver hätte. Um zu häu­fige Log­in­ver­su­che abzu­blo­cken, gibt es Fail2ban. Die­ses Pro­gramm­pa­ket durch­sucht die ent­spre­chen­den Logs und blockiert bös­wil­lige Ver­su­che, in das Sys­tem ein­zu­bre­chen. Damit gehört Fail2ban zu den Intru­sion Preven­tion-Sys­te­men. Damit kann es auch zur Auswertung von Login-Versuchen auf die eigenen WordPress-Installationen genutzt werden. Wer in die Logs schaut, wird dort ähnliche Zeilen finden:

18.217.216.181 – – [23/Nov/2021:19:32:40 +0100] „POST /wp-login.php HTTP/1.1“ 200 8408 „https://seeseekey.net/wp-login.php“ „Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:94.0) Gecko/20100101 Firefox/94.0“

Um WordPress mit Fail2ban zu verheiraten muss ein einsprechender Jail und ein Filter angelegt werden. Was mich im Vorfeld in Bezug auf WordPress irritierte war der Statuscode 200, wenn ein Login in WordPress fehlschlägt. Hintergrund ist hier das WordPress bei einem erfolgreichen Login stattdessen den Statuscode 302 (Found) nutzt. Damit kann im ersten Schritt der Jail für Fail2ban erstellt werden:

nano /etc/fail2ban/jail.d/wordpress.conf

Diese Datei wird nun wie folgt befüllt:

[wordpress]
enabled = true
port = http,https
filter = wordpress
logpath = /var/log/nginx/access.log
maxretry = 3

Anschließend muss der genutzte Filter ebenfalls angelegt werden:

nano /etc/fail2ban/filter.d/wordpress.conf

Der entsprechende Filter sieht wie folgt aus:

# Filter for WordPress login

[INCLUDES]

before = common.conf
 
[Definition]

failregex = <HOST>.*POST.*(wp-login\.php|xmlrpc\.php).* 200

datepattern = %%d/%%b/%%Y:%%H:%%M:%%S %%z

Nach einem Neustart von Fail2ban mittels:

service fail2ban restart

ist der neue Jail aktiv. Über das Log kann die Arbeit desselben betrachtet werden:

tail -f /var/log/fail2ban.log

Damit sind die WordPress-Installationen gegen den Versuch unbefugter Logins besser abgesichert. Nach drei Fehlversuchen, wird die entsprechende IP-Adresse gesperrt, sodass weitere Verbindungsversuche von dieser IP-Adresse vom Server nicht mehr beantwortet werden.