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