Skip to content

Replace Fail2Ban's basic email alerts with beautiful HTML notifications featuring WHOIS, logs, and system metrics

License

Notifications You must be signed in to change notification settings

rcland12/fail2email

Repository files navigation

fail2email Logo

fail2email

Rich HTML Email Notifications for Fail2Ban

License: MIT Python 3.6+ Fail2Ban


Overview

Replace Fail2Ban's basic email notifications with beautiful, information-rich HTML emails. Get comprehensive incident reports delivered straight to your inbox with detailed context about security events.

What You Get

  • Incident Details - IP address, jail name, failure count, timestamps
  • WHOIS Lookup - Geographic and network information for banned IPs
  • Log Context - Recent log entries showing the actual attack patterns
  • Fail2Ban Statistics - Total banned IPs, active jails, per-jail metrics
  • System Health - CPU, memory, disk, network connections, GPU usage, Docker stats, uptime

Email Events

  • Ban - When an IP is blocked
  • Unban - When an IP ban expires or is manually removed
  • Start - When Fail2Ban service starts
  • Stop - When Fail2Ban service stops

Table of Contents


Prerequisites

Don't have Fail2Ban installed yet?

See INSTALL.md for a complete installation and configuration guide covering common services like SSH, Nginx, and Postfix.

This guide assumes you already have Fail2Ban installed and running on your system.


Quick Start

# 1. Install system packages
sudo apt update
sudo apt install -y python3 python3-pip whois

# 2. Install Python dependencies
sudo apt install python3-psutil
# Optional: GPU monitoring (Nvidia only)
sudo python3 -m pip install nvidia-ml-py --break-system-packages

# 3. Install notification script
sudo cp fail2ban_notify.py /usr/local/bin/fail2ban_notify.py
sudo chmod +x /usr/local/bin/fail2ban_notify.py
sudo chown root:root /usr/local/bin/fail2ban_notify.py

# 4. Install Fail2Ban action
sudo cp sendmail-python.conf /etc/fail2ban/action.d/sendmail-python.conf
sudo chmod 644 /etc/fail2ban/action.d/sendmail-python.conf

# 5. Configure jail.local (see section 4 below)
# 6. Setup Postfix (see section 5 below)
# 7. Restart Fail2Ban
sudo systemctl restart fail2ban

Installation

1. System Requirements

Install required system packages:

sudo apt update
sudo apt install -y python3 python3-pip whois

Verify Python installation:

which python3
# Should output: /usr/bin/python3

Supported Systems:

  • Ubuntu 18.04+
  • Debian 10+
  • Any Linux distribution with Python 3.6+ and Fail2Ban 0.11+

2. Python Dependencies

Install required Python packages:

sudo apt install python3-psutil

Optional: If you have an Nvidia GPU and want GPU stats in emails:

sudo python3 -m pip install nvidia-ml-py --break-system-packages

Note: The --break-system-packages flag is needed on newer Python versions to install packages system-wide. Skip the GPU package if you don't have Nvidia hardware.

Install the notification script:

sudo cp fail2ban_notify.py /usr/local/bin/fail2ban_notify.py
sudo chmod +x /usr/local/bin/fail2ban_notify.py
sudo chown root:root /usr/local/bin/fail2ban_notify.py

Verify installation:

ls -l /usr/local/bin/fail2ban_notify.py
# Should show: -rwxr-xr-x 1 root root ... /usr/local/bin/fail2ban_notify.py

3. Fail2Ban Action Configuration

Install the custom action file:

sudo cp sendmail-python.conf /etc/fail2ban/action.d/sendmail-python.conf
sudo chmod 644 /etc/fail2ban/action.d/sendmail-python.conf
sudo chown root:root /etc/fail2ban/action.d/sendmail-python.conf

Verify:

sudo fail2ban-client reload
# Should reload without errors

4. Fail2Ban Jail Configuration

Edit your Fail2Ban configuration (typically /etc/fail2ban/jail.local):

sudo nano /etc/fail2ban/jail.local

Add or update the [DEFAULT] section:

[DEFAULT]
# Email configuration
destemail  = your-email@example.com
sender     = fail2ban@yourhostname.com
sendername = Fail2Ban Alert System
linecount  = 15

# Action with Python HTML notifications
action_mwl = iptables-multiport[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s"]
             sendmail-python[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", sendername="%(sendername)s", linecount="%(linecount)s"]

# Apply to all jails (or specify per jail)
action = %(action_mwl)s

Configuration Variables:

Variable Description Example
destemail Email address to receive notifications admin@example.com
sender From email address fail2ban@server.com
sendername Display name in email client Fail2Ban Security
linecount Number of log lines to include in email 15

Custom SMTP Port (Bridge Network):

If you're running Postfix on a different port (e.g., 2525 on localhost):

Edit /etc/fail2ban/action.d/sendmail-python.conf and modify the actionban, actionunban, actionstart, and actionstop sections to include:

--smtp-host 127.0.0.1 --smtp-port 2525

5. Postfix Email Relay Setup

Postfix acts as an email relay to send notifications through your email provider.

Gmail App Password Setup

  1. Visit Google App Passwords
  2. Create a new app password named "Postfix" or "Fail2Ban"
  3. Copy the 16-character password (remove spaces)
  4. Use this password in the configuration below

Note: You must have 2-Factor Authentication enabled on your Google account to use App Passwords.

Option A: Docker Compose (Recommended)

Edit docker-compose.yaml with your credentials:

version: "3.8"
services:
  postfix:
    image: boky/postfix:latest
    container_name: postfix
    restart: unless-stopped
    ports:
      - "127.0.0.1:2525:25" # Expose on 127.0.0.1:2525
    environment:
      RELAYHOST: "[smtp.gmail.com]:587"
      RELAYHOST_USERNAME: "youremail@gmail.com"
      RELAYHOST_PASSWORD: "your_app_password_here"
      HOSTNAME: "mail"
      ALLOWED_SENDER_DOMAINS: "example.com localhost"
      MESSAGE_SIZE_LIMIT: "52428800"
      SMTP_TLS_SECURITY_LEVEL: "may"
      SMTP_USE_TLS: "yes"
      SMTPD_USE_TLS: "yes"

Deploy:

docker compose up -d

Verify:

docker compose ps
docker compose logs postfix -f

Option B: Docker Run

For non-Docker Compose deployments:

docker run -d \
    --name postfix \
    --restart unless-stopped \
    -p 127.0.0.1:2525:25 \
    --security-opt no-new-privileges:true \
    --cap-drop ALL \
    --cap-add CHOWN \
    --cap-add DAC_OVERRIDE \
    --cap-add SETGID \
    --cap-add SETUID \
    --cap-add NET_BIND_SERVICE \
    --health-cmd "nc -z localhost 25" \
    --health-interval 30s \
    --health-timeout 10s \
    --health-retries 3 \
    --health-start-period 10s \
    -e RELAYHOST="[smtp.gmail.com]:587" \
    -e RELAYHOST_USERNAME="youremail@gmail.com" \
    -e RELAYHOST_PASSWORD="your_app_password_here" \
    -e HOSTNAME="mail" \
    -e ALLOWED_SENDER_DOMAINS="example.com localhost" \
    -e MESSAGE_SIZE_LIMIT="52428800" \
    -e SMTP_HEADER_CHECKS="regexp:/etc/postfix/smtp_header_checks" \
    -e SMTP_TLS_SECURITY_LEVEL="may" \
    -e SMTP_USE_TLS="yes" \
    -e SMTPD_USE_TLS="yes" \
    -e INBOUND_DEBUGGING="0" \
    -e DISABLE_SMTP_UTF8="0" \
    boky/postfix:latest

Verify:

docker ps
docker logs postfix -f

Other Email Providers

While this guide focuses on Gmail, other providers work similarly. Update the RELAYHOST and credentials accordingly:

  • Outlook/Office365: [smtp.office365.com]:587
  • Yahoo: [smtp.mail.yahoo.com]:587
  • SendGrid: [smtp.sendgrid.net]:587
  • AWS SES: [email-smtp.us-east-1.amazonaws.com]:587

6. Testing & Verification

Test Email Delivery

Send a test notification:

/usr/bin/python3 /usr/local/bin/fail2ban_notify.py \
    --event ban \
    --ip "1.2.3.4" \
    --jail "test-jail" \
    --hostname "$(hostname -f)" \
    --logpath "/var/log/fail2ban.log" \
    --failures "5" \
    --dest "your@email.com" \
    --sender "fail2ban@test" \
    --sendername "Fail2Ban-Test" \
    --linecount 10

Test with Custom SMTP Port

If using port 2525:

/usr/bin/python3 /usr/local/bin/fail2ban_notify.py \
    --event ban \
    --ip "1.2.3.4" \
    --jail "test-jail" \
    --hostname "$(hostname -f)" \
    --logpath "/var/log/fail2ban.log" \
    --failures "5" \
    --dest "your@email.com" \
    --sender "fail2ban@test" \
    --sendername "Fail2Ban-Test" \
    --linecount 10 \
    --smtp-host 127.0.0.1 \
    --smtp-port 2525

Restart Fail2Ban

Apply all changes:

sudo systemctl restart fail2ban

Check status:

sudo fail2ban-client status
sudo systemctl status fail2ban

Trigger a Real Ban (Optional)

Test with SSH from another machine:

# From another computer, try SSH with wrong password 3+ times
ssh wronguser@yourserver

# Check if ban occurred
sudo fail2ban-client status sshd

You should receive an email notification!


Configuration Reference

Script Command-Line Arguments

The fail2ban_notify.py script accepts these arguments:

Argument Required Description
--event Yes Event type: ban, unban, start, stop
--ip For ban/unban IP address being banned/unbanned
--jail Yes Fail2Ban jail name (e.g., sshd, nginx-limit-req)
--hostname Yes Server hostname
--logpath Yes Path to log file being monitored
--failures For ban Number of failures that triggered the ban
--dest Yes Destination email address
--sender Yes Sender email address
--sendername Yes Sender display name
--linecount No Number of log lines to include (default: 10)
--smtp-host No SMTP server hostname (default: localhost)
--smtp-port No SMTP server port (default: 25)

Postfix Environment Variables

Variable Description Default
RELAYHOST Upstream SMTP server None
RELAYHOST_USERNAME SMTP authentication username None
RELAYHOST_PASSWORD SMTP authentication password None
HOSTNAME Postfix hostname Container hostname
ALLOWED_SENDER_DOMAINS Domains allowed to send email None
MESSAGE_SIZE_LIMIT Max message size in bytes 10240000 (10MB)
SMTP_TLS_SECURITY_LEVEL TLS security level may
SMTP_USE_TLS Enable outbound TLS no
SMTPD_USE_TLS Enable inbound TLS no

Troubleshooting

No Emails Being Sent

Check Fail2Ban logs:

sudo tail -f /var/log/fail2ban.log

Check Postfix logs:

docker logs postfix -f
# Look for SMTP errors or authentication failures

Verify script has execute permissions:

ls -l /usr/local/bin/fail2ban_notify.py
# Should show: -rwxr-xr-x

Test script manually:

sudo /usr/bin/python3 /usr/local/bin/fail2ban_notify.py --help
# Should display help without errors

Email Sent but Not Received

Check spam folder - Initial emails may be filtered as spam

Verify Gmail App Password:

  • Password should be 16 characters without spaces
  • 2FA must be enabled on Google account

Check sender domain:

  • Make sure sender domain is in ALLOWED_SENDER_DOMAINS

Test Postfix directly:

docker exec -it postfix bash
echo "Test email body" | mail -s "Test Subject" your@email.com

Python Script Errors

Missing dependencies:

# Reinstall psutil
sudo apt install --reinstall python3-psutil

# Check if psutil loads
python3 -c "import psutil; print(psutil.__version__)"

Permission errors:

# Ensure script is owned by root
sudo chown root:root /usr/local/bin/fail2ban_notify.py
sudo chmod 755 /usr/local/bin/fail2ban_notify.py

WHOIS Lookup Failures

Install whois:

sudo apt install whois
which whois  # Should output /usr/bin/whois

GPU Stats Not Showing

Verify Nvidia drivers:

nvidia-smi  # Should display GPU info

Install pynvml:

sudo python3 -m pip install nvidia-ml-py --break-system-packages

Fail2Ban Action Not Found

Reload Fail2Ban:

sudo fail2ban-client reload

Verify action file exists:

ls -l /etc/fail2ban/action.d/sendmail-python.conf

Check configuration syntax:

sudo fail2ban-client -t
# Should output "OK" if configuration is valid

Custom SMTP Port Issues

Verify Postfix is listening:

netstat -tlnp | grep 2525
# Or
ss -tlnp | grep 2525

Test connection:

telnet localhost 2525
# Should connect to Postfix

Update action file:

Make sure /etc/fail2ban/action.d/sendmail-python.conf includes the port parameter in all action sections.


Uninstalling

To completely remove fail2email and revert to default Fail2Ban notifications:

1. Stop Postfix Container

Docker Compose:

cd /path/to/fail2email
docker compose down

Docker Run:

docker stop postfix
docker rm postfix

2. Revert Fail2Ban Configuration

Edit /etc/fail2ban/jail.local:

sudo nano /etc/fail2ban/jail.local

Remove or comment out the fail2email configuration:

[DEFAULT]
# Remove or comment these lines:
# destemail  = your-email@example.com
# sender     = fail2ban@yourhostname.com
# sendername = Fail2Ban Alert System
# linecount  = 15
# action_mwl = iptables-multiport[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s"]
#              sendmail-python[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", sendername="%(sendername)s", linecount="%(linecount)s"]
# action = %(action_mwl)s

Or revert to default Fail2Ban action:

[DEFAULT]
# Use default mail action (optional)
destemail = your-email@example.com
action = %(action_)s

3. Remove Fail2Ban Action File

sudo rm /etc/fail2ban/action.d/sendmail-python.conf

4. Remove Python Script

sudo rm /usr/local/bin/fail2ban_notify.py

5. Remove Python Dependencies (Optional)

Only remove if not used by other applications:

# Remove GPU monitoring (if installed)
sudo python3 -m pip uninstall -y nvidia-ml-py

# Note: Keep python3-psutil if other applications use it
# sudo apt remove python3-psutil  # Only if you're sure nothing else needs it

6. Restart Fail2Ban

Apply the changes:

sudo systemctl restart fail2ban

Verify Fail2Ban is running:

sudo systemctl status fail2ban
sudo fail2ban-client status

7. Clean Up Docker Images (Optional)

Remove the Postfix Docker image if no longer needed:

docker rmi boky/postfix:latest

Verification

After uninstalling, test that Fail2Ban still works:

# Check status
sudo fail2ban-client status

# Trigger a test ban (from another machine)
# Try failed SSH logins 3+ times

# Verify ban occurred
sudo fail2ban-client status sshd

You should see bans occurring but no email notifications being sent through fail2email.

Re-enabling Default Fail2Ban Emails

If you want to use Fail2Ban's default email notifications after uninstalling:

  1. Install a local mail server:

    sudo apt install mailutils postfix
    # Choose "Internet Site" during setup
  2. Configure /etc/fail2ban/jail.local:

    [DEFAULT]
    destemail = your-email@example.com
    sender = fail2ban@yourhostname
    action = %(action_mw)s
  3. Restart Fail2Ban:

    sudo systemctl restart fail2ban

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Development Setup

  1. Fork the repository
  2. Clone your fork: git clone https://github.com/rcland12/fail2email.git
  3. Create a feature branch: git checkout -b feature/amazing-feature
  4. Make your changes
  5. Test thoroughly
  6. Commit: git commit -m 'Add amazing feature'
  7. Push: git push origin feature/amazing-feature
  8. Open a Pull Request

Testing

Always test changes with:

# Syntax check
python3 -m py_compile fail2ban_notify.py

# Manual test
sudo /usr/bin/python3 fail2ban_notify.py [args...]

License

This project is licensed under the MIT License - see the LICENSE file for details.


Acknowledgments

  • Fail2Ban - Intrusion prevention framework
  • boky/postfix - Docker Postfix image
  • All contributors who have helped improve this project

Made with ❤️ for the security community

Report Bug · Request Feature

About

Replace Fail2Ban's basic email alerts with beautiful HTML notifications featuring WHOIS, logs, and system metrics

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Languages