Nginx's Role in DDoS Defense
Nginx cannot stop a true volumetric flood that saturates your network bandwidth - that requires upstream scrubbing at a CDN or ISP level - but it is highly effective against application-layer (Layer 7) attacks like HTTP floods, slow-loris style connection exhaustion, and login-endpoint brute forcing. The core tools are limit_req_zone for request-rate limiting, limit_conn_zone for concurrent-connection limiting, and tuned timeout directives that reject clients who hold connections open without sending complete requests.
Cricket analogy: It's like a ground's turnstiles that can efficiently manage a surge of fans arriving at once, but can't do anything if the actual stadium itself is too small for the demand - that's a capacity problem upstream, not a gate-management problem.
Rate Limiting Requests and Connections
limit_req_zone defines a shared memory zone keyed by a variable, typically $binary_remote_addr, that tracks request rate per client and rejects excess requests with 503 once the configured rate is exceeded; the burst parameter allows short spikes to queue rather than being dropped immediately, and nodelay processes burst requests without added latency. limit_conn_zone works similarly but caps simultaneous open connections per client, which is particularly effective against slow-loris attacks that try to exhaust the worker connection pool by holding many connections open.
Cricket analogy: It's like a bowler being restricted to a maximum number of overs per spell, with a short-burst allowance for a couple of extra deliveries in an emergency, but never letting one bowler monopolize the entire innings.
http {
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
server {
location /login {
limit_req zone=req_limit burst=20 nodelay;
limit_conn conn_limit 5;
limit_req_status 429;
proxy_pass http://backend;
}
client_body_timeout 10s;
client_header_timeout 10s;
keepalive_timeout 15s;
send_timeout 10s;
}
}Set limit_req_status 429 to return the semantically correct "Too Many Requests" code instead of the default 503, which helps monitoring tools and clients distinguish rate limiting from a genuine server outage.
Timeouts and Buffer Tuning Against Slowloris
Slowloris-style attacks send HTTP headers extremely slowly, one byte at a time, to keep connections open and exhaust the worker_connections pool without ever completing a request. Tightening client_header_timeout and client_body_timeout forces Nginx to drop connections that don't send data fast enough, while reasonable client_max_body_size and buffer size settings prevent an attacker from tying up memory with oversized or fragmented request bodies.
Cricket analogy: It's like a bowler enforcing a strict shot clock between deliveries - a batsman who takes forever fiddling with their gloves before every ball gets timed out and penalized rather than allowed to stall indefinitely.
Setting timeouts too aggressively can cut off legitimate users on slow mobile connections uploading large files - tune client_body_timeout and client_max_body_size to match realistic traffic patterns, and test with real-world slow connections before rolling out to production.
- Nginx defends effectively against Layer 7 (application) DDoS attacks but cannot stop true volumetric floods that saturate network bandwidth - that requires upstream scrubbing.
- limit_req_zone throttles request rate per client, typically keyed on $binary_remote_addr, with burst and nodelay controlling how spikes are handled.
- limit_conn_zone caps concurrent connections per client, directly mitigating slow-loris style connection exhaustion attacks.
- limit_req_status 429 returns the correct 'Too Many Requests' status instead of the default 503.
- client_header_timeout and client_body_timeout drop connections that send data too slowly, closing off slowloris-style attacks.
- Timeout and buffer settings must be tuned against real traffic patterns to avoid rejecting legitimate slow-connection users.
- Rate limiting should be applied selectively to sensitive endpoints like /login rather than uniformly, to avoid degrading normal traffic elsewhere.
Practice what you learned
1. Which type of DDoS attack can Nginx effectively mitigate on its own?
2. What does the burst parameter on limit_req do?
3. Which directive specifically limits the number of simultaneous open connections per client, mitigating slow-loris attacks?
4. Why set limit_req_status to 429 instead of leaving the default?
5. What risk comes with setting client_header_timeout and client_body_timeout too aggressively low?
Was this page helpful?
You May Also Like
Restricting Access with Nginx
Control who can reach specific routes and resources using Nginx's IP allow/deny rules, HTTP basic auth, and satisfy directives.
Nginx Hardening Checklist
A practical, prioritized checklist for locking down a production Nginx deployment, from TLS configuration to information disclosure and module minimization.
Nginx Security Headers
Learn how to configure HTTP response headers in Nginx to protect users from clickjacking, MIME-sniffing, XSS, and insecure transport.
Related Reading
Related Study Notes in DevOps
Browse all study notesAnsible Study Notes
DevOps · 30 topics
DevOpsAdvanced Kubernetes Study Notes
Kubernetes · 30 topics
DevOpsAdvanced Bash Scripting Study Notes
Bash · 30 topics
DevOpsApache Kafka Study Notes
Kafka · 30 topics
DevOpsDocker & Kubernetes Study Notes
YAML · 40 topics
DevOpsCI/CD Tools & Pipelines Study Notes
YAML · 37 topics