Study Note: macOS Server - fail2ban
Configuring Fail2Ban on macOS Silicon
Fail2Ban is a crucial security tool that helps protect your server from various types of brute force and malicious attacks by monitoring log files and banning IPs that show suspicious behavior.
Introduction to Fail2Ban
Fail2Ban is an intrusion prevention software framework that protects computer servers from brute-force attacks. It works by scanning log files and banning IPs that exhibit malicious behaviors, such as too many password failures, seeking for exploits, etc.
Installation and Basic Setup
Installation Steps
1. Install Fail2Ban using Homebrew:
brew install fail2ban
2. Directory Structure:
- Configuration files typically reside in
/usr/local/etc/fail2ban/
- Logs can be found at
/usr/local/var/log/fail2ban.log
Configuration
Copy the Default Configuration File
Create a local copy of the default configuration file.
sudo cp /usr/local/etc/fail2ban/jail.conf /usr/local/etc/fail2ban/jail.local
Configure Jail for SSH
Open the jail.local
file and enable the SSH jail by adding or modifying the following section:
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 5
Configure Jail for NGINX
Separated Configuration [Choice 1 of 2]
You can add separate sections for monitoring authentication errors and access logs if they are for different types of issues or combine them if you want a unified approach. Here's an example configuration that includes both log files:
[nginx-http-auth] enabled = true port = http,https filter = nginx-http-authlogpath = /opt/homebrew/etc/nginx/error.log
maxretry = 3 bantime = 3600 [nginx-access] enabled = true port = http,https filter = nginx-accesslogpath = /opt/homebrew/etc/nginx/access.log
maxretry = 5 bantime = 3600
Filter Definitions
nginx-http-auth Filter:
Create or edit the filter file /opt/homebrew/etc/fail2ban/filter.d/nginx-http-auth.conf
to match patterns related to authentication issues.
Example filter configuration for nginx-http-auth
:
[Definition] failregex = ^<HOST> - .* "GET .* HTTP/.*" 401 .* ignoreregex =
nginx-access Filter:
Create or edit the filter file /opt/homebrew/etc/fail2ban/filter.d/nginx-access.conf
to match patterns related to access issues.
Example filter configuration for nginx-access
:
[Definition] failregex = ^<HOST> - .* "GET .* HTTP/.*" 404 .* ignoreregex =
Combined Configuration [Choice 2 of 2]
If you prefer to combine the monitoring of both logs under a single section, you can specify multiple log paths in the logpath
directive. Here’s an example:
[nginx] enabled = true port = http,https filter = nginx logpath = /opt/homebrew/etc/nginx/error.log /opt/homebrew/etc/nginx/access.log maxretry = 5 bantime = 3600
Combined Filter Definition
Create or edit the filter file /opt/homebrew/etc/fail2ban/filter.d/nginx.conf
to include patterns from both error.log
and access.log
.
Example combined filter configuration for nginx
:
[Definition] failregex = ^<HOST> - .* "GET .* HTTP/.*" 401 .* # Unauthorized access ^<HOST> - .* "GET .* HTTP/.*" 404 .* # Not found ignoreregex =
Advanced Configuration
Persistent Bans
To make bans persistent across reboots, add the following:
[DEFAULT]
bantime = -1
Ensure bans persist across reboots by using a database.
dbfile = /var/lib/fail2ban/fail2ban.sqlite3
Whitelist Trusted IPs
To whitelist certain IPs, add:
ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24
Avoid banning trusted IPs.
ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24
Custom Filters
Create custom filters by defining regex patterns:
Custom filter file: /usr/local/etc/fail2ban/filter.d/custom.conf
[Definition]
failregex = <custom-regex-pattern>
Custom Actions
Create custom actions to integrate with other security tools or logging systems.
action = %(action_mwl)s
Integration with Firewalls
Integrate Fail2Ban with your firewall, e.g., pf
on macOS:
[DEFAULT]
banaction = pf
Rate-Limiting and SSH Specifics
Invalid User Attempts:
[sshd-invalid]
enabled = true
logpath = /var/log/auth.log
filter = sshd-invalid
maxretry = 3
Non-standard Port:
[sshd]
port = 2222
Brute-force Detection:
[sshd]
enabled = true
logpath = /var/log/auth.log
maxretry = 5
NGINX Specifics
404 Error Pattern:
[nginx-404]
enabled = true
logpath = /opt/homebrew/etc/nginx/access.log
maxretry = 10
Multiple Failed Login Attempts:
[nginx-login]
enabled = true
logpath = /opt/homebrew/etc/nginx/error.log
maxretry = 3
SQL Injection Attempts:
[nginx-sqli]
enabled = true
logpath = /opt/homebrew/etc/nginx/error.log
maxretry = 1
filter = nginx-sqli
Granular Ban Settings
Define ban times and retry limits:
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 3
Granular Ban Settings
Ban Time: Duration for which an IP is banned.
bantime = 3600 # 1 hour
Find Time: Time window within which maxretry attempts are counted.
findtime = 600 # 10 minutes
Max Retry: Number of attempts allowed before banning.
maxretry = 5
Custom Actions
Define custom actions in /usr/local/etc/fail2ban/action.d/
:
Create custom.conf
:
[Definition]
actionstart = <custom-start-command>
actionstop = <custom-stop-command>
actioncheck = <custom-check-command>
Starting and Managing Fail2Ban
Start Fail2Ban
sudo fail2ban-client start
Enable Fail2Ban at Startup
To ensure Fail2Ban starts at boot, create a LaunchDaemon. Save the following as /Library/LaunchDaemons/com.fail2ban.plist
:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.fail2ban</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/fail2ban-client</string>
<string>start</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
</dict>
</plist>
Load the Daemon
sudo launchctl load /Library/LaunchDaemons/com.fail2ban.plist
Monitoring and Logs
Check Fail2Ban Status
sudo fail2ban-client status
Check Specific Jail Status
sudo fail2ban-client status sshd
sudo fail2ban-client status nginx-http-auth
Unban an IP
sudo fail2ban-client set sshd unbanip <IP_ADDRESS>
View Logs
Check Fail2Ban logs:
tail -f /usr/local/var/log/fail2ban.log
Restart Fail2Ban
sudo brew services restart fail2ban
Core Components
Jails
Definition: A jail specifies the combination of a filter and an action.
Configuration: Jails are defined in the configuration file (/usr/local/etc/fail2ban/jail.conf
or /usr/local/etc/fail2ban/jail.local
).
Example:
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 5
bantime = 3600
Filters
Definition: Filters define the patterns to search for in log files.
Location: Filters are stored in the /usr/local/etc/fail2ban/filter.d/
directory.
Example:
[Definition]
failregex = ^<HOST> - .* "GET .* HTTP/.*" 404 .*
ignoreregex =
Actions
Definition: Actions define what to do when a filter catches an event.
Common Actions: Banning an IP via iptables, sending email notifications, etc.
Example:
action = iptables[name=HTTP, port=http, protocol=tcp]
Extending Fail2Ban
Custom Filters
Create custom filters for unique log patterns. Create a file in /etc/fail2ban/filter.d/custom.conf
:
[Definition]
failregex = <CUSTOM_REGEX>
ignoreregex =
Integration with Firewalls
Integrate Fail2Ban with firewalls like iptables or pf to enhance security:
[DEFAULT]
banaction = iptables-multiport
Rate Limiting
Implement rate limiting to mitigate abuse:
[http-get-dos]
enabled = true
port = http,https
filter = http-get-dos
logpath = /var/log/nginx/access.log
maxretry = 300
findtime = 300
bantime = 600
action = iptables[name=HTTP, port=http, protocol=tcp]
Custom Patterns for SSH
SSH Invalid User Attempts
[ssh-invalid-user]
enabled = true
filter = sshd-invalid-user
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
[Definition]
failregex = ^<HOST> .* Invalid user .*$
ignoreregex =
SSH Connection Attempts with Non-Standard Port
[ssh-non-standard-port]
enabled = true
filter = sshd-non-standard-port
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
[Definition]
failregex = ^<HOST> .* Failed password for .* from <HOST> port [^22].*$
ignoreregex =
SSH Brute-Force Detection
[ssh-brute-force]
enabled = true
filter = sshd-brute-force
logpath = /var/log/auth.log
maxretry = 5
bantime = 3600
[Definition]
failregex = ^<HOST> .* Received disconnect from <HOST>: 3: .* Too many authentication failures for .*$
ignoreregex =
Custom Patterns for NGINX
NGINX 404 Error Pattern
[nginx-404-errors]
enabled = true
filter = nginx-404
logpath = /opt/homebrew/etc/nginx/access.log
maxretry = 10
bantime = 3600
[Definition]
failregex = ^<HOST> - .* "GET .* HTTP/.*" 404 .*$
ignoreregex =
NGINX Multiple Failed Login Attempts
[nginx-login-fail]
enabled = true
filter = nginx-login-fail
logpath = /opt/homebrew/etc/nginx/error.log
maxretry = 5
bantime = 3600
[Definition]
failregex = ^<HOST> - .* "POST /login.*" 401 .*$
ignoreregex =
NGINX SQL Injection Attempts
[nginx-sql-injection]
enabled = true
filter = nginx-sql-injection
logpath = /opt/homebrew/etc/nginx/access.log
maxretry = 1
bantime = 86400
[Definition]
failregex = ^<HOST> - .* "GET .*select.*from.* HTTP/.*" 403 .*$
ignoreregex =