fail2ban
fail2ban is a security tool that automatically detects brute-force attacks against SSH, Nginx, Apache, and other services, then temporarily bans the offending source IP addresses. It monitors log files and blocks any IP that exceeds a failure threshold by adding rules to iptables / nftables. Ban targets are managed through configuration units called "jails," which can be tuned individually per service.
Syntax
# -----------------------------------------------
# /etc/fail2ban/jail.local — basic settings ([DEFAULT])
# -----------------------------------------------
# [DEFAULT] section
# → Sets default values shared across all jails
# → Individual jails can override these by specifying the same key
# bantime = {seconds | duration string}
# → Specifies how long a ban lasts
# → A negative value (-1) makes the ban permanent
# Example: bantime = 1h
# Example: bantime = -1
# findtime = {seconds | duration string}
# → The time window in which maxretry failures are counted
# Example: findtime = 10m
# maxretry = {integer}
# → Number of failures within findtime that triggers a ban
# Example: maxretry = 5
# ignoreip = {CIDR | IP address} [{CIDR | IP address} ...]
# → Space-separated list of addresses to exclude from banning
# → Always add your admin and management machine IPs here
# Example: ignoreip = 127.0.0.1/8 ::1 203.0.113.10
# -----------------------------------------------
# /etc/fail2ban/jail.local — jail settings
# -----------------------------------------------
# [{jail name}] section
# → Defines ban settings for each service
# → Set enabled = true to activate the jail
# enabled = {true | false}
# → Specifies whether this jail is active
# Example: enabled = true
# filter = {filter name}
# → References /etc/fail2ban/filter.d/{filter name}.conf
# → Many built-in filters are available
# Example: filter = sshd
# logpath = {path to log file}
# → Specifies the log file to monitor
# Example: logpath = /var/log/auth.log
# port = {port number | service name}
# → Specifies the port to block when banning
# Example: port = ssh
# Example: port = http,https
# -----------------------------------------------
# fail2ban-client — management commands
# -----------------------------------------------
# fail2ban-client status
# → Displays a list of active jails
# fail2ban-client status {jail name}
# → Displays details for the specified jail (ban count, currently banned IPs)
# Example: fail2ban-client status sshd
# fail2ban-client set {jail name} unbanip {IP address}
# → Manually removes a ban on the specified IP
# Example: fail2ban-client set sshd unbanip 198.51.100.42
# fail2ban-client set {jail name} banip {IP address}
# → Manually bans the specified IP
# Example: fail2ban-client set sshd banip 198.51.100.99
# fail2ban-client reload
# → Reloads the configuration files (no service restart required)
Syntax Reference
| Setting / Command | Description |
|---|---|
bantime | Specifies how long a ban lasts. Accepts seconds or a duration string such as 1h / 10m. Use -1 for a permanent ban. |
findtime | Specifies the time window for counting failures. An IP is banned if it exceeds maxretry failures within this period. |
maxretry | The maximum number of failures allowed within findtime. Any source IP that exceeds this limit becomes a ban candidate. |
ignoreip | Space-separated list of IP addresses or CIDR ranges to exclude from banning. Always register your admin machines and jump servers here. |
enabled | Activates or deactivates a jail using true / false. |
filter | Specifies the filter name to use. References a configuration file in /etc/fail2ban/filter.d/. |
logpath | Specifies the path of the log file to monitor. Multiple files can be specified on separate lines. |
port | Specifies the port to block when banning. Accepts a service name (e.g., ssh) or a port number. |
fail2ban-client status | Displays a list of active jails, giving a quick overview of which jails are running. |
fail2ban-client status {jail name} | Displays detailed information for the specified jail, including ban count and currently banned IP addresses. |
fail2ban-client set {jail name} unbanip {IP} | Manually removes a ban on the specified IP. Useful when your own IP has been banned by mistake. |
fail2ban-client set {jail name} banip {IP} | Manually bans the specified IP. Use this to immediately block an attacker not yet captured in the logs. |
fail2ban-client reload | Reloads the configuration files and applies changes without restarting the service. |
fail2ban-client stop / start | Stops or starts the fail2ban service from the client. The service can also be managed via systemctl. |
Examples
/etc/fail2ban/jail.local
# ----------------------------------------------- # [DEFAULT] — settings shared across all jails # ----------------------------------------------- [DEFAULT] # Ban duration: 1 hour bantime = 1h # Ban if failures exceed maxretry within 10 minutes findtime = 10m # Maximum allowed failures (up to 5) maxretry = 5 # IPs / CIDRs excluded from banning # Excludes the lab's admin machine and jump server ignoreip = 127.0.0.1/8 ::1 203.0.113.10 10.0.0.0/8 # ----------------------------------------------- # [sshd] — brute-force protection for SSH # ----------------------------------------------- [sshd] # Enable this jail enabled = true # Use the built-in sshd filter filter = sshd # Block the SSH port port = ssh # Log path for Ubuntu / Debian systems logpath = /var/log/auth.log # Set a stricter maxretry for SSH maxretry = 3 # ----------------------------------------------- # [nginx-http-auth] — Nginx Basic Auth failure protection # ----------------------------------------------- [nginx-http-auth] enabled = true filter = nginx-http-auth port = http,https # Monitor the Nginx error log logpath = /var/log/nginx/error.log # ----------------------------------------------- # [nginx-limit-req] — Nginx rate limit exceeded protection # ----------------------------------------------- [nginx-limit-req] enabled = true filter = nginx-limit-req port = http,https logpath = /var/log/nginx/error.log # Raise maxretry for rate limit events to reduce false positives maxretry = 10
Run the following command:
$ sudo systemctl restart fail2ban $ sudo fail2ban-client status Status |- Number of jail: 3 `- Jail list: nginx-http-auth, nginx-limit-req, sshd $ sudo fail2ban-client status sshd Status for the jail: sshd |- Filter | |- Currently failed: 2 | |- Total failed: 17 | `- File list: /var/log/auth.log `- Actions |- Currently banned: 1 |- Total banned: 3 `- Banned IP list: 198.51.100.42 $ sudo fail2ban-client set sshd unbanip 198.51.100.42 1 $ sudo fail2ban-client status sshd Status for the jail: sshd |- Filter | |- Currently failed: 0 | |- Total failed: 17 | `- File list: /var/log/auth.log `- Actions |- Currently banned: 0 |- Total banned: 3 `- Banned IP list:
Overview
fail2ban is a log-based intrusion prevention framework. A daemon tails log files in the background, counts failure entries matched by a filter (a regular expression), and fires an action — by default, adding a rule to iptables / nftables — when the count exceeds maxretry within findtime. The ban is automatically lifted after bantime expires. Rather than editing /etc/fail2ban/jail.conf directly, the best practice is to write only your overrides in /etc/fail2ban/jail.local. This protects your local settings when a package update overwrites jail.conf. Forgetting to add your admin machine to ignoreip risks locking yourself out of the server, so always verify this before applying your configuration. For hardening SSH further, see the ssh-keygen and sshd_config (passwd_shadow) pages. For integration with firewall rules, see the ufw / iptables page.
If you find any errors or copyright issues, please contact us.