Skip to content

Commit

Permalink
Added fail2ban webhook module (alerta#227)
Browse files Browse the repository at this point in the history
  • Loading branch information
psyhomb authored and satterly committed Dec 2, 2018
1 parent 12a5f6b commit 140c6b6
Show file tree
Hide file tree
Showing 8 changed files with 496 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ Webhooks
* [Azure Monitor](webhooks/azuremonitor)
* [Mailgun](webhooks/mailgun)
* [Sentry](webhooks/sentry)
* [Fail2Ban](webhooks/fail2ban)

License
-------
Expand Down
48 changes: 48 additions & 0 deletions integrations/fail2ban/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
Fail2Ban
========

Send Alerta event (alarm) if source IP is banned (valid user is using invalid password via SSHD or SFTP).

Configuration
-------------

Alerta webhook module and documentation can be found [here](../../webhooks/fail2ban)

Clone git repo on the server where `fail2ban` is installed and execute following commands as root:

Copy action script

```bash
cp -a fail2ban-alerta.sh /usr/local/bin/
chown root:root /usr/local/bin/fail2ban-alerta.sh
chmod +x /usr/local/bin/fail2ban-alerta.sh
```

Copy `fail2ban` action configuration file

```bash
cp -a alerta.conf /etc/fail2ban/action.d/
chown root:root /etc/fail2ban/action.d/alerta.conf
```

Modify configuration of `sshd` jail in the existing `/etc/fail2ban/jail.local` file by adding additional `alerta` action,
also be sure to modify action input parameters accordingly (`alertaurl` and `alertaapikey`).

**Note:** Example [jail.local](./jail.local) file is also provided

```plain
[sshd]
enabled = true
port = ssh
logpath = %(sshd_log)s
action = %(action_mwl)s
alerta[alertaurl=https://alerta.example.com/api/webhooks/fail2ban, alertaapikey=EXdp3haf4Xkk7Dpk5MFrqfafn6nYGgtz4JL4XzBY]
maxretry = 4
```

Restart `fail2ban` service

```plain
systemctl restart fail2ban
```
63 changes: 63 additions & 0 deletions integrations/fail2ban/alerta.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#
# Author: Milos Buncic
#
# IMPORTANT
#
# Please set jail.local's permission to 640 because it contains your Alerta API key.
#
# This action depends on curl.
#
# To create Alerta API Key: https://docs.alerta.io/en/latest/api/reference.html#api-keys
#

[Definition]

# Option: actionstart
# Notes.: command executed once at the start of Fail2Ban.
# Values: CMD
#
actionstart =

# Option: actionstop
# Notes.: command executed once at the end of Fail2Ban
# Values: CMD
#
actionstop =

# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =

# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: <ip> IP address
# <failures> number of failures
# <time> unix timestamp of the ban time
# Full list of Action Tags can be found in the man page:
# man jail.conf
# Values: CMD
#
actionban = echo <matches> | grep -q "Failed password for [a-z][-a-z0-9_]* from <ip>" && /usr/local/bin/fail2ban-alerta.sh <alertaurl> <alertaapikey> <ip> <failures> <logpath> || true

[Init]

# Option: alertaurl
# Notes.: Alerta API URL
# Values: STRING
#
alertaurl =

# Option: alertaapikey
# Notes.: Alerta API key
# Values: STRING
#
alertaapikey =

# Option: logpath
# Notes.: Absolute path to the log file
# Values: STRING
#
logpath = /var/log/auth.log
41 changes: 41 additions & 0 deletions integrations/fail2ban/fail2ban-alerta.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/bin/bash
# Author: Milos Buncic <[email protected]>
# Date: 2018/12/01
# Description: Send Alerta event if user exist but invalid password is used

# Example: https://alerta.example.com/api/webhooks/fail2ban
ALERTA_URL=${1}
# API key has to be generated on the Alerta side
# Example: EXdp3haf4Xkk7Dpk5MFrqfafn6nYGgtz4JL4XzBY
ALERTA_API_KEY=${2}

# Will be passed to by fail2ban as action tags (see alerta.conf): <ip> <failures> <logpath>
BANNED_IP=${3}
FAILURES=${4}
LOGPATH=${5}

if [[ ${#} -ne 5 ]]; then
echo "Usage: $(basename ${0}) alerta_url alerta_api_key banned_ip failures logpath"
exit 1
fi

MSG=$(egrep "\[[0-9]*?\]: Failed password for [a-z][-a-z0-9_]* from ${BANNED_IP}" ${LOGPATH} | tail -1)
BANNED_USER=$(echo ${MSG} | awk '{print $9}')
FQDN=$(hostname -f)

curl -sSL -X POST -H "X-API-Key: ${ALERTA_API_KEY}" -H "Content-Type: application/json" -d \
'
{
"hostname": "'${FQDN}'",
"attributes": {
"bannedIp": "'${BANNED_IP}'",
"bannedUser": "'${BANNED_USER}'"
},
"severity": "warning",
"environment": "Development",
"resource": "sshd",
"event": "The IP '${BANNED_IP}' has just been banned by Fail2Ban after '${FAILURES}' attempts!",
"message": "'"${MSG}"'"
}
' \
${ALERTA_URL}
226 changes: 226 additions & 0 deletions integrations/fail2ban/jail.local
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
[DEFAULT]

#
# MISCELLANEOUS OPTIONS
#

# "ignorself" specifies whether the local resp. own IP addresses should be ignored
# (default is true). Fail2ban will not ban a host which matches such addresses.
#ignorself = true

# "ignoreip" can be a list of IP addresses, CIDR masks or DNS hosts. Fail2ban
# will not ban a host which matches an address in this list. Several addresses
# can be defined using space (and/or comma) separator.
ignoreip = 127.0.0.1/8 ::1

# External command that will take an tagged arguments to ignore, e.g. <ip>,
# and return true if the IP is to be ignored. False otherwise.
#
# ignorecommand = /path/to/command <ip>
ignorecommand =

# "bantime" is the number of seconds that a host is banned.
bantime = 86400

# A host is banned if it has generated "maxretry" during the last "findtime"
# seconds.
findtime = 600

# "maxretry" is the number of failures before a host get banned.
maxretry = 3

# "backend" specifies the backend used to get files modification.
# Available options are "pyinotify", "gamin", "polling", "systemd" and "auto".
# This option can be overridden in each jail as well.
#
# pyinotify: requires pyinotify (a file alteration monitor) to be installed.
# If pyinotify is not installed, Fail2ban will use auto.
# gamin: requires Gamin (a file alteration monitor) to be installed.
# If Gamin is not installed, Fail2ban will use auto.
# polling: uses a polling algorithm which does not require external libraries.
# systemd: uses systemd python library to access the systemd journal.
# Specifying "logpath" is not valid for this backend.
# See "journalmatch" in the jails associated filter config
# auto: will try to use the following backends, in order:
# pyinotify, gamin, polling.
#
# Note: if systemd backend is chosen as the default but you enable a jail
# for which logs are present only in its own log files, specify some other
# backend for that jail (e.g. polling) and provide empty value for
# journalmatch. See https://github.com/fail2ban/fail2ban/issues/959#issuecomment-74901200
backend = auto

# "usedns" specifies if jails should trust hostnames in logs,
# warn when DNS lookups are performed, or ignore all hostnames in logs
#
# yes: if a hostname is encountered, a DNS lookup will be performed.
# warn: if a hostname is encountered, a DNS lookup will be performed,
# but it will be logged as a warning.
# no: if a hostname is encountered, will not be used for banning,
# but it will be logged as info.
# raw: use raw value (no hostname), allow use it for no-host filters/actions (example user)
usedns = warn

# "logencoding" specifies the encoding of the log files handled by the jail
# This is used to decode the lines from the log file.
# Typical examples: "ascii", "utf-8"
#
# auto: will use the system locale setting
logencoding = auto

# "enabled" enables the jails.
# By default all jails are disabled, and it should stay this way.
# Enable only relevant to your setup jails in your .local or jail.d/*.conf
#
# true: jail will be enabled and log files will get monitored for changes
# false: jail is not enabled
enabled = false

# "mode" defines the mode of the filter (see corresponding filter implementation for more info).
mode = normal

# "filter" defines the filter to use by the jail.
# By default jails have names matching their filter name
#
filter = %(__name__)s

#
# ACTIONS
#

# Some options used for actions

# Default banning action (e.g. iptables, iptables-new,
# iptables-multiport, shorewall, etc) It is used to define
# action_* variables. Can be overridden globally or per
# section within jail.local file
banaction = iptables-allports

# Destination email address used solely for the interpolations in
# jail.{conf,local,d/*} configuration files.
destemail = [email protected]

# Sender email address used solely for some actions
sendername = Fail2Ban
sender = fail2ban@<fq-hostname>

# E-mail action. Since 0.8.1 Fail2Ban uses sendmail MTA for the
# mailing. Change mta configuration parameter to mail if you want to
# revert to conventional 'mail'.
mta = sendmail

# Default protocol
protocol = tcp

# Specify chain where jumps would need to be added in ban-actions expecting parameter chain
chain = INPUT

# Ports to be banned
# Usually should be overridden in a particular jail
port = 0:65535

# Format of user-agent https://tools.ietf.org/html/rfc7231#section-5.5.3
fail2ban_agent = Fail2Ban/%(fail2ban_version)s

#
# Action shortcuts. To be used to define action parameter

# Default banning action (e.g. iptables, iptables-new,
# iptables-multiport, shorewall, etc) It is used to define
# action_* variables. Can be overridden globally or per
# section within jail.local file
# banaction = iptables-multiport
banaction_allports = iptables-allports

# The simplest action to take: ban only
action_ = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]

# ban & send an e-mail with whois report to the destemail.
action_mw = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
%(mta)s-whois[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"]

# ban & send an e-mail with whois report and relevant log lines
# to the destemail.
action_mwl = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
%(mta)s-whois-lines[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s"]

# See the IMPORTANT note in action.d/xarf-login-attack for when to use this action
#
# ban & send a xarf e-mail to abuse contact of IP address and include relevant log lines
# to the destemail.
action_xarf = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
xarf-login-attack[service=%(__name__)s, sender="%(sender)s", logpath=%(logpath)s, port="%(port)s"]

# ban IP on CloudFlare & send an e-mail with whois report and relevant log lines
# to the destemail.
action_cf_mwl = cloudflare[cfuser="%(cfemail)s", cftoken="%(cfapikey)s"]
%(mta)s-whois-lines[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s"]

# Report block via blocklist.de fail2ban reporting service API
#
# See the IMPORTANT note in action.d/blocklist_de.conf for when to use this action.
# Specify expected parameters in file action.d/blocklist_de.local or if the interpolation
# `action_blocklist_de` used for the action, set value of `blocklist_de_apikey`
# in your `jail.local` globally (section [DEFAULT]) or per specific jail section (resp. in
# corresponding jail.d/my-jail.local file).
#
action_blocklist_de = blocklist_de[email="%(sender)s", service=%(filter)s, apikey="%(blocklist_de_apikey)s", agent="%(fail2ban_agent)s"]

# Report ban via badips.com, and use as blacklist
#
# See BadIPsAction docstring in config/action.d/badips.py for
# documentation for this action.
#
# NOTE: This action relies on banaction being present on start and therefore
# should be last action defined for a jail.
#
action_badips = badips.py[category="%(__name__)s", banaction="%(banaction)s", agent="%(fail2ban_agent)s"]
#
# Report ban via badips.com (uses action.d/badips.conf for reporting only)
#
action_badips_report = badips[category="%(__name__)s", agent="%(fail2ban_agent)s"]

# Report ban via abuseipdb.com.
#
# See action.d/abuseipdb.conf for usage example and details.
#
action_abuseipdb = abuseipdb

# Choose default action. To change, just override value of 'action' with the
# interpolation to the chosen action shortcut (e.g. action_mw, action_mwl, etc) in jail.local
# globally (section [DEFAULT]) or per specific section
#action = iptables-allports
action = %(action_mwl)s


#
# JAILS
#

#
# SSH servers
#

[sshd]

enabled = true
port = ssh
logpath = %(sshd_log)s
action = %(action_mwl)s
alerta[alertaurl=https://alerta.example.com/api/webhooks/fail2ban, alertaapikey=EXdp3haf4Xkk7Dpk5MFrqfafn6nYGgtz4JL4XzBY]
maxretry = 4


[dropbear]

enabled = false
port = ssh
logpath = %(dropbear_log)s
maxretry = 6


[selinux-ssh]

enabled = false
port = ssh
logpath = %(auditd_log)s
Loading

0 comments on commit 140c6b6

Please sign in to comment.