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.

Updated 33 min readChecked against fail2ban 1.1.1

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.

bash
ls /etc/fail2ban/action.d/
sudo fail2ban-client get sshd actions

banaction 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:

/etc/fail2ban/jail.local
[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.

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>.local with 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#

output
$ sudo fail2ban-client get sshd actions
The jail sshd has the following actions:
nftables

To see the exact commands an action will run, after all parameters are filled in:

bash
sudo fail2ban-client get sshd action nftables actionban

All actions#

Search by name or description. Each name opens the action's page with its commands, parameters and usage.

ActionTypeWhat it does
abuseipdbReportreports each banned IP to AbuseIPDB using your API key
apfFirewallbans through APF (Advanced Policy Firewall) with apf --deny
appriseNotifysends a ban notification to any of Apprise's 100+ services (Telegram, Discord, Slack, ntfy…)
blocklist_deReportreports banned IPs to blocklist.de by e-mail
bsd-ipfwFirewallbans with ipfw tables on FreeBSD
cloudflare-tokenFirewallblocks the IP at Cloudflare's edge with an API token (IP access rules)
cloudflareFirewallblocks the IP at Cloudflare's edge using the legacy global API key
complainReporte-mails an abuse complaint to the addresses in the IP's whois record
csfFirewallbans through ConfigServer Security & Firewall (csf -d)
dshieldReportsubmits attack reports to DShield (SANS Internet Storm Center)
dummyTestingwrites bans to a text file instead of a firewall; useful for testing jails safely
firewallcmd-allportsFirewallbans on all ports with firewalld direct rules
firewallcmd-commonIncludeshared settings included by the other firewallcmd-* actions
firewallcmd-ipsetFirewallbans with an ipset managed through firewalld (fast with many bans)
firewallcmd-multiportFirewallbans on the jail's ports with firewalld direct rules
firewallcmd-newFirewallbans new connections on the jail's ports with firewalld direct rules
firewallcmd-rich-loggingFirewallbans with firewalld rich rules and logs the dropped packets
firewallcmd-rich-rulesFirewallbans with firewalld rich rules (the usual choice on Fedora, RHEL, Rocky, AlmaLinux)
helpers-commonIncludehelper commands (log grepping) shared by the mail actions
hostsdenyBanadds the IP to /etc/hosts.deny (TCP wrappers) instead of the firewall
ipfilterFirewallbans with IPFilter (ipf) on NetBSD/Solaris
ipfwFirewallbans with ipfw rules on FreeBSD
iptables-allportsFirewallold name for iptables[type=allports]: blocks every port for the banned IP
iptables-ipset-proto4Firewallipset ban for very old ipset v4 systems
iptables-ipset-proto6-allportsFirewalliptables + ipset ban on all ports
iptables-ipset-proto6Firewalliptables + ipset ban on the jail's ports
iptables-ipsetFirewalliptables with an ipset set: one rule, any number of banned IPs (fast)
iptables-multiport-logFirewalliptables multiport ban that also logs dropped packets
iptables-multiportFirewallold name for iptables[type=multiport]: blocks the jail's ports
iptables-newFirewalliptables ban that only matches new connections
iptables-xt_recent-echoFirewallbans with the xt_recent kernel module (no rule reload per ban)
iptablesFirewallthe base iptables action (types oneport, multiport, allports); default on many older systems
ipthreatReportreports banned IPs to ipthreat.net
mail-bufferedNotifye-mails a summary after a number of bans instead of one mail per ban
mail-whois-commonIncludeshared settings for the mail-whois actions
mail-whois-linesNotifye-mails each ban with whois data and the matching log lines (mail command)
mail-whoisNotifye-mails each ban with whois data (mail command)
mailNotifye-mails a short notice for each ban (mail command)
mikrotikFirewalladds the banned IP to an address list on a MikroTik router over SSH
mynetwatchmanReportsubmits attack reports to myNetWatchman
netscalerFirewalladds banned IPs to a Citrix NetScaler (ADC) dataset
nftables-allportsFirewallold name for nftables[type=allports]
nftables-multiportFirewallold name for nftables[type=multiport]
nftablesFirewallbans with an nftables set; the default banaction on Debian, Ubuntu and other current distros
nginx-block-mapBanbans inside nginx with a map file, so it also works behind CDNs and proxies
npfFirewallbans with NPF tables on NetBSD
nsupdateBanpublishes banned IPs as DNS records with nsupdate (a DIY DNS blocklist)
osx-afctlFirewallbans with afctl on old macOS Server
osx-ipfwFirewallbans with ipfw on old macOS
pfFirewallbans with pf tables on OpenBSD, FreeBSD and macOS
routeFirewallbans with a blackhole/unreachable route instead of a firewall rule
sendmail-bufferedNotifye-mails a summary after a number of bans (sendmail)
sendmail-commonIncludeshared settings for the sendmail-* actions
sendmail-geoip-linesNotifye-mails each ban with GeoIP country data and log lines (sendmail)
sendmail-whois-ipjailmatchesNotifye-mails each ban with whois data and all matches of the IP in this jail
sendmail-whois-ipmatchesNotifye-mails each ban with whois data and all matches of the IP
sendmail-whois-linesNotifye-mails each ban with whois data and the log lines (sendmail); used by action_mwl
sendmail-whois-matchesNotifye-mails each ban with whois data and the matches that triggered it
sendmail-whoisNotifye-mails each ban with whois data (sendmail); used by action_mw
sendmailNotifye-mails a short notice for each ban (sendmail)
shorewall-ipset-proto6Firewallbans with Shorewall using an ipset
shorewallFirewallbans through Shorewall's blacklist
symbiosis-blacklist-allportsFirewallbans with the Bytemark Symbiosis firewall
ufwFirewallbans by inserting ufw deny rules (needs ufw enabled)
xarf-login-attackReporte-mails an X-ARF login-attack report to the IP owner's abuse contact
smtpNotifyPython 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
actionban
apf --deny <ip> "banned by Fail2Ban <name>"
actionunban
apf --remove <ip>
ParameterDefault
namedefault

action.d/apf.conf

bsd-ipfw

action.d/bsd-ipfw.conf bans with ipfw tables on FreeBSD.

Commands and parameters
actionstart
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>"
)
actionban
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; }
actionunban
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; }
ParameterDefault
table1
port(empty)
startstatefile/var/run/fail2ban/ipfw-started-table_<table>
blockip
blocktypeunreach port
lowest_rule_num111

action.d/bsd-ipfw.conf

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
actionban
curl -s -o /dev/null -X POST <_cf_api_prms> \
-d '{"mode":"block","configuration":{"target":"<cftarget>","value":"<ip>"},"notes":"Fail2Ban <name>"}' \
<_cf_api_url>
actionunban
id=$(curl -s -X GET <_cf_api_prms> \
"<_cf_api_url>?mode=block&configuration_target=<cftarget>&configuration_value=<ip>&page=1&per_page=1&notes=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"
ParameterDefault
cftoken(empty)
cfuser(empty)
cftargetip

action.d/cloudflare.conf

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
actionban
curl -s -X POST "<_cf_api_url>" \
<_cf_api_prms> \
--data '{"mode":"<cfmode>","configuration":{"target":"<cftarget>","value":"<ip>"},"notes":"<notes>"}'
actionunban
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"}'
ParameterDefault
cftargetip
cfmodeblock
notesFail2Ban <name>

action.d/cloudflare-token.conf

csf

action.d/csf.conf bans through ConfigServer Security & Firewall (csf -d).

Commands and parameters
actionban
csf --deny <ip> "banned by Fail2Ban <name>"
actionunban
csf --denyrm <ip>
ParameterDefault
namedefault

action.d/csf.conf

firewallcmd-allports

action.d/firewallcmd-allports.conf bans on all ports with firewalld direct rules. Full setup: this guide.

Commands and parameters
actionstart
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>
actionban
firewall-cmd --direct --add-rule <family> filter f2b-<name> 0 -s <ip> -j <blocktype>
actionunban
firewall-cmd --direct --remove-rule <family> filter f2b-<name> 0 -s <ip> -j <blocktype>

action.d/firewallcmd-allports.conf

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
actionstart
<ipsbackend_<ipsetbackend>/actionstart>
firewall-cmd --direct --add-rule <family> filter <chain> 0 <actiontype> -m set --match-set <ipmset> src -j <blocktype>
actionban
<ipsbackend_<ipsetbackend>/actionban>
actionunban
<ipsbackend_<ipsetbackend>/actionunban>
ParameterDefault
ipsettypehash:ip
chainINPUT_direct
default-ipsettime0
ipsettime0
maxelem65536
timeout-bantime$([ "<bantime>" -le 2147483 ] && echo "<bantime>" || echo 0)
ipsetbackendipset
actiontype<multiport>
allports-p <protocol>
multiport-p <protocol> -m multiport --dports <port>
ipmsetf2b-<name>
familyopt(empty)
firewalld_familyopt(empty)

action.d/firewallcmd-ipset.conf

firewallcmd-multiport

action.d/firewallcmd-multiport.conf bans on the jail's ports with firewalld direct rules. Full setup: this guide.

Commands and parameters
actionstart
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>
actionban
firewall-cmd --direct --add-rule <family> filter f2b-<name> 0 -s <ip> -j <blocktype>
actionunban
firewall-cmd --direct --remove-rule <family> filter f2b-<name> 0 -s <ip> -j <blocktype>

action.d/firewallcmd-multiport.conf

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
actionstart
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>
actionban
firewall-cmd --direct --add-rule <family> filter f2b-<name> 0 -s <ip> -j <blocktype>
actionunban
firewall-cmd --direct --remove-rule <family> filter f2b-<name> 0 -s <ip> -j <blocktype>

action.d/firewallcmd-new.conf

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
ParameterDefault
levelinfo
rate1

action.d/firewallcmd-rich-logging.conf

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
actionban
ports="<port>"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --zone="<zone>" --add-rich-rule="%(fwcmd_rich_rule)s"; done
actionunban
ports="<port>"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --zone="<zone>" --remove-rich-rule="%(fwcmd_rich_rule)s"; done

action.d/firewallcmd-rich-rules.conf

hostsdeny

action.d/hostsdeny.conf adds the IP to /etc/hosts.deny (TCP wrappers) instead of the firewall.

Commands and parameters
actionban
printf %%b "<daemon_list>: <ip_value>\n" >> <file>
actionunban
IP=$(echo "<ip_value>" | sed 's/[][\.]/\\\0/g') && sed -i "/^<daemon_list>: $IP$/d" <file>
ParameterDefault
file/etc/hosts.deny
daemon_listALL
ip_value<ip>

action.d/hostsdeny.conf

ipfilter

action.d/ipfilter.conf bans with IPFilter (ipf) on NetBSD/Solaris.

Commands and parameters
actionstart
/sbin/ipf -E
actionban
echo block <blocktype> in quick from <ip>/32 | /sbin/ipf -f -
actionunban
echo block <blocktype> in quick from <ip>/32 | /sbin/ipf -r -f -
ParameterDefault
blocktype"return-icmp(port-unr)"

action.d/ipfilter.conf

ipfw

action.d/ipfw.conf bans with ipfw rules on FreeBSD.

Commands and parameters
actionban
ipfw add <blocktype> tcp from <ip> to <localhost> <port>
actionunban
ipfw delete `ipfw list | grep -i "[^0-9]<ip>[^0-9]" | awk '{print $1;}'`
ParameterDefault
portssh
localhost127.0.0.1
blocktypeunreach port

action.d/ipfw.conf

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
actionstart
{ <iptables> -C f2b-<name> -j <returntype> >/dev/null 2>&1; } || { <iptables> -N f2b-<name> || true; <iptables> -A f2b-<name> -j <returntype>; }
<_ipt_add_rules>
actionban
<iptables> -I f2b-<name> 1 -s <ip> -j <blocktype>
actionunban
<iptables> -D f2b-<name> -s <ip> -j <blocktype>
ParameterDefault
chainINPUT
namedefault
portssh
protocoltcp
blocktypeREJECT --reject-with icmp-port-unreachable
returntypeRETURN
lockingopt-w
iptablesiptables <lockingopt>

action.d/iptables.conf

iptables-allports

action.d/iptables-allports.conf old name for iptables[type=allports]: blocks every port for the banned IP. Full setup: this guide.

action.d/iptables-allports.conf

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
actionstart
ipset -exist create <ipmset> <ipsettype> timeout <default-ipsettime> maxelem <maxelem> <familyopt>
<_ipt_add_rules>
actionban
ipset -exist add <ipmset> <ip> timeout <ipsettime>
actionunban
ipset -exist del <ipmset> <ip>
ParameterDefault
ipsettypehash:ip
default-ipsettime0
ipsettime0
maxelem65536
timeout-bantime$([ "<bantime>" -le 2147483 ] && echo "<bantime>" || echo 0)
ipmsetf2b-<name>
familyopt(empty)

action.d/iptables-ipset.conf

iptables-ipset-proto4

action.d/iptables-ipset-proto4.conf ipset ban for very old ipset v4 systems. Full setup: this guide.

Commands and parameters
actionstart
ipset --create f2b-<name> maxelem <maxelem> iphash
<_ipt_add_rules>
actionban
ipset --test f2b-<name> <ip> ||  ipset --add f2b-<name> <ip>
actionunban
ipset --test f2b-<name> <ip> && ipset --del f2b-<name> <ip>
ParameterDefault
maxelem65536

action.d/iptables-ipset-proto4.conf

iptables-ipset-proto6

action.d/iptables-ipset-proto6.conf iptables + ipset ban on the jail's ports. Full setup: this guide.

action.d/iptables-ipset-proto6.conf

iptables-ipset-proto6-allports

action.d/iptables-ipset-proto6-allports.conf iptables + ipset ban on all ports. Full setup: this guide.

action.d/iptables-ipset-proto6-allports.conf

iptables-multiport

action.d/iptables-multiport.conf old name for iptables[type=multiport]: blocks the jail's ports. Full setup: this guide.

action.d/iptables-multiport.conf

iptables-multiport-log

action.d/iptables-multiport-log.conf iptables multiport ban that also logs dropped packets. Full setup: this guide.

Commands and parameters
actionstart
<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>
actionban
<iptables> -I f2b-<name> 1 -s <ip> -j f2b-<name>-log
actionunban
<iptables> -D f2b-<name> -s <ip> -j f2b-<name>-log

action.d/iptables-multiport-log.conf

iptables-new

action.d/iptables-new.conf iptables ban that only matches new connections. Full setup: this guide.

action.d/iptables-new.conf

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
actionstart
if [ `id -u` -eq 0 ];then
{ %(_ipt_check_rule)s >/dev/null 2>&1; } || { <iptables> -I <chain> %(_ipt_chain_rule)s; }
fi
actionban
echo +<ip> > /proc/net/xt_recent/<iptname>
actionunban
echo -<ip> > /proc/net/xt_recent/<iptname>
ParameterDefault
iptnamef2b-<name>

action.d/iptables-xt_recent-echo.conf

mikrotik

action.d/mikrotik.conf adds the banned IP to an address list on a MikroTik router over SSH.

Commands and parameters
actionban
%(command)s "/ip firewall address-list add list=\"%(list)s\" address=<ip> comment=%(comment)s"
actionunban
%(command)s "/ip firewall address-list remove [find list=\"%(list)s\" comment=%(comment)s]"
ParameterDefault
name"%(__name__)s"

action.d/mikrotik.conf

netscaler

action.d/netscaler.conf adds banned IPs to a Citrix NetScaler (ADC) dataset.

Commands and parameters
actionstart
curl -kH 'Authorization: Basic <ns_auth>' https://<ns_host>/nitro/v1/config
actionban
curl -k -H 'Authorization: Basic <ns_auth>' -X PUT -d '{"policydataset_value_binding":{"name":"<ns_dataset>","value":"<ip>"}}' https://<ns_host>/nitro/v1/config/
actionunban
curl -H 'Authorization: Basic <ns_auth>' -X DELETE -k "https://<ns_host>/nitro/v1/config/policydataset_value_binding/<ns_dataset>?args=value:<ip>"
ParameterDefault
ns_host(empty)
ns_auth(empty)
ns_dataset(empty)

action.d/netscaler.conf

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
actionstart
<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
actionban
<nftables> add element <table_family> <table> <addr_set> \{ <ip> \}
actionunban
<nftables> delete element <table_family> <table> <addr_set> \{ <ip> \}
ParameterDefault
tablef2b-table
table_familyinet
chainf2b-chain
chain_typefilter
chain_hookinput
chain_priority-1
addr_typeipv4_addr
namedefault
portssh
protocoltcp
blocktypereject
nftablesnft
addr_setaddr-set-<name>
addr_familyip
addr_options<sp>flags interval\;

action.d/nftables.conf

nftables-allports

action.d/nftables-allports.conf old name for nftables[type=allports]. Full setup: this guide.

action.d/nftables-allports.conf

nftables-multiport

action.d/nftables-multiport.conf old name for nftables[type=multiport]. Full setup: this guide.

action.d/nftables-multiport.conf

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
actionstart
touch '%(blck_lst_file)s'
actionban
%(_echo_blck_row)s >> '%(blck_lst_file)s'; %(blck_lst_reload)s
actionunban
id=$(%(_echo_blck_row)s | sed -e 's/[]\/$*.^|[]/\\&/g'); sed -i "/^$id$/d" %(blck_lst_file)s; %(blck_lst_reload)s

action.d/nginx-block-map.conf

npf

action.d/npf.conf bans with NPF tables on NetBSD.

Commands and parameters
actionban
/sbin/npfctl table <tablename> add <ip>
actionunban
/sbin/npfctl table <tablename> rem <ip>
ParameterDefault
tablenamefail2ban

action.d/npf.conf

nsupdate

action.d/nsupdate.conf publishes banned IPs as DNS records with nsupdate (a DIY DNS blocklist).

Commands and parameters
actionban
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>
actionunban
echo <ip> | awk -F. '{print "update delete "$4"."$3"."$2"."$1".<domain>"; print "send"}' | <nsupdatecmd> -k <keyfile>
ParameterDefault
domain(empty)
ttl60
rdataYour IP has been banned
nsupdatecmd/usr/bin/nsupdate
keyfile(empty)

action.d/nsupdate.conf

osx-afctl

action.d/osx-afctl.conf bans with afctl on old macOS Server.

Commands and parameters
actionban
/usr/libexec/afctl -a <ip> -t <bantime>
actionunban
/usr/libexec/afctl -r <ip>

action.d/osx-afctl.conf

osx-ipfw

action.d/osx-ipfw.conf bans with ipfw on old macOS.

Commands and parameters
actionban
ipfw add <rulenum> set <setnum> <blocktype> log <block> from <ip> to <dst> <port>
actionunban
ipfw delete `ipfw -S list | grep -i 'set <setnum> <blocktype> log <block> from <ip> to <dst>' | awk '{print $1;}'`
ParameterDefault
portssh
dstme
blocktcp
blocktypeunreach port
setnum10
rulenum"`echo $((RANDOM%%2000+10000))`"

action.d/osx-ipfw.conf

pf

action.d/pf.conf bans with pf tables on OpenBSD, FreeBSD and macOS.

Commands and parameters
actionstart
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-
actionban
<pfctl> -t <tablename>-<name> -T add <ip>
actionunban
<pfctl> -t <tablename>-<name> -T delete <ip>
ParameterDefault
tablenamef2b
blockblock quick
protocoltcp
actiontype<multiport>
allportsany
multiportany port $port

action.d/pf.conf

route

action.d/route.conf bans with a blackhole/unreachable route instead of a firewall rule.

Commands and parameters
actionban
ip route add <blocktype> <ip>
actionunban
ip route del <blocktype> <ip>
ParameterDefault
blocktypeunreachable

action.d/route.conf

shorewall

action.d/shorewall.conf bans through Shorewall's blacklist.

Commands and parameters
actionban
shorewall<family> <blocktype> <ip>
actionunban
shorewall<family> allow <ip>
ParameterDefault
family(empty)
blocktypereject

action.d/shorewall.conf

shorewall-ipset-proto6

action.d/shorewall-ipset-proto6.conf bans with Shorewall using an ipset.

Commands and parameters
actionstart
if ! ipset -quiet -name list f2b-<name> >/dev/null;
then ipset -quiet -exist create f2b-<name> <ipsettype> timeout <default-ipsettime> maxelem <maxelem>;
fi
actionban
ipset add f2b-<name> <ip> timeout <ipsettime> -exist
actionunban
ipset del f2b-<name> <ip> -exist
ParameterDefault
ipsettypehash:ip
maxelem65536

action.d/shorewall-ipset-proto6.conf

symbiosis-blacklist-allports

action.d/symbiosis-blacklist-allports.conf bans with the Bytemark Symbiosis firewall.

Commands and parameters
actionban
echo 'all' >| /etc/symbiosis/firewall/blacklist.d/<ip>.auto
<iptables> -I <chain> 1 -s <ip> -j <blocktype>
actionunban
rm -f /etc/symbiosis/firewall/blacklist.d/<ip>.auto
<iptables> -D <chain> -s <ip> -j <blocktype> || :
ParameterDefault
chainblacklist
blocktypeDROP

action.d/symbiosis-blacklist-allports.conf

ufw

action.d/ufw.conf bans by inserting ufw deny rules (needs ufw enabled). Full setup: this guide.

Commands and parameters
actionban
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>
actionunban
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
ParameterDefault
addprepend
blocktypereject
destinationany
application(empty)
commentby Fail2Ban after <failures> attempts against <name>

action.d/ufw.conf

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
actionstart
printf %%b "The jail <name> has been started successfully." | <apprise> -t "[Fail2Ban] <name>: started on `uname -n`"
actionban
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`"
ParameterDefault
config/etc/fail2ban/apprise.conf
args(empty)
appriseapprise -c "<config>" <args>

action.d/apprise.conf

mail

action.d/mail.conf e-mails a short notice for each ban (mail command). Full setup: email alerts.

Commands and parameters
actionstart
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>
actionban
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>
ParameterDefault
namedefault
destroot

action.d/mail.conf

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
actionstart
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>
actionban
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
ParameterDefault
namedefault
lines5
tmpfile/var/run/fail2ban/tmp-mail.txt
destroot

action.d/mail-buffered.conf

mail-whois

action.d/mail-whois.conf e-mails each ban with whois data (mail command). Full setup: email alerts.

Commands and parameters
actionstart
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>
actionban
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>
ParameterDefault
namedefault
destroot

action.d/mail-whois.conf

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
actionstart
printf %%b "Hi,\n
The jail <name> has been started successfully.\n
Regards,\n
Fail2Ban" | <mailcmd> "[Fail2Ban] <name>: started on <fq-hostname>" <dest>
actionban
%(_ban_mail_content)s | <mailcmd> "[Fail2Ban] <name>: banned <ip> from <fq-hostname>" <dest>
ParameterDefault
mailcmdmail -E 'set escape' -s
namedefault
destroot
logpath/dev/null

action.d/mail-whois-lines.conf

sendmail

action.d/sendmail.conf e-mails a short notice for each ban (sendmail). Full setup: email alerts.

Commands and parameters
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
Regards,\n
Fail2Ban" | <mailcmd>
ParameterDefault
namedefault

action.d/sendmail.conf

sendmail-buffered

action.d/sendmail-buffered.conf e-mails a summary after a number of bans (sendmail). Full setup: email alerts.

Commands and parameters
actionstart
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>
actionban
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
ParameterDefault
namedefault
lines5
tmpfile/var/run/fail2ban/tmp-mail.txt

action.d/sendmail-buffered.conf

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
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
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>
ParameterDefault
namedefault
logpath/dev/null

action.d/sendmail-geoip-lines.conf

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
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
Here is more information about <ip> :\n
`%(_whois_command)s`\n
Regards,\n
Fail2Ban" | <mailcmd>
ParameterDefault
namedefault

action.d/sendmail-whois.conf

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
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
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>
ParameterDefault
namedefault

action.d/sendmail-whois-ipjailmatches.conf

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
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
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>
ParameterDefault
namedefault

action.d/sendmail-whois-ipmatches.conf

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
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
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>
ParameterDefault
namedefault
logpath/dev/null

action.d/sendmail-whois-lines.conf

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
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
Here is more information about <ip> :\n
`%(_whois_command)s`\n\n
Matches:\n
<matches>\n\n
Regards,\n
Fail2Ban" | <mailcmd>
ParameterDefault
namedefault

action.d/sendmail-whois-matches.conf

smtp

action.d/smtp.py Python action that e-mails ban notices over SMTP directly (no local MTA needed). Full setup: email alerts.

action.d/smtp.py

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
actionban
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>"
ParameterDefault
abuseipdb_apikey(empty)

action.d/abuseipdb.conf

blocklist_de

action.d/blocklist_de.conf reports banned IPs to blocklist.de by e-mail. Full setup: this guide.

Commands and parameters
actionban
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"

action.d/blocklist_de.conf

complain

action.d/complain.conf e-mails an abuse complaint to the addresses in the IP's whois record.

Commands and parameters
actionban
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
fi

action.d/complain.conf

dshield

action.d/dshield.conf submits attack reports to DShield (SANS Internet Storm Center).

Commands and parameters
actionban
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
fi
actionunban
if [ -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
ParameterDefault
port???
userid0
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}).*/
protocoltcp
lines50
minreportinterval3600
maxbufferage21600
srcport???
tcpflags(empty)
mailcmdmail -E 'set escape' -s
mailargs(empty)
destreports@dshield.org
tmpfile/var/run/fail2ban/tmp-dshield

action.d/dshield.conf

ipthreat

action.d/ipthreat.conf reports banned IPs to ipthreat.net. Full setup: this guide.

Commands and parameters
actionban
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\"}"
ParameterDefault
ipthreat_apikey(empty)
ipthreat_system<name>
ipthreat_flags8

action.d/ipthreat.conf

mynetwatchman

action.d/mynetwatchman.conf submits attack reports to myNetWatchman.

Commands and parameters
actionban
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
ParameterDefault
port0
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}).*/
protocoltcp
agentFail2ban
getcmdwget --no-verbose --tries=3 --waitretry=10 --connect-timeout=10 --read-timeout=60 --retry-connrefused --output-document=
srcport0
mnwurlhttp://mynetwatchman.com/insertwebreport.asp
tmpfile/var/run/fail2ban/tmp-mynetwatchman

action.d/mynetwatchman.conf

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
actionban
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> $ADDRESSES

action.d/xarf-login-attack.conf

Testing 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
actionstart
if [ ! -z '<target>' ]; then touch <target>; fi;
printf %%b "<init>\n" <to_target>
echo "%(debug)s started"
actionban
printf %%b "+<ip>\n" <to_target>
echo "%(debug)s banned <ip> (family: <family>)"
actionunban
printf %%b "-<ip>\n" <to_target>
echo "%(debug)s unbanned <ip> (family: <family>)"
ParameterDefault
init123
target/var/run/fail2ban/fail2ban.dummy
to_target>> <target>

action.d/dummy.conf

firewallcmd-common

action.d/firewallcmd-common.conf shared settings included by the other firewallcmd-* actions. Full setup: this guide.

Commands and parameters
ParameterDefault
namedefault
port1:65535
protocoltcp
familyipv4
chainINPUT_direct
zonepublic
servicessh
rejecttypeicmp-port-unreachable
blocktypeREJECT --reject-with <rejecttype>
rich-blocktypereject type='<rejecttype>'

action.d/firewallcmd-common.conf

helpers-common

action.d/helpers-common.conf helper commands (log grepping) shared by the mail actions.

Commands and parameters
ParameterDefault
greplimittail -n <grepmax>
grepmax1000
grepopts-m <grepmax>

action.d/helpers-common.conf

mail-whois-common

action.d/mail-whois-common.conf shared settings for the mail-whois actions.

action.d/mail-whois-common.conf

sendmail-common

action.d/sendmail-common.conf shared settings for the sendmail-* actions.

Commands and parameters
actionstart
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>
ParameterDefault
mailcmd/usr/sbin/sendmail -f "<sender>" "<dest>"
destroot
senderfail2ban
sendernameFail2Ban

action.d/sendmail-common.conf

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.