Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added postfix and dovecot for fail2ban #476

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions modoboa_installer/config_dict_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,14 @@ def is_email(user_input):
"option": "find_time",
"default": "30"
},
{
"option": "ports_blocked",
"default": "http,https,pop3,pop3s,imap,imaps,587"
},
{
"option": "postfix_dovecot_filter",
"default": "true"
}
]
},
{
Expand Down
24 changes: 24 additions & 0 deletions modoboa_installer/scripts/fail2ban.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
"""fail2ban related functions."""

import os

from . import base
from .. import utils


class Fail2ban(base.Installer):
Expand All @@ -15,3 +18,24 @@ class Fail2ban(base.Installer):
"jail.d/modoboa.conf",
"filter.d/modoboa-auth.conf",
]

def get_config_files(self):
"""Add dovecot and postfix jails if enabled."""

config_files = super().get_config_files()

if self.app_config["postfix_dovecot_filter"].lower() == "true":
config_files += ["jail.d/postfix.conf",
"jail.d/dovecot.conf"]
return config_files

def install_config_files(self):
"""Installer postfix and dovecot filters if enabled."""

if self.app_config["postfix_dovecot_filter"].lower() == "true":
for config_file in ["filter.d/postfix-modoboa.conf",
"filter.d/dovecot-modoboa.conf"]:
src = self.get_file_path(config_file)
dst = os.path.join(self.config_dir, config_file)
utils.copy_file(src, dst)
super().install_config_files()
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Fail2Ban filter Dovecot authentication and pop3/imap server
#
# Author: Martin Waschbuesch
# Daniel Black (rewrote with begin and end anchors)
# Martin O'Neal (added LDAP authentication failure regex)
# Sergey G. Brester aka sebres (reviewed, optimized, IPv6-compatibility)

[INCLUDES]

before = common.conf

[Definition]

_auth_worker = (?:dovecot: )?auth(?:-worker)?
_daemon = (?:dovecot(?:-auth)?|auth)

prefregex = ^%(__prefix_line)s(?:%(_auth_worker)s(?:\([^\)]+\))?: )?(?:%(__pam_auth)s(?:\(dovecot:auth\))?: |(?:pop3|imap|managesieve|submission)-login: )?(?:Info: )?<F-CONTENT>.+</F-CONTENT>$

failregex = ^authentication failure; logname=<F-ALT_USER1>\S*</F-ALT_USER1> uid=\S* euid=\S* tty=dovecot ruser=<F-USER>\S*</F-USER> rhost=<HOST>(?:\s+user=<F-ALT_USER>\S*</F-ALT_USER>)?\s*$
^(?:Aborted login|Disconnected|Remote closed connection|Client has quit the connection)(?::(?: [^ \(]+)+)? \((?:auth failed, \d+ attempts(?: in \d+ secs)?|tried to use (?:disabled|disallowed) \S+ auth|proxy dest auth failed)\):(?: user=<<F-USER>[^>]*</F-USER>>,)?(?: method=\S+,)? rip=<HOST>(?:[^>]*(?:, session=<\S+>)?)\s*$
^pam\(\S+,<HOST>(?:,\S*)?\): pam_authenticate\(\) failed: (?:User not known to the underlying authentication module: \d+ Time\(s\)|Authentication failure \(password mismatch\?\)|Permission denied)\s*$
^[a-z\-]{3,15}\(\S*,<HOST>(?:,\S*)?\): (?:unknown user|invalid credentials|Password mismatch)
<mdre-<mode>>

mdre-aggressive = ^(?:Aborted login|Disconnected|Remote closed connection|Client has quit the connection)(?::(?: [^ \(]+)+)? \((?:no auth attempts|disconnected before auth was ready,|client didn't finish \S+ auth,)(?: (?:in|waited) \d+ secs)?\):(?: user=<[^>]*>,)?(?: method=\S+,)? rip=<HOST>(?:[^>]*(?:, session=<\S+>)?)\s*$

mdre-normal =

# Parameter `mode` - `normal` or `aggressive`.
# Aggressive mode can be used to match log-entries like:
# 'no auth attempts', 'disconnected before auth was ready', 'client didn't finish SASL auth'.
# Note it may produce lots of false positives on misconfigured MTAs.
# Ex.:
# filter = dovecot[mode=aggressive]
mode = normal

ignoreregex =

journalmatch = _SYSTEMD_UNIT=dovecot.service

datepattern = {^LN-BEG}TAI64N
{^LN-BEG}

# DEV Notes:
# * the first regex is essentially a copy of pam-generic.conf
# * Probably doesn't do dovecot sql/ldap backends properly (resolved in edit 21/03/2016)
#
# Author: Martin Waschbuesch
# Daniel Black (rewrote with begin and end anchors)
# Martin O'Neal (added LDAP authentication failure regex)
# Sergey G. Brester aka sebres (reviewed, optimized, IPv6-compatibility)
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Fail2Ban filter for selected Postfix SMTP rejections
#
#
# Author: Cyril Jaquier

[INCLUDES]

# Read common prefixes. If any customizations available -- read them from
# common.local
before = common.conf

[Definition]

_daemon = postfix(-\w+)?/\w+(?:/smtp[ds])?
_port = (?::\d+)?

prefregex = ^%(__prefix_line)s<mdpr-<mode>> <F-CONTENT>.+</F-CONTENT>$

mdpr-normal = (?:\w+: reject:|(?:improper command pipelining|too many errors) after \S+)
mdre-normal=^RCPT from [^[]*\[<HOST>\]%(_port)s: 55[04] 5\.7\.1\s
^RCPT from [^[]*\[<HOST>\]%(_port)s: 45[04] 4\.7\.\d+ (?:Service unavailable\b|Client host rejected: cannot find your (reverse )?hostname\b)
^RCPT from [^[]*\[<HOST>\]%(_port)s: 450 4\.7\.\d+ (<[^>]*>)?: Helo command rejected: Host not found\b
^EHLO from [^[]*\[<HOST>\]%(_port)s: 504 5\.5\.\d+ (<[^>]*>)?: Helo command rejected: need fully-qualified hostname\b
^(RCPT|VRFY) from [^[]*\[<HOST>\]%(_port)s: 550 5\.1\.1\s
^RCPT from [^[]*\[<HOST>\]%(_port)s: 450 4\.1\.\d+ (<[^>]*>)?: Sender address rejected: Domain not found\b
^from [^[]*\[<HOST>\]%(_port)s:?

mdpr-auth = warning:
mdre-auth = ^[^[]*\[<HOST>\]%(_port)s: SASL ((?i)LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed:(?! Connection lost to authentication server| Invalid authentication mechanism)
mdre-auth2= ^[^[]*\[<HOST>\]%(_port)s: SASL ((?i)LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed:(?! Connection lost to authentication server)
# todo: check/remove "Invalid authentication mechanism" from ignore list, if gh-1243 will get finished (see gh-1297).

# Mode "rbl" currently included in mode "normal", but if needed for jail "postfix-rbl" only:
mdpr-rbl = %(mdpr-normal)s
mdre-rbl = ^RCPT from [^[]*\[<HOST>\]%(_port)s: [45]54 [45]\.7\.1 Service unavailable; Client host \[\S+\] blocked\b

# Mode "rbl" currently included in mode "normal" (within 1st rule)
mdpr-more = %(mdpr-normal)s
mdre-more = %(mdre-normal)s

mdpr-ddos = (?:lost connection after(?! DATA) [A-Z]+|disconnect(?= from \S+(?: \S+=\d+)* auth=0/(?:[1-9]|\d\d+)))
mdre-ddos = ^from [^[]*\[<HOST>\]%(_port)s:?

mdpr-extra = (?:%(mdpr-auth)s|%(mdpr-normal)s)
mdre-extra = %(mdre-auth)s
%(mdre-normal)s

mdpr-aggressive = (?:%(mdpr-auth)s|%(mdpr-normal)s|%(mdpr-ddos)s)
mdre-aggressive = %(mdre-auth2)s
%(mdre-normal)s

mdpr-errors = too many errors after \S+
mdre-errors = ^from [^[]*\[<HOST>\]%(_port)s$


failregex = <mdre-<mode>>

# Parameter "mode": more (default combines normal and rbl), auth, normal, rbl, ddos, extra or aggressive (combines all)
# Usage example (for jail.local):
# [postfix]
# mode = aggressive
#
# # or another jail (rewrite filter parameters of jail):
# [postfix-rbl]
# filter = postfix[mode=rbl]
#
# # jail to match "too many errors", related postconf `smtpd_hard_error_limit`:
# # (normally included in other modes (normal, more, extra, aggressive), but this jail'd allow to ban on the first message)
# [postfix-many-errors]
# filter = postfix[mode=errors]
# maxretry = 1
#
mode = more

ignoreregex =

[Init]

journalmatch = _SYSTEMD_UNIT=postfix.service

# Author: Cyril Jaquier
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[dovecot]
enabled = true
port = %ports_blocked
filter = dovecot
logpath = /var/log/mail.log
maxretry = %max_retry
bantime = %ban_time
findtime = %find_time
ignoreip = ::1 127.0.01/8
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[modoboa]
enabled = true
port = http,https
port = %ports_blocked
protocol = tcp
filter = modoboa-auth
maxretry = %max_retry
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[postfix]
enabled = true
port = %ports_blocked
maxretry = %max_retry
bantime = %ban_time
findtime = %find_time
filter = postfix[mode=aggressive]
logpath = /var/log/mail.log
ignoreip = ::1 127.0.0.1/8