Filters & actions
fail2ban action library
Every action that ships with fail2ban 1.1.1: what it does, which parameters it takes and how to use it in a jail. Firewall actions block the IP; others notify you or report the attacker.
A fail2ban action is a file in /etc/fail2ban/action.d/ that defines the commands run when a jail bans or unbans an IP. Firewall actions such as nftables, iptables-multiport, ufw and firewallcmd-rich-rules block the address; other actions send email (sendmail-whois), chat notifications (apprise) or abuse reports (abuseipdb). fail2ban 1.1.1 ships 66 of them. A jail can run several actions at once.
ls /etc/fail2ban/action.d/
sudo fail2ban-client get sshd actionsbanaction vs action vs extra actions#
| Setting | Purpose | Example |
|---|---|---|
banaction |
The firewall action used by every jail through the shortcuts | banaction = nftables |
banaction_allports |
Firewall action for all-ports bans (recidive) |
banaction_allports = nftables[type=allports] |
action |
The full list of actions for a jail; by default %(action_)s = banaction with the jail's ports |
action = %(action_mw)s |
| Extra actions | Add more lines to action |
ban + AbuseIPDB report + Telegram |
Most setups only change banaction (choosing a banaction) and maybe action for email alerts. Several actions look like this:
[sshd]
enabled = true
action = %(action_)s
abuseipdb[abuseipdb_apikey="YOUR_KEY", abuseipdb_category="18,22"]
apprise[config="/etc/fail2ban/apprise.conf"]Parameters go in square brackets after the action name and override the defaults from the action's [Init] section. Each action's entry below lists its parameters.
Action categories#
Firewall (ban) actions#
These block traffic from the banned IP. Use one that matches the firewall you actually run.
Others: iptables-allports, iptables-new, iptables-multiport-log, nftables-allports, nftables-multiport, firewallcmd-allports, firewallcmd-multiport, firewallcmd-new, shorewall, shorewall-ipset-proto6, pf (BSD/macOS), ipfw, bsd-ipfw, npf, ipfilter, osx-afctl, osx-ipfw, apf, csf, hostsdeny, mikrotik (RouterOS address lists), netscaler, nginx-block-map, nsupdate (DNS blocklist zone), symbiosis-blacklist-allports, cloudflare (legacy global API key).
Notification actions#
Also: sendmail, sendmail-buffered, sendmail-whois-matches, sendmail-whois-ipmatches, sendmail-whois-ipjailmatches, sendmail-geoip-lines, and the mail, mail-whois, mail-whois-lines, mail-buffered family for mta = mail. Setup and testing: email alerts.
Reporting actions#
Share attacker IPs with blocklist services. Use them only for jails where false positives are unlikely, since you're reporting someone to the world.
- abuseipdb: report to AbuseIPDB (needs an API key; see the AbuseIPDB guide)
- blocklist_de: report to blocklist.de
- dshield, mynetwatchman, ipthreat: other reporting services
- xarf-login-attack, complain: email the abuse contact from whois
Testing and helper files#
- dummy: writes bans to a file instead of touching the firewall; ideal for testing a new jail safely
helpers-common,sendmail-common,mail-whois-common,firewallcmd-common: shared definitions included by other actions, not used directly
Customize an action#
Don't edit files in action.d/; package upgrades replace them.
- Change a parameter for one jail: brackets in the jail, e.g.
banaction = nftables[blocktype=drop]. - Change it everywhere: create
action.d/<name>.localwith the changed[Init]or[Definition]keys only. It's read after the.conf. - New behavior (a webhook, an API call, your own script): write a new action, see custom actions.
Check what a jail is running#
$ sudo fail2ban-client get sshd actions
The jail sshd has the following actions:
nftablesTo see the exact commands an action will run, after all parameters are filled in:
sudo fail2ban-client get sshd action nftables actionbanAll actions#
Search by name or description. Each name opens the action's page with its commands, parameters and usage.
| Action | Type | What it does |
|---|---|---|
abuseipdb | Report | reports each banned IP to AbuseIPDB using your API key |
apf | Firewall | bans through APF (Advanced Policy Firewall) with apf --deny |
apprise | Notify | sends a ban notification to any of Apprise's 100+ services (Telegram, Discord, Slack, ntfy…) |
blocklist_de | Report | reports banned IPs to blocklist.de by e-mail |
bsd-ipfw | Firewall | bans with ipfw tables on FreeBSD |
cloudflare-token | Firewall | blocks the IP at Cloudflare's edge with an API token (IP access rules) |
cloudflare | Firewall | blocks the IP at Cloudflare's edge using the legacy global API key |
complain | Report | e-mails an abuse complaint to the addresses in the IP's whois record |
csf | Firewall | bans through ConfigServer Security & Firewall (csf -d) |
dshield | Report | submits attack reports to DShield (SANS Internet Storm Center) |
dummy | Testing | writes bans to a text file instead of a firewall; useful for testing jails safely |
firewallcmd-allports | Firewall | bans on all ports with firewalld direct rules |
firewallcmd-common | Include | shared settings included by the other firewallcmd-* actions |
firewallcmd-ipset | Firewall | bans with an ipset managed through firewalld (fast with many bans) |
firewallcmd-multiport | Firewall | bans on the jail's ports with firewalld direct rules |
firewallcmd-new | Firewall | bans new connections on the jail's ports with firewalld direct rules |
firewallcmd-rich-logging | Firewall | bans with firewalld rich rules and logs the dropped packets |
firewallcmd-rich-rules | Firewall | bans with firewalld rich rules (the usual choice on Fedora, RHEL, Rocky, AlmaLinux) |
helpers-common | Include | helper commands (log grepping) shared by the mail actions |
hostsdeny | Ban | adds the IP to /etc/hosts.deny (TCP wrappers) instead of the firewall |
ipfilter | Firewall | bans with IPFilter (ipf) on NetBSD/Solaris |
ipfw | Firewall | bans with ipfw rules on FreeBSD |
iptables-allports | Firewall | old name for iptables[type=allports]: blocks every port for the banned IP |
iptables-ipset-proto4 | Firewall | ipset ban for very old ipset v4 systems |
iptables-ipset-proto6-allports | Firewall | iptables + ipset ban on all ports |
iptables-ipset-proto6 | Firewall | iptables + ipset ban on the jail's ports |
iptables-ipset | Firewall | iptables with an ipset set: one rule, any number of banned IPs (fast) |
iptables-multiport-log | Firewall | iptables multiport ban that also logs dropped packets |
iptables-multiport | Firewall | old name for iptables[type=multiport]: blocks the jail's ports |
iptables-new | Firewall | iptables ban that only matches new connections |
iptables-xt_recent-echo | Firewall | bans with the xt_recent kernel module (no rule reload per ban) |
iptables | Firewall | the base iptables action (types oneport, multiport, allports); default on many older systems |
ipthreat | Report | reports banned IPs to ipthreat.net |
mail-buffered | Notify | e-mails a summary after a number of bans instead of one mail per ban |
mail-whois-common | Include | shared settings for the mail-whois actions |
mail-whois-lines | Notify | e-mails each ban with whois data and the matching log lines (mail command) |
mail-whois | Notify | e-mails each ban with whois data (mail command) |
mail | Notify | e-mails a short notice for each ban (mail command) |
mikrotik | Firewall | adds the banned IP to an address list on a MikroTik router over SSH |
mynetwatchman | Report | submits attack reports to myNetWatchman |
netscaler | Firewall | adds banned IPs to a Citrix NetScaler (ADC) dataset |
nftables-allports | Firewall | old name for nftables[type=allports] |
nftables-multiport | Firewall | old name for nftables[type=multiport] |
nftables | Firewall | bans with an nftables set; the default banaction on Debian, Ubuntu and other current distros |
nginx-block-map | Ban | bans inside nginx with a map file, so it also works behind CDNs and proxies |
npf | Firewall | bans with NPF tables on NetBSD |
nsupdate | Ban | publishes banned IPs as DNS records with nsupdate (a DIY DNS blocklist) |
osx-afctl | Firewall | bans with afctl on old macOS Server |
osx-ipfw | Firewall | bans with ipfw on old macOS |
pf | Firewall | bans with pf tables on OpenBSD, FreeBSD and macOS |
route | Firewall | bans with a blackhole/unreachable route instead of a firewall rule |
sendmail-buffered | Notify | e-mails a summary after a number of bans (sendmail) |
sendmail-common | Include | shared settings for the sendmail-* actions |
sendmail-geoip-lines | Notify | e-mails each ban with GeoIP country data and log lines (sendmail) |
sendmail-whois-ipjailmatches | Notify | e-mails each ban with whois data and all matches of the IP in this jail |
sendmail-whois-ipmatches | Notify | e-mails each ban with whois data and all matches of the IP |
sendmail-whois-lines | Notify | e-mails each ban with whois data and the log lines (sendmail); used by action_mwl |
sendmail-whois-matches | Notify | e-mails each ban with whois data and the matches that triggered it |
sendmail-whois | Notify | e-mails each ban with whois data (sendmail); used by action_mw |
sendmail | Notify | e-mails a short notice for each ban (sendmail) |
shorewall-ipset-proto6 | Firewall | bans with Shorewall using an ipset |
shorewall | Firewall | bans through Shorewall's blacklist |
symbiosis-blacklist-allports | Firewall | bans with the Bytemark Symbiosis firewall |
ufw | Firewall | bans by inserting ufw deny rules (needs ufw enabled) |
xarf-login-attack | Report | e-mails an X-ARF login-attack report to the IP owner's abuse contact |
smtp | Notify | Python action that e-mails ban notices over SMTP directly (no local MTA needed) |
Firewall and ban actions##
apf
action.d/apf.conf bans through APF (Advanced Policy Firewall) with apf --deny.
Commands and parameters
apf --deny <ip> "banned by Fail2Ban <name>"apf --remove <ip>| Parameter | Default |
|---|---|
name | default |
bsd-ipfw
action.d/bsd-ipfw.conf bans with ipfw tables on FreeBSD.
Commands and parameters
ipfw show | fgrep -c -m 1 -s 'table(<table>)' > /dev/null 2>&1 || (
num=$(ipfw show | awk 'BEGIN { b = <lowest_rule_num> } { if ($1 == b) { b = $1 + 1 } } END { print b }');
ipfw -q add "$num" <blocktype> <block> from table\(<table>\) to me <port>; echo "$num" > "<startstatefile>"
)e=`ipfw table <table> add <ip> 2>&1`; x=$?; [ $x -eq 0 -o "$e" = 'ipfw: setsockopt(IP_FW_TABLE_XADD): File exists' ] || echo "$e" | grep -q "record already exists" || { echo "$e" 1>&2; exit $x; }e=`ipfw table <table> delete <ip> 2>&1`; x=$?; [ $x -eq 0 -o "$e" = 'ipfw: setsockopt(IP_FW_TABLE_XDEL): No such process' ] || echo "$e" | grep -q "record not found" || { echo "$e" 1>&2; exit $x; }| Parameter | Default |
|---|---|
table | 1 |
port | (empty) |
startstatefile | /var/run/fail2ban/ipfw-started-table_<table> |
block | ip |
blocktype | unreach port |
lowest_rule_num | 111 |
cloudflare
action.d/cloudflare.conf blocks the IP at Cloudflare's edge using the legacy global API key. Full setup: this guide.
Commands and parameters
curl -s -o /dev/null -X POST <_cf_api_prms> \
-d '{"mode":"block","configuration":{"target":"<cftarget>","value":"<ip>"},"notes":"Fail2Ban <name>"}' \
<_cf_api_url>id=$(curl -s -X GET <_cf_api_prms> \
"<_cf_api_url>?mode=block&configuration_target=<cftarget>&configuration_value=<ip>&page=1&per_page=1¬es=Fail2Ban%%20<name>" \
| { jq -r '.result[0].id' 2>/dev/null || tr -d '\n' | sed -nE 's/^.*"result"\s*:\s*\[\s*\{\s*"id"\s*:\s*"([^"]+)".*$/\1/p'; })
if [ -z "$id" ]; then echo "<name>: id for <ip> cannot be found"; exit 0; fi;
curl -s -o /dev/null -X DELETE <_cf_api_prms> "<_cf_api_url>/$id"| Parameter | Default |
|---|---|
cftoken | (empty) |
cfuser | (empty) |
cftarget | ip |
cloudflare-token
action.d/cloudflare-token.conf blocks the IP at Cloudflare's edge with an API token (IP access rules). Full setup: this guide.
Commands and parameters
curl -s -X POST "<_cf_api_url>" \
<_cf_api_prms> \
--data '{"mode":"<cfmode>","configuration":{"target":"<cftarget>","value":"<ip>"},"notes":"<notes>"}'id=$(curl -s -G -X GET "<_cf_api_url>" \
--data-urlencode "mode=<cfmode>" --data-urlencode "notes=<notes>" --data-urlencode "configuration.target=<cftarget>" --data-urlencode "configuration.value=<ip>" \
<_cf_api_prms> \
| awk -F"[,:}]" '{for(i=1;i<=NF;i++){if($i~/'id'\042/){print $(i+1)}}}' \
| tr -d ' "' \
| head -n 1)
if [ -z "$id" ]; then echo "<name>: id for <ip> cannot be found using target <cftarget>"; exit 0; fi; \
curl -s -X DELETE "<_cf_api_url>/$id" \
<_cf_api_prms> \
--data '{"cascade": "none"}'| Parameter | Default |
|---|---|
cftarget | ip |
cfmode | block |
notes | Fail2Ban <name> |
csf
action.d/csf.conf bans through ConfigServer Security & Firewall (csf -d).
Commands and parameters
csf --deny <ip> "banned by Fail2Ban <name>"csf --denyrm <ip>| Parameter | Default |
|---|---|
name | default |
firewallcmd-allports
action.d/firewallcmd-allports.conf bans on all ports with firewalld direct rules. Full setup: this guide.
Commands and parameters
firewall-cmd --direct --add-chain <family> filter f2b-<name>
firewall-cmd --direct --add-rule <family> filter f2b-<name> 1000 -j RETURN
firewall-cmd --direct --add-rule <family> filter <chain> 0 -j f2b-<name>firewall-cmd --direct --add-rule <family> filter f2b-<name> 0 -s <ip> -j <blocktype>firewall-cmd --direct --remove-rule <family> filter f2b-<name> 0 -s <ip> -j <blocktype>firewallcmd-ipset
action.d/firewallcmd-ipset.conf bans with an ipset managed through firewalld (fast with many bans). Full setup: this guide.
Commands and parameters
<ipsbackend_<ipsetbackend>/actionstart>
firewall-cmd --direct --add-rule <family> filter <chain> 0 <actiontype> -m set --match-set <ipmset> src -j <blocktype><ipsbackend_<ipsetbackend>/actionban><ipsbackend_<ipsetbackend>/actionunban>| Parameter | Default |
|---|---|
ipsettype | hash:ip |
chain | INPUT_direct |
default-ipsettime | 0 |
ipsettime | 0 |
maxelem | 65536 |
timeout-bantime | $([ "<bantime>" -le 2147483 ] && echo "<bantime>" || echo 0) |
ipsetbackend | ipset |
actiontype | <multiport> |
allports | -p <protocol> |
multiport | -p <protocol> -m multiport --dports <port> |
ipmset | f2b-<name> |
familyopt | (empty) |
firewalld_familyopt | (empty) |
firewallcmd-multiport
action.d/firewallcmd-multiport.conf bans on the jail's ports with firewalld direct rules. Full setup: this guide.
Commands and parameters
firewall-cmd --direct --add-chain <family> filter f2b-<name>
firewall-cmd --direct --add-rule <family> filter f2b-<name> 1000 -j RETURN
firewall-cmd --direct --add-rule <family> filter <chain> 0 -m conntrack --ctstate NEW -p <protocol> -m multiport --dports <port> -j f2b-<name>firewall-cmd --direct --add-rule <family> filter f2b-<name> 0 -s <ip> -j <blocktype>firewall-cmd --direct --remove-rule <family> filter f2b-<name> 0 -s <ip> -j <blocktype>firewallcmd-new
action.d/firewallcmd-new.conf bans new connections on the jail's ports with firewalld direct rules. Full setup: this guide.
Commands and parameters
firewall-cmd --direct --add-chain <family> filter f2b-<name>
firewall-cmd --direct --add-rule <family> filter f2b-<name> 1000 -j RETURN
firewall-cmd --direct --add-rule <family> filter <chain> 0 -m state --state NEW -p <protocol> -m multiport --dports <port> -j f2b-<name>firewall-cmd --direct --add-rule <family> filter f2b-<name> 0 -s <ip> -j <blocktype>firewall-cmd --direct --remove-rule <family> filter f2b-<name> 0 -s <ip> -j <blocktype>firewallcmd-rich-logging
action.d/firewallcmd-rich-logging.conf bans with firewalld rich rules and logs the dropped packets. Full setup: this guide.
Commands and parameters
| Parameter | Default |
|---|---|
level | info |
rate | 1 |
firewallcmd-rich-rules
action.d/firewallcmd-rich-rules.conf bans with firewalld rich rules (the usual choice on Fedora, RHEL, Rocky, AlmaLinux). Full setup: this guide.
Commands and parameters
ports="<port>"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --zone="<zone>" --add-rich-rule="%(fwcmd_rich_rule)s"; doneports="<port>"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --zone="<zone>" --remove-rich-rule="%(fwcmd_rich_rule)s"; donehostsdeny
action.d/hostsdeny.conf adds the IP to /etc/hosts.deny (TCP wrappers) instead of the firewall.
Commands and parameters
printf %%b "<daemon_list>: <ip_value>\n" >> <file>IP=$(echo "<ip_value>" | sed 's/[][\.]/\\\0/g') && sed -i "/^<daemon_list>: $IP$/d" <file>| Parameter | Default |
|---|---|
file | /etc/hosts.deny |
daemon_list | ALL |
ip_value | <ip> |
ipfilter
action.d/ipfilter.conf bans with IPFilter (ipf) on NetBSD/Solaris.
Commands and parameters
/sbin/ipf -Eecho block <blocktype> in quick from <ip>/32 | /sbin/ipf -f -echo block <blocktype> in quick from <ip>/32 | /sbin/ipf -r -f -| Parameter | Default |
|---|---|
blocktype | "return-icmp(port-unr)" |
ipfw
action.d/ipfw.conf bans with ipfw rules on FreeBSD.
Commands and parameters
ipfw add <blocktype> tcp from <ip> to <localhost> <port>ipfw delete `ipfw list | grep -i "[^0-9]<ip>[^0-9]" | awk '{print $1;}'`| Parameter | Default |
|---|---|
port | ssh |
localhost | 127.0.0.1 |
blocktype | unreach port |
iptables
action.d/iptables.conf the base iptables action (types oneport, multiport, allports); default on many older systems. Full setup: this guide.
Commands and parameters
{ <iptables> -C f2b-<name> -j <returntype> >/dev/null 2>&1; } || { <iptables> -N f2b-<name> || true; <iptables> -A f2b-<name> -j <returntype>; }
<_ipt_add_rules><iptables> -I f2b-<name> 1 -s <ip> -j <blocktype><iptables> -D f2b-<name> -s <ip> -j <blocktype>| Parameter | Default |
|---|---|
chain | INPUT |
name | default |
port | ssh |
protocol | tcp |
blocktype | REJECT --reject-with icmp-port-unreachable |
returntype | RETURN |
lockingopt | -w |
iptables | iptables <lockingopt> |
iptables-allports
action.d/iptables-allports.conf old name for iptables[type=allports]: blocks every port for the banned IP. Full setup: this guide.
iptables-ipset
action.d/iptables-ipset.conf iptables with an ipset set: one rule, any number of banned IPs (fast). Full setup: this guide.
Commands and parameters
ipset -exist create <ipmset> <ipsettype> timeout <default-ipsettime> maxelem <maxelem> <familyopt>
<_ipt_add_rules>ipset -exist add <ipmset> <ip> timeout <ipsettime>ipset -exist del <ipmset> <ip>| Parameter | Default |
|---|---|
ipsettype | hash:ip |
default-ipsettime | 0 |
ipsettime | 0 |
maxelem | 65536 |
timeout-bantime | $([ "<bantime>" -le 2147483 ] && echo "<bantime>" || echo 0) |
ipmset | f2b-<name> |
familyopt | (empty) |
iptables-ipset-proto4
action.d/iptables-ipset-proto4.conf ipset ban for very old ipset v4 systems. Full setup: this guide.
Commands and parameters
ipset --create f2b-<name> maxelem <maxelem> iphash
<_ipt_add_rules>ipset --test f2b-<name> <ip> || ipset --add f2b-<name> <ip>ipset --test f2b-<name> <ip> && ipset --del f2b-<name> <ip>| Parameter | Default |
|---|---|
maxelem | 65536 |
iptables-ipset-proto6
action.d/iptables-ipset-proto6.conf iptables + ipset ban on the jail's ports. Full setup: this guide.
iptables-ipset-proto6-allports
action.d/iptables-ipset-proto6-allports.conf iptables + ipset ban on all ports. Full setup: this guide.
iptables-multiport
action.d/iptables-multiport.conf old name for iptables[type=multiport]: blocks the jail's ports. Full setup: this guide.
iptables-multiport-log
action.d/iptables-multiport-log.conf iptables multiport ban that also logs dropped packets. Full setup: this guide.
Commands and parameters
<iptables> -N f2b-<name>
<iptables> -A f2b-<name> -j <returntype>
<iptables> -I <chain> 1 -p <protocol> -m multiport --dports <port> -j f2b-<name>
<iptables> -N f2b-<name>-log
<iptables> -I f2b-<name>-log -j LOG --log-prefix "$(expr f2b-<name> : '\(.\{1,23\}\)'):DROP " --log-level warning -m limit --limit 6/m --limit-burst 2
<iptables> -A f2b-<name>-log -j <blocktype><iptables> -I f2b-<name> 1 -s <ip> -j f2b-<name>-log<iptables> -D f2b-<name> -s <ip> -j f2b-<name>-logiptables-new
action.d/iptables-new.conf iptables ban that only matches new connections. Full setup: this guide.
iptables-xt_recent-echo
action.d/iptables-xt_recent-echo.conf bans with the xt_recent kernel module (no rule reload per ban). Full setup: this guide.
Commands and parameters
if [ `id -u` -eq 0 ];then
{ %(_ipt_check_rule)s >/dev/null 2>&1; } || { <iptables> -I <chain> %(_ipt_chain_rule)s; }
fiecho +<ip> > /proc/net/xt_recent/<iptname>echo -<ip> > /proc/net/xt_recent/<iptname>| Parameter | Default |
|---|---|
iptname | f2b-<name> |
mikrotik
action.d/mikrotik.conf adds the banned IP to an address list on a MikroTik router over SSH.
Commands and parameters
%(command)s "/ip firewall address-list add list=\"%(list)s\" address=<ip> comment=%(comment)s"%(command)s "/ip firewall address-list remove [find list=\"%(list)s\" comment=%(comment)s]"| Parameter | Default |
|---|---|
name | "%(__name__)s" |
netscaler
action.d/netscaler.conf adds banned IPs to a Citrix NetScaler (ADC) dataset.
Commands and parameters
curl -kH 'Authorization: Basic <ns_auth>' https://<ns_host>/nitro/v1/configcurl -k -H 'Authorization: Basic <ns_auth>' -X PUT -d '{"policydataset_value_binding":{"name":"<ns_dataset>","value":"<ip>"}}' https://<ns_host>/nitro/v1/config/curl -H 'Authorization: Basic <ns_auth>' -X DELETE -k "https://<ns_host>/nitro/v1/config/policydataset_value_binding/<ns_dataset>?args=value:<ip>"| Parameter | Default |
|---|---|
ns_host | (empty) |
ns_auth | (empty) |
ns_dataset | (empty) |
nftables
action.d/nftables.conf bans with an nftables set; the default banaction on Debian, Ubuntu and other current distros. Full setup: this guide.
Commands and parameters
<nftables> add table <table_family> <table>
<nftables> -- add chain <table_family> <table> <chain> \{ type <chain_type> hook <chain_hook> priority <chain_priority> \; \}
%(_nft_add_set)s<nftables> add element <table_family> <table> <addr_set> \{ <ip> \}<nftables> delete element <table_family> <table> <addr_set> \{ <ip> \}| Parameter | Default |
|---|---|
table | f2b-table |
table_family | inet |
chain | f2b-chain |
chain_type | filter |
chain_hook | input |
chain_priority | -1 |
addr_type | ipv4_addr |
name | default |
port | ssh |
protocol | tcp |
blocktype | reject |
nftables | nft |
addr_set | addr-set-<name> |
addr_family | ip |
addr_options | <sp>flags interval\; |
nftables-allports
action.d/nftables-allports.conf old name for nftables[type=allports]. Full setup: this guide.
nftables-multiport
action.d/nftables-multiport.conf old name for nftables[type=multiport]. Full setup: this guide.
nginx-block-map
action.d/nginx-block-map.conf bans inside nginx with a map file, so it also works behind CDNs and proxies.
Commands and parameters
touch '%(blck_lst_file)s'%(_echo_blck_row)s >> '%(blck_lst_file)s'; %(blck_lst_reload)sid=$(%(_echo_blck_row)s | sed -e 's/[]\/$*.^|[]/\\&/g'); sed -i "/^$id$/d" %(blck_lst_file)s; %(blck_lst_reload)snpf
action.d/npf.conf bans with NPF tables on NetBSD.
Commands and parameters
/sbin/npfctl table <tablename> add <ip>/sbin/npfctl table <tablename> rem <ip>| Parameter | Default |
|---|---|
tablename | fail2ban |
nsupdate
action.d/nsupdate.conf publishes banned IPs as DNS records with nsupdate (a DIY DNS blocklist).
Commands and parameters
echo <ip> | awk -F. '{print "prereq nxrrset "$4"."$3"."$2"."$1".<domain> TXT"; print "update add "$4"."$3"."$2"."$1".<domain> <ttl> IN TXT \"<rdata>\""; print "send"}' | <nsupdatecmd> -k <keyfile>echo <ip> | awk -F. '{print "update delete "$4"."$3"."$2"."$1".<domain>"; print "send"}' | <nsupdatecmd> -k <keyfile>| Parameter | Default |
|---|---|
domain | (empty) |
ttl | 60 |
rdata | Your IP has been banned |
nsupdatecmd | /usr/bin/nsupdate |
keyfile | (empty) |
osx-afctl
action.d/osx-afctl.conf bans with afctl on old macOS Server.
Commands and parameters
/usr/libexec/afctl -a <ip> -t <bantime>/usr/libexec/afctl -r <ip>osx-ipfw
action.d/osx-ipfw.conf bans with ipfw on old macOS.
Commands and parameters
ipfw add <rulenum> set <setnum> <blocktype> log <block> from <ip> to <dst> <port>ipfw delete `ipfw -S list | grep -i 'set <setnum> <blocktype> log <block> from <ip> to <dst>' | awk '{print $1;}'`| Parameter | Default |
|---|---|
port | ssh |
dst | me |
block | tcp |
blocktype | unreach port |
setnum | 10 |
rulenum | "`echo $((RANDOM%%2000+10000))`" |
pf
action.d/pf.conf bans with pf tables on OpenBSD, FreeBSD and macOS.
Commands and parameters
echo "table <<tablename>-<name>> persist counters" | <pfctl> -f-
port="<port>"; if [ "$port" != "" ] && case "$port" in \{*) false;; esac; then port="{$port}"; fi
protocol="<protocol>"; if [ "$protocol" != "all" ]; then protocol="proto $protocol"; else protocol=all; fi
echo "<block> $protocol from <<tablename>-<name>> to <actiontype>" | <pfctl> -f-<pfctl> -t <tablename>-<name> -T add <ip><pfctl> -t <tablename>-<name> -T delete <ip>| Parameter | Default |
|---|---|
tablename | f2b |
block | block quick |
protocol | tcp |
actiontype | <multiport> |
allports | any |
multiport | any port $port |
route
action.d/route.conf bans with a blackhole/unreachable route instead of a firewall rule.
Commands and parameters
ip route add <blocktype> <ip>ip route del <blocktype> <ip>| Parameter | Default |
|---|---|
blocktype | unreachable |
shorewall
action.d/shorewall.conf bans through Shorewall's blacklist.
Commands and parameters
shorewall<family> <blocktype> <ip>shorewall<family> allow <ip>| Parameter | Default |
|---|---|
family | (empty) |
blocktype | reject |
shorewall-ipset-proto6
action.d/shorewall-ipset-proto6.conf bans with Shorewall using an ipset.
Commands and parameters
if ! ipset -quiet -name list f2b-<name> >/dev/null;
then ipset -quiet -exist create f2b-<name> <ipsettype> timeout <default-ipsettime> maxelem <maxelem>;
fiipset add f2b-<name> <ip> timeout <ipsettime> -existipset del f2b-<name> <ip> -exist| Parameter | Default |
|---|---|
ipsettype | hash:ip |
maxelem | 65536 |
symbiosis-blacklist-allports
action.d/symbiosis-blacklist-allports.conf bans with the Bytemark Symbiosis firewall.
Commands and parameters
echo 'all' >| /etc/symbiosis/firewall/blacklist.d/<ip>.auto
<iptables> -I <chain> 1 -s <ip> -j <blocktype>rm -f /etc/symbiosis/firewall/blacklist.d/<ip>.auto
<iptables> -D <chain> -s <ip> -j <blocktype> || :| Parameter | Default |
|---|---|
chain | blacklist |
blocktype | DROP |
ufw
action.d/ufw.conf bans by inserting ufw deny rules (needs ufw enabled). Full setup: this guide.
Commands and parameters
if [ -n "<application>" ] && ufw app info "<application>"
then
ufw <add> <blocktype> from <ip> to <destination> app "<application>" comment "<comment>"
else
ufw <add> <blocktype> from <ip> to <destination> comment "<comment>"
fi
<kill>if [ -n "<application>" ] && ufw app info "<application>"
then
ufw delete <blocktype> from <ip> to <destination> app "<application>"
else
ufw delete <blocktype> from <ip> to <destination>
fi| Parameter | Default |
|---|---|
add | prepend |
blocktype | reject |
destination | any |
application | (empty) |
comment | by Fail2Ban after <failures> attempts against <name> |
Notification actions##
apprise
action.d/apprise.conf sends a ban notification to any of Apprise's 100+ services (Telegram, Discord, Slack, ntfy…).
Commands and parameters
printf %%b "The jail <name> has been started successfully." | <apprise> -t "[Fail2Ban] <name>: started on `uname -n`"printf %%b "The IP <ip> has just been banned by Fail2Ban after <failures> attempts against <name>" | <apprise> -n "warning" -t "[Fail2Ban] <name>: banned <ip> from `uname -n`"| Parameter | Default |
|---|---|
config | /etc/fail2ban/apprise.conf |
args | (empty) |
apprise | apprise -c "<config>" <args> |
mail
action.d/mail.conf e-mails a short notice for each ban (mail command). Full setup: email alerts.
Commands and parameters
printf %%b "Hi,\n
The jail <name> has been started successfully.\n
Regards,\n
Fail2Ban"|mail -E 'set escape' -s "[Fail2Ban] <name>: started on <fq-hostname>" <dest>printf %%b "Hi,\n
The IP <ip> has just been banned by Fail2Ban after
<failures> attempts against <name>.\n
Regards,\n
Fail2Ban"|mail -E 'set escape' -s "[Fail2Ban] <name>: banned <ip> from <fq-hostname>" <dest>| Parameter | Default |
|---|---|
name | default |
dest | root |
mail-buffered
action.d/mail-buffered.conf e-mails a summary after a number of bans instead of one mail per ban. Full setup: email alerts.
Commands and parameters
printf %%b "Hi,\n
The jail <name> has been started successfully.\n
Output will be buffered until <lines> lines are available.\n
Regards,\n
Fail2Ban"|mail -E 'set escape' -s "[Fail2Ban] <name>: started on <fq-hostname>" <dest>printf %%b "`date`: <ip> (<failures> failures)\n" >> <tmpfile>
LINE=$( wc -l <tmpfile> | awk '{ print $1 }' )
if [ $LINE -ge <lines> ]; then
printf %%b "Hi,\n
These hosts have been banned by Fail2Ban.\n
`cat <tmpfile>`
\nRegards,\n
Fail2Ban"|mail -E 'set escape' -s "[Fail2Ban] <name>: Summary" <dest>
rm <tmpfile>
fi| Parameter | Default |
|---|---|
name | default |
lines | 5 |
tmpfile | /var/run/fail2ban/tmp-mail.txt |
dest | root |
mail-whois
action.d/mail-whois.conf e-mails each ban with whois data (mail command). Full setup: email alerts.
Commands and parameters
printf %%b "Hi,\n
The jail <name> has been started successfully.\n
Regards,\n
Fail2Ban"|mail -E 'set escape' -s "[Fail2Ban] <name>: started on <fq-hostname>" <dest>printf %%b "Hi,\n
The IP <ip> has just been banned by Fail2Ban after
<failures> attempts against <name>.\n\n
Here is more information about <ip> :\n
`%(_whois_command)s`\n
Regards,\n
Fail2Ban"|mail -E 'set escape' -s "[Fail2Ban] <name>: banned <ip> from <fq-hostname>" <dest>| Parameter | Default |
|---|---|
name | default |
dest | root |
mail-whois-lines
action.d/mail-whois-lines.conf e-mails each ban with whois data and the matching log lines (mail command). Full setup: email alerts.
Commands and parameters
printf %%b "Hi,\n
The jail <name> has been started successfully.\n
Regards,\n
Fail2Ban" | <mailcmd> "[Fail2Ban] <name>: started on <fq-hostname>" <dest>%(_ban_mail_content)s | <mailcmd> "[Fail2Ban] <name>: banned <ip> from <fq-hostname>" <dest>| Parameter | Default |
|---|---|
mailcmd | mail -E 'set escape' -s |
name | default |
dest | root |
logpath | /dev/null |
sendmail
action.d/sendmail.conf e-mails a short notice for each ban (sendmail). Full setup: email alerts.
Commands and parameters
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
Regards,\n
Fail2Ban" | <mailcmd>| Parameter | Default |
|---|---|
name | default |
sendmail-buffered
action.d/sendmail-buffered.conf e-mails a summary after a number of bans (sendmail). Full setup: email alerts.
Commands and parameters
printf %%b "Subject: [Fail2Ban] <name>: started on <fq-hostname>
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
The jail <name> has been started successfully.\n
Output will be buffered until <lines> lines are available.\n
Regards,\n
Fail2Ban" | <mailcmd>printf %%b "`date`: <ip> (<failures> failures)\n" >> <tmpfile>
LINE=$( wc -l <tmpfile> | awk '{ print $1 }' )
if [ $LINE -ge <lines> ]; then
printf %%b "Subject: [Fail2Ban] <name>: summary from <fq-hostname>
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
These hosts have been banned by Fail2Ban.\n
`cat <tmpfile>`
Regards,\n
Fail2Ban" | <mailcmd>
rm <tmpfile>
fi| Parameter | Default |
|---|---|
name | default |
lines | 5 |
tmpfile | /var/run/fail2ban/tmp-mail.txt |
sendmail-geoip-lines
action.d/sendmail-geoip-lines.conf e-mails each ban with GeoIP country data and log lines (sendmail). Full setup: email alerts.
Commands and parameters
( 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
Here is more information about <ip> :\n
http://bgp.he.net/ip/<ip>
http://www.projecthoneypot.org/ip_<ip>
http://whois.domaintools.com/<ip>\n\n
Country:`geoiplookup -f /usr/share/GeoIP/GeoIP.dat "<ip>" | cut -d':' -f2-`
AS:`geoiplookup -f /usr/share/GeoIP/GeoIPASNum.dat "<ip>" | cut -d':' -f2-`
hostname: <ip-host>\n\n
Lines containing failures of <ip> (max <grepmax>)\n";
%(_grep_logs)s;
printf %%b "\n
Regards,\n
Fail2Ban" ) | <mailcmd>| Parameter | Default |
|---|---|
name | default |
logpath | /dev/null |
sendmail-whois
action.d/sendmail-whois.conf e-mails each ban with whois data (sendmail); used by action_mw. Full setup: email alerts.
Commands and parameters
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
Here is more information about <ip> :\n
`%(_whois_command)s`\n
Regards,\n
Fail2Ban" | <mailcmd>| Parameter | Default |
|---|---|
name | default |
sendmail-whois-ipjailmatches
action.d/sendmail-whois-ipjailmatches.conf e-mails each ban with whois data and all matches of the IP in this jail. Full setup: email alerts.
Commands and parameters
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
Here is more information about <ip> :\n
`%(_whois_command)s`\n\n
Matches for <name> with <ipjailfailures> failures IP:<ip>\n
<ipjailmatches>\n\n
Regards,\n
Fail2Ban" | <mailcmd>| Parameter | Default |
|---|---|
name | default |
sendmail-whois-ipmatches
action.d/sendmail-whois-ipmatches.conf e-mails each ban with whois data and all matches of the IP. Full setup: email alerts.
Commands and parameters
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
Here is more information about <ip> :\n
`%(_whois_command)s`\n\n
Matches with <ipfailures> failures IP:<ip>\n
<ipmatches>\n\n
Regards,\n
Fail2Ban" | <mailcmd>| Parameter | Default |
|---|---|
name | default |
sendmail-whois-lines
action.d/sendmail-whois-lines.conf e-mails each ban with whois data and the log lines (sendmail); used by action_mwl. Full setup: email alerts.
Commands and parameters
( 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
Here is more information about <ip> :\n"
%(_whois_command)s;
printf %%b "\nLines containing failures of <ip> (max <grepmax>)\n";
%(_grep_logs)s;
printf %%b "\n
Regards,\n
Fail2Ban" ) | <mailcmd>| Parameter | Default |
|---|---|
name | default |
logpath | /dev/null |
sendmail-whois-matches
action.d/sendmail-whois-matches.conf e-mails each ban with whois data and the matches that triggered it. Full setup: email alerts.
Commands and parameters
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
Here is more information about <ip> :\n
`%(_whois_command)s`\n\n
Matches:\n
<matches>\n\n
Regards,\n
Fail2Ban" | <mailcmd>| Parameter | Default |
|---|---|
name | default |
smtp
action.d/smtp.py Python action that e-mails ban notices over SMTP directly (no local MTA needed). Full setup: email alerts.
Abuse-reporting actions##
abuseipdb
action.d/abuseipdb.conf reports each banned IP to AbuseIPDB using your API key. Full setup: this guide.
Commands and parameters
lgm=$(printf '%%.1000s\n...' "<matches>"); curl -sSf "https://api.abuseipdb.com/api/v2/report" -H "Accept: application/json" -H "Key: <abuseipdb_apikey>" --data-urlencode "comment=$lgm" --data-urlencode "ip=<ip>" --data "categories=<abuseipdb_category>"| Parameter | Default |
|---|---|
abuseipdb_apikey | (empty) |
blocklist_de
action.d/blocklist_de.conf reports banned IPs to blocklist.de by e-mail. Full setup: this guide.
Commands and parameters
curl --fail --data-urlencode "server=<email>" --data "apikey=<apikey>" --data "service=<service>" --data "ip=<ip>" --data-urlencode "logs=<matches><br>" --data 'format=text' --user-agent "<agent>" "https://www.blocklist.de/en/httpreports.html"complain
action.d/complain.conf e-mails an abuse complaint to the addresses in the IP's whois record.
Commands and parameters
oifs=${IFS};
RESOLVER_ADDR="%(addr_resolver)s"
if [ "<debug>" -gt 0 ]; then echo "try to resolve $RESOLVER_ADDR"; fi
ADDRESSES=$(dig +short -t txt -q $RESOLVER_ADDR | tr -d '"')
IFS=,; ADDRESSES=$(echo $ADDRESSES)
IFS=${oifs}
IP=<ip>
if [ ! -z "$ADDRESSES" ]; then
( printf %%b "<message>\n"; date '+Note: Local timezone is %%z (%%Z)';
printf %%b "\nLines containing failures of <ip> (max <grepmax>)\n";
%(_grep_logs)s;
) | <mailcmd> "Abuse from <ip>" <mailargs> $ADDRESSES
fidshield
action.d/dshield.conf submits attack reports to DShield (SANS Internet Storm Center).
Commands and parameters
TZONE=`date +%%z | sed 's/\([+-]..\)\(..\)/\1:\2/'`
DATETIME="`perl -e '@t=localtime(<time>);printf "%%4d-%%02d-%%02d %%02d:%%02d:%%02d",1900+$t[5],$t[4]+1,$t[3],$t[2],$t[1],$t[0]'` $TZONE"
PROTOCOL=`awk '{IGNORECASE=1;if($1=="<protocol>"){print $2;exit}}' /etc/protocols`
if [ -z "$PROTOCOL" ]; then PROTOCOL=<protocol>; fi
printf %%b "$DATETIME\t<userid>\t<failures>\t<ip>\t<srcport>\t<myip>\t<port>\t$PROTOCOL\t<tcpflags>\n" >> <tmpfile>.buffer
NOW=`date +%%s`
if [ ! -f <tmpfile>.first ]; then
echo <time> | cut -d. -f1 > <tmpfile>.first
fi
if [ ! -f <tmpfile>.lastsent ]; then
echo 0 > <tmpfile>.lastsent
fi
LOGAGE=$(($NOW - `cat <tmpfile>.first`))
LASTREPORT=$(($NOW - `cat <tmpfile>.lastsent`))
LINES=$( wc -l <tmpfile>.buffer | awk '{ print $1 }' )
if [ $LINES -ge <lines> && $LASTREPORT -gt <minreportinterval> ] || [ $LOGAGE -gt <maxbufferage> ]; then
cat <tmpfile>.buffer | <mailcmd> "FORMAT DSHIELD USERID <userid> TZ $TZONE Fail2Ban" <mailargs> <dest>
rm -f <tmpfile>.buffer <tmpfile>.first
echo $NOW > <tmpfile>.lastsent
fiif [ -f <tmpfile>.first ]; then
NOW=`date +%%s`
LOGAGE=$(($NOW - `cat <tmpfile>.first`))
if [ $LOGAGE -gt <maxbufferage> ]; then
cat <tmpfile>.buffer | <mailcmd> "FORMAT DSHIELD USERID <userid> TZ `date +%%z | sed 's/\([+-]..\)\(..\)/\1:\2/'` Fail2Ban" <mailargs> <dest>
rm -f <tmpfile>.buffer <tmpfile>.first
echo $NOW > <tmpfile>.lastsent
fi
fi| Parameter | Default |
|---|---|
port | ??? |
userid | 0 |
myip | `ip -4 addr show dev eth0 | grep inet | head -n 1 | sed -r 's/.*inet ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*/ |
protocol | tcp |
lines | 50 |
minreportinterval | 3600 |
maxbufferage | 21600 |
srcport | ??? |
tcpflags | (empty) |
mailcmd | mail -E 'set escape' -s |
mailargs | (empty) |
dest | reports@dshield.org |
tmpfile | /var/run/fail2ban/tmp-dshield |
ipthreat
action.d/ipthreat.conf reports banned IPs to ipthreat.net. Full setup: this guide.
Commands and parameters
curl -sSf "https://api.ipthreat.net/api/report" -X POST -H "Content-Type: application/json" -H "X-API-KEY: <ipthreat_apikey>" -d "{\"ip\":\"<ip>\",\"flags\":\"<ipthreat_flags>\",\"system\":\"<ipthreat_system>\",\"notes\":\"fail2ban\"}"| Parameter | Default |
|---|---|
ipthreat_apikey | (empty) |
ipthreat_system | <name> |
ipthreat_flags | 8 |
mynetwatchman
action.d/mynetwatchman.conf submits attack reports to myNetWatchman.
Commands and parameters
MNWLOGIN=`perl -e '$s=shift;$s=~s/([\W])/"%%".uc(sprintf("%%2.2x",ord($1)))/eg;print $s' '<mnwlogin>'`
MNWPASS=`perl -e '$s=shift;$s=~s/([\W])/"%%".uc(sprintf("%%2.2x",ord($1)))/eg;print $s' '<mnwpass>'`
PROTOCOL=`awk '{IGNORECASE=1;if($1=="<protocol>"){print $2;exit}}' /etc/protocols`
if [ -z "$PROTOCOL" ]; then PROTOCOL=<protocol>; fi
DATETIME=`perl -e '@t=gmtime(<time>);printf "%%4d-%%02d-%%02d+%%02d:%%02d:%%02d",1900+$t[5],$t[4]+1,$t[3],$t[2],$t[1],$t[0]'`
<getcmd> "<mnwurl>?AT=2&AV=0&AgentEmail=$MNWLOGIN&AgentPassword=$MNWPASS&AttackerIP=<ip>&SrcPort=<srcport>&ProtocolID=$PROTOCOL&DestPort=<port>&AttackCount=<failures>&VictimIP=<myip>&AttackDateTime=$DATETIME" 2>&1 >> <tmpfile>.out && grep -q 'Attack Report Insert Successful' <tmpfile>.out && rm -f <tmpfile>.out| Parameter | Default |
|---|---|
port | 0 |
mnwlogin | (empty) |
mnwpass | (empty) |
myip | `ip -4 addr show dev eth0 | grep inet | head -n 1 | sed -r 's/.*inet ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*/ |
protocol | tcp |
agent | Fail2ban |
getcmd | wget --no-verbose --tries=3 --waitretry=10 --connect-timeout=10 --read-timeout=60 --retry-connrefused --output-document= |
srcport | 0 |
mnwurl | http://mynetwatchman.com/insertwebreport.asp |
tmpfile | /var/run/fail2ban/tmp-mynetwatchman |
xarf-login-attack
action.d/xarf-login-attack.conf e-mails an X-ARF login-attack report to the IP owner's abuse contact.
Commands and parameters
oifs=${IFS};
RESOLVER_ADDR="%(addr_resolver)s"
if [ "<debug>" -gt 0 ]; then echo "try to resolve $RESOLVER_ADDR"; fi
ADDRESSES=$(dig +short -t txt -q $RESOLVER_ADDR | grep -v ';;' | tr -d '"')
if [ "<debug>" -gt 0 ]; then echo "returned address $ADDRESSES"; fi
if [ -z "$ADDRESSES" ]; then
echo "address for $RESOLVER_ADDR cannot be found or timeout from dig";
if [ "<debug>" -gt 0 ]; then exit 1; fi
exit 0
fi
IFS=,; ADDRESSES=$(echo $ADDRESSES)
IFS=${oifs}
IP=<ip>
FROM=<sender>
SERVICE=<service>
FAILURES=<failures>
REPORTID=<time>@<fq-hostname>
TLP=<tlp>
PORT=<port>
DATE=`LC_ALL=C date --date=@<time> +"%%a, %%d %%h %%Y %%T %%z"`
oifs=${IFS}; IFS=,; ADDRESSES=$(echo $ADDRESSES)
IFS=${oifs}
(printf -- %%b "<header>\n<message>\n<report>\n\n";
date '+Note: Local timezone is %%z (%%Z)';
printf -- %%b "\n<ipmatches>\n\n<footer>") | <mailcmd> <mailargs> $ADDRESSESTesting and include files##
dummy
action.d/dummy.conf writes bans to a text file instead of a firewall; useful for testing jails safely.
Commands and parameters
if [ ! -z '<target>' ]; then touch <target>; fi;
printf %%b "<init>\n" <to_target>
echo "%(debug)s started"printf %%b "+<ip>\n" <to_target>
echo "%(debug)s banned <ip> (family: <family>)"printf %%b "-<ip>\n" <to_target>
echo "%(debug)s unbanned <ip> (family: <family>)"| Parameter | Default |
|---|---|
init | 123 |
target | /var/run/fail2ban/fail2ban.dummy |
to_target | >> <target> |
firewallcmd-common
action.d/firewallcmd-common.conf shared settings included by the other firewallcmd-* actions. Full setup: this guide.
Commands and parameters
| Parameter | Default |
|---|---|
name | default |
port | 1:65535 |
protocol | tcp |
family | ipv4 |
chain | INPUT_direct |
zone | public |
service | ssh |
rejecttype | icmp-port-unreachable |
blocktype | REJECT --reject-with <rejecttype> |
rich-blocktype | reject type='<rejecttype>' |
helpers-common
action.d/helpers-common.conf helper commands (log grepping) shared by the mail actions.
Commands and parameters
| Parameter | Default |
|---|---|
greplimit | tail -n <grepmax> |
grepmax | 1000 |
grepopts | -m <grepmax> |
mail-whois-common
action.d/mail-whois-common.conf shared settings for the mail-whois actions.
sendmail-common
action.d/sendmail-common.conf shared settings for the sendmail-* actions.
Commands and parameters
printf %%b "Subject: [Fail2Ban] <name>: started on <fq-hostname>
Date: `LC_ALL=C date +"%%a, %%d %%h %%Y %%T %%z"`
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
The jail <name> has been started successfully.\n
Regards,\n
Fail2Ban" | <mailcmd>| Parameter | Default |
|---|---|
mailcmd | /usr/sbin/sendmail -f "<sender>" "<dest>" |
dest | root |
sender | fail2ban |
sendername | Fail2Ban |
FAQ#
Where are fail2ban actions located?#
In /etc/fail2ban/action.d/. Each .conf file is a shell-command action named after the file (nftables.conf is the nftables action); .py files such as smtp.py are Python actions. Put your changes in a .local file with the same name, or create a new file for a custom action.
Can a jail have multiple actions?#
Yes. List them in action, one per line, with the continuation lines indented, for example %(action_)s followed by abuseipdb[...]. Every action runs on each ban. To use the same action twice with different settings, give each an actname, such as smtp.py[dest=a@example.com, actname=smtp-a].
How do I test a fail2ban action?#
Ban a documentation address by hand with sudo fail2ban-client set <jail> banip 192.0.2.15; every action of the jail runs. Check the firewall or your inbox, then sudo fail2ban-client set <jail> unbanip 192.0.2.15. Errors appear in /var/log/fail2ban.log.
Spotted something wrong or out of date? Tell us — every page is checked against the current fail2ban release.