Postfix / Postscreen – IP in die Firewall eintragen


Der Beitrag von Robert Schetterer (Botnet-Angriffe mit rsyslog und iptables recent module abwehren) zum sofortigen Eintrag von durch Postscreen abgelehnten IP-Adressen mittels rsyslog hat mich dazu animiert, hier meine Lösung für syslog-ng vorzustellen.
Ich setze dabei aber nicht auf eine Pipe, sondern trage über syslog-ng die entsprechende IP direkt in die Firewall ein.

Die Voraussetzungen sind identisch: Postfix/Postscreen und das recent-Modul von iptables sind zwingend erforderlich. Da Robert dies sehr schön dokumentiert hat, verzichte ich darauf an dieser Stelle. Ich habe das Prinzip aber auch schon in meinen Posts Traffic auf einem clamav-mirror limitieren und Block outdated clients für recent und in Postscreen im Kampf gegen Spam für Postscreen gepostet.

Nachdem Postscreen und iptables entsprechend eingericht sind, kommt es nur noch darauf an, auf Logeinträge über syslog-ng entsprechend zu reagieren.

Ein Logeintrag sieht bspw. so aus:

Feb 2 12:35:49 idefix.schaal-24.de postfix/postscreen[20189]: NOQUEUE: reject: RCPT from [1.2.3.4]:37669: 550 5.7.1 Service unavailable; client [1.2.3.4] blocked using bl.blocklist.de; from=, to=, proto=ESMTP, helo=

Als erstes brauchen wir einen Filter, der reagiert, wenn durch postfix/postscreen ein ‘NOQUEUE reject’ gemeldet wird.

filter f_reject_mail {
  program('postfix/postscreen')
  and match('NOQUEUE: reject: RCPT from', value('MESSAGE'));
};

Danach wird aus dem entsprechende Log-Eintrag durch die pattern-DB (s.u.) gefiltert oder mit zwei CSV-Parser die IP extrahiert.
Beim CSV-Parser sind zwei Durchläufe erforderlich, da dieser einen Logstring nicht mehrfach splitten kann. Man könnte zwar ‘:’ als delimiter verwenden, dass würde aber das Blocken von IPv6-Adressen verhindern. Im ersten Schritt wird der (interne) Logstring zu

[1.2.3.4]:37669:

extrahiert:

parser p_reject_mail {
  csv-parser(columns(
    ".col1",
    ".col2",
    ".col3",
    ".col4",
    ".reject_ip_block")
  flags(escape-double-char,strip-whitespace)
  delimiters(" ")
  );
};

Der zweite Parser extrahiert daraus die IP-Adresse:

parser p_reject_mail_get_ip {
  csv-parser(columns(
    ".reject_ip")
  quote-pairs('[]')
  delimiters(":")
  template("${.reject_ip_block}")
  );
};

Zum Schluss wird die IP über die destination in die Firewall (postfix-reject ist der Jail) eingetragen:

destination d_reject_mail {
  file("/proc/net/xt_recent/postfix-reject"
  template("+${.mail.rejected.ip}\n"));
};

Um die IP durch syslog-ng zu blocken:

log {
  source(src);
  filter(f_reject_mail);
  parser(p_reject_mail);
  parser(p_reject_mail_get_ip);
  destination(d_reject_mail);
};

Blocks wie oben beschrieben können aber auch durch postfix/smtpd erfolgen:

Feb 3 10:56:03 idefix.schaal-24.de postfix/smtpd[3612]: NOQUEUE: reject: RCPT from xx-xxx-xx-xx.xx-xx.xx.net[1.2.3.4]: 554 5.7.1 : Recipient address rejected: Access denied; from= to= proto=SMTP helo=

Der Aufbau variert nicht wesentlich. Hier bekommen wir durch den ersten Parser

xx-xxx-xx-xx.xx-xx.xx.net[xx.xxx.xx.xx]:

Und über den zweiten wie gewohnt die IP. Um auch solche IP-Adressen zu blocken, muss lediglich der Filter erweitert werden:

filter f_reject_mail {
  (program('postfix/postscreen') or
  program('postfix/smtpd'))
  and match('NOQUEUE: reject: RCPT from', value('MESSAGE'));
};

Und hier das ganze noch für die pattern-DB.
Ich denke, diese Variante ist die besser – einfacher zu konfigurieren (wenn die pattern-DB einmal läuft) und auch schneller als CSV-Parser:

filter f_reject_mail {
  match("rejected" value(".classifier.class"))
  and match("12" value(".classifier.rule_id"))
  and tags("rejected");
};

destination d_reject_mail {
  file("/proc/net/xt_recent/postfix-reject"
  template("+${.mail.rejected.ip}\n"));
};

log {
  source(src);
  parser(pattern_db);
  filter(f_reject_mail);
  destination(d_reject_mail);
};

Und das File für die pattern-DB:


<?xml version='1.0' encoding='UTF-8'?>
<patterndb version="3" pub_date="2011-04-01">
<ruleset id='12' name='mail'>
  <pattern>postfix/postscreen</pattern>
  <pattern>postfix/smtpd</pattern>
  <rules>
    <rule class='rejected' id='12' provider='fs'>
      <patterns>
        <pattern>NOQUEUE: reject: RCPT from [@IPv4:.mail.rejected.ip@]:@NUMBER@: 550</pattern>
        <pattern>NOQUEUE: reject: RCPT from [@IPv6:.mail.rejected.ip@]:@NUMBER@: 550</pattern>
      </patterns>
      <tags>
        <tag>rejected</tag>
      </tags>
    </rule>
  </rules>
</ruleset>
</patterndb>

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *