InfraFenceInfraFence

Live Security Operations

Loslegen

Wenn dein Server Spam versendet: so stoppst du ihn

Zuletzt aktualisiert:

Das erste Anzeichen ist selten der Spam selbst. Es ist eine Abuse-Mail des Providers, ein Kunde, dessen Rechnungen im Spam-Ordner landen, Bounces für Mails, die du nie verschickt hast, oder eine Mail-Queue mit zehntausend Nachrichten. Bis dahin steht die Adresse des Servers meist schon auf einer Blocklist, und jede legitime Mail von ihm leidet mit.

Spam verlässt einen Server auf drei Wegen: über ein Postfach, dessen Passwort erraten oder gestohlen wurde, über ein PHP-Skript (ein gehacktes Plugin oder ein missbrauchtes Kontaktformular), das mail() aufruft, oder über ein Programm, das selbst per SMTP mit anderen Servern spricht. Die Schritte unten zeigen, welcher Weg es ist, stoppen ihn, räumen auf, schließen die Lücke und holen die Adresse von den Listen. Die Befehle gelten für Postfix und Exim unter Debian, Ubuntu und der RHEL-Familie; spammer@example.com, QUEUE_ID und 203.0.113.10 stehen für das, was du findest.

Prüfen, ob der Server Spam verschickt

Fang mit der Mail-Queue an. Ein gesunder Server hat eine Handvoll wartender Nachrichten, oft gar keine. Tausende Nachrichten oder ein einzelner Absender, dem die meisten davon gehören, bedeuten Spam. Der zweite Befehl listet die Absender mit den meisten Nachrichten in der Queue.

Postfix
sudo postqueue -p | tail -n 1
sudo postqueue -p | awk '/^[0-9A-Za-z]/ {print $7}' | sort | uniq -c | sort -rn | head

Exim, wie unter cPanel und mit Debians exim4 (der Befehl exim ist auch dort vorhanden), zählt die Queue mit exim -bpc. Die nächsten Zeilen listen die häufigsten Absender und Zieldomains:

Exim
sudo exim -bpc
sudo exim -bp | awk '/^ *[0-9]+[mhd] / {print $4}' | sort | uniq -c | sort -rn | head
sudo exim -bp | exiqsumm | sort -rn | head

Ein Absender <> oder MAILER-DAEMON ist ein Bounce. Eine Queue voller Bounces bedeutet, dass der Server Mails an Adressen angenommen oder verschickt hat, die es nicht gibt: typisch für Spam von hier oder für Backscatter aus einem Formular, das eine Kopie an jede eingetippte Adresse schickt.

Welches Konto versendet

Spam über ein Postfach zeigt sich als ein angemeldeter Benutzer mit weit mehr Nachrichten als alle anderen. Postfix protokolliert ihn als sasl_username, in den Logdateien oder, ohne rsyslog, im Journal:

Postfix
sudo sh -c "zgrep -h -o 'sasl_username=[^ ,]*' /var/log/mail.log* /var/log/maillog* 2>/dev/null" \
  | sort | uniq -c | sort -rn | head
sudo journalctl --since "24 hours ago" -t postfix/smtpd | grep -o 'sasl_username=[^ ,]*' \
  | sort | uniq -c | sort -rn | head

Exim protokolliert die Anmeldung als A= bei jeder angenommenen Nachricht und bei lokal eingelieferter Mail den Ordner des Skripts als cwd= (cPanel tut das standardmäßig). Ein cwd= innerhalb einer Website, etwa /home/user/public_html/wp-content/…, zeigt auf das Skript:

Exim
sudo grep -h ' <= ' /var/log/exim_mainlog /var/log/exim4/mainlog 2>/dev/null \
  | grep -o ' A=[^ ]*' | sort | uniq -c | sort -rn | head
sudo grep -h -o 'cwd=[^ ]*' /var/log/exim_mainlog /var/log/exim4/mainlog 2>/dev/null \
  | sort | uniq -c | sort -rn | head

Welches PHP-Skript versendet

Mails von PHPs mail() laufen über das lokale sendmail und melden sich nicht an, haben also keinen Benutzer. Lies die Header einer Nachricht aus der Queue: Mit mail.add_x_header fügt PHP X-PHP-Originating-Script hinzu, die Benutzer-ID und den Dateinamen des Skripts.

Postfix, dann Exim
sudo postcat -hq QUEUE_ID | grep -iE '^(From|To|Subject|X-PHP-Originating-Script):'
sudo exim -Mvh QUEUE_ID | grep -iE '(From|To|Subject|X-PHP-Originating-Script):'

Fehlt der Header, schalte ihn ein und lass PHP jeden mail()-Aufruf mit vollständigem Pfad und Zeile des Skripts protokollieren. Finde die php.ini, die dein Webserver verwendet (PHP-FPM hat unter Debian und Ubuntu eine eigene):

Jede Distribution
php --ini | grep 'Loaded Configuration'
ls /etc/php/*/fpm/php.ini /etc/php.ini 2>/dev/null
php.ini
mail.add_x_header = On
mail.log = syslog

Starte PHP-FPM oder den Webserver neu (sudo systemctl restart php8.3-fpm, php-fpm oder httpd, je nach System), warte ein paar Minuten und lies das Log:

Jede Distribution
sudo journalctl --since "1 hour ago" | grep 'mail() on' | tail -n 20
sudo grep -h 'mail() on' /var/log/syslog /var/log/messages 2>/dev/null | tail -n 20

Programme, die direkt SMTP sprechen

Manche Spam-Tools umgehen den Mailserver und verbinden sich selbst mit Port 25 der Empfängerserver, sie hinterlassen also nichts in der Queue. Sieh dir die ausgehenden SMTP-Verbindungen und die Programme an, denen sie gehören. Dein Mailserver (master/smtp bei Postfix, exim) ist normal; php, perl, python oder ein zufälliger Name ist es nicht.

Jede Distribution
sudo ss -tnp state established '( dport = :25 or dport = :465 or dport = :587 )'
sudo ss -tnp state established '( dport = :25 )' | grep -o 'users:(("[^"]*"' | sort | uniq -c | sort -rn

Den Spam sofort stoppen

Stopp zuerst die Quelle, dann die Queue. Bei einem Postfach änderst du das Passwort in deinem Panel oder Mailsystem und beendest seine Sitzungen. Bei einem Skript behältst du eine Kopie als Beweis und machst es unlesbar, damit der Webserver es nicht mehr ausführen kann:

Jede Distribution
sudo mkdir -p /root/evidence
sudo cp -p /path/to/script.php /root/evidence/
sudo chmod 000 /path/to/script.php

Bei einem Prozess, der direkt SMTP spricht, findest du seine PID in der ss-Ausgabe oben, prüfst, woher er kommt, und stoppst ihn wie in der Anleitung zu Krypto-Minern: Es ist Malware, und sie hat ihre eigene Persistenz.

Während du aufräumst, hältst du die Queue zurück. Bei Postfix hält defer_transports alles für die Zustellung nach außen fest und nimmt weiter neue Mails an, es geht also nichts verloren:

Postfix
sudo postconf -e 'defer_transports = smtp'
sudo postfix reload

Wenn die Queue sauber ist (nächster Schritt), gibst du sie wieder frei:

Postfix
sudo postconf -e 'defer_transports ='
sudo postfix reload
sudo postqueue -f

Bei Exim frierst du die Nachrichten des gefundenen Absenders ein. Eingefrorene Nachrichten bleiben in der Queue und werden nicht zugestellt:

Exim
sudo exiqgrep -i -f 'spammer@example\.com' | xargs -r sudo exim -Mf

Achtung: Solange die Zustellung nach außen pausiert, warten auch legitime Mails. Lass sie nicht länger als ein paar Stunden pausiert: Nach der Queue-Lebensdauer (bei Postfix standardmäßig 5 Tage) gehen wartende Nachrichten als Bounce zurück.

Die Mail-Queue aufräumen

Lösch den Spam nach Absender und die Bounces gleich mit, damit die legitimen Nachrichten in der Queue bleiben. Führ vorher Schritt 1 noch einmal aus, um dir beim Absender sicher zu sein.

Postfix
sudo postqueue -p | awk '/^[0-9A-Za-z]/ && $7 == "spammer@example.com" {sub(/[*!]$/, "", $1); print $1}' \
  | sudo postsuper -d -
sudo postqueue -p | awk '/^[0-9A-Za-z]/ && $7 == "MAILER-DAEMON" {sub(/[*!]$/, "", $1); print $1}' \
  | sudo postsuper -d -

Bei Exim löscht die erste Zeile die Nachrichten des Absenders, die zweite die eingefrorenen, die nach Spam meist Bounces sind:

Exim
sudo exiqgrep -i -f 'spammer@example\.com' | xargs -r sudo exim -Mrm
sudo exiqgrep -z -i | xargs -r sudo exim -Mrm

Achtung: postsuper -d ALL und das Löschen der ganzen Exim-Queue entfernen auch legitime Nachrichten, und gelöschte Nachrichten lassen sich nicht wiederherstellen. Lösch nach Absender, es sei denn, die Queue enthält nichts anderes.

Zähl die Queue noch einmal. Wächst sie wieder, ist die Quelle noch aktiv: zurück zu Schritt 1.

Herausfinden, wie der Spam rauskam

Ein neues Passwort oder ein gelöschtes Skript beendet diese Runde. Die nächste beginnt, wenn du nicht weißt, wie es angefangen hat.

Ein kompromittiertes Postfach

Ein Postfach, das ein Spammer nutzt, meldet sich von vielen Adressen an, oft aus vielen Ländern, manchmal tausendfach am Tag. Zähl die Adressen, die es benutzt haben:

Postfix oder Exim
sudo sh -c "zgrep -h 'user@example.com' /var/log/mail.log* /var/log/maillog* /var/log/exim_mainlog* /var/log/exim4/mainlog* 2>/dev/null" \
  | grep -oE '\[[0-9]{1,3}(\.[0-9]{1,3}){3}\]' | sort | uniq -c | sort -rn | head -20

Das Passwort wurde erraten (achte auf viele fehlgeschlagene Anmeldungen an diesem Postfach vor der ersten erfolgreichen) oder vom Rechner des Benutzers oder von einer anderen Website gestohlen. Wähl ein langes neues Passwort und prüf jedes andere Postfach mit einem schwachen.

Ein PHP-Skript

Ein Skript, das verschickt, was eine Anfrage verlangt, ist entweder Malware, die durch eine Lücke hochgeladen wurde, oder ein legitimes Formular ohne Schutz. Such in den Websites nach Mailern und kürzlich geänderten PHP-Dateien:

Jede Distribution
sudo grep -rlE 'mail\s*\(\s*\$_(POST|GET|REQUEST)|LeafMailer|eval\s*\(\s*base64_decode' \
  --include='*.php' /var/www /home 2>/dev/null | head -50
sudo find /var/www /home -name '*.php' -type f -mtime -7 2>/dev/null | head -50

Dann sieh nach, wer das Skript aufgerufen hat und wie oft. Ein Kontaktformular, das von wenigen Adressen tausendfach abgeschickt wird, wird missbraucht; eine Datei, von der niemand wissen sollte und die von vielen Adressen aufgerufen wird, ist eine Hintertür.

Webserver-Logs
sudo sh -c "grep -hI 'POST /path/to/script.php' /var/log/nginx/*access*.log /var/log/apache2/*access*.log /var/log/httpd/*access_log 2>/dev/null" \
  | awk '{print $1}' | sort | uniq -c | sort -rn | head
  • Ein bösartiges Skript: Entferne es und finde dann heraus, wie es hochgeladen wurde (ein veraltetes Plugin oder Theme, ein schwaches Admin-Passwort, ein Upload-Formular), und schließ diesen Weg. Die Anleitung zu Krypto-Minern zeigt, wie du nach dem Rest suchst, den ein Angreifer hinterlässt.
  • Ein missbrauchtes Formular: Füg ein CAPTCHA oder ein verstecktes Feld hinzu, das nur Bots ausfüllen, lass den Besucher nie den Empfänger wählen und schick keine Kopie an die im Formular eingetippte Adresse.

Ein offenes Relay

Heute seltener, aber prüf es: ein Mailserver, der Mails von jedem an jeden zustellt. Bei Postfix darf mynetworks nur den Server selbst und deine eigenen Netze enthalten, und die Relay-Beschränkungen müssen mit reject_unauth_destination enden:

Postfix
postconf mynetworks smtpd_relay_restrictions smtpd_recipient_restrictions

Verhindern, dass es wieder passiert

SPF, DKIM und DMARC

Diese drei DNS-Einträge sagen anderen Mailservern, welche Server für deine Domain senden dürfen und ob eine Nachricht wirklich von dir kommt. Sie halten ein gehacktes Postfach nicht davon ab, Spam über deinen Server zu schicken, aber sie verhindern, dass andere deine Domain fälschen, und die großen Anbieter erwarten sie inzwischen, bevor sie deine Mails zustellen. Ein Beispiel für eine Domain, deren Mails von 203.0.113.10 ausgehen:

DNS-Zone
example.com.         TXT  "v=spf1 mx ip4:203.0.113.10 -all"
_dmarc.example.com.  TXT  "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com"

DKIM braucht einen Schlüssel auf dem Mailserver (OpenDKIM für Postfix, in Exim eingebaut; Panels wie cPanel und Plesk erledigen das für dich) und dessen öffentlichen Teil im DNS. Prüf, was veröffentlicht ist:

Jede Distribution
dig +short TXT example.com
dig +short TXT _dmarc.example.com
dig +short TXT default._domainkey.example.com

Hinweis: dig steckt unter Debian und Ubuntu im Paket dnsutils (bind9-dnsutils in neueren Versionen) und in der RHEL-Familie in bind-utils. Der DKIM-Selektor, hier default, hängt von deiner Einrichtung ab.

Ratenlimits

Ein Limit macht aus einem kompromittierten Konto statt hunderttausend Nachrichten ein paar hundert. Postfix begrenzt die Nachrichten pro Client-Adresse; Mails, die PHP über sendmail verschickt, laufen nicht darüber, und Limits pro Benutzer brauchen einen Policy-Dienst wie postfwd.

Postfix
sudo postconf -e 'smtpd_client_message_rate_limit = 100' 'anvil_rate_time_unit = 3600s'
sudo postfix reload

Exim kann jeden angemeldeten Benutzer in seiner RCPT-ACL begrenzen. Unter cPanel nimmst du stattdessen **Max hourly emails per domain** in den Tweak Settings von WHM.

Exim
# In the RCPT ACL (acl_check_rcpt), before the accept for authenticated users
deny  authenticated = *
      ratelimit     = 200 / 1h / strict / per_rcpt / $authenticated_id
      message       = Sending rate limit exceeded

Nur der Mailserver darf Port 25 nutzen

Auf einem Webserver muss außer dem Mailserver nichts eine Verbindung zu Port 25 anderer Server aufbauen. Diese nftables-Regel weist ausgehende Verbindungen zu Port 25 von allen anderen Benutzern ab und stoppt damit Skripte und Malware, die direkt SMTP sprechen. Ersetze postfix durch den Benutzer deines Mailservers: Debian-exim für Exim unter Debian und Ubuntu, exim in der RHEL-Familie, mailnull unter cPanel.

Jede Distribution mit nftables
sudo nft add table inet smtpguard
sudo nft 'add chain inet smtpguard out { type filter hook output priority 0; policy accept; }'
sudo nft add rule inet smtpguard out tcp dport 25 meta skuid != { root, postfix } reject

Achtung: Achte auf den richtigen Benutzernamen: Mit dem falschen stellt der Server gar keine Mails mehr zu. Anwendungen, die über einen externen SMTP-Server auf Port 25 senden, hören ebenfalls auf; sie sollten ohnehin 587 mit Anmeldung nutzen. Die Tabelle ist nach einem Neustart weg: Sobald sie funktioniert, nimm sie in deine Firewall-Konfiguration auf. Unter cPanel macht **SMTP Restrictions** in WHM dasselbe.

Viele Cloud-Anbieter sperren ausgehenden Port 25 standardmäßig und öffnen ihn auf Anfrage. Wenn du vom Server gar keine Mails verschickst, lass ihn gesperrt und versende über einen Relay-Dienst auf 587.

Und die übliche Härtung

  • Halte WordPress, Plugins und Themes aktuell und entferne die, die du nicht nutzt.
  • Schütz die Mail-Anmeldungen wie SSH vor Brute Force: siehe SSH-Brute-Force-Angriffe stoppen.
  • Lass mail.add_x_header und mail.log eingeschaltet, damit du das Skript beim nächsten Mal in Sekunden kennst.

Den Server von Blocklisten holen

Beantrage die Entfernung erst, wenn der Spam aufgehört hat und die Ursache geschlossen ist: Ein Server, der direkt nach dem Delisting wieder gelistet wird, wird beim zweiten Mal strenger behandelt. Prüf die wichtigsten Listen per DNS, mit der öffentlichen Adresse des Servers in IP:

Jede Distribution
IP=203.0.113.10
REV=$(echo "$IP" | awk -F. '{print $4"."$3"."$2"."$1}')
for bl in zen.spamhaus.org bl.spamcop.net; do echo "$bl: $(dig +short "$REV.$bl" A)"; done
dig +short -x "$IP"

Eine leere Antwort heißt nicht gelistet; eine Adresse wie 127.0.0.2 heißt gelistet. Spamhaus verweigert Anfragen über öffentliche Resolver und antwortet darauf mit 127.255.255.254: Nimm dann die Website. Die letzte Zeile zeigt den Reverse-DNS-Eintrag (PTR) der Adresse, der ein Hostname sein sollte, der wieder auf sie auflöst.

  • Spamhaus: Schlag die Adresse auf check.spamhaus.org nach; dort steht zu jedem Eintrag, was er bedeutet und wie du die Entfernung beantragst.
  • SpamCop: Einträge laufen von selbst aus, sobald keine Meldungen mehr kommen (spamcop.net).
  • Microsoft (Outlook, Hotmail): Beantrage das Delisting unter sender.office.com.
  • Gmail: kein Formular zum Delisting; die Postmaster Tools zeigen, wie sich der Ruf deiner Domain erholt.

Hinweis: Verfahren mit Stand November 2026, laut den Seiten der Listen selbst. Die Erholung dauert Tage, nicht Stunden: Der Ruf bei den großen Anbietern wird nur besser, solange du weiter saubere Mails verschickst.

Was InfraFence gegen Spam von deinem Server tut

InfraFence setzt eher bei den Ursachen an als bei den Mails selbst:

  • Brute Force auf Mail: Der Agent liest die Logs von Postfix, Exim, Dovecot und Roundcube (oder das systemd-Journal) und sperrt eine Adresse nach 5 fehlgeschlagenen Anmeldungen oder Relay-Versuchen in 5 Minuten, bei SMTP, Submission, IMAP, POP3 und Webmail. Jedes Ereignis nennt das versuchte Postfach. Siehe SSH- und Login-Brute-Force.
  • Mailer-Skripte: Der Malware-Scanner hat Signaturen für PHP-Skripte, die verschicken, was eine Anfrage verlangt (mail() direkt aus $_POST gespeist, LeafMailer), für Web-Shells und Hintertüren, YARA-Regeln, und er meldet PHP-Dateien, die in Upload-Ordnern angelegt werden. Mit **Automatische Scans aktiv** werden neue PHP-Dateien in Upload-Ordnern innerhalb von 30 Sekunden gescannt. Siehe Malware-Scan.
  • Ausgehende Bedrohungen: Verbindungen vom Server zu Adressen auf den Listen Spamhaus DROP und Emerging Threats werden als kritisch gemeldet. Siehe Ausgehende und DNS-Bedrohungen.

Was es nicht tut: InfraFence liest die Mail-Queue nicht, zählt oder begrenzt ausgehende Mails nicht und sperrt Port 25 nicht, und es prüft nicht, ob deine Adresse auf einer Blocklist steht. Ein Postfach, das mit seinem richtigen Passwort benutzt wird, sieht für InfraFence wie eine normale Anmeldung aus. Die Queue, die Limits und das Delisting aus dieser Anleitung bleiben deine Aufgabe.

Fragen

Der Server hat keinen Mailserver. Wie kann er Spam verschicken?
PHPs mail() nutzt das sendmail, das fast jede Distribution installiert, und Malware kann sich selbst mit Port 25 anderer Server verbinden. Prüf die ausgehenden Verbindungen aus Schritt 1 und die Regel, die Port 25 dem Mailserver vorbehält.
Stoppen SPF, DKIM und DMARC den Spam?
Nein. Sie belegen, welche Server für deine Domain senden dürfen, und Spam über ein gehacktes Postfach auf deinem Server besteht diese Prüfung. Sie schützen deine Domain vor Fälschung und helfen, dass deine legitimen Mails ankommen.
Wie lange dauert es, von einer Blocklist zu kommen?
Das hängt von der Liste ab. SpamCop-Einträge laufen von selbst aus, sobald die Meldungen aufhören; Spamhaus und Microsoft reagieren auf einen Antrag auf Entfernung, sobald das Problem behoben ist. Der Ruf bei Gmail und Outlook erholt sich über Tage sauberen Versands.

Kostenlos auf 1 Server testen

Starter ist für einen Server kostenlos, mit vollem Schutz und automatischen Sperren. Ohne Kreditkarte.

Installiere den Agenten als root, mit deinem Token anstelle von <TOKEN>:

curl -fsSL https://github.com/infrafence/infrafence-agent/releases/latest/download/install.sh | sudo bash -s -- --token <TOKEN>

Das Token erstellst du im Dashboard unter Server › Server hinzufügen.