Architectural Differences: How Nginx and Lighttpd Mitigate Slowloris DDoS Attacks


10 views

Slowloris operates by maintaining multiple partial HTTP connections to the target server. Traditional web servers like Apache create a separate thread or process for each connection, exhausting available worker slots with these incomplete requests. Here's a simplified example of how a Slowloris attack might look in Python:

import socket
import time

target = "vulnerable-server.com"
port = 80

for i in range(1000):
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((target, port))
        s.send("GET / HTTP/1.1\r\n".encode())
        s.send("Host: {}\r\n".format(target).encode())
        while True:
            s.send("X-a: b\r\n".encode())
            time.sleep(100)
    except:
        pass

Nginx and Lighttpd fundamentally differ in their concurrency models. Instead of spawning threads/processes per connection, they use:

  • Event-driven, asynchronous I/O model (epoll/kqueue)
  • Fixed-size worker processes handling thousands of connections
  • Connection state machines rather than per-connection resources

This architectural difference means incomplete connections don't consume significant resources. Here's how Nginx typically configures worker connections:

worker_processes auto;
events {
    worker_connections 1024;
    use epoll;
    multi_accept on;
}

Both servers implement strict default timeouts that automatically close stalled connections:

# Lighttpd example
server.max-keep-alive-requests = 16
server.max-keep-alive-idle = 5
server.max-read-idle = 60
server.max-write-idle = 360

# Nginx example
client_header_timeout 60s;
client_body_timeout 60s;
keepalive_timeout 75s;

Beyond their core architecture, both web servers offer:

  1. Rate limiting:
    limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
  2. Connection queue limits:
    listen 80 backlog=512;
  3. OS-level protections (sysctl tuning):
    net.ipv4.tcp_syncookies = 1
    net.core.somaxconn = 4096

You can validate your server's resilience using tools like slowhttptest:

slowhttptest -c 1000 -H -g -o slowhttp -i 10 -r 200 -t GET -u http://yourserver.com -x 24 -p 3

Modern versions of Apache can also achieve similar protection using event MPM and modules like mod_reqtimeout.


Slowloris operates by exploiting a fundamental design characteristic of traditional web servers like Apache. It maintains multiple partial HTTP connections by:


// Typical malicious request pattern
GET / HTTP/1.1\r\n
Host: victim.com\r\n
User-Agent: Slowloris\r\n
Content-Length: 42\r\n
X-a: b\r\n
[artificial delay here]

The attack works because Apache:

  • Creates a separate thread/process per connection
  • Maintains connection state in memory
  • Has fixed limits on concurrent connections

NginX implements several protective measures:


// NginX connection handling pseudocode
while (true) {
    events = epoll_wait(epoll_fd, ...);
    for each event {
        if (event.is_readable) {
            process_request(event.fd);
        }
    }
}

Key architectural advantages:

  • Asynchronous, non-blocking I/O model
  • Single master process manages multiple worker processes
  • Workers handle thousands of connections in event loop
  • Configurable timeouts (default 60s): client_header_timeout, client_body_timeout

Lighttpd employs several protective mechanisms:


# lighttpd.conf hardening against Slowloris
server.max-keep-alive-requests = 100
server.max-keep-alive-idle = 5
server.max-read-idle = 15
server.max-write-idle = 15
server.max-connections = 2048

Technical differentiators include:

  • Fixed-size connection pool with configurable limits
  • Aggressive timeout defaults (much shorter than Apache)
  • Single-process event loop design
  • Built-in connection rate limiting
Server Architecture Default Timeout Connection Handling
Apache Process/thread-per-connection 300s Synchronous
NginX Event-driven 60s Asynchronous
Lighttpd Single-process event loop 15-30s Asynchronous

For servers vulnerable to Slowloris, consider these mitigation techniques:


# Apache mitigation example
Timeout 30
KeepAliveTimeout 5
MaxClients 256
LimitRequestFields 50
LimitRequestFieldSize 2048

For NginX/Lighttpd administrators, additional hardening:


# NginX additional protection
limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_conn addr 20;

# Rate limiting
limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;