ThisCalculator

Everyday

Block DDoS Attacks with Nginx: Practical Guide

Updated · Standard formula, shown below

Block DDoS Attacks with Nginx: Practical Guide

This guide shows you how to configure Nginx to absorb and mitigate common Distributed Denial of Service (DDoS) attacks—such as SYN floods, HTTP floods, and slowloris—before they exhaust your server’s resources. You’ll learn concrete directives for rate limiting, connection limits, timeouts, and IP blocking, which together can keep your site responsive during an attack. You’ll need root or sudo access to your Nginx server and a basic familiarity with editing Nginx configuration files.

What You’ll Need

  • A server running Nginx (tested on Nginx 1.18+ but works on most modern versions)
  • Root or sudo access to edit configuration files
  • Basic knowledge of the command line and Nginx’s config structure
  • Optional: a firewall (like UFW or iptables) for additional IP blocking

Step-by-Step

  1. Back up your current configuration. Before making changes, copy your main config and site configs: sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup and similarly for each site in /etc/nginx/sites-available/.
  2. Set global timeouts in the http block. Open /etc/nginx/nginx.conf and inside the http { } block, add or adjust these directives to close idle connections faster:
    client_body_timeout 10s;
    client_header_timeout 10s;
    keepalive_timeout 5s 5;
    send_timeout 10s;

    These limit how long Nginx waits for a client to send data, which mitigates slowloris attacks.

  3. Limit connection rates per IP. In the same http block, define a limit zone (outside server blocks):
    limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
    limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=5r/s;

    The first creates a zone to track concurrent connections, the second tracks request rate. Adjust the rate (e.g., 5r/s) based on your normal traffic—too low will block legitimate users.

  4. Apply limits in your server or location blocks. In your site’s config (e.g., /etc/nginx/sites-available/example.com), add these inside the server { } or specific location { } blocks:
    limit_conn conn_limit_per_ip 10;
    limit_req zone=req_limit_per_ip burst=20 nodelay;

    The burst allows short spikes above the rate; nodelay processes them immediately but counts them. Tune these values—too strict will block legitimate users during traffic spikes.

  5. Block specific IPs or subnets. If you know attack sources, add a deny list at the top of your server block:
    deny 192.168.1.0/24;
    allow all;

    Place allow all; after all deny rules. For dynamic blocking, use a file included from the http block: include /etc/nginx/blocked_ips.conf; and update that file with deny rules.

  6. Limit request size to prevent large payload floods. In your server or location block, set:
    client_max_body_size 1m;

    Adjust based on your legitimate needs (e.g., file uploads need more).

  7. Enable SYN cookies (if using Nginx as a reverse proxy). If Nginx fronts your app, set in the http block:
    listen 80 backlog=1024;
    listen 443 ssl backlog=1024;

    The backlog increases the queue for pending connections, helping absorb SYN floods. For full SYN cookie protection, use a firewall like iptables or a dedicated DDoS mitigation service.

  8. Use a caching layer for static content. In your location blocks for static files, add:
    location ~* \.(jpg|jpeg|png|css|js)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }

    This reduces the load on your backend, making it harder to overwhelm.

  9. Test the configuration. Run sudo nginx -t to check for syntax errors. If it passes, reload Nginx with sudo systemctl reload nginx (or sudo service nginx reload).
  10. Monitor and adjust. Watch your access and error logs (/var/log/nginx/access.log, error.log) to see if legitimate users are being blocked. Use sudo tail -f to watch in real time during an attack.

Common Mistakes

  • Setting rates too low. A rate of 1r/s might block users behind a NAT or proxy. Start with 10r/s and lower gradually.
  • Forgetting to apply limits to all locations. Attackers can target unguarded endpoints (like /api). Apply limits at the server level, not just the root location.
  • Using limit_req without a burst. Without burst, legitimate short spikes get 503 errors. Always set a reasonable burst.
  • Blocking your own IP. Test with your own IP first to ensure you don’t lock yourself out. Always have a backup way to access the server (e.g., console).
  • Not testing after changes. A syntax error can take your site down. Always run nginx -t before reloading.

Tips

  • Use a CDN or DDoS protection service for large-scale attacks—Nginx alone can’t handle volumetric floods that saturate your bandwidth.
  • Combine with fail2ban to automatically block IPs that trigger Nginx error codes (like 503 from rate limiting).
  • Separate dynamic and static traffic. Serve static files from a different server or cache them aggressively.
  • Keep Nginx updated. Newer versions have better performance and security fixes.
  • Use a separate rate limit for login endpoints (e.g., 2r/s) to prevent brute-force attacks.

Troubleshooting

  • Legitimate users getting 503 errors. Increase the burst value or the rate in limit_req_zone. Also check if your limits are too low for your normal traffic.
  • Nginx won’t start after changes. Run sudo nginx -t to see the exact error. Common issues: missing semicolons, duplicate zones, or incorrect paths in include.
  • Attack still succeeds. Check if the attack is targeting a different port (e.g., 443) or using distributed IPs that bypass rate limits. Consider adding a WAF or using a cloud-based mitigation service.
  • IP blocking isn’t working. Ensure the deny rules are in the correct order—deny must come before allow all;. Also check that you’re editing the right server block (e.g., the one with the listen directive for your domain).
  • Logs show many 503s from your own IP. You’re likely behind a NAT or proxy—your IP appears as the same to Nginx. Adjust limits to allow more per IP or use $http_x_forwarded_for if behind a proxy.

Frequently Asked Questions

Can Nginx completely stop a DDoS attack?

No. Nginx can mitigate application-layer attacks (HTTP floods, slowloris) and some connection floods, but it cannot handle volumetric attacks that saturate your bandwidth. For those, you need a CDN or DDoS protection service.

What is the difference between limit_req and limit_conn?

limit_req limits the number of requests per second from an IP, while limit_conn limits the number of concurrent connections. Use both—they address different attack vectors.

Will rate limiting affect SEO or crawlers?

Googlebot and other crawlers typically respect rate limits and may slow down, but they won’t be permanently blocked if your limits are reasonable. Set a higher rate for known crawler IPs if needed.

How do I know if I’m under a DDoS attack?

Check your server load (top), network traffic (iftop), and Nginx logs for a surge in requests from a single IP or many IPs. Also monitor connection timeouts and 503 errors.

Should I block IPs manually during an attack?

Only if you can identify attack sources quickly. Manual blocking can help, but automated tools like fail2ban or a CDN’s rate limiting are more effective for large-scale attacks.

Can I use these settings on a reverse proxy setup?

Yes, these directives work the same when Nginx is a reverse proxy. Just ensure the rate limits apply to the client IP, not the proxy IP—use $binary_remote_addr as shown, or $http_x_forwarded_for if your proxy forwards the original IP.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.