fail2ban doesn't recognize failed public key ssh logins and I assume that this can be solved by modifying the failregex of /etc/fail2ban/filter.d/sshd.config to match the following line:

<date> <time> <server-hostname> sshd[25917]: Connection closed by <client-ip> [preauth]

But I can't find a decent introduction on how to correctly modify said failregex. As I don't really know what variables like ^%(__prefix_line)s include it's hard to get a working regex.

I understand that the most recent version 0.9.1 includes the regex to matche the "Connection closed by [preauth]" line, but I'm using fai2ban from the Debian repository and the configuration of 0.9.1 is not compatible with the one I have.


This line does it:

^%(__prefix_line)sConnection closed by <HOST> \[preauth\]$

Tested with the following logstring:

Apr 29 12:30:12 sendai sshd[25917]: Connection closed by [preauth]

Successfully tested with:

$ fail2ban-regex ~/ssh.log sshd.conf 

Running tests

Use regex file : sshd.conf
Use log file   : /home/user/ssh.log


|- Regular expressions:
|  [12] ^\s*(?:\S+ )?(?:kernel: \[\d+\.\d+\] )?(?:@vserver_\S+ )?(?:(?:\[\d+\])?:\s+[\[\(]?sshd(?:\(\S+\))?[\]\)]?:?|[\[\(]?sshd(?:\(\S+\))?[\]\)]?:?(?:\[\d+\])?:)?\s*Connection closed by <HOST> \[preauth\]$
`- Number of matches:
   [12] 1 match(es)


Addresses found:
[12] (Wed Apr 29 12:30:12 2015)

Success, the total number of match is 1
| improve this answer | |
  • I assumed fail2ban would log to /var/log/fail2ban.log on matches, but it didn't, only when banned it finally logged. Thank you very much for the help! – apoc Apr 29 '15 at 15:15
  • I'm using 0.9.3 and the closest filter I could were one for multiline: fail2ban #227f27c. It does not match with your logstring (or mine, for that matter), but for MaxAuthTries=N in /etc/ssh/sshd_config. Do you know if something like your regex is intentionally left out from the default filter? Thanks! – timss Oct 26 '15 at 17:56

At least in openssh 7.3 the log messages also contain a port number. So I had to modify sebix's solution to the following:

^%(__prefix_line)sConnection closed by <HOST> port \d+ \[preauth\]$
| improve this answer | |

No regex hacking is required (at least since fail2ban 0.10.4). In /etc/fail2ban/jail.conf is the following information:


# 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

So follow the recommendations by creating /etc/fail2ban/jail.local with your other customisations, along with one of the more stringent modes, for example,

mode   = aggressive

This mode now covers failed public keys.

| improve this answer | |
  • 1
    This is correct answer, excepting that error Connection closed ... [preauth] has basically nothing with failed public keys (you'd get Failed publickey ... instead). See github.com/fail2ban/fail2ban/blob/… for more failed messages. Connection closed means only that the connection was closed on preauth phase (so user is not authenticated for any reason). – sebres Jan 27 at 14:30
  • @sebres my system actually does shows the Connection closed… message for "Failure on connect with valid user-name but wrong public keys", which is the final line you linked to. – Sparhawk Jan 27 at 21:34
  • Sure it does. As well as after every other failure on preauth phase (for example if trying unsupported/disabled auth method, or even if it got closed totally without authentication). As already said, the message has nothing with wrong public keys at all, it just signals that connection is closed before authentication process fulfilled. – sebres Jan 28 at 12:50
  • @sebres Ah okay got it. On your second point though, I don't get the same behaviour. When I fail with the wrong public key, I don't get the Failed publickey… message, just the Connection closed… one. – Sparhawk Jan 28 at 23:33
  • Clear, because several messages are logged only in VERBOSE level, see serverfault.com/a/477424/488604 – sebres Jan 29 at 11:23

On Ubuntu 18.04 with OpenSSH 7.6p1 I had to extend the "cmnfailre" rules in /etc/fail2ban/filter.d/sshd.conf by

^%(__prefix_line)sConnection closed by authenticating user <F-USER>.+</F-USER> <HOST> port \d+ \[preauth\]$

to match ssh login attempts without correct ssh key:

Apr 14 15:27:15 ubuntu-server sshd[8719]: Connection closed by authenticating user root x.x.x.x port 42664 [preauth]
Apr 14 15:27:15 ubuntu-server sshd[8721]: Connection closed by authenticating user root x.x.x.x port 42666 [preauth]
Apr 14 15:27:16 ubuntu-server sshd[8723]: Connection closed by authenticating user root x.x.x.x port 42668 [preauth]
Apr 14 15:27:16 ubuntu-server sshd[8725]: Connection closed by authenticating user root x.x.x.x port 42670 [preauth]
Apr 14 15:27:17 ubuntu-server sshd[8727]: Connection closed by authenticating user root x.x.x.x port 42672 [preauth]
| improve this answer | |
  • This worked for my Ubuntu 18.04 as well, thank you! Is there a way to extend the default sshd.conf with just that line or is the only option to copy the whole thing to .local and add it there? – chrisan Feb 18 at 15:35
  • 1
    @chrisan You could create a file /etc/fail2ban/filter.d/sshd.local like this: ` [Definition] failregex = %(known/failregex)s %(__prefix_line)sConnection closed by authenticating user <F-USER>.+</F-USER> <HOST> port \d+ [preauth]$ ` – Arnel A. Borja Feb 19 at 0:59
  • @ArnelA.Borja and that will add to the base .conf not override it? That was my main concern. I created the .local originally but just copied the entire config and added the new filter – chrisan Feb 20 at 10:33
  • 1
    @chrisan Yes it won't override it, it will just add a new value to failregex, due to %(known/failregex)s. You could confirm this by running sudo fail2ban-regex -v /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf before and after adding the said file; the number of Failregex entries will increase by 1. – Arnel A. Borja Feb 28 at 5:24

For me, this works better, as I get tons of legit log entries, matching the "Connection closed" regex, at least in OpenSSH 6.6.1 variations. Believe it also covers the new OpenSSH log format, which includes "port":

^%(__prefix_line)sDid not receive identification string from <HOST>\s*$
^%(__prefix_line)sReceived disconnect from <HOST>: (port \d*: ){,1}11: (Bye Bye){,1} \[preauth\]\s*$

$ cat /etc/*relea* | grep -i desc

$ fail2ban-regex /var/log/auth.log filter.d/sshd.conf

Running tests

Use   failregex file : filter.d/sshd.conf
Use         log file : /var/log/auth.log


Failregex: 39 total
|-  #) [# of hits] regular expression
|  12) [16] ^\s*(<[^.]+\.[^.]+>)?\s*(?:\S+ )?(?:kernel: \[\d+\.\d+\] )?(?:@vserver_\S+ )?(?:(?:\[\d+\])?:\s+[\[\(]?sshd(?:\(\S+\))?[\]\)]?:?|[\[\(]?sshd(?:\(\S+\))?[\]\)]?:?(?:\[\d+\])?:?)?\s(?:\[ID \d+ \S+\])?\s*Did not receive identification string from <HOST>\s*$
|  13) [23] ^\s*(<[^.]+\.[^.]+>)?\s*(?:\S+ )?(?:kernel: \[\d+\.\d+\] )?(?:@vserver_\S+ )?(?:(?:\[\d+\])?:\s+[\[\(]?sshd(?:\(\S+\))?[\]\)]?:?|[\[\(]?sshd(?:\(\S+\))?[\]\)]?:?(?:\[\d+\])?:?)?\s(?:\[ID \d+ \S+\])?\s*Received disconnect from <HOST>: (port \d*: ){,1}11: (Bye Bye){,1} \[preauth\]\s*$

Ignoreregex: 0 total

Date template hits:
|- [# of hits] date format
|  [62412] MONTH Day Hour:Minute:Second

Lines: 62412 lines, 0 ignored, 39 matched, 62373 missed
Missed line(s):: too many to print.  Use --print-all-missed to print all 62373 lines

$ grep "Did not receive identification string from" /var/log/auth.log | wc -l
$ grep "Received disconnect from" /var/log/auth.log | grep -v x.x.x.x | wc -l
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.