Firewalld & Fail2Ban
- 🐧 Linux Command Line
Ansible Playbook
Core
Disable IPTABLES and IP6TABLES
systemctl stop iptables
systemctl disable iptables
systemctl stop ip6tables
systemctl disable ip6tables
Enable Firewalld and Add Basic Rules
systemctl start firewalld
firewall-cmd --permanent --zone=public --set-target=DROP
firewall-cmd --zone=public --add-port=22/tcp --permanent
firewall-cmd --zone=public --add-port=80/tcp --permanent
firewall-cmd --zone=public --add-port=443/tcp --permanent
firewall-cmd --reload
systemctl enable firewalld
# View all rules
firewall-cmd --list-all
Install Fail2Ban
# dnf install -y https://rpms.remirepo.net/enterprise/remi-release-9.rpm
dnf install -y fail2ban GeoIP GeoIP-data python3-inotify
Create Nginx 4xx/5xx Filter
/etc/fail2ban/filter.d/nginx-4xx-5xx.conf
[Definition]
failregex = ^<HOST>.*"(GET|POST|HEAD|PUT|DELETE|OPTIONS|PATCH).*" (4\d{2}|5\d{2}) .*$
ignoreregex =.*(robots.txt|favicon.ico)
Create Fail2Ban Jail
/etc/fail2ban/jail.local
[DEFAULT]
banaction = firewallcmd-rich-rules[actiontype=<multiport>]
banaction_allports = firewallcmd-rich-rules[actiontype=<allports>]
ignoreip = 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
action = sendmail-geoip-lines
dest = <receiver@domain.com>
sender = <sender@your-domain.com>
destemail =
[nginx-4xx-5xx]
enabled = true
logpath = /var/log/nginx/access_for_fail2ban.log
filter = nginx-4xx-5xx
action = firewallcmd-rich-rules[name=nginx-4xx-5xx, port="80,443", protocol=tcp]
sendmail-geoip-lines
findtime = 10
maxretry = 20
bantime = 3600
bantime.increment = true
bantime.rndtime = 300
bantime.maxtime = 86400
bantime.overalljails = true
[sshd]
enabled = true
findtime = 3600
maxretry = 5
bantime = 7200
Configure Sendmail
/etc/fail2ban/action.d/sendmail-common.local
[Definition]
actionstart =
actionstop =
actioncheck =
actionban =
actionunban =
[Init]
mailcmd = /usr/sbin/sendmail -f "<sender>" "<dest>"
dest = <receiver@domain.com>
sender = <sender@your-domain.com>
sendername = <server-name>-Fail2Ban
Configure Sendmail GeoIP Template
/etc/fail2ban/action.d/sendmail-geoip-lines.conf
# Fail2Ban configuration file
#
# Author: Viktor Szépe
#
#
[INCLUDES]
before = sendmail-common.conf
helpers-common.conf
[Definition]
# bypass ban/unban for restored tickets
norestored = 1
# Option: actionban
# Notes.: Command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# You need to install geoiplookup and the GeoLite or GeoIP databases.
# (geoip-bin and geoip-database in Debian)
# The host command comes from bind9-host package.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = ( printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from <fq-hostname>
Date: `LC_ALL=C date +"%%a, %%d %%h %%Y %%T %%z"`
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
The IP <ip> has just been banned by Fail2Ban after
<failures> attempts against <name>.\n\n
Country:`geoiplookup -f /usr/share/GeoIP/GeoIP.dat "<ip>" | cut -d':' -f2-`
hostname: <ip-host>\n\n
Information from ipinfo.io:\n
`curl -s "https://ipinfo.io/<ip>" | jq '.'`\n\n
Information from ip-api.com:\n
`curl -s "http://ip-api.com/json/<ip>" | jq '.'`\n\n
Lines containing failures of <ip> (max <grepmax>)\n";
%(_grep_logs)s;
printf %%b "\n
Regards,\n
Fail2Ban" ) | <mailcmd>
[Init]
# Default name of the chain
#
name = default
# Path to the log files which contain relevant lines for the abuser IP
#
logpath = /dev/null
# Number of log lines to include in the email
#
#grepmax = 1000
#grepopts = -m <grepmax>
Start Fail2Ban
systemctl enable --now fail2ban
Extended
Useful Fail2Ban Commands
# check status
fail2ban-client status
fail2ban-client status nginx-4xx-5xx
# view log
tail -f /var/log/fail2ban.log
# reload after config change
fail2ban-client reload
# ban IP manually
fail2ban-client set sshd banip <ip-address>
# unban IP
fail2ban-client set nginx-4xx-5xx unbanip <ip-address>
Fail2ban Official Documentation
https://github.com/fail2ban/fail2ban/wiki/Best-practice
Find failed ssh login attempts
tail -f /var/log/secure
grep 'sshd.*Failed password for' /var/log/secure
fail2ban.yml
- name: Install and Configure Fail2Ban
hosts: all
remote_user: root
vars:
email_dest: "receiver@domain.com"
email_sender: "sender@your-domain.com"
fail2ban_ignore_ip: "10.0.0.0/8 172.16.0.0/12 192.168.0.0/16"
nginx_log_path: "/var/log/nginx/access_for_fail2ban.log"
tasks:
- name: Install Remi GPG key
rpm_key:
state: present
key: https://rpms.remirepo.net/RPM-GPG-KEY-remi
- name: Install Remi repository
dnf:
name: https://rpms.remirepo.net/enterprise/remi-release-9.rpm
state: present
disable_gpg_check: true
- name: Install required packages
dnf:
name:
- fail2ban
- GeoIP
- GeoIP-data
- python3-inotify
state: present
- name: Deploy Fail2Ban filter for nginx 4xx/5xx
copy:
dest: "/etc/fail2ban/filter.d/nginx-4xx-5xx.conf"
owner: "root"
group: "root"
mode: "0644"
content: |
[Definition]
failregex = ^<HOST>.*"(GET|POST|HEAD|PUT|DELETE|OPTIONS|PATCH).*" (4\d{2}|5\d{2}) .*$
ignoreregex =.*(robots.txt|favicon.ico)
- name: Deploy Fail2Ban jail configuration
copy:
dest: "/etc/fail2ban/jail.local"
owner: "root"
group: "root"
mode: "0644"
content: |
[DEFAULT]
banaction = firewallcmd-rich-rules[actiontype=<multiport>]
banaction_allports = firewallcmd-rich-rules[actiontype=<allports>]
ignoreip = {{ fail2ban_ignore_ip }}
action = sendmail-geoip-lines
sender = {{ email_sender }}
dest = {{ email_dest }}
destemail =
[nginx-4xx-5xx]
enabled = true
logpath = {{ nginx_log_path }}
filter = nginx-4xx-5xx
action = firewallcmd-rich-rules[name=nginx-4xx-5xx, port="80,443", protocol=tcp]
sendmail-geoip-lines
findtime = 10
maxretry = 20
bantime = 3600
bantime.increment = true
bantime.rndtime = 300
bantime.maxtime = 86400
bantime.overalljails = true
[sshd]
enabled = true
findtime = 3600
maxretry = 5
bantime = 7200
- name: Deploy Fail2Ban sendmail-geoip-lines action
copy:
dest: "/etc/fail2ban/action.d/sendmail-geoip-lines.conf"
owner: "root"
group: "root"
mode: "0644"
content: |
[INCLUDES]
before = sendmail-common.conf
helpers-common.conf
[Definition]
norestored = 1
actionban = ( printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from <fq-hostname>
Date: `LC_ALL=C date +"%%a, %%d %%h %%Y %%T %%z"`
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
The IP <ip> has just been banned by Fail2Ban after
<failures> attempts against <name>.\n\n
Country:`geoiplookup -f /usr/share/GeoIP/GeoIP.dat "<ip>" | cut -d':' -f2-`
hostname: <ip-host>\n\n
Information from ipinfo.io:\n
`curl -s "https://ipinfo.io/<ip>" | jq '.'`\n\n
Information from ip-api.com:\n
`curl -s "http://ip-api.com/json/<ip>" | jq '.'`\n\n
Lines containing failures of <ip> (max <grepmax>)\n";
%(_grep_logs)s;
printf %%b "\n
Regards,\n
Fail2Ban" ) | <mailcmd>
[Init]
name = default
logpath = /dev/null
- name: Deploy Fail2Ban sendmail-common configuration
copy:
dest: "/etc/fail2ban/action.d/sendmail-common.local"
owner: "root"
group: "root"
mode: "0644"
content: |
[Definition]
actionstart =
actionstop =
actioncheck =
actionban =
actionunban =
[Init]
mailcmd = /usr/sbin/sendmail -f "<sender>" "<dest>"
dest = {{ email_dest }}
sender = {{ email_sender }}
sendername = Server1-Fail2Ban
- name: Enable and start Fail2Ban
systemd:
name: fail2ban
enabled: true
state: started