Skip to main content
This guide demonstrates how to allow and deny client traffic with Nginx using the allow and deny directives, and how to use fail2ban to automatically block abusive clients that repeatedly fail HTTP Basic authentication. The example site is example.com; its /admin endpoint is protected by HTTP Basic auth. Instead of maintaining long static deny lists in Nginx, fail2ban can detect repeated failed authentication attempts and temporarily ban offending IPs. Table of contents
  • Environment summary
  • Initial Nginx configuration
  • Mapping example.com on test clients
  • TLS note for curl
  • Basic connectivity tests
  • Manual IP deny examples (single IP, allow-only, CIDR)
  • Using fail2ban to auto-block failed auth attempts
  • fail2ban configuration and status checks
  • Demonstration (browser)
  • Why combine fail2ban and Nginx allow/deny
  • Final notes and references
Environment summary Initial Nginx configuration Below is the starting server block for example.com. It redirects HTTP to HTTPS, serves the site over TLS, and protects /admin with auth_basic:
Mapping example.com on test clients On both test client nodes (node01 and node02) add the Nginx server IP to /etc/hosts so example.com resolves to the server used in this demo (example shown uses 192.231.128.10). Also add entries for client hostnames so examples below map consistently:
Note about TLS and curl Because the certificates were created with a non-public CA (mkcert), curl will refuse to verify the certificate unless you add -k / --insecure to bypass certificate verification. That only disables validation — traffic is still encrypted.
Using curl -k disables TLS certificate verification and should only be used for testing. Do not use --insecure in production.
Basic connectivity tests from a client (node01)
  • Check HTTP redirect (expected 301):
  • HTTPS without -k (expected certificate verification error):
  • HTTPS with -k to skip verification (use --head/-I for headers only):
  • Request to the protected admin endpoint without credentials (expected 401):
Manual deny/allow examples
  1. Manually denying a specific client IP To block node02 from accessing the site, add a deny for its IP in the location / block (for a single IP you can use /32, or simply the address without CIDR):
After saving the config, always test and reload Nginx:
Results:
  • From node01: access to example.com returns 200 OK.
  • From node02: requests now return 403 Forbidden because the IP is explicitly denied.
  1. Allow only a single IP for /admin and deny all others Scope allow/deny rules to the /admin location so only a trusted IP (example: node01) can reach it:
After reloading Nginx:
  • node02 receives 403 Forbidden for /admin.
  • node01 receives 401 Unauthorized when hitting /admin (because it is allowed by IP but did not provide valid credentials).
  1. Allowing a CIDR range (/24) for a subnet To permit an entire subnet, use /24 instead of listing multiple individual /32 entries:
Troubleshooting tip: each allow/deny accepts exactly one address/keyword per statement and must end with a semicolon. If you see invalid number of arguments in "allow" directive, check for missing semicolons or malformed addresses and re-run nginx -t. Using fail2ban to block repeated failed auth attempts Maintaining long deny lists in Nginx is not scalable for dynamic threats (e.g., brute-force attempts). fail2ban automates this by scanning log files (such as the Nginx error log) for failed authentication entries and adding temporary firewall bans when thresholds are exceeded. Install and configure fail2ban (Debian/Ubuntu example):
Do not edit /etc/fail2ban/jail.conf directly. Use /etc/fail2ban/jail.local or /etc/fail2ban/jail.d/*.conf to override defaults so package updates do not overwrite your settings.
Configure the nginx-http-auth jail in /etc/fail2ban/jail.local (example settings):
fail2ban settings explained Start (or restart) fail2ban and check status:
Check the status of the nginx-http-auth jail and list banned IPs:
Sample fail2ban interaction (ban/unban) Common commands and example outputs:
Demonstration: triggering fail2ban from a browser If a client attempts to authenticate to /admin with invalid credentials multiple times, Nginx logs failed auth attempts to the error log. fail2ban monitors that log; once maxretry is exceeded, fail2ban bans the client IP using the configured action (typically iptables/nftables). Here is the browser prompt when entering credentials (attempting an auth that fail2ban will count as a failure):
A web browser screenshot showing a centered "Sign in" dialog for example.com with "admin" filled in the username field and a masked password. The dialog includes "Cancel" and "Sign In" buttons and a green browser toolbar across the top.
After a couple of failed attempts the fail2ban status will show the client IP as banned, and network-level traffic from that IP to the server will be blocked until the ban expires or is manually removed. Why use fail2ban vs. static Nginx deny lists
  • Use Nginx allow/deny for static whitelists/blacklists (trusted administrative networks, known bad IPs).
  • Use fail2ban for dynamic, automated blocking of abusive clients (brute-force or repeated failed auth attempts).
  • Combine both: keep a small static allow list for trusted sources and rely on fail2ban to handle unknown or changing threats.
Final notes and references
  • Always validate Nginx config changes with nginx -t and reload Nginx: nginx -s reload or systemctl reload nginx.
  • After changing fail2ban configuration, restart the service and verify jails with fail2ban-client status and fail2ban-client status <jail>.
Further reading: That completes this demo of blocking traffic with Nginx and using fail2ban to automate IP bans for repeated failed authentication attempts.

Watch Video

Practice Lab