diff --git a/config/filter.d/sshd.conf b/config/filter.d/sshd.conf
index 60b61241..60efead7 100644
--- a/config/filter.d/sshd.conf
+++ b/config/filter.d/sshd.conf
@@ -24,6 +24,8 @@ __pref = (?:(?:error|fatal): (?:PAM: )?)?
#__suff = (?: port \d+)?(?: \[preauth\])?\s*
__suff = (?: (?:port \d+|on \S+|\[preauth\])){0,3}\s*
__on_port_opt = (?: (?:port \d+|on \S+)){0,2}
+# close by authenticating user:
+__authng_user = (?: authenticating user \S+|.+?)?
# for all possible (also future) forms of "no matching (cipher|mac|MAC|compression method|key exchange method|host key type) found",
# see ssherr.c for all possible SSH_ERR_..._ALG_MATCH errors.
@@ -54,16 +56,16 @@ cmnfailre = ^[aA]uthentication (?:failure|error|failed) for .*
^User .+ not allowed because account is locked%(__suff)s
^Disconnecting: Too many authentication failures(?: for .+?)?%(__suff)s$
^Received disconnect from %(__on_port_opt)s:\s*11:
- ^Connection closed by -suff-onclosed>
+ ^Connection closed by%(__authng_user)s -suff-onclosed>
^Accepted \w+ for \S+ from (?:\s|$)
mdre-normal =
# used to differentiate "connection closed" with and without `[preauth]` (fail/nofail cases in ddos mode)
-mdrp-normal-suff-onclosed =
+mdrp-normal-suff-onclosed = (?:%(__suff)s|\s*)$
mdre-ddos = ^Did not receive identification string from
^Connection reset by
- ^Connection closed by %(__on_port_opt)s\s+\[preauth\]\s*$
+ ^Connection closed by%(__authng_user)s %(__on_port_opt)s\s+\[preauth\]\s*$
^SSH: Server;Ltype: (?:Authname|Version|Kex);Remote: -\d+;[A-Z]\w+:
^Read from socket failed: Connection reset by peer
mdrp-ddos-suff-onclosed = %(__on_port_opt)s\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 5717c316..98fca7f5 100644
--- a/fail2ban/tests/config/filter.d/zzz-sshd-obsolete-multiline.conf
+++ b/fail2ban/tests/config/filter.d/zzz-sshd-obsolete-multiline.conf
@@ -16,6 +16,8 @@ __pref = (?:(?:error|fatal): (?:PAM: )?)?
# optional suffix (logged from several ssh versions) like " [preauth]"
__suff = (?: (?:port \d+|on \S+|\[preauth\])){0,3}\s*
__on_port_opt = (?: (?:port \d+|on \S+)){0,2}
+# close by authenticating user:
+__authng_user = (?: authenticating user \S+|.+?)?
# single line prefix:
__prefix_line_sl = %(__prefix_line)s%(__pref)s
@@ -48,12 +50,13 @@ cmnfailre = ^%(__prefix_line_sl)s[aA]uthentication (?:failure|error|failed) for
^%(__prefix_line_ml1)s%(__pam_auth)s\(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$%(__prefix_line_ml2)sConnection closed
^%(__prefix_line_sl)s(error: )?maximum authentication attempts exceeded for .* from %(__on_port_opt)s(?: ssh\d*)? \[preauth\]$
^%(__prefix_line_ml1)sUser .+ not allowed because account is locked%(__prefix_line_ml2)sReceived disconnect from %(__on_port_opt)s:\s*11: .+%(__suff)s$
- ^%(__prefix_line_ml1)sDisconnecting: Too many authentication failures(?: for .+?)?%(__suff)s%(__prefix_line_ml2)sConnection closed by %(__suff)s$
+ ^%(__prefix_line_ml1)sDisconnecting: Too many authentication failures(?: for .+?)?%(__suff)s%(__prefix_line_ml2)sConnection closed by%(__authng_user)s %(__suff)s$
^%(__prefix_line_ml1)sConnection from %(__on_port_opt)s%(__prefix_line_ml2)sDisconnecting: Too many authentication failures(?: for .+?)?%(__suff)s$
mdre-normal =
mdre-ddos = ^%(__prefix_line_sl)sDid not receive identification string from
+ ^%(__prefix_line_sl)sConnection closed by%(__authng_user)s %(__on_port_opt)s\s+\[preauth\]\s*$
^%(__prefix_line_sl)sConnection reset by
^%(__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$
diff --git a/fail2ban/tests/files/logs/sshd b/fail2ban/tests/files/logs/sshd
index 21629fb7..e2b3d456 100644
--- a/fail2ban/tests/files/logs/sshd
+++ b/fail2ban/tests/files/logs/sshd
@@ -283,6 +283,13 @@ Nov 24 23:46:43 host sshd[32686]: fatal: Read from socket failed: Connection res
# failJSON: { "time": "2005-03-15T09:20:57", "match": true , "host": "192.0.2.39", "desc": "Singleline for connection reset by" }
Mar 15 09:20:57 host sshd[28972]: Connection reset by 192.0.2.39 port 14282 [preauth]
+# failJSON: { "time": "2005-07-17T23:03:05", "match": true , "host": "192.0.2.10", "user": "root", "desc": "user name additionally, gh-2185" }
+Jul 17 23:03:05 srv sshd[1296]: Connection closed by authenticating user root 192.0.2.10 port 46038 [preauth]
+# failJSON: { "time": "2005-07-17T23:04:00", "match": true , "host": "192.0.2.11", "user": "test 127.0.0.1", "desc": "check inject on username, gh-2185" }
+Jul 17 23:04:00 srv sshd[1300]: Connection closed by authenticating user test 127.0.0.1 192.0.2.11 port 46039 [preauth]
+# failJSON: { "time": "2005-07-17T23:04:01", "match": true , "host": "192.0.2.11", "user": "test 127.0.0.1 port 12345", "desc": "check inject on username, gh-2185" }
+Jul 17 23:04:01 srv sshd[1300]: Connection closed by authenticating user test 127.0.0.1 port 12345 192.0.2.11 port 46039 [preauth]
+
# filterOptions: [{"test.condition":"name=='sshd'", "mode": "ddos"}, {"test.condition":"name=='sshd'", "mode": "aggressive"}]
# failJSON: { "time": "2005-03-15T09:21:01", "match": true , "host": "192.0.2.212", "desc": "DDOS mode causes failure on close within preauth stage" }
@@ -290,8 +297,6 @@ Mar 15 09:21:01 host sshd[2717]: Connection closed by 192.0.2.212 [preauth]
# failJSON: { "time": "2005-03-15T09:21:02", "match": true , "host": "192.0.2.212", "desc": "DDOS mode causes failure on close within preauth stage" }
Mar 15 09:21:02 host sshd[2717]: Connection closed by 192.0.2.212 [preauth]
-
-
# filterOptions: [{"mode": "extra"}, {"mode": "aggressive"}]
# several other cases from gh-864: