HxHippy

DDoS Protection

Protecting your Nginx server from DDoS attacks.

Last updated: 2025-01-15

Connection Limits

# In http context
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;

server {
    # Limit connections per IP
    limit_conn conn_limit 10;

    # Limit requests per IP
    limit_req zone=req_limit burst=20 nodelay;

    # Return 429 instead of 503
    limit_req_status 429;
    limit_conn_status 429;
}

Buffer Limits

http {
    # Limit request body size
    client_max_body_size 10m;

    # Limit buffer sizes
    client_body_buffer_size 1k;
    client_header_buffer_size 1k;
    large_client_header_buffers 2 1k;

    # Timeouts
    client_body_timeout 10;
    client_header_timeout 10;
    send_timeout 10;
    keepalive_timeout 5 5;
}

Slowloris Protection

http {
    # Short timeouts for slow attacks
    client_body_timeout 10;
    client_header_timeout 10;

    # Limit header buffer
    client_header_buffer_size 1k;

    # Reset slow connections
    reset_timedout_connection on;
}

HTTP Flood Protection

# Strict rate limiting
limit_req_zone $binary_remote_addr zone=flood:10m rate=5r/s;

location / {
    limit_req zone=flood burst=10 nodelay;

    # Challenge suspicious requests
    if ($http_user_agent = "") {
        return 403;
    }
}

Block Bad Requests

# Block unusual methods
if ($request_method !~ ^(GET|HEAD|POST|PUT|DELETE)$) {
    return 444;
}

# Block requests without Host
if ($host = "") {
    return 444;
}

# Block invalid Host
if ($host !~* ^(example\.com|www\.example\.com)$) {
    return 444;
}

Map-Based Blocking

# Block by various criteria
map $http_user_agent $block_ua {
    default 0;
    ~*bot 1;
    ~*spider 1;
    "" 1;
}

map $request_uri $block_uri {
    default 0;
    ~*\.php$ 1;
    ~*wp-admin 1;
    ~*xmlrpc 1;
}

server {
    if ($block_ua) {
        return 403;
    }

    if ($block_uri) {
        return 403;
    }
}

Geographic Blocking

# Requires GeoIP2 module
geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
    $geoip2_country_code country iso_code;
}

map $geoip2_country_code $allowed_country {
    default no;
    US yes;
    CA yes;
    GB yes;
}

server {
    if ($allowed_country = no) {
        return 403;
    }
}

Emergency Mode

# Maintenance/Under Attack page
server {
    listen 80;
    server_name example.com;

    # Serve static maintenance page
    root /var/www/maintenance;

    location / {
        # Ultra-strict rate limiting
        limit_req zone=emergency burst=1 nodelay;

        try_files /index.html =503;
    }
}

Complete DDoS Protection Config

# In http context
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;

# Blacklist
geo $blacklist {
    default 0;
    include /etc/nginx/conf.d/blacklist.conf;
}

server {
    listen 80;
    server_name example.com;

    # Block blacklisted IPs
    if ($blacklist) {
        return 444;
    }

    # Connection limits
    limit_conn conn_limit 20;
    limit_req zone=req_limit burst=50 nodelay;

    # Buffer limits
    client_body_buffer_size 1k;
    client_header_buffer_size 1k;
    client_max_body_size 10m;

    # Timeouts
    client_body_timeout 10;
    client_header_timeout 10;
    send_timeout 10;

    # Block bad requests
    if ($request_method !~ ^(GET|HEAD|POST)$) {
        return 444;
    }

    if ($http_user_agent = "") {
        return 444;
    }

    location / {
        proxy_pass http://backend;
    }
}

Monitoring

# Watch connections
watch 'netstat -an | grep :80 | wc -l'

# Top IPs
netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -20

# Add to blacklist
echo "1.2.3.4 1;" >> /etc/nginx/conf.d/blacklist.conf
nginx -s reload
advanced Security Updated 2025-01-15
  • nginx
  • ddos
  • protection
  • security
  • mitigation