fail2ban regex tester

Paste log lines and pick one of fail2ban's filters, or paste your own failregex or filter file. Each line shows whether fail2ban counts it as a failure, which failregex matched and which address it would ban, as fail2ban-regex reports it. It runs fail2ban 1.1.1's filters and line processing in your browser; nothing is uploaded.

Same test on your server: fail2ban-regex /var/log/auth.log sshd

Checked against fail2ban itself

fail2ban ships a test log for each filter. All 1,564 lines of them (96 filters, every mode they use) were run through fail2ban 1.1.1 and through this page's engine: the failures, addresses, users and ignored lines are identical on every line. The filters themselves are fail2ban's, resolved by fail2ban's own reader (129 filter and mode combinations), from fail2ban 1.1.1 (GPL-2.0).

What fail2ban's default sshd filter does not count on a key-only server

Once a server accepts only SSH keys, a password guess no longer produces "Failed password". The client is refused before any password is asked for, and sshd logs only that the connection closed. fail2ban's sshd filter in its default normal mode does not count those lines, and neither do the ten-connection streams below (fail2ban 1.1.1, failures counted for the attacking address):

Ten connectionsnormal (default)ddosextraaggressive
Password guesses for root (the server takes keys only)010010
The same, from a client that says goodbye0101010
Guesses for a user that does not exist10201020
Connections that never authenticate (LoginGraceTime)010010

0 failures means the address is never banned, whatever maxretry is. Measured with fail2ban 1.1.1 itself and pinned in this page's tests.

What that means in practice, from our own key-only server: the sshd lines it logged from 10 October 2026 to 9 November 2026, one real example line of each through each mode. "Only with other lines" is a line the filter matches with F-NOFAIL: it counts only when the same connection also logs a failure.

sshd messageLines in 30 daysnormal (default)ddosextraaggressive
connection-closed Connection closed by invalid user admin 203.0.113.45 port 51234 [preauth] 48,747 only with other linescountednot countedcounted
invalid-user Invalid user admin from 203.0.113.45 port 51234 34,304 countedcountedcountedcounted
received-disconnect Received disconnect from 203.0.113.45 port 51234:11: Bye Bye [preauth] 19,447 only with other linesonly with other linesonly with other linesonly with other lines
disconnected-preauth Disconnected from invalid user admin 203.0.113.45 port 51234 [preauth] 19,447 only with other linescountedcountedcounted
connection-reset Connection reset by authenticating user root 203.0.113.45 port 51234 [preauth] 3,555 only with other linescountednot countedcounted
timeout-before-auth Timeout before authentication for 203.0.113.45 port 51234, pid = 4242 2,047 not countedcountednot countedcounted
unable-to-negotiate Unable to negotiate with 203.0.113.45 port 51234: no matching key exchange method found. Their offer: diffie-hellman-group1-sha1 [preauth] 294 not countednot countedcountedcounted
kex-identification error: kex_exchange_identification: read: Connection reset by peer 288 not countedno addressnot countedno address
banner-invalid-format banner exchange: Connection from 203.0.113.45 port 51234: invalid format 284 not countedcountednot countedcounted
max-auth-attempts error: maximum authentication attempts exceeded for root from 203.0.113.45 port 51234 ssh2 [preauth] 199 countedcountedcountedcounted
too-many-auth-failures Disconnecting authenticating user root 203.0.113.45 port 51234: Too many authentication failures [preauth] 199 not countednot countednot countednot counted
pubkey-algorithm-not-accepted userauth_pubkey: signature algorithm ssh-rsa not in PubkeyAcceptedAlgorithms [preauth] 112 not countednot countednot countednot counted
protocol-major-versions-differ error: Protocol major versions differ: 2 vs. 1 25 not countednot countednot countednot counted
banner-no-protocol-version banner exchange: Connection from 203.0.113.45 port 51234: could not read protocol version 25 not countednot countednot countednot counted
parse-publickey-packet fatal: userauth_pubkey: parse publickey packet: incomplete message [preauth] 7 not countednot countednot countednot counted
dispatch-run-fatal ssh_dispatch_run_fatal: Connection from 203.0.113.45 port 51234: message authentication code incorrect [preauth] 6 not countedcountednot countedcounted
bad-protocol-version error: Bad remote protocol version identification: 'SSH-2.0-' 1 not countednot countednot countednot counted

Counts from LogTriage's server (monthly attack report); successful logins, sessions and sshd's own penalty lines left out.

To count them, set the mode in /etc/fail2ban/jail.local, check it with fail2ban-regex, and restart:

[sshd]
enabled = true
mode    = aggressive

# check what it would catch, then apply
fail2ban-regex /var/log/auth.log "sshd[mode=aggressive]"
systemctl restart fail2ban

On systemd systems without /var/log/auth.log, test the journal instead: fail2ban-regex systemd-journal "sshd[mode=aggressive]".

How fail2ban reads a line

  1. The date is found and cut out. fail2ban tries its date templates (most filters only at the start of the line) and removes the matched date; the regexes see the rest. A line whose date is not found is still matched, but fail2ban cannot place it in time.
  2. prefregex, if the filter has one, must match first. Its <F-CONTENT> part is what the failregexes then see; sshd's prefregex strips the host and program prefix this way.
  3. Every failregex is tried (fail2ban-regex's default). A match needs an address or failure id: <HOST>, <ADDR> or <F-ID>.
  4. ignoreregex can drop a match.
  5. Each failure counts toward the address's maxretry (5 by default) within findtime (10 minutes by default).

Tags you can use in a failregex

<HOST>An IPv4 or IPv6 address, or a host name (fail2ban resolves names unless usedns = no). The usual tag for the attacker.
<ADDR>An IPv4 or IPv6 address only, never a host name.
<IP4>, <IP6>Only an IPv4 or only an IPv6 address.
<F-USER>…</F-USER>Captures the user name, shown by fail2ban-regex and usable in actions.
<F-ID>…</F-ID>, <F-ID/>A failure id other than an address (a session or account), counted like an address.
<F-NOFAIL>…</F-NOFAIL>The line matches but is not a failure by itself; sshd uses it for lines that only count together with others of the same connection.
<F-MLFID>…</F-MLFID>Ties lines of one connection together (sshd uses the process id in the prefix).
<SKIPLINES>Skips lines inside a multi-line match (filters with maxlines above 1).

A filter file for your own application, using fail2ban's shared syslog prefix from common.conf:

[INCLUDES]
before = common.conf

[Definition]
_daemon = myapp
failregex = ^%(__prefix_line)sLogin failed for user <F-USER>\S+</F-USER> from <HOST>$
ignoreregex =

Paste it into "My own failregex or filter file" with a few of your log lines to see each one matched or missed before you deploy it. The page's reader resolves [INCLUDES], %(…)s and <tags> the way fail2ban does for every filter fail2ban ships. A custom datepattern that no shipped filter uses falls back to fail2ban's default date templates.

The SSH lines themselves are explained one by one in the sshd log message reference, with counts from our server.

Questions

Is there an online fail2ban regex tester?
This page is one. It runs fail2ban 1.1.1's filters and its line processing (date detection, prefregex, failregex, ignoreregex and the sshd connection merging) in your browser, the way fail2ban-regex does. On all 1,564 lines of fail2ban's own test logs it gives the same result as fail2ban, line for line.
Why does fail2ban-regex say "Missed" for a line that looks like an attack?
Because no failregex of the filter matches it in the mode you run. fail2ban’s sshd filter in the default normal mode does not count "Timeout before authentication", "kex_exchange_identification" or "Connection closed by authenticating user … [preauth]" as failures. The mode ddos or aggressive does: pick it above and the line shows as a failure.
How do I make fail2ban ban SSH clients on a server that only accepts keys?
Set the filter mode in jail.local: under [sshd] add "mode = aggressive" (or ddos), then restart fail2ban. In the default normal mode, password guesses against an existing account on a key-only server leave only "Connection closed by authenticating user … [preauth]" lines, which fail2ban does not count, so those clients are never banned.
Does fail2ban read OpenSSH 10’s sshd-session lines?
Yes, from fail2ban 1.1.1 (August 2026) on: its sshd filter accepts both sshd and sshd-session as the program name (_daemon = sshd(?:-session)?), because OpenSSH 9.8 and later log most messages from sshd-session. Older fail2ban versions miss those lines, so upgrade, or test your version’s filter file here with your own lines.
Can I test my own failregex or filter file?
Yes. Choose "My own failregex or filter file" and paste either one failregex per line, or a whole filter file. A filter file is read the way fail2ban reads it, including [INCLUDES] before = common.conf, %(__prefix_line)s and <tags>; this reader gives the same failregex as fail2ban for every filter fail2ban ships.
How many failures get an address banned?
fail2ban’s jail.conf defaults are maxretry = 5 failures within findtime = 10 minutes, then a bantime of 10 minutes. The table above counts failures per address over the whole paste; whether they fall inside findtime depends on their times.

Seeing more than fail2ban bans?

Load the whole auth.log into the free analyzer: SSH brute force, user-name guessing and a login that succeeded after failures, per address. Nothing is uploaded.

Investigating something right now? LogTriage checks every address in the file against threat intelligence and writes the incident report: 10 analyses a month free. The incident pack adds the in-depth AI analysis and files up to 100 MB: 25 analyses for $19, one payment, no subscription. Pricing

Every query on this site's reference pages, the Sigma rules and a cheat sheet in one download: the Incident Response Kit, $29 once.