> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Blocking Traffic

> How to block and allow traffic in NGINX, using allow/deny directives, CIDR notation, and Fail2Ban for automated IP banning, plus handling real client IPs behind proxies

Hackers can steal data, spread spyware or ransomware, and even take down entire websites. While legitimate bots index content for search engines, malicious bots scrape data, spam forms, and post fake reviews. Controlling which clients can reach your application is a critical layer of defense.

![An infographic titled "Hackers" showing a hooded hacker at a computer with a skull emblem. Three icons list threats: "Steal data," "Spread spyware and ransomware," and "Take down the whole site."](https://mintcdn.com/kodekloud-c4ac6d9a/x1wBthvq78ZWHRHX/images/Nginx-for-Beginners/Security/Blocking-Traffic/hackers-infographic-hooded-skull-data-ransomware.jpg?fit=max\&auto=format\&n=x1wBthvq78ZWHRHX\&q=85\&s=0d338b324eb554848f68c576251656c5)

NGINX supports access control through the ngx\_http\_access\_module using the allow and deny directives. You can use these directives inside the http, server, and location blocks to explicitly permit or block individual IPs or CIDR ranges.

Example — allow a few IPs and deny everyone else:

```nginx theme={null}
server {
    listen 80;
    server_name www.example.com;

    # Allow two specific single IPv4 addresses (/32)
    allow 192.168.1.100/32;
    allow 174.168.100.252/32;

    # Deny everyone else
    deny all;

    location / {
        # site config...
    }
}
```

To permit or block a network range, specify a CIDR block. Example: deny a /24 and restrict /admin to a specific /24:

```nginx theme={null}
server {
    listen 80;
    server_name example.com;

    # Deny a whole range (203.0.113.0/24 blocks 203.0.113.0–203.0.113.255)
    deny 203.0.113.0/24;

    location /admin {
        # Only allow connections from a specific /24 range (e.g., internal office or VPN)
        allow 174.0.252.0/24;
        deny all;
    }
}
```

Quick CIDR reference:

| CIDR | What it means | Example range |
| - | - | - |
| `/32` | Single IPv4 address | `203.0.113.45` |
| `/24` | First three octets fixed, last octet varies | `203.0.113.0`–`203.0.113.255` |

Blocking individual IPs is straightforward but not always scalable: attackers rotate IPs, and long lists of allow/deny directives are hard to maintain. A common automated approach is Fail2Ban, which detects abusive behavior from logs and updates firewall rules automatically.

If NGINX is behind a reverse proxy or load balancer, your access logs may show the proxy's IP instead of the client’s IP. Make sure NGINX records the real client IP by using an appropriate `log_format` with X-Forwarded-For or by enabling the `realip` module:

* Use the `X-Forwarded-For` header properly when your proxy sets it. See MDN’s X-Forwarded-For documentation: [https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For)
* Or use the NGINX realip module: [https://nginx.org/en/docs/http/ngx\_http\_realip\_module.html](https://nginx.org/en/docs/http/ngx_http_realip_module.html)

![An infographic titled "Blocking Traffic" showing IPs, bots, and network traffic on the left routed toward a block symbol. The block prevents those requests from reaching a website mockup on the right.](https://mintcdn.com/kodekloud-c4ac6d9a/x1wBthvq78ZWHRHX/images/Nginx-for-Beginners/Security/Blocking-Traffic/blocking-traffic-ips-bots-website.jpg?fit=max\&auto=format\&n=x1wBthvq78ZWHRHX\&q=85\&s=18a06875f072bf18580d2170331600a4)

Fail2Ban watches service logs for patterns of abuse (failed logins, suspicious requests) and automatically updates firewall rules to temporarily ban offending IPs. It’s a practical way to reduce brute-force attacks and automated scraping without manually maintaining blocklists.

Fail2Ban — quick start and examples

Example tail of Fail2Ban activity:

```text theme={null}
ubuntushell@linux:~$ sudo tail -f /var/log/fail2ban.log
2024-08-10 19:26:27,469 fail2ban.jail    [7786]: INFO    Creating new jail 'ssh'
2024-08-10 19:26:27,472 fail2ban.jail    [7786]: INFO    Initiated 'pyinotify' backend
2024-08-10 19:26:27,475 fail2ban.jail    [7786]: INFO    Jail 'sshd' started
2024-08-10 19:26:46,275 fail2ban.filter  [7786]: INFO    [sshd] Found 192.168.8.131 - 2024-08-10 19:26:46
2024-08-10 19:27:40,771 fail2ban.actions [7786]: NOTICE  [sshd] Ban 192.168.8.131
```

Install Fail2Ban on common distributions:

```bash theme={null}
# Debian/Ubuntu
sudo apt update
sudo apt install -y fail2ban

# RHEL/CentOS or Fedora
sudo yum install -y fail2ban
# or (newer Fedora/RHEL)
sudo dnf install -y fail2ban
```

After installation, create a local configuration override to avoid editing packaged files:

```bash theme={null}
cd /etc/fail2ban
sudo cp jail.conf jail.local
sudo vim jail.local
```

Example NGINX jail entries for `jail.local`:

```ini theme={null}
[nginx-http-auth]
enabled = true
port    = http,https
filter  = nginx-http-auth
logpath = /var/log/nginx/access.log
maxretry = 3
bantime  = 600
findtime = 600

[nginx-badbots]
enabled = true
port    = http,https
filter  = nginx-badbots
logpath = /var/log/nginx/access.log
maxretry = 1
bantime  = 48h
```

Common Fail2Ban parameters explained:

| Parameter | Purpose | Example |
| - | - | - |
| `filter` | Name of the filter in `/etc/fail2ban/filter.d` that contains `failregex` | `nginx-http-auth` |
| `logpath` | Path to the log file to monitor | `/var/log/nginx/access.log` |
| `maxretry` | Number of matches within `findtime` before banning | `3` |
| `bantime` | Duration of ban (seconds or suffix like `48h`) | `600` or `48h` |
| `findtime` | Time window (in seconds) during which `maxretry` failures must occur | `600` |

Fail2Ban filter files live under `/etc/fail2ban/filter.d`. They use regular expressions and the `<HOST>` token to capture the offending IP address. Example snippet from an `nginx-http-auth` filter:

```ini theme={null}
# /etc/fail2ban/filter.d/nginx-http-auth.conf
[Definition]
mode = normal

# Match authentication errors and capture IP as <HOST>
failregex = ^\s*\[error\] \d+#\d+: \*\d+ user "(?:[^"]+|.*?)"?:? (?:password mismatch|was not found in "[^"]*"), client: <HOST>, server: \S*, request: "\S+ \S+ HTTP/\d+\.\d+", host: "\S+"(?:, referrer: "\S+")?\s*$
# Fallback for SSL handshake failures (example)
failregex = ^\s*\[crit\] \d+#\d+: \*\d+ SSL_do_handshake\(\) failed \(SSL: error:\S+(?: \S+){1,3} too (?:long|short)\)[^,]*, client: <HOST>
```

Inspect jail status and banned IPs:

```bash theme={null}
sudo fail2ban-client status nginx-http-auth
```

Example output:

```text theme={null}
Status for the jail: nginx-http-auth
|- Filter
|  |- Currently failed: 0
|  |- Total failed: 3
|  `- File list: /var/log/nginx/access.log
`- Actions
   |- Currently banned: 1
   `- Banned IP list: 108.172.85.62
```

Unban an IP from a specific jail:

```bash theme={null}
sudo fail2ban-client set nginx-http-auth unbanip 108.172.85.62
```

Fail2Ban works well with traditional server setups because it manipulates host-level firewall rules and parses log files. If you run NGINX behind load balancers or in containers, adjust your logging and network strategy so Fail2Ban sees real client IPs or use alternative protections.

Fail2Ban relies on host-level logs and firewall control; it is not ideal inside isolated containers where logs are aggregated and firewall control is limited. For containerized environments (Kubernetes, Docker), consider sidecar log monitoring, cluster-level ingress policies, or an external WAF.

Further reading and references

* NGINX access module: [https://nginx.org/en/docs/http/ngx\_http\_access\_module.html](https://nginx.org/en/docs/http/ngx_http_access_module.html)
* NGINX realip module: [https://nginx.org/en/docs/http/ngx\_http\_realip\_module.html](https://nginx.org/en/docs/http/ngx_http_realip_module.html)
* X-Forwarded-For header: [https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For)
* Fail2Ban official site: [https://www.fail2ban.org/](https://www.fail2ban.org/)

Note: This article describes how to use NGINX allow/deny directives and Fail2Ban in typical server environments. In Kubernetes or other orchestrated environments, adapt these patterns to your logging and network model (ingress controllers, cluster policies, or external WAFs).

> **[Watch Video](https://learn.kodekloud.com/user/courses/nginx-for-beginners/module/8905470e-b1ea-48ec-b0cd-711687ce7159/lesson/328c0054-1639-4d6d-aeda-f1255e8ebaa0)**


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.