Brute Force Defenses

Implementing Layered Defenses Against Brute Force Logins

Modern network infrastructure resides in a state of constant adversarial pressure. Automated authentication attacks target the ingress points of every major technical stack; whether the environment controls water treatment logic, energy distribution grids, or cloud database clusters, the risk of a breach remains critical. Brute Force Defenses serve as the primary mitigating layer against credential stuffing and dictionary attacks. By implementing a multi-tiered architecture that combines rate limiting, session monitoring, and kernel-level packet filtering, architects can preserve system throughput while minimizing the computational overhead associated with failed password hashing. The objective is to shift the burden of proof from the server to the client. This manual details the implementation of an idempotent defense strategy designed to scale with rising concurrency demands. Failure to implement these controls subjects the hardware to unnecessary thermal-inertia from sustained CPU spikes during high-intensity attacks; it also risks total service unavailability through resource exhaustion.

Technical Specifications

| Requirement | Default Port/Range | Protocol/Standard | Impact Level (1-10) | Recommended Resources |
| :— | :— | :— | :— | :— |
| SSH Hardening | 22/TCP | SSHv2 / RFC 4253 | 10 | 1 vCPU / 512MB RAM |
| Fail2Ban Service | N/A | Python 3.x / Systemd | 8 | 1 vCPU / 1GB RAM |
| PAM-Authentication | N/A | IEEE 802.1X | 9 | Negligible (Kernel Level) |
| NFTables/IPSet | N/A | Netlink / IPv4/v6 | 7 | 2GB RAM (For large sets) |
| MFA Gateway | 443/TCP | OIDC / SAML 2.0 | 9 | 2 vCPUs / 4GB RAM |

Environment Prerequisites:

1. Operating System: Linux Kernel 5.4 or higher (Debian 11+, RHEL 8+, or Ubuntu 20.04+).
2. Permissions: Root or sudo-level access with NOPASSWD privileges for specific systemctl operations.
3. Dependencies: nftables, fail2ban, libpam-modules, and ipset must be indexed in the system package manager.
4. Hardware: Network Interface Cards (NIC) must support hardware-level packet filtering to prevent signal-attenuation in high-traffic scenarios.

Section A: Implementation Logic:

The theoretical foundation of structured login defense is the Principle of Increasing Friction. Authentication is a resource-intensive process; the CPU must execute expensive hashing algorithms like Argon2 or BCrypt to verify a payload. A brute force attack exploits this by forcing the system to perform these operations thousands of times per second. By moving the defense to the network layer (Layer 3/4) and using idempotent configuration scripts, we drop packets from malicious sources before they reach the application layer (Layer 7). This reduces latency for legitimate users and prevents packet-loss during intense traffic bursts.

Step-By-Step Execution

1. Initial SSH Hardening

Modify the global daemon configuration located at /etc/ssh/sshd_config. Ensure the following directives are strictly enforced: PermitRootLogin no, PasswordAuthentication no, and MaxAuthTries 3.

System Note: Changing MaxAuthTries tells the sshd service precisely how many times a single connection can attempt a password before the daemon terminates the session. This prevents a single TCP stream from attempting hundreds of passwords through multiplexing. Use systemctl restart ssh to apply changes.

2. Implementation of pam_faillock

Navigate to /etc/pam.d/common-auth or /etc/pam.d/system-auth. Append the pam_faillock.so module to the configuration. Define deny=5 and unlock_time=900 to lock accounts after five failed attempts for fifteen minutes.

System Note: The pam_faillock module interacts directly with the Pluggable Authentication Module (PAM) architecture at the kernel-userland interface. It maintains a persistent state of login failures in /var/run/faillock/. This ensures that even if a service is restarted, the lock-out state remains intact.

3. Fail2Ban Jail Configuration

Create an override configuration file at /etc/fail2ban/jail.local. Assign a specific jail for the SSH service by setting enabled = true, port = ssh, filter = sshd, and banaction = nftables-multiport.

System Note: Using jail.local instead of jail.conf ensures that package updates do not overwrite custom security logic. Fail2Ban monitors the /var/log/auth.log for specific regex patterns. When a threshold is met, it issues a command to nftables to insert a temporary drop rule into the input chain.

4. IPSET and NFTables Integration

Execute the command ipset create blacklist hash:ip hashsize 4096. Integrate this set into the nftables ruleset by adding a rule that drops any source IP matching the blacklist set.

System Note: Using ipset is significantly more efficient than standard firewall rules. It utilizes a hash table lookup which ensures that the processing time for a packet remains constant regardless of whether you are blocking ten IPs or ten thousand. This maintains high throughput and low latency.

5. Automated Log Rotation

Configure /etc/logrotate.d/rsyslog to ensure that authentication logs are rotated daily with a minimum of thirty days of retention.

System Note: Large log files create significant disk I/O overhead. By rotating logs frequently, the Fail2Ban service can parse the payload of local logs faster, decreasing the time between the attack detection and the firewall block. This prevents storage-related bottlenecks that lead to packet-loss.

Section B: Dependency Fault-Lines:

A common failure point in modern layered defense is the “Log Collision” error. If multiple services (e.g., rsyslog and systemd-journald) compete for access to the same log buffer, Fail2Ban may experience a read-timeout. This results in delayed banning or missed attacks. Another bottleneck occurs when the sqlite database used by Fail2Ban for persistent storage becomes corrupted due to improper shutdowns; this requires a manual purge of /var/lib/fail2ban/fail2ban.sqlite3. Lastly, ensure that DNS reverse-lookups are disabled in the firewall configuration. If the system attempts to resolve every attacking IP to a hostname, the resulting DNS latency can crash the network subsystem.

Troubleshooting Matrix

Section C: Logs & Debugging:

When a service fails to start or a user is incorrectly blocked, the first point of audit is the fail2ban-client status sshd command. This provides a real-time count of currently banned IPs. For deep inspection of blocked packets, use nft list ruleset to verify if the firewall has correctly ingested the ban from the application layer.

If a legitimate user is locked out, check the /var/log/auth.log for the string “pam_faillock”. This log will indicate exactly which PAM module triggered the rejection. To manually reset a user, execute faillock –user –reset. To debug regex failures in custom filters, use the tool fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf; this will output exactly how many lines matched the current filter logic without requiring a service restart.

Optimization & Hardening

Performance Tuning:
To increase the throughput of the defense layer, move the Fail2Ban database and logs to a memory-mapped file or a RAMDisk. This reduces the latency associated with physical disk writes. For environments with high concurrency, adjust the dbpurgeage in fail2ban.conf to keep the internal database small and responsive.

Security Hardening:
Restrict access to the fail2ban-client to specific admin groups using chmod and chown on the socket file located at /var/run/fail2ban/fail2ban.sock. Implement a “Geofence” by using nftables to drop all traffic originating from geographic regions where your organization has no physical or digital presence. This reduces the attack surface and significantly lowers the CPU overhead of the firewall.

Scaling Logic:
In a distributed architecture (e.g., a load-balanced web farm), defense must be centralized. Use a shared database or a tool like CrowdSec to synchronize banned IPs across all nodes. This ensures that if an attacker is blocked on Node A, they are preemptively restricted from Node B, Node C, and the central database cluster. Ensure that the synchronization heartbeat does not introduce excessive network overhead.

The Admin Desk

How do I unban an IP immediately?
Execute fail2ban-client set sshd unbanip . This command is idempotent and will update both the internal database and the active firewall ruleset. Verify the removal by checking nft list ruleset to ensure the address is purged.

Why is Fail2Ban not catching any failed logins?
Verify the backend setting in jail.local. On modern systemd distributions, you may need to set backend = systemd instead of auto. This ensures Fail2Ban reads directly from the journal rather than a flat log file.

Will these rules cause packet-loss for legitimate users?
Only if the blacklist becomes excessively large (over 100,000 entries) without utilizing ipset. Standard linear firewall lists increase latency for every packet. Use hash-based sets to ensure consistent performance regardless of the number of active bans.

What happens if the Fail2Ban service crashes?
The existing rules in nftables or iptables will remain active until the next reboot or a manual flush. However, no new bans will be processed. Configure systemd to auto-restart the service by adding Restart=always to the unit file.

Can I use this for non-SSH services?
Yes. You can create custom jails for any service that generates a log entry on failure. Simply define a new header in jail.local, point it to the relevant log path, and provide a regex in filter.d to match the failure payload.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top