Securing NGINX and SSH Servers on Ubuntu Using Fail2Ban
Ubuntu, a Debian-based, open-source Linux distribution, has emerged as a prominent operating system utilized extensively across both desktop and server environments. Its structured release cycle and robust Long-Term Support (LTS) versions ensure architectural stability, long-term sustainability, and enhanced security, making it a preferred choice for mission-critical applications. Notably, Ubuntu’s compliance with internationally recognized certifications, including Common Criteria, HITECH, FISMA, and FedRAMP, further reinforces its suitability for deployment within enterprise infrastructures and governmental frameworks requiring stringent security assurances. Ubuntu’s native support for critical network services such as NGINX and Secure Shell (SSH) underscores its utility as a server-grade operating system. NGINX functions as a high-performance, scalable web server capable of handling large volumes of concurrent connections, excelling in tasks such as static content delivery, reverse proxying and load balancing. Conversely, the SSH server provides cryptographically secured remote access for system administration, facilitating encrypted communications over untrusted networks.
However, the exposure of these services—particularly NGINX and SSH—to the public internet inevitably positions them as primary vectors for cyberattacks. Among the most pervasive threats are brute-force attacks, credential stuffing, and unauthorized access attempts, all of which pose significant risks to system confidentiality, integrity, and availability. Consequently, implementing proactive defense mechanisms is imperative to mitigate these risks within a holistic cybersecurity framework.
In this context, Fail2Ban emerges as a pivotal intrusion prevention system (IPS) within the Ubuntu ecosystem. This tutorial explains how you can secure NGINX and SSH services on your Ubuntu Linux servers using Fail2ban.
What is Fail2ban?
Fail2Ban is an intrusion prevention software framework used to monitor service logs and prohibit clients who consistently fail authentication attempts. Developed in the Python programming language, it aims to prevent brute-force attacks. It may operate on POSIX systems equipped with a locally installed interface to a packet-control system or firewall, such as iptables or TCP Wrapper.
Operating as a log-based defensive mechanism, Fail2Ban continuously monitors service logs, identifying repetitive unauthorized access attempts that surpass predefined thresholds. Upon detection, it dynamically enforces IP-based bans, effectively neutralizing ongoing attack vectors and preserving system integrity.
Fail2Ban's architecture is inherently modular and service-agnostic, allowing seamless integration with a range of services, including SSH, NGINX, and other commonly deployed network applications. Its configuration flexibility enables system administrators to tailor response strategies based on specific threat models, enhancing adaptive security postures. Readily available through Ubuntu’s official repositories, Fail2Ban plays a critical role in minimizing the system’s attack surface while ensuring service continuity and data integrity—core tenets of resilient cybersecurity design.
Prerequisites for Installing Fail2Ban on Ubuntu 24.04 LTS
Fail2Ban is a specialized security utility designed to protect servers against brute-force attacks, which represent a persistent and significant cybersecurity threat. Before proceeding with the installation of Fail2Ban on Ubuntu 24.04 LTS, it is essential to meet the following prerequisites to ensure optimal performance and compatibility.
System Resource Requirements
Owing to its lightweight architecture, Fail2Ban imposes minimal demands on system resources. Provided that the host system possesses adequate general resources, Fail2Ban operates efficiently without introducing significant overhead. Nevertheless, understanding the recommended baseline requirements ensures smooth operation, particularly in multi-service environments.
| Resource | Minimum Requirement | Recommended Specification | Notes | 
|---|---|---|---|
| CPU | 1 Core | --- | Minimal processing power is sufficient as Fail2Ban primarily performs lightweight log file analysis. | 
| RAM | 512 MB | 1 GB or higher | Additional memory is recommended if Fail2Ban operates concurrently with other resource-intensive services. | 
| Disk Space | 2 GB free space | --- | Log files may grow over time; continuous monitoring of disk usage is advisable. | 
| Network | Ethernet or Wi-Fi | --- | Monitors network traffic but introduces negligible additional load. | 
Table 1. Fail2Ban System Requirements
System Updates
Prior to installation, it is critical to ensure that all system packages are up to date. This guarantees compatibility and mitigates vulnerabilities that may be present in outdated components. The following command should be executed in the terminal to update the package repositories and installed packages.
sudo apt update && sudo apt upgrade -y
This command refreshes the package lists and upgrades all installed packages to their most recent versions, thereby ensuring system integrity and compatibility.
Python
Ensure that Python is properly installed and updated to the latest version to guarantee compatibility and optimal performance. Verifying the Python environment is a critical prerequisite for the smooth operation of Fail2Ban and related system components.
The following command can be executed to check the installed Python version.
python3 --version
This command will display the current Python version installed on the system.
Firewall
Ensure that the Uncomplicated Firewall (UFW) is properly installed and actively enabled to establish a foundational layer of network security. UFW provides a simplified interface for configuring firewall rules, effectively controlling inbound and outbound traffic on the Ubuntu server. The following commands should be executed to install and enable UFW on Ubuntu.
sudo apt install ufw  
sudo ufw enable
These commands will install UFW (if not already present) and activate the firewall to enforce the configured security policies.
SSH
To ensure secure remote access to the server, it is essential to explicitly allow SSH connections through the firewall. This configuration prevents the firewall from blocking legitimate administrative access. Execute the following command to allow SSH traffic.
sudo ufw allow OpenSSH
This rule enables incoming connections on the default SSH port (TCP 22), ensuring that system administrators can securely access the server.
Postfix
For enhanced monitoring and proactive security management, it is recommended to configure an email notification system. This enables Fail2Ban to send real-time alerts regarding suspicious activities or banned IP addresses.
The following command installs Postfix, a widely used Mail Transfer Agent (MTA), to handle outbound email notifications:
sudo apt install postfix
While optional, enabling email notifications significantly improves administrative responsiveness by providing timely updates on potential security incidents.
You can then set up Fail2Ban to successfully defend your server against brute-force attacks after these requirements have been met.
Proper configuration ensures that repeated unauthorized access attempts are detected and mitigated in real time, thereby enhancing the overall security posture of the system.
Installing Fail2Ban on Ubuntu
The installation of Fail2Ban on an Ubuntu 24.04 LTS server is a straightforward process that can be completed efficiently. Below are the essential steps required to install and perform the initial configuration of Fail2Ban:
Step 1: Install the Fail2Ban Package
Execute the following command to install the Fail2Ban package.
sudo apt install fail2ban -y  
This command downloads and installs Fail2Ban along with its dependencies, enabling the system to perform real-time log monitoring and intrusion prevention.
Step 2: Starting and Enabling the Fail2Ban Service
After installation, the Fail2Ban service must be started and configured to launch automatically upon system boot. This ensures continuous protection against unauthorized access attempts. Use the following commands to start and enable the Fail2Ban service.
sudo systemctl start fail2ban  
sudo systemctl enable fail2ban
The first command initiates the Fail2Ban service, activating its log monitoring and IP banning capabilities. The second command ensures that Fail2Ban runs automatically every time the system is restarted, maintaining persistent protection against cyber threats.
Step 3: Verifying the Status of the Fail2Ban Service
After starting the service, it is essential to verify that Fail2Ban is running correctly and actively monitoring system logs. Execute the following command to check the service status.
sudo systemctl status fail2ban  
This command provides detailed information regarding the operational state of Fail2Ban, including whether the service is active and running, as well as recent log entries. Regular status verification is considered a best practice to ensure continuous and effective protection against intrusion attempts.
Step 4: Editing the Configuration Files
For effective deployment, Fail2Ban must be properly configured to define the protection rules and monitoring parameters for various services. It is strongly recommended to avoid modifying the default configuration file directly. Instead, create a local configuration file to preserve the integrity of the original settings by running the next commands.
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local  
sudo nano /etc/fail2ban/jail.local  
The first command creates a copy of the default jail.conf file, allowing custom configurations to be safely applied within jail.local. The second command opens the new configuration file in a text editor for modification.
This approach ensures that updates to the Fail2Ban package do not overwrite or disrupt custom security policies, maintaining system stability and consistency.
Step 5: Example Fail2Ban Configuration for the SSH Service
To safeguard the SSH service against brute-force attacks, an explicit Fail2Ban configuration must be defined within the jail.local file. This configuration enables monitoring of authentication logs and sets the parameters for detecting and mitigating repeated unauthorized access attempts.
An example of Fail2Ban configuration lines for the SSH service is as follows.
[sshd]  
enabled = true  
port = ssh  
logpath = /var/log/auth.log  
maxretry = 3  
findtime = 600  
bantime = 3600  
An explanation of fail2ban parameters is given below.
- enabled = true: Activates the SSH jail.
- port = ssh: Specifies the monitored port, typically TCP 22.
- logpath: Defines the log file monitored for authentication failures.
- maxretry: Sets the maximum number of failed login attempts before a ban is enforced.
- findtime: Specifies the time window (in seconds) within which failed attempts are counted.
- bantime: Determines the duration (in seconds) for which the offending IP address is banned.
This configuration ensures that any IP address exceeding the defined threshold for failed SSH login attempts is temporarily banned, thereby enhancing the server’s resilience against brute-force attacks.
Step 6: Fail2Ban Configuration for the NGINX Service
To protect the NGINX web server against unauthorized access attempts and malicious bot activities, dedicated Fail2Ban jails should be configured. These configurations enable real-time monitoring of NGINX log files and automated mitigation of detected threats.
An example fail2ban configuration for NGINX is provided below.
[nginx-http-auth]  
enabled = true  
port = http,https  
logpath = /var/log/nginx/error.log  
maxretry = 3  
findtime = 600  
bantime = 3600  
  
[nginx-botsearch]  
enabled = true  
port = http,https  
logpath = /var/log/nginx/access.log  
maxretry = 2  
findtime = 300  
bantime = 1800  
An explanation of fail2ban parameters is given below.
- enabled = true: Activates the jail for the specified NGINX context.
- port = http,https: Specifies the monitored service ports.
- logpath: Points to the relevant NGINX log files for monitoring.
- maxretry: Sets the threshold for the number of failed or suspicious requests before a ban is triggered.
- findtime: Defines the time window for counting infractions.
- bantime: Determines how long the offending IP address will be banned.
These configurations provide effective protection against unauthorized login attempts, bot scanning activities, and potential DDoS attacks targeting the NGINX service. By proactively banning malicious IP addresses, system administrators can significantly reduce the attack surface and maintain the availability and integrity of the web server.
All Fail2Ban activities, including detected attacks and banned IPs, are logged in the /var/log/fail2ban.log file.  Reviewing this log file allows administrators to analyze attack patterns and adjust security configurations accordingly.
Step 7: Restarting the Fail2Ban Service
After completing the configuration changes, it is imperative to restart the Fail2Ban service to apply the new settings and activate the defined protection rules. Execute the following command to restart the fail2ban service.
sudo systemctl restart fail2ban  
Restarting the service ensures that all configuration updates take effect immediately, allowing Fail2Ban to commence monitoring and enforcing the specified security policies. Regular restarts after configuration adjustments are considered best practice to maintain the system’s defensive integrity.
Step 8: Monitoring Active Jails and Banned IP Addresses
It is essential to monitor the status of active Fail2Ban jails and review any IP addresses that have been banned. This enables system administrators to verify the effectiveness of the configured security policies and to adjust parameters if necessary.
Use the following commands to check the overall status and the status of specific fail2ban jails.
sudo fail2ban-client status  
sudo fail2ban-client status sshd  
sudo fail2ban-client status nginx-http-auth  
sudo fail2ban-client status nginx-botsearch  
An explanation of fail2ban parameters is given below:
- 
statusthe general status of the Fail2Ban service and lists all active jails.
- 
status <jail>: Provides detailed information for a specific jail, including the number of currently banned IP
Regularly checking these metrics is an important part of keeping your cybersecurity strong because it lets you respond quickly to new threats and makes sure that the server's defenses against intrusions keep working.
With this configuration, the installation and deployment of Fail2Ban on Ubuntu 24.04 LTS provides system administrators with a robust access control and intrusion prevention mechanism, particularly for critical services such as SSH and NGINX.
Fail2Ban's dynamic IP banning capability significantly enhances the server’s defense against cyberattacks by automatically identifying and mitigating hostile activities in real time. This not only strengthens the overall security posture but also contributes to maintaining service availability and data integrity, which are fundamental to reliable system operations.
Configuring Fail2Ban Default Policies
Fail2Ban provides robust protection, particularly against brute-force attacks targeting critical services. However, careful configuration of its default policy settings is essential to ensure both effectiveness and system stability. You may configure fail2ban default policies by following the next steps.
Step 1: Prepare the Configuration File
By default, Fail2Ban’s baseline settings are defined in the /etc/fail2ban/jail.conf file. Direct modification of this file is strongly discouraged, as future software updates may overwrite any changes made to it.
To customize the default policies while preserving the integrity of the original configuration, it is recommended to create a local copy using the following command.
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
Subsequent modifications should be performed exclusively within the jail.local file to maintain system compatibility and facilitate future maintenance.
You can open and edit the configuration file using the nano text editor by executing the following command:
sudo nano /etc/fail2ban/jail.local
This allows administrators to apply custom policy adjustments in a controlled and secure manner, ensuring that the changes align with organizational security requirements.
Step 2: Configure the [DEFAULT] Section
The [DEFAULT] section of the configuration file governs all global settings that apply across the various Fail2Ban jails. Carefully configuring this section is critical to ensure consistent enforcement of security policies system-wide. An example configuration is provided below.
[DEFAULT]  
bantime = 1h  
findtime = 10m  
maxretry = 5  
backend = systemd
These parameters define the core operational behavior of Fail2Ban and serve as the foundation for individual jail policies.
Key configuration parameters are listed below:
- bantime: Defines the duration of the ban imposed on offending IP addresses. Example: 1h represents a ban duration of one hour.
- findtime: Specifies the time window within which failed authentication attempts are counted. Example: 10m corresponds to ten minutes.
- maxretry: Determines the maximum number of failed login attempts allowed before an IP is banned.
- backend: Sets the log reading method. It is recommended to use systemd for optimal compatibility and performance on modern Ubuntu systems.
Adjust the bantime value according to the perceived threat level. Longer ban durations serve as a deterrent by significantly delaying subsequent attack attempts from the same source.
Step 3: Recommended Settings for Persistent Bans
To ensure that banned IP addresses remain blocked even after the Fail2Ban service is restarted, the following configuration can be applied within the [DEFAULT] section.
[DEFAULT]  
bantime = 3600  
findtime = 600  
maxretry = 3  
persistent = true
An explanation of ban parameters is listed below.
- bantime: Specifies the duration of the ban in seconds (3600 seconds = 1 hour).
- findtime: Defines the time window in seconds to track repeated failures (600 seconds = 10 minutes).
- maxretry: Sets the number of allowed failed attempts before triggering a ban.
- persistent = true: Ensures that the ban list is retained across Fail2Ban service restarts, providing continuous protection.
This configuration is highly recommended for critical services where maintaining bans across system reboots or service restarts is essential for sustained security.
Setting the maxretry value too low increases the risk of inadvertently banning your own IP address, especially during legitimate but repeated login attempts.
Consider assigning a longer bantime value to effectively block persistent attackers. Extending the ban duration significantly deters repeated brute-force attempts from the same source.
Step 4: Restart the Service to Apply the Configuration
Once the configuration changes are completed, it is essential to restart the Fail2Ban service to ensure that all modifications are applied and actively enforced. Execute the following command:
sudo systemctl restart fail2ban
Restarting the service activates the updated policies, enabling Fail2Ban to operate based on the newly defined security parameters.
Properly configured default policies significantly enhance the overall security posture of your system. It is highly recommended to regularly review and adjust these settings, particularly for critical services such as SSH and NGINX, to ensure continued protection against evolving cyber threats.
Managing Fail2Ban Application Profiles (Jails)
Fail2Ban utilizes application profiles, referred to as jails, to define protective rules and filters for specific services or applications. Each jail contains service-specific configurations designed to monitor and respond to security events uniquely associated with that service.
Step 1: List Existing Jails
To view all installed and active jail profiles configured within Fail2Ban, execute the following command.
sudo fail2ban-client status
This command displays a summary of all active jails along with their current status, providing administrators with critical visibility into the system’s active intrusion prevention mechanisms.
Step 2: Check the Status of a Specific Jail
To monitor the status of a particular Fail2Ban jail and review its activity, execute the following command.
sudo fail2ban-client status <jail_name>
For example, to check the status of the SSH jail, run the next command.
sudo fail2ban-client status sshd
This command provides detailed information about the selected jail, including the number of currently banned IP addresses and recent log activity. Regular monitoring of individual jails is essential for maintaining granular control over the system’s security posture.
Step 3: Configure Application Profiles (Jails)
To activate a new application-specific profile (jail), you must add the corresponding configuration block to the jail.local file. This enables Fail2Ban to monitor and protect the specified service based on customized security rules.
An example fail2ban configuration to monitor NGINX is as follows.
[nginx-http-auth]  
enabled = true  
port = http,https  
filter = nginx-http-auth  
logpath = /var/log/nginx/error.log  
maxretry = 3
This configuration instructs Fail2Ban to monitor the NGINX HTTP authentication logs, applying the defined thresholds and response actions.
Ensure that the parameter enabled = true is explicitly set within each jail block. Without this directive, the jail will not be activated, and the associated service will remain unprotected by Fail2Ban.
Step 4: Activate the New Jail Profile
After modifying the configuration file to define a new jail, it is essential to restart the Fail2Ban service to apply the changes and activate the newly configured profile. Execute the following command to restart fail2ban.
sudo systemctl restart fail2ban
Restarting the service ensures that the new jail is properly loaded and operational, thereby extending Fail2Ban’s protection to the specified service.
Step 5: Dynamic Management — Manually Banning an IP in a Specific Jail
Fail2Ban supports manual IP banning within a specific jail, allowing administrators to dynamically respond to emerging threats in real time. To manually ban an IP address in a particular jail, execute the following command.
sudo fail2ban-client set <jail_name> banip <IP_address>
An example for manually banning an IP for NGINX service is given below.
sudo fail2ban-client set nginx-http-auth banip 192.168.1.100
This command immediately bans the specified IP address within the selected jail, providing administrators with precise and timely control over the server’s access policies.
Step 6: Remove an IP Ban from a Specific Jail
Fail2Ban allows administrators to manually unban an IP address from a specific jail, providing flexibility in managing access control and correcting potential false positives. To remove a previously imposed ban on an IP address, execute the following command.
sudo fail2ban-client set nginx-http-auth unbanip 192.168.1.100
This command immediately lifts the ban on the specified IP within the selected jail, restoring access if the block was applied in error or the threat has been mitigated.
Effectively managing Fail2Ban application profiles (jails) enables administrators to define in detail how each service is protected. Regular monitoring and proper configuration of these profiles are essential for maintaining a robust and resilient defense against cyber threats.
Managing Port Ranges in Fail2Ban
Fail2Ban provides the capability to protect not only individual ports but also multiple ports or port ranges within a single configuration. This feature is particularly beneficial for applications that operate across custom or multiple ports.
1. Port Definition Syntax
Within the jail.local configuration file, the port directive is used inside the relevant jail block to specify which ports Fail2Ban should monitor and protect.
[custom-jail]  
enabled = true  
port = 8000:8100  
filter = your-filter  
logpath = /var/log/yourapp.log  
maxretry = 5
In this example, all ports within the range 8000 to 8100 are protected by Fail2Ban.
2. Defining Multiple Ports and Port Ranges Simultaneously
Fail2Ban allows the combination of individual service names and port ranges within a single port directive. For example:
port = ssh,http,https,9000:9010
In this configuration, both standard services such as ssh, http, and https, as well as the entire port range 9000 to 9010, are monitored and protected.
Service names specified in the port directive are resolved based on the definitions found in the /etc/services file. Alternatively, specific port numbers can be directly specified for precise control.
When defining port ranges, the colon symbol (:) must be used to separate the range boundaries. Example: 8000:8100
Ensure that the port ranges you define for protection are actively utilized by your system to avoid unnecessary monitoring overhead.
4. Restart the Service After Configuration
After modifying the configuration to define port ranges or additional ports, it is essential to restart the Fail2Ban service to activate the changes:
sudo systemctl restart fail2ban
Restarting the service ensures that the updated port monitoring rules are applied immediately.
Effectively managing port ranges with Fail2Ban is particularly valuable for protecting custom applications or systems operating across wide port ranges. When properly configured, this approach establishes a robust defensive layer against network-based attacks.
The Importance of Using Fail2Ban with SSH and NGINX Services on Ubuntu
SSH and NGINX are two of the most widely utilized core services on Ubuntu systems. Due to their constant exposure to the internet, both services are frequent targets of cyberattacks. Integrating Fail2Ban significantly enhances server security by protecting these critical services from repeated unauthorized access attempts.
Protecting the SSH service is vital because SSH is the primary service for remote system management and is often the first target of brute-force attacks. Fail2Ban monitors authentication logs to detect repeated failed login attempts and enforces IP-based bans. This mechanism not only prevents password-guessing attacks but also reduces unnecessary system resource consumption caused by repeated failed attempts.
Since NGINX is a widely deployed web server for web services and APIs, safeguarding the NGINX service is important. Fail2Ban enhances protection against HTTP Basic Authentication attacks, bot scanning activities, unauthorized access attempts, and Distributed Denial of Service (DDoS) attacks. By analyzing NGINX log files, Fail2Ban identifies suspicious requests and dynamically bans the corresponding IP addresses.
On servers running NGINX, malicious bots and automated scanners are common. Fail2Ban significantly reduces the system load by blocking such unnecessary traffic, improving overall server performance.
Securing SSH and NGINX services with Fail2Ban on Ubuntu systems establishes a robust defensive layer against cyber threats. By providing a dynamic and automated security solution, Fail2Ban helps protect both service availability and data integrity, ensuring operational resilience.
What are the Benefits of Fail2Ban?
Key advantages of using Fail2Ban are as follows.
- Dynamic Firewall Integration: Fail2Ban integrates directly with system-level firewalls such as iptables or nftables, enabling real-time blocking of malicious IP addresses.
- Resource Efficiency: Fail2Ban is highly efficient in resource usage, offering effective protection even on low-resource VPS and cloud servers. It detects and blocks persistent attack sources, reducing system overhead and performance degradation.
- Customizable Policies and Filters: Through its jail-based architecture, Fail2Ban allows service-specific configurations, providing fine-grained control over detection sensitivity and reaction policies.
- Behavioral Analysis Based on Logs: By continuously scanning logs, Fail2Ban detects malicious behaviors and automatically triggers predefined security actions.
- Automation: Provides automatic IP banning for both SSH and NGINX services.
- Notifications: Supports email notifications, allowing administrators to be promptly alerted of potential threats.
- Lowers Risks: Minimizes long-term risks and damages caused by exploited vulnerabilities.
Improperly configured Fail2Ban jails may inadvertently block legitimate users. Careful tuning of maxretry and bantime parameters is crucial to avoid false positives.
Why Choose Fail2Ban Firewall to Protect SSH and NGINX Services on Ubuntu?
In today’s cybersecurity landscape, SSH and NGINX services, constantly exposed to the internet, are among the most frequently targeted critical infrastructure components. According to the 2023 Verizon Data Breach Investigations Report (DBIR), brute-force attacks and authentication vulnerabilities remain among the most prevalent cyberattack vectors. Targeted attacks on services like SSH and NGINX have increased by 45% over the past five years (Verizon DBIR, 2023). Protecting these services on widely deployed Linux distributions like Ubuntu is essential for ensuring overall system security.
While SSH services are vulnerable to brute-force attacks, phishing attempts, and vulnerability scans, NGINX services are major targets for malicious bot scans, DDoS attacks, and unauthorized access attempts. At this point, the deployment of specialized tools like Fail2Ban, which provide dynamic and effective protection layers, plays a crucial role in strengthening system defenses.
Fail2Ban is an open-source cybersecurity tool designed to continuously monitor system logs and detect suspicious activities, with the capability of automatically banning offending IP addresses.
It provides real-time intervention against failed login attempts, unauthorized access attempts, or bot-based attacks, particularly for internet-exposed services such as SSH and NGINX.
Protecting SSH and NGINX services on Ubuntu systems against cyber threats is now a necessity to ensure service availability and data integrity. Fail2Ban is widely recommended by both academia and cybersecurity professionals due to its low-cost, highly effective protection capabilities.
With its rapid configuration potential, minimal resource consumption, and real-time detection of malicious behaviors, Fail2Ban stands out as one of the most effective tools for securing such services against modern cyber threats.
