121

When I run this command fail2ban-client status sshd I got this:

Status for the jail: sshd
|- Filter
|  |- Currently failed: 1
|  |- Total failed:     81
|  `- File list:        /var/log/auth.log
`- Actions
   |- Currently banned: 2
   |- Total banned:     8
   `- Banned IP list:   218.65.30.61 116.31.116.7

It only show two IP in banned IP list instead of 8 just like Total Banned says.

While I do tail -f /var/log/auth.log I got this:

Mar 29 11:08:40 DBSERVER sshd[29163]: error: maximum authentication attempts exceeded for root from 218.65.30.61 port 50935 ssh2 [preauth]
Mar 29 11:08:40 DBSERVER sshd[29163]: Disconnecting: Too many authentication failures [preauth]
Mar 29 11:08:40 DBSERVER sshd[29163]: PAM 5 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=218.65.30.61  user=root
Mar 29 11:08:40 DBSERVER sshd[29163]: PAM service(sshd) ignoring max retries; 6 > 3
Mar 29 11:08:44 DBSERVER sshd[29165]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=218.65.30.61  user=root
Mar 29 11:08:46 DBSERVER sshd[29165]: Failed password for root from 218.65.30.61 port 11857 ssh2
Mar 29 11:09:01 DBSERVER CRON[29172]: pam_unix(cron:session): session opened for user root by (uid=0)
Mar 29 11:09:01 DBSERVER CRON[29172]: pam_unix(cron:session): session closed for user root
Mar 29 11:10:01 DBSERVER CRON[29226]: pam_unix(cron:session): session opened for user root by (uid=0)
Mar 29 11:10:02 DBSERVER CRON[29226]: pam_unix(cron:session): session closed for user root
Mar 29 11:10:18 DBSERVER sshd[29238]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=113.122.43.185  user=root
Mar 29 11:10:20 DBSERVER sshd[29238]: Failed password for root from 113.122.43.185 port 46017 ssh2
Mar 29 11:10:33 DBSERVER sshd[29238]: message repeated 5 times: [ Failed password for root from 113.122.43.185 port 46017 ssh2]
Mar 29 11:10:33 DBSERVER sshd[29238]: error: maximum authentication attempts exceeded for root from 113.122.43.185 port 46017 ssh2 [preauth]
Mar 29 11:10:33 DBSERVER sshd[29238]: Disconnecting: Too many authentication failures [preauth]
Mar 29 11:10:33 DBSERVER sshd[29238]: PAM 5 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=113.122.43.185  user=root
Mar 29 11:10:33 DBSERVER sshd[29238]: PAM service(sshd) ignoring max retries; 6 > 3
Mar 29 11:11:36 DBSERVER sshd[29245]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=116.31.116.7  user=root
Mar 29 11:11:38 DBSERVER sshd[29245]: Failed password for root from 116.31.116.7 port 24892 ssh2
Mar 29 11:11:43 DBSERVER sshd[29245]: message repeated 2 times: [ Failed password for root from 116.31.116.7 port 24892 ssh2]
Mar 29 11:11:43 DBSERVER sshd[29245]: Received disconnect from 116.31.116.7 port 24892:11:  [preauth]
Mar 29 11:11:43 DBSERVER sshd[29245]: Disconnected from 116.31.116.7 port 24892 [preauth]
Mar 29 11:11:43 DBSERVER sshd[29245]: PAM 2 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=116.31.116.7  user=root
Mar 29 11:12:39 DBSERVER sshd[29247]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=116.31.116.7  user=root
Mar 29 11:12:41 DBSERVER sshd[29247]: Failed password for root from 116.31.116.7 port 26739 ssh2
Mar 29 11:12:45 DBSERVER sshd[29247]: message repeated 2 times: [ Failed password for root from 116.31.116.7 port 26739 ssh2]
Mar 29 11:12:45 DBSERVER sshd[29247]: Received disconnect from 116.31.116.7 port 26739:11:  [preauth]
Mar 29 11:12:45 DBSERVER sshd[29247]: Disconnected from 116.31.116.7 port 26739 [preauth]
Mar 29 11:12:45 DBSERVER sshd[29247]: PAM 2 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=116.31.116.7  user=root
Mar 29 11:13:41 DBSERVER sshd[29249]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=116.31.116.7  user=root
Mar 29 11:13:43 DBSERVER sshd[29249]: Failed password for root from 116.31.116.7 port 27040 ssh2

banned IP still trying.

However when I check with sudo iptables -L INPUT -v -n I got this:

Chain INPUT (policy ACCEPT 228 packets, 18000 bytes)
 pkts bytes target     prot opt in     out     source               destination
 6050  435K f2b-sshd   tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            multiport dports 22

What am I doing wrong here?

How can I show all banned IP list?

2
  • 2
    "Total" means total ever banned, not total currently banned. The only place you will find previously-banned addresses is in the logs (if you kept them).
    – OrangeDog
    Jul 31, 2018 at 11:08
  • 1
    in jail.local or jail.conf, you seem to have a small bantime. Make it 200m or even higher and then do sudo service fail2ban restart and then fail2ban-client status sshd
    – Allen King
    Oct 19, 2019 at 17:55

15 Answers 15

76

Please keep in mind that the fail2ban banning of IP is temporary in nature.

The best way to have a look at the full list of IPs that have been blocked would be to check the log file:

sudo zgrep 'Ban' /var/log/fail2ban.log*

Edit: this answer previously searched for 'Ban:', but even in 2013 the source has no colon (ref).

The following command can also give you a clean list of input rules:

sudo iptables -L INPUT -v -n | less
5
  • 10
    There's no colon in my logfiles (thus needed to adjust the grep). Leaving as a comment rather than an edit though, as I don't know how widespread this is / if this is a recent change.
    – kwah
    Apr 15, 2018 at 15:54
  • Bear in mind that listing iptables rules only works in case iptables is your banning action. Sometimes this is not the case.
    – gilad905
    May 18, 2018 at 10:09
  • @kwah same for me, no colon in the log file. Probably a recent change in the output, or a typo. Jun 10, 2019 at 2:36
  • 2
    Remove the ':' after the search term 'Ban' because the ':' is not written in the log file anymore. So you will be able the see the blocked IPs again with the above mentioned command. Jun 13, 2019 at 7:13
  • for Oracle Linux 6 and fail2ban 0.9.6, the correct command is sudo zgrep 'Ban' /var/log/messages since it doesn't use /var/log/fail2ban.log Aug 19, 2021 at 5:16
38

Similar to NA AE above with kwaa's comments included, this lists all IPs:

sudo zgrep 'Ban' /var/log/fail2ban.log*

but that output has so many lines. This counts lines of all logged banned (and likely unbanned) ip's:

sudo zgrep 'Ban' /var/log/fail2ban.log* | wc -l

The output from above command (with line count) should match 'Total Banned' count in fail2ban's status output:

fail2ban-client status sshd

tested in Ubuntu 18.04.1 LTS.

My output from 'wc -l' line:

7244

And from fail2ban's status, the same 7244 number is verified:

Status for the jail: sshd
|- Filter
|  |- Currently failed: 7
|  |- Total failed: 49457
|  `- File list:    /var/log/auth.log
`- Actions
   |- Currently banned: 9
   |- Total banned: 7244
   `- Banned IP list:   [...]
1
  • Count is interesting. Can you modify this command to count number of bans on a particular IP and sort them in descending order? It'll print out repeat offenders.
    – Whip
    Jan 19, 2022 at 4:25
22

You can use sqlite3 command to do some statistics by querying bips table of /var/lib/fail2ban/fail2ban.sqlite3 database (if your fail2ban version < v0.11.1, change bips to bans).

Show all IP address and its jail:

sqlite3 /var/lib/fail2ban/fail2ban.sqlite3 "select ip,jail from bips"

Show all unique IP address:

sqlite3 /var/lib/fail2ban/fail2ban.sqlite3 "select distinct ip from bips"

Show all unique IP address in sshd jail:

sqlite3 /var/lib/fail2ban/fail2ban.sqlite3 "select distinct ip from bips where jail='sshd'"

Show top 20 most banned IP address in all jails:

sqlite3 /var/lib/fail2ban/fail2ban.sqlite3 "select jail,ip,count(*) as count from bips group by ip order by count desc limit 20"

If you want to see structure and all data of this file in a GUI app, I recommend DB Browser For Sqlite.


As of version v0.11.1, fail2ban changed its database structure. I run this command in my Linux machine to see what's the difference (Fail2Ban v0.11.1, Ubuntu 20.04)

sqlite3 /var/lib/fail2ban/fail2ban.sqlite3 '.schema'

Part of the output is:

CREATE TABLE bans(jail TEXT NOT NULL, ip TEXT, timeofban INTEGER NOT NULL, bantime INTEGER NOT NULL, bancount INTEGER NOT NULL default 1, data JSON, FOREIGN KEY(jail) REFERENCES jails(name) );
CREATE TABLE bips(ip TEXT NOT NULL, jail TEXT NOT NULL, timeofban INTEGER NOT NULL, bantime INTEGER NOT NULL, bancount INTEGER NOT NULL default 1, data JSON, PRIMARY KEY(ip, jail), FOREIGN KEY(jail) REFERENCES jails(name) );
1
  • 2
    It's SELECT jail,ip,timeofban FROM bans now (2020 oct), if you want to skip data field which contains the full log matched.
    – grin
    Oct 26, 2020 at 21:27
15

To view the complete line of iptables:

sudo iptables -L -n | awk '$1=="REJECT" && $4!="0.0.0.0/0"'

To view only the IP address:

sudo iptables -L -n | awk '$1=="REJECT" && $4!="0.0.0.0/0" {print $4}'

You can change "REJECT" by "DROP", depending of your case.

14

There is the banned command (v0.11.2):

fail2ban-client banned

Sample output:

[{'sshd': []}, {'apache-badbots': []}, {'apache-auth': ['XXX.24.23.164', 'XXX.155.205.108', 'XXX.62.130.158']}]

3
  • 4
    I get the following error: [8760]: ERROR NOK: ('Invalid command',) Invalid command
    – Pathros
    Feb 7, 2021 at 18:10
  • 1
    Maybe you're using an older version. I checked it with v0.11.2.
    – Veles
    Feb 8, 2021 at 3:20
  • 2
    I tried with v0.11.1 and got invalid command also, so it seems that such command was introduced in v0.11.2
    – DarkCygnus
    Oct 28, 2021 at 19:53
8

Just an FYI:

  • "Total banned" are the total IPs that have been banned for that jail (and probably have been unbanned).
  • "Currently banned" are the ONLY IPs that are currently banned for that jail (and the IP list confirms this).

Hope that helps.

5

if you want to see the list of banned IP with their timeout ( timeout expires they are removed from the banned pool ) you can use:

ipset list
4
  • Why is this not giving any output? I'm sure there are IPs currently banned.
    – Sam Sirry
    Mar 1, 2020 at 17:40
  • 1
    I think there could be a lot of reasons for this. If its completely empty not showing headers like "Name: f2b-sshd" maybe not registering and maybe fail2ban is working with iptables rules directly instead of firewalld. on a clean centos7 w/ recent kernel fail2ban should talk to firewalld. rebooting fail2ban while doing tailf /var/log/fail2ban.log could show you the rules going on being flushed. I know ipset list needs the latest kernel installed as well. The ones before the recent updates from Linus
    – gstlouis
    Mar 2, 2020 at 18:44
  • In my installation fail2ban is working with iptables. This is probably the reason. Thank you for following up. I learned to use sudo iptables -L to see the bans that are in a separate chain.
    – Sam Sirry
    Mar 4, 2020 at 14:58
  • 1
    Ya but forget you can use fail2ban-client status sshd to show those bans, pipe in grey and you can id banned ips. Have fun
    – gstlouis
    Mar 4, 2020 at 15:10
5

'Just finished updating my config's to deal with an attack on ssh.

This is how I see the banned IP's with their expire times, and verify that the bans are in-place. I'm using Fail2Ban v0.11.2 on Debian 11.2.

> fail2ban-client get sshd banip --with-time
45.9.20.73  2022-02-21 23:56:35 + 3456000 = 2022-04-02 23:56:35

> iptables -L f2b-sshd
Chain f2b-sshd (1 references)
target     prot opt source               destination         
REJECT     all  --  45.9.20.73           anywhere             reject-with icmp-port-unreachable
RETURN     all  --  anywhere             anywhere
4

This will show what is currently banned (REJECT) in the Chain fail2ban-ssh portion of iptables.

sudo iptables -L fail2ban-ssh -v -n
1
  • 2
    iptables: No chain/target/match by that name.
    – Pathros
    Sep 2, 2021 at 17:30
4

Grouping by IP address:

awk '($(NF-1) = /Ban/){print $NF}' /var/log/fail2ban.log | sort | uniq -c | sort -n

Note: the variable NF equals the number of fields in each row of the logfile. So $NF is the value of the last field.

Sample output:

...
  4 XXX.124.81.130
  5 XXX.248.175.246
  8 XXX.29.45.142

Visit this Link for more detail

3

To add more generic answer:

Please note that iptables might not be correct answer and might not give you relevant information at all (for original poster it is). It depends on which value for banaction = [action] you are using in your DEFAULT or specific jail definition.

I have many small ARM powered boxes running linux but kernel does not have all relevant iptables modules available, so iptables will not work in that case.

*BSD might not have iptables at all and use use something like pf instead.

On my ARM boxes I am using route for blocking. It adds invalid route for banned IPs and therefore return packets are undeliverable and IP is essentially blocked. Works very well. In that case you can check banned IPs by using:

# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
# normal routing entries
0.0.0.0         192.168.0.1     0.0.0.0         UG    0      0        0 eth0
192.168.0.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0
# banned IPs (no gateway, no iface)
223.96.95.85    -               255.255.255.255 !H    0      -        0 -

You have many options for banning. And therefore many options to check ban list. Which one to use depends on your platform and preference. There are many pre-configured configuration files in: /etc/fail2ban/action.d/ to choose from.

3

# fail2ban-client has some useful commands.

fail2ban-client start       # Starts the Fail2ban server and jails.
fail2ban-client reload      # Reloads Fail2ban’s configuration files.
fail2ban-client reload JAIL # Replaces JAIL with the name of a Fail2ban jail; this will reload the jail.
fail2ban-client stop        # Terminates the server.
fail2ban-client status      # Will show the status of the server, and enable jails.
fail2ban-client status JAIL # Will show the status of the jail, including any currently-banned IPs.

See them all at https://www.fail2ban.org/wiki/index.php/Commands

Somebody clever posted this (I don't remember where, not mine) to list all jails in one go:

fail2ban-client status | sed -n 's/,//g;s/.*Jail list://p' | xargs -n1 fail2ban-client status
2

see the database

/var/lib/fail2ban/fail2ban.sqlite3

2
  • 5
    You should explain how that addresses the question.
    – RalfFriedl
    Jan 7, 2020 at 7:04
  • sudo: /var/lib/fail2ban/fail2ban.sqlite3: command not found
    – Pathros
    Sep 2, 2021 at 17:29
1

Can you try the following

while true; do
  # Clear the terminal
  clear

  # Display static header
  echo -e "\e[1;44m        List of Banned IPs         \n\e[0m"

  # Fetch dynamic info
  IPs=$(sudo fail2ban-client status sshd | grep "Banned IP list:" | sed 's/.*Banned IP list://g' | tr -s ' ' '\n')
  current_count=$(echo -e "$IPs" | wc -l)
  total_count=$(grep "Ban " /var/log/fail2ban.log | wc -l)

  # Display Currently Banned IPs and Total Banned to Date
  echo -e "\e[1;32m   Currently Banned IPs: $current_count\e[0m"
  echo -e "\e[1;32m   Total Banned to Date: $total_count\n\e[0m"
  

  # Display table headers
  echo -e " ┌─────┬──────────────────────┬───────────┐"
  echo -e " │ No. │          IP          │  Unban In │"
  echo -e " ├─────┼──────────────────────┼───────────┤"

  # Parse each IP and look up its ban time in the log file
  echo -e "$IPs" | awk '{print NR, $1}' | while read -r num ip; do
    ban_time=$(grep "$ip" /var/log/fail2ban.log | tail -1 | awk '{print $1 " " $2}' | xargs -I {} date -d {} +%s)
    current_time=$(date +%s)
    time_left=$(( 3600 - (current_time - ban_time) ))
    mins=$(( (time_left + 59) / 60 ))
    [ $mins -eq 0 ] && mins=1
    printf " │ %2d  │     %-15s  │%4d mins  │\n" "$num" "$ip" "$mins"
    
  done
echo " └─────┴──────────────────────┴───────────┘"  # Line below each IP
  counter=0
  server_info=""

  for i in {59..0}; do
    if ((counter % 10 == 0)); then
      cpu_temp=$(cat /sys/class/thermal/thermal_zone0/temp 2>/dev/null)
      cpu_load=$(uptime | awk -F 'load average: ' '{print $2}')
      disk_usage=$(df -h / | awk 'NR==2 {print $5}')
      memory_usage=$(free -m | awk 'NR==2 {print $3 "/" $2 "MB"}')
      logged_users=$(who | awk '{print $1}' | sort -u | wc -l)
      logged_users_list=$(who | awk '{print $1}' | sort | uniq | tr '\n' ', ' | sed 's/,$//')
      cpu_temp_c=$(awk -v temp="$cpu_temp" 'BEGIN{printf "%.1f", temp / 1000}')


      server_info="\e[1;32m\n - Server Info:\n - CPU Load : $cpu_load\n - CPU Temp : $cpu_temp_c °C\n - Disk Usage : $disk_usage\n - Memory Usage : $memory_usage\n - Count of unique logged-in users : $logged_users\n - Logged in as : $logged_users_list\n\e[0m"
    fi

    echo -e "\e[1;32m  Current Time: $(date '+%H:%M:%S')\e[0m"
    echo " ──────────────────────────────────────────"
    echo -e "$server_info"
    echo " ──────────────────────────────────────────"
    counter=$((counter + 1))
    sleep 1

    # Clear the lines for server info and time, but no more than that
    echo -ne "\033[2K\033[A\033[2K\033[A\033[2K\033[A\033[2K\033[A\033[2K\033[A\033[2K\033[A\033[2K\033[A\033[2K\033[A\033[2K\033[A\033[2K\033[A\033[2K\033[A\033[2K\033[A"
  done
done
0

Show usernames (attempted from banned sources) in order of frequency:

sqlite3 /var/lib/fail2ban/fail2ban.sqlite3 "select json_extract(data,'$.users') from bips" | cut -d\' -f 2 | sort | uniq -c | sort -nk 1

sample output

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .