diff --git a/MANIFEST b/MANIFEST
index f03f185b..b726a111 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -138,7 +138,6 @@ config/filter.d/solid-pop3d.conf
config/filter.d/squid.conf
config/filter.d/squirrelmail.conf
config/filter.d/sshd.conf
-config/filter.d/sshd-ddos.conf
config/filter.d/stunnel.conf
config/filter.d/suhosin.conf
config/filter.d/tine20.conf
@@ -327,7 +326,6 @@ fail2ban/tests/files/logs/solid-pop3d
fail2ban/tests/files/logs/squid
fail2ban/tests/files/logs/squirrelmail
fail2ban/tests/files/logs/sshd
-fail2ban/tests/files/logs/sshd-ddos
fail2ban/tests/files/logs/stunnel
fail2ban/tests/files/logs/suhosin
fail2ban/tests/files/logs/tine20
diff --git a/config/filter.d/sshd-aggressive.conf b/config/filter.d/sshd-aggressive.conf
deleted file mode 100644
index 98175cbe..00000000
--- a/config/filter.d/sshd-aggressive.conf
+++ /dev/null
@@ -1,11 +0,0 @@
-# Fail2Ban aggressive ssh filter for at attempted exploit
-#
-# Includes failregex of both sshd and sshd-ddos filters
-#
-[INCLUDES]
-
-before = sshd.conf
-
-[Definition]
-
-mode = %(aggressive)s
diff --git a/config/filter.d/sshd-ddos.conf b/config/filter.d/sshd-ddos.conf
deleted file mode 100644
index 69b42069..00000000
--- a/config/filter.d/sshd-ddos.conf
+++ /dev/null
@@ -1,17 +0,0 @@
-# Fail2Ban ssh filter for at attempted exploit
-#
-# The regex here also relates to a exploit:
-#
-# http://www.securityfocus.com/bid/17958/exploit
-# The example code here shows the pushing of the exploit straight after
-# reading the server version. This is where the client version string normally
-# pushed. As such the server will read this unparsible information as
-# "Did not receive identification string".
-
-[INCLUDES]
-
-before = sshd.conf
-
-[Definition]
-
-mode = %(ddos)s
diff --git a/config/filter.d/sshd.conf b/config/filter.d/sshd.conf
index 922ea193..8163aa03 100644
--- a/config/filter.d/sshd.conf
+++ b/config/filter.d/sshd.conf
@@ -24,45 +24,59 @@ __pref = (?:(?:error|fatal): (?:PAM: )?)?
__suff = (?: \[preauth\])?\s*
__on_port_opt = (?: port \d+)?(?: on \S+(?: port \d+)?)?
-prefregex = ^%(__prefix_line)s%(__pref)s.+$
-
-mode = %(normal)s
-
-normal = ^[aA]uthentication (?:failure|error|failed) for .* from ( via \S+)?\s*%(__suff)s$
- ^User not known to the underlying authentication module for .* from \s*%(__suff)s$
- ^Failed \S+ for (?Pinvalid user )?(?P\S+)|(?(cond_inv)(?:(?! from ).)*?|[^:]+) from %(__on_port_opt)s(?: ssh\d*)?(?(cond_user): |(?:(?:(?! from ).)*)$)
- ^ROOT LOGIN REFUSED.* FROM \s*%(__suff)s$
- ^[iI](?:llegal|nvalid) user .*? from %(__on_port_opt)s\s*$
- ^User .+ from not allowed because not listed in AllowUsers\s*%(__suff)s$
- ^User .+ from not allowed because listed in DenyUsers\s*%(__suff)s$
- ^User .+ from not allowed because not in any group\s*%(__suff)s$
- ^refused connect from \S+ \(\)\s*%(__suff)s$
- ^Received disconnect from %(__on_port_opt)s:\s*3: .*: Auth fail%(__suff)s$
- ^User .+ from not allowed because a group is listed in DenyGroups\s*%(__suff)s$
- ^User .+ from not allowed because none of user's groups are listed in AllowGroups\s*%(__suff)s$
- ^pam_unix\(sshd:auth\):\s+authentication failure;\s*logname=\S*\s*uid=\d*\s*euid=\d*\s*tty=\S*\s*ruser=\S*\s*rhost=\s.*%(__suff)s$
- ^(error: )?maximum authentication attempts exceeded for .* from %(__on_port_opt)s(?: ssh\d*)? \[preauth\]$
- ^User .+ not allowed because account is locked%(__suff)s
- ^Disconnecting: Too many authentication failures for .+?%(__suff)s
- ^Received disconnect from : 11:
- ^Connection closed by %(__suff)s$
-
-ddos = ^Did not receive identification string from %(__suff)s$
- ^Received disconnect from %(__on_port_opt)s:\s*14: No supported authentication methods available%(__suff)s$
- ^Unable to negotiate with %(__on_port_opt)s: no matching (?:cipher|key exchange method) found.
- ^Unable to negotiate a (?:cipher|key exchange method)%(__suff)s$
- ^SSH: Server;Ltype: (?:Authname|Version|Kex);Remote: -\d+;[A-Z]\w+:
- ^Read from socket failed: Connection reset by peer \[preauth\]
-
-common = ^Connection from
-
-aggressive = %(normal)s
- %(ddos)s
-
[Definition]
-failregex = %(mode)s
- %(common)s
+prefregex = ^%(__prefix_line)s%(__pref)s.+$
+
+cmnfailre = ^[aA]uthentication (?:failure|error|failed) for .* from ( via \S+)?\s*%(__suff)s$
+ ^User not known to the underlying authentication module for .* from \s*%(__suff)s$
+ ^Failed \S+ for (?Pinvalid user )?(?P\S+)|(?(cond_inv)(?:(?! from ).)*?|[^:]+) from %(__on_port_opt)s(?: ssh\d*)?(?(cond_user): |(?:(?:(?! from ).)*)$)
+ ^ROOT LOGIN REFUSED.* FROM \s*%(__suff)s$
+ ^[iI](?:llegal|nvalid) user .*? from %(__on_port_opt)s\s*$
+ ^User .+ from not allowed because not listed in AllowUsers\s*%(__suff)s$
+ ^User .+ from not allowed because listed in DenyUsers\s*%(__suff)s$
+ ^User .+ from not allowed because not in any group\s*%(__suff)s$
+ ^refused connect from \S+ \(\)\s*%(__suff)s$
+ ^Received disconnect from %(__on_port_opt)s:\s*3: .*: Auth fail%(__suff)s$
+ ^User .+ from not allowed because a group is listed in DenyGroups\s*%(__suff)s$
+ ^User .+ from not allowed because none of user's groups are listed in AllowGroups\s*%(__suff)s$
+ ^pam_unix\(sshd:auth\):\s+authentication failure;\s*logname=\S*\s*uid=\d*\s*euid=\d*\s*tty=\S*\s*ruser=\S*\s*rhost=\s.*%(__suff)s$
+ ^(error: )?maximum authentication attempts exceeded for .* from %(__on_port_opt)s(?: ssh\d*)? \[preauth\]$
+ ^User .+ not allowed because account is locked%(__suff)s
+ ^Disconnecting: Too many authentication failures for .+?%(__suff)s
+ ^Received disconnect from : 11:
+ ^Connection closed by %(__suff)s$
+
+mdre-normal =
+
+mdre-ddos = ^Did not receive identification string from %(__suff)s$
+ ^SSH: Server;Ltype: (?:Authname|Version|Kex);Remote: -\d+;[A-Z]\w+:
+ ^Read from socket failed: Connection reset by peer \[preauth\]
+
+mdre-extra = ^Received disconnect from %(__on_port_opt)s:\s*14: No supported authentication methods available%(__suff)s$
+ ^Unable to negotiate with %(__on_port_opt)s: no matching (?:cipher|key exchange method) found.
+ ^Unable to negotiate a (?:cipher|key exchange method)%(__suff)s$
+
+mdre-aggressive = %(mdre-ddos)s
+ %(mdre-extra)s
+
+cfooterre = ^Connection from
+
+failregex = %(cmnfailre)s
+ >
+ %(cfooterre)s
+
+# Parameter "mode": normal (default), ddos, extra or aggressive (combines all)
+# Usage example (for jail.local):
+# [sshd]
+# mode = extra
+# # or another jail (rewrite filter parameters of jail):
+# [sshd-aggressive]
+# filter = sshd[mode=aggressive]
+#
+mode = normal
+
+#filter = sshd[mode=aggressive]
ignoreregex =
@@ -79,5 +93,5 @@ datepattern = {^LN-BEG}
# and later catch-all's could contain user-provided input, which need to be greedily
# matched away first.
#
-# Author: Cyril Jaquier, Yaroslav Halchenko, Petr Voralek, Daniel Black
-
+# Author: Cyril Jaquier, Yaroslav Halchenko, Petr Voralek, Daniel Black and Sergey Brester aka sebres
+# Rewritten using prefregex (and introduced "mode" parameter) by Serg G. Brester.
diff --git a/config/jail.conf b/config/jail.conf
index 3e917b34..c5440b71 100644
--- a/config/jail.conf
+++ b/config/jail.conf
@@ -229,17 +229,11 @@ action = %(action_)s
[sshd]
-# To use more aggressive sshd filter (inclusive sshd-ddos failregex):
-#filter = sshd-aggressive
-port = ssh
-logpath = %(sshd_log)s
-backend = %(sshd_backend)s
-
-
-[sshd-ddos]
-# This jail corresponds to the standard configuration in Fail2ban.
-# The mail-whois action send a notification e-mail with a whois request
-# in the body.
+# To use more aggressive sshd modes set filter parameter "mode" in jail.local:
+# normal (default), ddos, extra or aggressive (combines all).
+# See "tests/files/logs/sshd" or "filter.d/sshd.conf" for usage example and details.
+mode = normal
+filter = sshd[mode=%(mode)s]
port = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s
@@ -555,7 +549,11 @@ backend = %(syslog_backend)s
[sendmail-reject]
-
+# To use more aggressive modes set filter parameter "mode" in jail.local:
+# normal (default), extra or aggressive
+# See "tests/files/logs/sendmail-reject" or "filter.d/sendmail-reject.conf" for usage example and details.
+mode = normal
+filter = sendmail-reject[mode=%(mode)s]
port = smtp,465,submission
logpath = %(syslog_mail)s
backend = %(syslog_backend)s
diff --git a/fail2ban/tests/config/filter.d/zzz-sshd-obsolete-multiline.conf b/fail2ban/tests/config/filter.d/zzz-sshd-obsolete-multiline.conf
index 729fecd7..4f28e60f 100644
--- a/fail2ban/tests/config/filter.d/zzz-sshd-obsolete-multiline.conf
+++ b/fail2ban/tests/config/filter.d/zzz-sshd-obsolete-multiline.conf
@@ -23,9 +23,9 @@ __prefix_line_sl = %(__prefix_line)s%(__pref)s
__prefix_line_ml1 = (?P<__prefix>%(__prefix_line)s)%(__pref)s
__prefix_line_ml2 = %(__suff)s$^(?P=__prefix)%(__pref)s
-mode = %(normal)s
+[Definition]
-normal = ^%(__prefix_line_sl)s[aA]uthentication (?:failure|error|failed) for .* from ( via \S+)?\s*%(__suff)s$
+cmnfailre = ^%(__prefix_line_sl)s[aA]uthentication (?:failure|error|failed) for .* from ( via \S+)?\s*%(__suff)s$
^%(__prefix_line_sl)sUser not known to the underlying authentication module for .* from \s*%(__suff)s$
^%(__prefix_line_sl)sFailed \S+ for (?Pinvalid user )?(?P(?P\S+)|(?(cond_inv)(?:(?! from ).)*?|[^:]+)) from %(__on_port_opt)s(?: ssh\d*)?(?(cond_user): |(?:(?:(?! from ).)*)$)
^%(__prefix_line_sl)sROOT LOGIN REFUSED.* FROM \s*%(__suff)s$
@@ -43,18 +43,30 @@ normal = ^%(__prefix_line_sl)s[aA]uthentication (?:failure|error|failed) for .*
^%(__prefix_line_ml1)sDisconnecting: Too many authentication failures for .+?%(__prefix_line_ml2)sConnection closed by %(__suff)s$
^%(__prefix_line_ml1)sConnection from %(__on_port_opt)s%(__prefix_line_ml2)sDisconnecting: Too many authentication failures for .+%(__suff)s$
-ddos = ^%(__prefix_line_sl)sDid not receive identification string from %(__suff)s$
- ^%(__prefix_line_sl)sReceived disconnect from %(__on_port_opt)s:\s*14: No supported authentication methods available%(__suff)s$
- ^%(__prefix_line_sl)sUnable to negotiate with %(__on_port_opt)s: no matching (?:cipher|key exchange method) found.
- ^%(__prefix_line_ml1)sConnection from %(__on_port_opt)s%(__prefix_line_ml2)sUnable to negotiate a (?:cipher|key exchange method)%(__suff)s$
- ^%(__prefix_line_ml1)sSSH: Server;Ltype: (?:Authname|Version|Kex);Remote: -\d+;[A-Z]\w+:.*%(__prefix_line_ml2)sRead from socket failed: Connection reset by peer%(__suff)s$
+mdre-normal =
-aggressive = %(normal)s
- %(ddos)s
+mdre-ddos = ^%(__prefix_line_sl)sDid not receive identification string from %(__suff)s$
+ ^%(__prefix_line_ml1)sSSH: Server;Ltype: (?:Authname|Version|Kex);Remote: -\d+;[A-Z]\w+:.*%(__prefix_line_ml2)sRead from socket failed: Connection reset by peer%(__suff)s$
-[Definition]
+mdre-extra = ^%(__prefix_line_sl)sReceived disconnect from %(__on_port_opt)s:\s*14: No supported authentication methods available%(__suff)s$
+ ^%(__prefix_line_sl)sUnable to negotiate with %(__on_port_opt)s: no matching (?:cipher|key exchange method) found.
+ ^%(__prefix_line_ml1)sConnection from %(__on_port_opt)s%(__prefix_line_ml2)sUnable to negotiate a (?:cipher|key exchange method)%(__suff)s$
-failregex = %(mode)s
+mdre-aggressive = %(mdre-ddos)s
+ %(mdre-extra)s
+
+failregex = %(cmnfailre)s
+ >
+
+# Parameter "mode": normal (default), ddos, extra or aggressive (combines all)
+# Usage example (for jail.local):
+# [sshd]
+# mode = extra
+# # or another jail (rewrite filter parameters of jail):
+# [sshd-aggressive]
+# filter = sshd[mode=aggressive]
+#
+mode = normal
ignoreregex =
diff --git a/fail2ban/tests/files/logs/sshd b/fail2ban/tests/files/logs/sshd
index e2c5f537..b53b3d96 100644
--- a/fail2ban/tests/files/logs/sshd
+++ b/fail2ban/tests/files/logs/sshd
@@ -183,3 +183,49 @@ Apr 27 13:02:04 host sshd[29116]: Received disconnect from 1.2.3.4: 11: Normal S
# Match sshd auth errors on OpenSUSE systems
# failJSON: { "time": "2015-04-16T20:02:50", "match": true , "host": "222.186.21.217", "desc": "Authentication for user failed" }
2015-04-16T18:02:50.321974+00:00 host sshd[2716]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=222.186.21.217 user=root
+
+# filterOptions: {"mode": "ddos"}
+
+# http://forums.powervps.com/showthread.php?t=1667
+# failJSON: { "time": "2005-06-07T01:10:56", "match": true , "host": "69.61.56.114" }
+Jun 7 01:10:56 host sshd[5937]: Did not receive identification string from 69.61.56.114
+
+# gh-864(1):
+# failJSON: { "match": false }
+Nov 24 23:46:39 host sshd[32686]: SSH: Server;Ltype: Version;Remote: 127.0.0.1-1780;Protocol: 2.0;Client: libssh2_1.4.3
+# failJSON: { "time": "2004-11-24T23:46:43", "match": true , "host": "127.0.0.1", "desc": "Multiline for connection reset by peer (1)" }
+Nov 24 23:46:43 host sshd[32686]: fatal: Read from socket failed: Connection reset by peer [preauth]
+
+# gh-864(2):
+# failJSON: { "match": false }
+Nov 24 23:46:40 host sshd[32686]: SSH: Server;Ltype: Kex;Remote: 127.0.0.1-1780;Enc: aes128-ctr;MAC: hmac-sha1;Comp: none [preauth]
+# failJSON: { "time": "2004-11-24T23:46:43", "match": true , "host": "127.0.0.1", "desc": "Multiline for connection reset by peer (2)" }
+Nov 24 23:46:43 host sshd[32686]: fatal: Read from socket failed: Connection reset by peer [preauth]
+
+# gh-864(3):
+# failJSON: { "match": false }
+Nov 24 23:46:41 host sshd[32686]: SSH: Server;Ltype: Authname;Remote: 127.0.0.1-1780;Name: root [preauth]
+# failJSON: { "time": "2004-11-24T23:46:43", "match": true , "host": "127.0.0.1", "desc": "Multiline for connection reset by peer (3)" }
+Nov 24 23:46:43 host sshd[32686]: fatal: Read from socket failed: Connection reset by peer [preauth]
+
+# filterOptions: {"mode": "extra"}
+
+# several other cases from gh-864:
+# failJSON: { "time": "2004-11-25T01:34:12", "match": true , "host": "127.0.0.1", "desc": "No supported authentication methods" }
+Nov 25 01:34:12 srv sshd[123]: Received disconnect from 127.0.0.1: 14: No supported authentication methods available [preauth]
+# failJSON: { "time": "2004-11-25T01:35:13", "match": true , "host": "127.0.0.1", "desc": "No supported authentication methods" }
+Nov 25 01:35:13 srv sshd[123]: error: Received disconnect from 127.0.0.1: 14: No supported authentication methods available [preauth]
+# failJSON: { "time": "2004-11-25T01:35:14", "match": true , "host": "192.168.2.92", "desc": "Optional space after port" }
+Nov 25 01:35:14 srv sshd[3625]: error: Received disconnect from 192.168.2.92 port 1684:14: No supported authentication methods available [preauth]
+
+# gh-1545:
+# failJSON: { "time": "2004-11-26T13:03:29", "match": true , "host": "192.0.2.1", "desc": "No matching cipher" }
+Nov 26 13:03:29 srv sshd[45]: Unable to negotiate with 192.0.2.1 port 55419: no matching cipher found. Their offer: aes256-cbc,rijndael-cbc@lysator.liu.se,aes192-cbc,aes128-cbc,arcfour128,arcfour,3des-cbc,none [preauth]
+
+# gh-1117:
+# failJSON: { "time": "2004-11-26T13:03:30", "match": true , "host": "192.0.2.2", "desc": "No matching key exchange method" }
+Nov 26 13:03:30 srv sshd[45]: fatal: Unable to negotiate with 192.0.2.2 port 55419: no matching key exchange method found. Their offer: diffie-hellman-group1-sha1
+# failJSON: { "match": false }
+Nov 26 15:03:30 host sshd[22440]: Connection from 192.0.2.3 port 39678 on 192.168.1.9 port 22
+# failJSON: { "time": "2004-11-26T15:03:31", "match": true , "host": "192.0.2.3", "desc": "Multiline - no matching key exchange method" }
+Nov 26 15:03:31 host sshd[22440]: fatal: Unable to negotiate a key exchange method [preauth]
\ No newline at end of file
diff --git a/fail2ban/tests/files/logs/sshd-aggressive b/fail2ban/tests/files/logs/sshd-aggressive
deleted file mode 100644
index 5b4d3a12..00000000
--- a/fail2ban/tests/files/logs/sshd-aggressive
+++ /dev/null
@@ -1,3 +0,0 @@
-# sshd-aggressive includes sshd and sshd-ddos failregex's:
-# addFILE: "sshd"
-# addFILE: "sshd-ddos"
\ No newline at end of file
diff --git a/fail2ban/tests/files/logs/sshd-ddos b/fail2ban/tests/files/logs/sshd-ddos
deleted file mode 100644
index f0a787a1..00000000
--- a/fail2ban/tests/files/logs/sshd-ddos
+++ /dev/null
@@ -1,41 +0,0 @@
-# http://forums.powervps.com/showthread.php?t=1667
-# failJSON: { "time": "2005-06-07T01:10:56", "match": true , "host": "69.61.56.114" }
-Jun 7 01:10:56 host sshd[5937]: Did not receive identification string from 69.61.56.114
-
-# gh-864(1):
-# failJSON: { "match": false }
-Nov 24 23:46:39 host sshd[32686]: SSH: Server;Ltype: Version;Remote: 127.0.0.1-1780;Protocol: 2.0;Client: libssh2_1.4.3
-# failJSON: { "time": "2004-11-24T23:46:43", "match": true , "host": "127.0.0.1", "desc": "Multiline for connection reset by peer (1)" }
-Nov 24 23:46:43 host sshd[32686]: fatal: Read from socket failed: Connection reset by peer [preauth]
-
-# gh-864(2):
-# failJSON: { "match": false }
-Nov 24 23:46:40 host sshd[32686]: SSH: Server;Ltype: Kex;Remote: 127.0.0.1-1780;Enc: aes128-ctr;MAC: hmac-sha1;Comp: none [preauth]
-# failJSON: { "time": "2004-11-24T23:46:43", "match": true , "host": "127.0.0.1", "desc": "Multiline for connection reset by peer (2)" }
-Nov 24 23:46:43 host sshd[32686]: fatal: Read from socket failed: Connection reset by peer [preauth]
-
-# gh-864(3):
-# failJSON: { "match": false }
-Nov 24 23:46:41 host sshd[32686]: SSH: Server;Ltype: Authname;Remote: 127.0.0.1-1780;Name: root [preauth]
-# failJSON: { "time": "2004-11-24T23:46:43", "match": true , "host": "127.0.0.1", "desc": "Multiline for connection reset by peer (3)" }
-Nov 24 23:46:43 host sshd[32686]: fatal: Read from socket failed: Connection reset by peer [preauth]
-
-# several other cases from gh-864:
-# failJSON: { "time": "2004-11-25T01:34:12", "match": true , "host": "127.0.0.1", "desc": "No supported authentication methods" }
-Nov 25 01:34:12 srv sshd[123]: Received disconnect from 127.0.0.1: 14: No supported authentication methods available [preauth]
-# failJSON: { "time": "2004-11-25T01:35:13", "match": true , "host": "127.0.0.1", "desc": "No supported authentication methods" }
-Nov 25 01:35:13 srv sshd[123]: error: Received disconnect from 127.0.0.1: 14: No supported authentication methods available [preauth]
-# failJSON: { "time": "2004-11-25T01:35:14", "match": true , "host": "192.168.2.92", "desc": "Optional space after port" }
-Nov 25 01:35:14 srv sshd[3625]: error: Received disconnect from 192.168.2.92 port 1684:14: No supported authentication methods available [preauth]
-
-# gh-1545:
-# failJSON: { "time": "2004-11-26T13:03:29", "match": true , "host": "192.0.2.1", "desc": "No matching cipher" }
-Nov 26 13:03:29 srv sshd[45]: Unable to negotiate with 192.0.2.1 port 55419: no matching cipher found. Their offer: aes256-cbc,rijndael-cbc@lysator.liu.se,aes192-cbc,aes128-cbc,arcfour128,arcfour,3des-cbc,none [preauth]
-
-# gh-1117:
-# failJSON: { "time": "2004-11-26T13:03:30", "match": true , "host": "192.0.2.2", "desc": "No matching key exchange method" }
-Nov 26 13:03:30 srv sshd[45]: fatal: Unable to negotiate with 192.0.2.2 port 55419: no matching key exchange method found. Their offer: diffie-hellman-group1-sha1
-# failJSON: { "match": false }
-Nov 26 15:03:30 host sshd[22440]: Connection from 192.0.2.3 port 39678 on 192.168.1.9 port 22
-# failJSON: { "time": "2004-11-26T15:03:31", "match": true , "host": "192.0.2.3", "desc": "Multiline - no matching key exchange method" }
-Nov 26 15:03:31 host sshd[22440]: fatal: Unable to negotiate a key exchange method [preauth]
\ No newline at end of file