Logging Fail2Ban to Discord
Fail2Ban is a service that scans files like /var/log/auth.log
, looking for failed authentication types and bans IPs that make repeated failed requests. It does this by updating firewall rules on the host to reject new connections from those IPs. It comes ready to go for reading many standard log files (sshd, Apache, etc) and is easily configurable for any other log files you want to scan for auth errors. Even though Fail2Ban is great at reducing the rate of incoming failed authentication requests, it is only one step in securing your host.
Having a secure authentication set up is recommended along side to reduce the risk of a nefarious user gaining access to your system.
In my previous post, SSH Login Logging to Discord via Webhooks, we set up pam.d
to log SSH logins to Discord over a webhook. We can also do this with Fail2Ban using a custom action. If you already have Fail2Ban installed you can skip ahead to the configuration.
Installing Fail2Ban
I use Ubuntu Server as my main linux distribution, so all my commands are geared toward it.
First update your package repositories
1
sudo apt update
Then install the Fail2Ban package
1
sudo apt install fail2ban
Now verify if Fail2Ban was installed correctly you can check the status of the fail2ban
service. Since it is not configured yet, it won’t be running.
1
systemctl status fail2ban.service
Output of the systemctl status
command showing the status of the Fail2Ban service
Configuring Fail2Ban
Now that Fail2Ban is installed we can configure it to log to Discord. First let’s create our /etc/fail2ban/jail.local
to tell Fail2Ban what to do.
The default file (
/etc/fail2ban/jail.conf
) contains all the default supported monitoring points (Jails)
1
2
3
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
# using -l with nano gives you line numbers making it easier to read files.
sudo nano -l /etc/fail2ban/jail.local
Hit CTRL
+W
and type “bantime.increment” and hit ENTER
. Uncomment the line by deleted the #
at the beginning of it and set the value to true
.
bantime.icrement example:
1
2
3
# "bantime.increment" allows to use database for searching of previously banned ip's to increase a
# default ban time using special formula, default it is banTime * 1, 2, 4, 8, 16, 32...
bantime.increment = true
Hit CTRL
+W
and type “ignoreip” and hit ENTER
. Uncomment the line and verify that the IPs listed are the local IPs 127.0.0.1/8 ::1
. Then add a space at the end and add your local network subnet.
ignoreip example:
1
2
3
4
# "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 10.9.9.0/24 10.8.8.0/24
Hit CTRL
+w
again and search for “sshd”.
Replace:
1
2
3
port = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s
With:
1
2
3
4
5
6
enabled = true
action = discord_notifications
iptables-allports
port = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s
Hit CTRL
+x
and then y
to save and close the jail.local
file.
Creating the Discord Action
Now that we have our /etc/fail2ban/jail.local
file we can create the /etc/fail2ban/action.d/discord_notifications.conf
action. First we need to get a webhook URL from Discord. To do this open Discord and navigate to the channel settings of the channel you want to log to. Open the integration settings and create a webhook. Give it a name you’ll recognize and copy the url.
1
sudo nano /etc/fail2ban/action.d/discord_notifications.conf
Copy the following contents into the file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# discord_notifications.conf
# Fail2Ban Discord Webhook Action
# Updated By: Alex from https://blog.alexsguardian.net
# Author Source: Gilbn from https://technicalramblings.com
# Original Source: https://gist.github.com/sander1/075736a42db2c66bc6ce0fab159ca683
# Create the Discord Webhook in: Server settings -> Webhooks -> Create Webhooks
[Definition]
# Notify on Jail Startup
actionstart = curl -X POST "<webhook>" \
-H "Content-Type: application/json" \
-d '{"username": "Fail2Ban", "content":":white_check_mark: <hostname> - **[<name>]** jail has started"}'
# Notify on Jail Shutdown
actionstop = curl -X POST "<webhook>" \
-H "Content-Type: application/json" \
-d '{"username": "Fail2Ban", "content":":no_entry: <hostname> - **[<name>]** jail has been stopped"}'
# Notify on Ban
actionban = curl -X POST "<webhook>" \
-H "Content-Type: application/json" \
-d '{"username":"Fail2Ban", "content":":bell: <hostname> - **[<name>]** **BANNED** IP: `<ip>` for <bantime> hours after **<failures>** failure(s). Here is some info about the IP: https://db-ip.com/<ip>. Unban by running: `fail2ban-client unban <ip>`"}'
# Notify on Unban
actionunban = curl -X POST "<webhook>" \
-H "Content-Type: application/json" \
-d '{"username":"Fail2Ban", "content":":bell: <hostname> - **[<name>]** **UNBANNED** IP: [<ip>](https://db-ip.com/<ip>)"}'
[Init]
# Name of the jail in your jail.local file. default = [your-jail-name]
name = default
# Discord Webhook URL
webhook = <discord_webhook_url>
hostname = <hostname>
The above file is an edited version of the one edited by GilbN over at https://technicalramblings.com!
Replace <discord_webhook_url>
with the full webhook url you created earlier. Then update the <hostname>
with the name of the host you are running fail2ban on.
Example:
1
2
3
# Discord Webhook URL
webhook = https://discord.com/api/webhooks/17590182726070/AUJHWITUGHAIWUTYIAYWIT27617-Adg-hawuthawuhgiautgwaitgawiut
hostname = lab_host_1
Hit CTRL
+x
then y
to save and close the file.
Starting and Testing Fail2Ban
With everything configured we can now start up the fail2ban service and then check it’s status.
1
2
sudo systemctl start fail2ban.service
systemctl status fail2ban.service
Output of the systemctl status
command showing the running status of the Fail2Ban service
In your Discord channel you should see a new message from your webhook user stating that the “[sshd] Jail has started” for your host.
Discord channel message stating that the [sshd] jail has started
Now to test Fail2Ban (without another host/network) we need to edit our Jail.local
config file again and remove our IP address from the ignoreip
list as well as update the ban time so we don’t have to wait long.
1
sudo nano /etc/fail2ban/jail.local
Hit CTRL
+w
and type “ignoreip =” then hit ENTER
Edit the line and remove your ip subnet so it looks like the following:
1
2
3
4
# "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
Hit CTRL
+w
again and type “bantime =”. Change the line to “30s”.
bantime example:
1
2
# "bantime" is the number of seconds that a host is banned.
bantime = 30s
Hit CTRL
+x
then y
to save and close the file. Now restart the fail2ban service.
1
sudo systemctl restart fail2ban.service
You will see two notifications in your Discord channel. One stating the “[sshd] jail stopped” and then a follow up one stating “[sshd] jail started.”
Discord channel messages stating that the [sshd] jail has stopped and started
PROCEED WITH CAUTION!
If you miss configure the settings you can ban yourself for 10m by default… or permanently. If this is on a machine with the ability for physical access you can unban yourself by running:
sudo fail2ban-client unban <ip>
Open a new terminal session on a different device (or the one you are using already if you are not on the device using fail2ban) and open a new ssh session.
Try and login as root
a few times with incorrect info. By default its 5 times before a ban happens.
1
ssh root@ip
You should see a ban message show up in your Discord channel and then 30s later an unban message.
Discord channel messages showing ban and unban of an IP
Once you confirm it is working you can re-edit your /etc/fail2ban/jail.local
config file and update the bantime =
option back to the value you want (default is 10m
though, I usually set it for 24h
). Also make sure to update ignoreip =
to include your subnet / IP again.
Extras and Conclusion
If you want to get an @ notification when a host is banned you can update the /etc/fail2ban/action.d/discord_notifications.conf
action to include an @ in the payload. To do this edit the file and replace:
1
-d '{"username":"Fail2Ban", "content":":bell: <hostname> - **[<name>]** **BANNED** IP: `<ip>` for <bantime> hours after **<failures>** failure(s). Here is some info about the IP: https://db-ip.com/<ip>. Unban by running: `fail2ban-client unban <ip>`"}'
with:
1
-d '{"username":"Fail2Ban", "content":"<@your-discord-user-id> :bell: <hostname> - **[<name>]** **BANNED** IP: `<ip>` for <bantime> hours after **<failures>** failure(s). Here is some info about the IP: https://db-ip.com/<ip>. Unban by running: `fail2ban-client unban <ip>`"}'
Make sure to replace the <@your-discord-user-id>
with your actual ID. If you do not know how to obtain this you can read the Discord docs, here, for more info.
If you have any questions please reach out via the comments down below or shoot me an email!
Happy banning!