User Tools

Site Tools


computing:fail2ban

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
computing:fail2ban [2019/11/03 01:41] oemb1905computing:fail2ban [2026/03/22 21:31] (current) oemb1905
Line 1: Line 1:
 +-------------------------------------------
 +  * **fail2ban** 
 +  * **Jonathan Haack**
 +  * **Haack's Networking**
 +  * **support@haacksnetworking.org** 
  
 +-------------------------------------------
  
 +//fail2ban//      
  
 +-------------------------------------------
 +
 +This tutorial is designed to help you install fail2ban and get a basic set of configurations in place. My logic is as follows:
 +
 +//My defaults give a very small 1 hour punishment for first time offense of 3 violations of any jail. Repeat offenders, however, get immediate life-bans. So, the default is very tolerant and the extreme is essentially for life punishment. Using this framework, you override individual services with ''maxretry = xx'' to fit that service's tolerance level. For example, email and web services get a value of 5-10, while ssh might get 1-3. For floods, bot attacks, etc., you will also need to adjust ''findtime = yy'' to fit the interval.//
 +
 +You will need to change this recipe to fit your needs. At the same time, there are certain aspects in this tutorial, that are just "always best to do" kind of things, so hopefully you recognize those! Be careful, and don't f2b yourself out of your instance too many times ;)
  
   sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local   sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
Line 11: Line 25:
   <action = %(action_mwl)s>   <action = %(action_mwl)s>
  
-If you attempt to log in via ssh and fail within any 4 hour period 4 different timesthen you are immediately blocked.+Default policy targets the middle in this example. Later, jails like sshd or recidive are stricter and get maxretry = 1 overrideswhere apache or public servers are overridden to maxretry = 5 for more tolerance:
  
   [DEFAULT]   [DEFAULT]
-  bantime 1w +  bantime 1h 
-  findtime 240m +  findtime 30d  
-  maxretry = 4+  maxretry = 3
  
-The recidive filter below states that the last 3 weeks will be reviewed and if the ip address in question was banned more for 2 or more of those weeks, then the stricter ban of 20 weeks takes effect.  If you plan to review 3 weeks of information, with up to three violations each for a week, then you probably need at least 21 days of data.  I rounded to 30 for slightly more granularity. +Increase db purge age so as to retain enough for the jail parameters:
  
-  [recidive]+  sudo nano /etc/fail2ban/fail2ban.conf 
 +  <dbpurgeage = 30d>   
 + 
 +Add ''enabled = true'' to desired jails. Here's an example of me setting ssh to something very strict. Only do this in tightly monitored and low access scenarios, or you will have a lot of false positives from user error: 
 + 
 +  [sshd]
   enabled = true   enabled = true
-  logpath  /var/log/fail2ban.log +  port    ssh 
-  banaction = %(banaction_allports)s +  logpath = %(sshd_log)s 
-  bantime  20w +  backend %(sshd_backend)s 
-  findtime 3w+  maxretry 3
  
-In order for this to workthe database purge parameter needs to be adjusted to be greater than or equal to what you specify for the find time in recidive.+The repeat offender, or recidivist jail, is listed under ''[recidive]'' and I give it particular attention. In a tightly controlled environmentif someone has banged once on ssh invalidly and does it again, they have no reason to bang again indefinitely. Again, in larger environments, it might not be possible to enforce maxretry = 1.
  
-  sudo nano /etc/fail2ban/fail2ban.conf +  [recidive] 
-  <dbpurgeage 30d>  +  enabled   = true 
 +  logpath   /var/log/fail2ban.log 
 +  banaction iptables-allports[blocktype=DROP] 
 +  bantime   = 100y 
 +  maxretry  = 1 
 +   
 +Here's an example of keeping postfix more tolerant, so that you don't get false positives on more common services while users are setting up stuff or accessing public facing resources:
  
-Once your configuration changes are done, restart the service, and then check the logs to verify functionality and debug as needed.  Verify what fail2ban has done to your iptables in order to enact the policies above.+  [apache-auth] 
 +  enabled  = true 
 +  port     = http,https 
 +  logpath  = %(apache_error_log)s 
 +  maxretry = 5 #increased to 5 
 + 
 +Once you activate desired jails, restart service or reload config:
      
-  sudo systemctl restart fail2ban.service +  sudo systemctl restart fail2ban.service  
-  sudo tail -/var/log/fail2ban.log +  sudo fail2ban-client reload  
-  sudo iptables -L f2b-sshd+ 
 +Hope this helps!  Oh yeah ... here is how to remove a false positive! 
 + 
 +  fail2ban-client set ssh unbanip 10.xx.15x.12x 
 +  fail2ban-client unban --all 
 + 
 +Another method that does more than individual services, and instead zaps all records: 
 + 
 +  sudo systemctl stop fail2ban 
 +  sudo truncate -s 0 /var/log/fail2ban.log 
 +  sudo rm /var/lib/fail2ban/fail2ban.sqlite3 
 +  sudo systemctl restart fail2ban 
 + 
 +Systemd log issues. Change the sshd jail as follows 
 + 
 +  sudo nano /etc/fail2ban/jail.local 
 +  backend = systemd 
 +  #backend = %(sshd_backend)s 
 +   
 +Some recommend adding backend = systemd into jail.conf, but I've found that does nothing. The error over ipv6 not being set and using auto can be removed as follows: 
 +   
 +  sudo nano /etc/fail2ban/fail2ban.conf  
 +  'allowipv6 = auto' 
 +   
 +To check a particular jail's statistics: 
 + 
 +  sudo fail2ban-client status recidive 
 +   
 +Install rpl and use it to change default banaction to DROP: 
 + 
 +  sudo apt install rpl 
 +  sudo rpl -q 'banaction = iptables-multiport' 'banaction = iptables-multiport[blocktype=DROP]' /etc/fail2ban/jail.local &&  
 +  sudo rpl -q 'banaction_allports = iptables-allports' 'banaction_allports = iptables-allports[blocktype=DROP]' /etc/fail2ban/jail.local &&  
 +  sudo fail2ban-client reload 
 +   
 +Small script / one-liner to avoid remembering iptables flags for jails I monitor a lot: 
 + 
 +  cat << 'EOF' > /usr/local/bin/list-recidive-ips.sh 
 +  #!/bin/bash 
 +  iptables -L f2b-recidive -v -n 
 +  EOF 
 +  chmod 750 /usr/local/bin/list-recidive-ips.sh 
 + 
 +Change all reject rules to drop for a given iptables fail2ban managed jail/entry: 
 + 
 +  sudo iptables -L f2b-recidive -n --line-numbers | grep REJECT | awk '{print $1}' | sort -r | xargs -I {} sudo iptables -R f2b-recidive {} -j DROP 
 +   
 +Script, ''fail2ban-stats.sh'', which queries all jails for historical and current bans: 
 + 
 +<code> 
 +sudo cat > /usr/local/bin/fail2ban-stats.sh << 'EOF' 
 +#!/bin/bash 
 +# /usr/local/bin/fail2ban-stats.sh 
 + 
 +#header 
 +echo "Jail                          | Banned now | Total failed | Total banned | Actions taken" 
 +echo "------------------------------|------------|--------------|--------------|--------------" 
 + 
 +# Get list of jails 
 +jails=$(sudo fail2ban-client status | grep "Jail list" | sed 's/.*Jail list://' | tr -d ' ' | tr ',' ' ') 
 + 
 +for jail in $jails; do 
 +  stats=$(sudo fail2ban-client status "$jail" 2>/dev/null) 
 +  if [ -z "$stats" ]; then 
 +    printf "%-30s | inactive or error\n" "$jail" 
 +    continue 
 +  fi 
 + 
 +  banned=$(echo "$stats" | awk '/Currently banned:/ {print $NF}' || echo 0) 
 +  failed=$(echo "$stats" | awk '/Total failed:/ {print $NF}' || echo 0) 
 +  tbanned=$(echo "$stats" | awk '/Total banned:/ {print $NF}' || echo 0) 
 +  actions=$(echo "$stats" | awk '/Actions executed:/ {print $NF}' || echo 0)   
 + 
 +  printf "%-30s | %10s | %12s | %12s | %12s\n" "$jail" "$banned" "$failed" "$tbanned" "$actions" 
 +done 
 +EOF 
 + 
 +sudo chmod 750 /usr/local/bin/fail2ban-stats.sh 
 +</code> 
 + 
 +A small script that I wrote before I knew how to write systemd units that checks and restarts the service: 
 + 
 +<code> 
 +sudo cat > /usr/local/bin/fail2ban-restart.sh << 'EOF' 
 +#!/bin/bash 
 +RESTART="/bin/systemctl restart fail2ban.service" 
 +STATUS="/bin/systemctl status fail2ban.service" 
 +SERVICE="fail2ban.service" 
 +LOGFILE="/home/logs/fail2ban.log" 
 +if $STATUS | grep -q -E 'failed|dead|inactive'; then 
 +    echo "[$(date '+%Y-%m-%d %H:%M:%S')] Jonathan, fail2ban failed → restarting" >> "$LOGFILE" 
 +    echo "----------------------------------------" >> "$LOGFILE" 
 +    $RESTART >> "$LOGFILE" 2>&
 +    echo "----------------------------------------" >> "$LOGFILE" 
 +    # Send email with the log content 
 +    mail -s "[fail2ban-restart] $(hostname -f) - $(date '+%Y-%m-%d %H:%M:%S')"
 +        fail2ban@haacksnetworking.org < "$LOGFILE" 
 +else 
 +    # Optional: log successful check (uncomment if desired) 
 +    # echo "[$(date '+%Y-%m-%d %H:%M:%S')] fail2ban is running OK" >> "$LOGFILE" 
 +    exit 0 
 +fi 
 +exit 0 
 +EOF 
 +sudo chmod 750 /usr/local/bin/fail2ban-restart.sh 
 +</code> 
 + 
 +Here is another script that sends the fail2ban-stats report to an email of one's choosing: 
 + 
 +<code> 
 +sudo cat > /usr/local/bin/fail2ban-report.sh << 'EOF' 
 +#!/bin/bash 
 +DATE=$(date +"%Y%m%d-%H:%M:%S"
 +LOG="/home/logs/fail2ban-report.log" 
 + 
 +# create log (touch is idempotent) 
 +touch "$LOG" 
 + 
 +# generate report 
 +echo "Jonathan, at $(date), your fail2ban stats for $(hostname -f) were as follows:" > "$LOG" 
 +/bin/bash /usr/local/bin/fail2ban-stats.sh >> "$LOG" 
 + 
 +#mail log 
 +mail -s "[$(hostname -f)]-fail2ban-stats-$(date)]" email@haacksnetworking.org < "$LOG" 
 +rm "$LOG" 
 +EOF 
 + 
 +mkdir -p /home/logs 
 +sudo chmod 750 /usr/local/bin/fail2ban-report.sh 
 +</code> 
 + 
 +Run it hourly: 
 + 
 +  0 * * * * /usr/bin/flock --nonblock /tmp/f2b-report.lock /bin/bash /usr/local/bin/fail2ban-report.sh > /dev/null 2>&
 + 
 +Create a custom jail for postfix floods, for example: 
 + 
 +<code> 
 +cat << 'EOF' >> /etc/fail2ban/jail.local 
 + 
 +[postfix-flood-attack] 
 +enabled  = true 
 +maxretry = 1 
 +filter   = postfix-flood-attack 
 +action   = iptables-multiport[name=postfix, port="http,https,smtp,submission,pop3,pop3s,imap,imaps,sieve", protocol=tcp] 
 +logpath  = /var/log/mail.log 
 + 
 +EOF 
 + 
 +# 2. Create the filter definition 
 +cat << 'EOF' > /etc/fail2ban/filter.d/postfix-flood-attack.conf 
 +[Definition] 
 +failregex = lost connection after AUTH from (.*)\[<HOST>\] 
 +ignoreregex = 
 +EOF
  
-Hope this helps!+# Set permissions and reload the jail 
 +chmod 750 /etc/fail2ban/jail.local /etc/fail2ban/filter.d/postfix-flood-attack.conf 
 +systemctl restart fail2ban.service 
 +</code>
  
- --- //[[oemb1905@jonathanhaack.com|oemb1905]] 2019/11/02 19:20//+ --- //[[alerts@haacksnetworking.org|oemb1905]] 2026/03/22 20:44//
computing/fail2ban.1572745303.txt.gz · Last modified: by oemb1905