Proxmox Mail Gateway PMG Emails auf Wörter in Nachricht filtern Mailbody
Aus znilwiki
Changelog:
- 02.06.2025 Skript Version 1.0 => erste Version
- 03.06.2025 Skript Version 1.1 => mehr Details in den Logmeldungen / Syslog, Farbige Meldungen in der Konsole
Vorwort
In letzter Zeit werden meine Familie und ich von Spam-Mails über Erektionsproblemen überflutet. Ein Großteil filtert das PMG schon aus so das dieses schon mal in Quarantäne landen. Aber es sind so viele das immer noch ein großer Teil durchrutscht.
Die Mails sehen alle so aus:
Der Text variiert, der Aufbau ist immer gleich. Die Mails werden dabei immer von vertrauenswürdigen Quellen gesendet, vermutlich also gehackte Emailkonten.
Allen gemein ist das immer auf eine URL verwiesen wird die auf
apotheke.html
endet. Die HTML-Datei liegt dabei oft auch auf den Webspace von vertrauenswürdigen Webseiten (die vermutlich auch gehackt wurden).
Also eigentlich etwas wonach man prima filtern könnte.
Es stellte sich aber heraus das es dann doch nicht ganz so einfach mit PMG ist, denn es gibt keinen direkten Weg über die Weboberfläche.
Custom Check Skript erstellen
Die Grundlage der Lösung findet sich in der Hilfe:
https://pmg.proxmox.com/pmg-docs/pmg-admin-guide.html#pmgconfig_custom_check
Ich wollte es erst per SpamAssassin machen (mache ich vielleicht noch), die Lösung mit dem Skript gefiel mir jedoch im Moment besser.
Wir erstellen das folgende Skript:
nano /usr/local/bin/pmg-custom-check
mit folgendem Inhalt:
#!/bin/bash
# Siehe https://znil.net/index.php?title=Proxmox_Mail_Gateway_PMG_Emails_auf_W%C3%B6rter_in_Nachricht_filtern_Mailbody
#
# V1.1 vom 03.06.2025 von Bernhard Linz => Bernhard@znil.de
#
# Filter, weitere einfach mit Leerzeichen und in "..." hinzufügen, Es wird auf "String in String" getestet
# Nach SPAM
filterArraySPAM=("apotheke.html" "test1234567890")
# Spam Score der gesetzt werden soll wenn es einen SPAM Treffer gibt
spamScoreSPAM=4
# Nach Whitelisting
filterArrayWHITE=("Test Abrakadabra")
# Spam Score der gesetzt werden soll wenn es einen WHITE Treffer gibt
spamScoreWHITE=-10
###############################################################################
# schreibt nach STDERR durch 1>&2, das landet dann nur im Logfile /var/log/mail.log
# und wird nicht als Rückgabe des Skriptes interpretiert
# echo "/usr/bin/pmg-custom-check called with $*" 1>&2
echo -e "\e[31m/usr/bin/pmg-custom-check called with $*\e[0m" 1>&2
# Fehler wenn nicht 2 Argumente
if [ "$#" -ne 2 ]; then
echo "usage: $0 APIVERSION QUEUEFILENAME" 1>&2
exit 1
fi
# Argument $1 ist die API-Version
apiver="$1"
# Argument $2 ist die Datei mit der Email
queue_file="$2"
# shift würde das Argument $2 zu $1 verschieben
#shift
if [ "$apiver" != "v1" ]; then
echo "/usr/bin/pmg-custom-check wrong APIVERSION: $apiver" 1>&2
exit 2
fi
#queue_file="$1"
# Das Skirpt muss auf STDOUT 2 Ausgaben machen:
# Die API-Version, hier also v1
echo "v1"
# Und eine(!) der folgenden 3 Ausgaben:
# 1: Es ist alles ok:
#echo "OK"
# 2: Die Mail enthält einen Virus
#echo "VIRUS: <virusdescription>"
# 3: Die Mail enthält SPAM, wir können den SPAM-Score beinflussen und z.B. um 2 erhöhen (der Startwert ist dann 2)
#echo SCORE: 2
# 4: Die Mail soll auf keinen Fall als SPAM erkannt werden, wir setzen den SCORE auf einen negativen Wert:<br>
#echo SCORE: -10
# Dateinhalte (=Mail) einlesen
#queue_filecontent=$(< $queue_file)
queue_filecontent=$(cat $queue_file)
# Variable die ggf. am Ende dafür sorgt das "OK" ausgegeben wird
bNoSPAM=true
# Test auf WHITE(-listing)
for strWHITE in ${filterArrayWHITE[@]}; do
# echo $strSPAM
if [[ "$queue_filecontent" =~ $strWHITE ]]; then
bNoSPAM=false
#echo "/usr/bin/pmg-custom-check SCORE: ${spamScoreWHITE}" 1>&2
echo -e "\e[31m/usr/bin/pmg-custom-check SCORE: ${spamScoreWHITE}\e[0m" 1>&2
echo "SCORE: ${spamScoreWHITE}"
break
fi
done
# Test auf SPAM:
for strSPAM in ${filterArraySPAM[@]}; do
# echo $strSPAM
if [[ "$queue_filecontent" =~ $strSPAM ]]; then
bNoSPAM=false
#echo "/usr/bin/pmg-custom-check SCORE: ${spamScoreSPAM}" 1>&2
echo -e "\e[31m/usr/bin/pmg-custom-check SCORE: ${spamScoreSPAM}\e[0m" 1>&2
echo "SCORE: ${spamScoreSPAM}"
break
fi
done
if $bNoSPAM; then
#echo "/usr/bin/pmg-custom-check OK" 1>&2
echo -e "\e[31m/usr/bin/pmg-custom-check OK\e[0m" 1>&2
echo "OK"
fi
exit 0
Und das Skript ausführbar machen:
chmod +x /usr/local/bin/pmg-custom-check
Im Skript könnte Ihr zwei Dinge einstellen:
# Nach SPAM filterArraySPAM=("apotheke.html" "test1234567890") # Spam Score der gesetzt werden soll wenn es einen SPAM Treffer gibt spamScoreSPAM=4
Da hinterlegt Ihr die Liste der Wörter, Sätze, Zeichenfolgen die als SPAM gekennzeichnet werden soll und entscheidet welche Punktzahl die Mail als Spam bekommt.
In diesem Fall hier die 4. Die Mail wird trotzdem weiter verarbeitet, also alles was im Bereich Mail Filter aktiviert ist, greift zusätzlich.
Ggf. kommen also weitere SPAM-Punkte hinzu und die Mail wird ganz ablehnt.
# Nach Whitelisting filterArrayWHITE=("Test Abrakadabra") # Spam Score der gesetzt werden soll wenn es einen WHITE Treffer gibt spamScoreWHITE=-10
Das gleiche Prinzip, nur das die Mail dann mit -10 in die weitere Verarbeitung geht. Selbst wenn dann noch Spam Punkte gesammelt werden, wird die Mail also höchstwahrscheinlich zugestellt.
Skript testen Teil 1
Dazu bräuchten wir Dateien mit Mails.
Wenn Ihr eine in der SPAM-Ansicht RAW habt, könnt mit einem eindeutigen Text danach suchen, in diesem Fall ist das die SPAM-Mail mit apotheke.html:
grep -lr "minute.eicindustria.com.br" /var/spool
Beispielausgabe:
/var/spool/pmg/spam/5A/10013F683BC2482795A
Damit können wir unser Skript nun testen
/usr/local/bin/pmg-custom-check v1 /var/spool/pmg/spam/5A/10013F683BC2482795A
Beispielausgabe:
/usr/bin/pmg-custom-check called with v1 /var/spool/pmg/spam/26/1002A068303219D3E26 v1 /usr/bin/pmg-custom-check SCORE: 4
Die erste und dritte Zeile landet später nur in /var/log/mail.log und im syslog, die anderen beiden sind die notwendige Rückgabe für das PMG.
Gegenprobe mit einer anderen Email, mit
find /var/spool/pmg/spam/ -type f -printf "%T@ %p\n" | sort -nr | cut -d\ -f2-
könnt Ihr euch alle vorhandenen SPAM-Emails anzeigen lassen.
/usr/local/bin/pmg-custom-check v1 /var/spool/pmg/spam/26/1002A068303219D3E26
Beispielausgabe:
Skript scharf schalten
Wir aktivieren das Skript:
nano /etc/pmg/pmg.conf
und im ersten Abschnitt
section: admin
hängen wir die folgenden beiden Zeilen an:
custom_check_path /usr/local/bin/pmg-custom-check custom_check 1
Leider weis ich nicht welchen der Dienste man nun neu starten müsste bzw. wie man das erneute Einlesen der Konfiguration anstößt.
Deshalb starte ich den PMG neu:
reboot
Testmail
Im Skript oben habe ich als Filter auch test1234567890 eingebaut,
also schicke ich mir mal eine Testmail von außerhalb mit der Zeichenfolge:
Und tatata! Der Spam Score ist 4! Ab 5 hätte er die Mail gleich verworfen!
Es funktioniert also!
Im Syslog
Im Mailgateway Syslog sehen wir die Aufrufe des Skriptes:
Die komischen Sonderzeichen kommen daher das ich den Text in der Konsole unbedingt in rot haben wollte.
ToDo
Folgendes möchte ich bei Gelegenheit noch in das Skript einbauen:
- Echte RegEx-Abfrage statt nur String in String
Quellen
- https://forum.proxmox.com/threads/mailbody-scan.136637/
- https://pmg.proxmox.com/pmg-docs/pmg-admin-guide.html#_custom_spamassassin_configuration