← News
/PLAYBOOK · 2026-07-26

Slowloris Slow-Attack Defense in Practice: Nginx and iptables Multilayer Protection Config

Slowloris slow attacks exhaust the server connection pool with tiny traffic. This article provides a three-layer protection config: Nginx parameter tuning, iptables connection limits, and Fail2ban auto-ban.

Applicable Scenarios

This article is for Nginx ops engineers, web security admins, and self-hosted site owners. Focus: defending Slowloris slow attacks. Slowloris abuses HTTP: it sends incomplete HTTP request headers at a very low rate, exhausts the server connection pool, and blocks legitimate users. This article provides a three-layer Nginx + iptables + Fail2ban protection scheme.

Prerequisites

How It Works

Slowloris was first published by Robert RSnake Hansen in 2009. Attack: the attacker opens many TCP connections, then keeps sending incomplete HTTP request headers (one extra header byte at a time, e.g. X-a: b\r\n). The server waits for the request to complete until max_clients is exhausted. Traditional DDoS defenses watch for high volume; Slowloris traffic is tiny, so you need dedicated config.

Procedure

Step 1: Tune Core Nginx Parameters

Edit the http block in /etc/nginx/nginx.conf and set these key parameters:

http {
    # Idle connection close timeout (seconds) — default 75; lower so Slowloris connections release faster
    keepalive_timeout 15;

    # Client request header timeout (seconds) — max wait from first byte to a complete header
    client_header_timeout 10;

    # Client request body timeout (seconds)
    client_body_timeout 10;

    # Timeout for sending the response to the client (seconds)
    send_timeout 10;

    # Cap concurrent connections per client (requires ngx_http_limit_conn_module)
    limit_conn_zone $binary_remote_addr zone=addr:10m;
    limit_conn addr 20;

    # Buffer settings — mitigate large-header attacks
    client_body_buffer_size 128k;
    client_header_buffer_size 1k;
    large_client_header_buffers 4 8k;
}

Step 2: Add Nginx Connection Monitoring and Auto-Release

In the server blocks you need to protect, add ngx_http_limit_req_module rate limiting:

server {
    listen 80;
    listen 443 ssl;
    server_name yourdomain.com;

    # Request rate limit — max 5 requests per second
    limit_req_zone $binary_remote_addr zone=sLowloris:10m rate=5r/s;
    limit_req zone=sLowloris burst=10 nodelay;

    location / {
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
}

Step 3: iptables Connection Limits

Use the connlimit module to cap concurrent connections per IP. Intercept Slowloris at the TCP layer before it reaches Nginx:

# Cap concurrent HTTP connections per IP at 30
iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 30 -j REJECT --reject-with tcp-reset
iptables -A INPUT -p tcp --dport 443 -m connlimit --connlimit-above 30 -j REJECT --reject-with tcp-reset

# Cap new connections per second (SYN Flood + Slowloris mix)
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --set --name HTTP
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --update --seconds 1 --hitcount 10 --name HTTP -j DROP

# Persist rules
apt-get install -y iptables-persistent  # Ubuntu
netfilter-persistent save

# CentOS:
# yum install -y iptables-services
# service iptables save

Step 4: Fail2ban Custom Rules to Detect Slowloris

Fail2ban inspects Nginx access logs for Slowloris signatures — connections that stay incomplete for a long time:

# Create Fail2ban filter /etc/fail2ban/filter.d/nginx-slowloris.conf
[Definition]
failregex = ^<HOST> -.*"(GET|POST).*HTTP/1\.[01]" 499 .*$
ignoreregex =

Create jail config /etc/fail2ban/jail.d/nginx-slowloris.conf:

[nginx-slowloris]
enabled  = true
port     = http,https
filter   = nginx-slowloris
logpath  = /var/log/nginx/access.log
maxretry = 20
findtime = 60
bantime  = 3600
action   = iptables[name=Slowloris, port=http, protocol=tcp]

Restart Fail2ban:

systemctl restart fail2ban
fail2ban-client status nginx-slowloris

Verify the Config

# 1. Check Nginx config syntax
nginx -t

# 2. Reload Nginx
systemctl reload nginx

# 3. Use a slowloris test script to verify defense
git clone https://github.com/llaera/slowloris-test.git
cd slowloris-test
python3 slowloris.py -s yourdomain.com -p 443

# 4. Monitor Nginx connection state
netstat -an | grep :80 | wc -l
# Under normal load this should stay under 30; under attack it should not exceed the configured limit_conn cap

# 5. Check Fail2ban ban logs
fail2ban-client status nginx-slowloris

FAQ

Q1: Will lowering keepalive_timeout hurt legitimate users?

Minor impact. Dropping keepalive_timeout from 75s to 15s frees idle connections faster; consecutive requests from real users pay a bit more TCP handshake cost. For most web apps (mean request interval under 5s), impact is tiny. If the site has lots of silent long-polling, set 30-45s as a compromise.

Q2: Will iptables connlimit of 30 false-ban users behind a corporate NAT egress?

Possible. Under NAT, many users share one public IP; a 30-connection cap may be too tight. Raise connlimit to 50-80 and add limit_req (request rate limit) as a second filter. Or measure peak concurrency in Nginx logs, then tune.

Summary

Core idea for Slowloris defense: shorten timeouts + cap connections, at both the Nginx app layer and the iptables network layer. Lower client_header_timeout/keepalive_timeout so incomplete connections drop fast; combine connlimit per-IP caps with Fail2ban auto-ban for a closed defense loop. Combine this config with the previously published Fail2ban SSH brute-force protection and Nginx limit_req CC defense to build a full site defense stack.