Shieldlist

postfix-dovecot Gratuit

Authentification mail et abus de relais — les parseurs pour Postfix et Dovecot.

Télécharger le pack tar.gz des fichiers listés ci-dessous

À propos de ce pack

Mail authentication and relay abuse, read from a single syslog file where rsyslog routes mail.*/var/log/maillog here; /var/log/mail.log on a stock Debian. Category mail.

Traditional syslog timestamps (Aug 14 08:49:30), which carry no year: the reader supplies its own, and a line dated ahead of it is taken as last year's.

Read the mail log once. On a machine where /var/log/syslog also carries postfix and dovecot lines, declaring both counts every failure twice and halves every threshold without saying so.

The parsers

parser what it is
postfix-sasl-fail SMTP authentication refused
postfix-relay-denied trying to send mail through this server to elsewhere
dovecot-auth-fail IMAP/POP3/submission login refused
dovecot-password-mismatch the auth process's view, with a truncated hash of what was tried
dovecot-login-ok a login that worked — for weighing negatively

The mailbox name is attacker-controlled and dovecot prints it before the address, so those patterns run greedily to the last rip= on the line. Keep that in anything derived from them.

Parseurs (8)

Les briques : chaque parseur nomme un journal, un préfiltre peu coûteux et la regex qui extrait l'adresse.

dovecot-auth-fail mail
# An IMAP, POP3 or submission login refused:
#   imap-login: Login aborted: Connection closed (auth failed, 1 attempts in 2 secs) (auth_failed): user=<admin@example.net>, method=PLAIN, rip=203.0.113.9, lip=192.0.2.1, TLS, session=<...>
#
# The mailbox name is chosen by whoever is connecting and is printed
# BEFORE the address, so the pattern runs greedily up to the last
# `rip=` on the line — the one dovecot wrote. A user called
# "x, rip=198.51.100.1, lip=" would otherwise frame a bystander.
parser: dovecot-auth-fail
log: mail
prefilter: "auth failed"
regex: '^(?P<time>[A-Z][a-z]{2} [ 0-9]\d \d{2}:\d{2}:\d{2}) \S+ dovecot(?:\[\d+\])?: (?P<service>[a-z0-9]+)-login: .*\(auth failed, \d+ attempts[^)]*\)[^:]*: user=<(?P<user>[^>]*)>, method=\S+, rip=(?P<ip>[0-9a-fA-F.:]+), lip='
time_field: time
time_format: syslog
dovecot-login-ok mail
# A login that worked:
#   imap-login: Logged in: user=<me@example.net>, method=CRAM-MD5, rip=203.0.113.9, lip=192.0.2.1, mpid=..., TLS, session=<...>
#
# Here so that a rule can weigh it NEGATIVELY against failures. On a
# host with real mailboxes that is what separates a phone with a stale
# password — which fails, succeeds, fails, succeeds — from a
# brute-force, which only ever fails. A host with no human mailboxes
# does not need it.
parser: dovecot-login-ok
log: mail
prefilter: "Logged in:"
regex: '^(?P<time>[A-Z][a-z]{2} [ 0-9]\d \d{2}:\d{2}:\d{2}) \S+ dovecot(?:\[\d+\])?: (?P<service>[a-z0-9]+)-login: Logged in: .*rip=(?P<ip>[0-9a-fA-F.:]+), lip='
time_field: time
time_format: syslog
dovecot-password-mismatch mail
# The auth process's own view of the same event, which carries a
# truncated hash of the password that was tried:
#   auth(admin@example.net,203.0.113.9,sasl:plain)<sess>: Password mismatch (SHA1 of given password: 7110ed)
#
# Only present where dovecot is configured with auth_verbose_passwords.
# It is worth reading separately from the login line because the hash
# distinguishes a device with one stale saved password, repeating it for
# ever, from a brute-force rotating a new one every attempt — a rule can
# count DISTINCT hashes.
parser: dovecot-password-mismatch
log: mail
prefilter: "Password mismatch"
regex: '^(?P<time>[A-Z][a-z]{2} [ 0-9]\d \d{2}:\d{2}:\d{2}) \S+ dovecot(?:\[\d+\])?: auth\((?P<user>[^,]*),(?P<ip>[0-9a-fA-F.:]+),[^)]*\)<[^>]*>: Password mismatch \(SHA1 of given password: (?P<password_hash>\w+)\)$'
time_field: time
time_format: syslog
postfix-non-smtp mail
# Something that is not a mail client talking to the SMTP port:
#   warning: non-SMTP command from unknown[203.0.113.9]: GET / HTTP/1.1
#   warning: non-SMTP command from unknown[203.0.113.9]: \026\003\001...
#
# HTTP verbs and TLS handshake bytes on port 25 are port scanners and
# exploit probes, never a misconfigured sender. Translated from
# CrowdSec's postfix-non-smtp-command (instant ban).
#
# The hostname before the bracket is rDNS and untrusted; the address
# inside the brackets is what postfix measured.
parser: postfix-non-smtp
log: mail
prefilter: "non-SMTP command"
regex: '^(?P<time>[A-Z][a-z]{2} [ 0-9]\d \d{2}:\d{2}:\d{2}) \S+ postfix/smtpd\[\d+\]: warning: non-SMTP command from \S+\[(?P<ip>[0-9a-fA-F.:]+)\]:'
time_field: time
time_format: syslog
postfix-reject mail
# Any recipient postfix refused at smtpd time:
#   NOQUEUE: reject: RCPT from unknown[203.0.113.9]: 454 4.7.1 <x@y>: Relay access denied; ...
#   NOQUEUE: reject: RCPT from unknown[203.0.113.9]: 550 5.1.1 <x@y>: Recipient address rejected: ...
#
# ONE reject is not a verdict — a legitimate correspondent's server
# typoing an address writes this line too, which is why this parser
# belongs in a THRESHOLD rule (CrowdSec models it as a leaky bucket in
# postfix-spam), never in an instant one. Relay attempts specifically
# are covered by postfix-relay-denied, which IS instant-worthy.
parser: postfix-reject
log: mail
prefilter: "NOQUEUE: reject"
regex: '^(?P<time>[A-Z][a-z]{2} [ 0-9]\d \d{2}:\d{2}:\d{2}) \S+ postfix/smtpd\[\d+\]: NOQUEUE: reject: RCPT from \S+\[(?P<ip>[0-9a-fA-F.:]+)\]: \d{3} '
time_field: time
time_format: syslog
postfix-relay-denied mail
# Someone trying to send mail through this server to somewhere else:
#   NOQUEUE: reject: RCPT from unknown[203.0.113.9]: 454 4.7.1 <x@example.com>: Relay access denied; from=<...> to=<...>
#
# There is no version of this that is a mistake by a legitimate sender:
# a client that should be relaying authenticates first. The address is
# read from the connection, before the recipient the client supplied.
parser: postfix-relay-denied
log: mail
prefilter: "Relay access denied"
regex: '^(?P<time>[A-Z][a-z]{2} [ 0-9]\d \d{2}:\d{2}:\d{2}) \S+ postfix/\S+\[\d+\]: NOQUEUE: reject: RCPT from \S*\[(?P<ip>[0-9a-fA-F.:]+)\]: 45\d 4\.7\.1 '
time_field: time
time_format: syslog
postfix-sasl-fail mail
# An SMTP authentication refused:
#   warning: unknown[203.0.113.9]: SASL LOGIN authentication failed: authentication failure, sasl_username=test@example.net
#   warning: host.example[203.0.113.9]: SASL login authentication failed: ...
#   warning: unknown[203.0.113.9]: SASL NTLM authentication failed: no mechanism available
#
# Postfix writes the mechanism in whatever case it received, so it is
# matched loosely. The address comes from the connection and is printed
# before anything the client chose.
parser: postfix-sasl-fail
log: mail
prefilter: "SASL"
regex: '^(?P<time>[A-Z][a-z]{2} [ 0-9]\d \d{2}:\d{2}:\d{2}) \S+ postfix/\S+\[\d+\]: warning: \S*\[(?P<ip>[0-9a-fA-F.:]+)\]: SASL \S+ authentication failed'
time_field: time
time_format: syslog
postfix-starttls-abort mail
# A connection dropped mid-handshake, before any mail business:
#   lost connection after STARTTLS from scan.example[203.0.113.9]
#   lost connection after EHLO from unknown[203.0.113.9]
#
# TLS scanners and service probes write these; so, rarely, does a
# broken sender — which is why this belongs in a THRESHOLD rule, never
# an instant one. Only the pre-mail stages are matched: a connection
# lost after RCPT or DATA is a network hiccup in real delivery and is
# none of our business.
parser: postfix-starttls-abort
log: mail
prefilter: "lost connection after"
regex: '^(?P<time>[A-Z][a-z]{2} [ 0-9]\d \d{2}:\d{2}:\d{2}) \S+ postfix/smtpd\[\d+\]: lost connection after (?:STARTTLS|EHLO|HELO|CONNECT|AUTH|UNKNOWN) from \S+\[(?P<ip>[0-9a-fA-F.:]+)\]$'
time_field: time
time_format: syslog

Fichiers