1. Disable Server Information Leakage (Fingerprinting)
By default, when Nginx serves an error page (e.g., 404 or 502) or responds to an HTTP request, it sends a Server: nginx/1.24.0 (Ubuntu) header. Automated vulnerability scanners (like Shodan) harvest these version numbers to look up published CVE exploits.
Always disable version broadcasting inside the http block of your nginx.conf:
http {
# Suppress Nginx version number in Server headers and error pages
server_tokens off;
}2. Enforce Modern SSL/TLS 1.3 Ciphers
Legacy protocols like SSLv3, TLS 1.0, and TLS 1.1 suffer from severe cryptographic flaws (e.g. POODLE, BEAST). Production web servers in 2026 must support only TLS 1.2 and TLS 1.3 with high-performance Perfect Forward Secrecy (PFS) ciphers:
ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384'; # Session cache for high-throughput TLS handshakes ssl_session_timeout 1d; ssl_session_cache shared:SSL:50m; ssl_session_tickets off; # OCSP Stapling (speeds up TLS handshakes & avoids CA bottleneck) ssl_stapling on; ssl_stapling_verify on; resolver 1.1.1.1 8.8.8.8 valid=300s; resolver_timeout 5s;
3. Inject Mandatory Security Response Headers
Security headers instruct modern browsers to enforce strict sandboxing, prevent cross-site scripting (XSS), and prohibit clickjacking iframe embedding:
- HSTS (Strict-Transport-Security): Forces browsers to interact only over HTTPS for 1 year, even if a user types
http://. - X-Frame-Options: Prevents unauthorized sites from embedding your application inside hidden
<iframe>elements (clickjacking defense). - X-Content-Type-Options: Blocks MIME-type sniffing, preventing executable scripts disguised as images from running.
# Add critical HTTP security headers add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
4. Prevent Slowloris & Buffer Overflow Exhaustion
In a Slowloris attack, an attacker opens hundreds of HTTP connections and sends tiny header fragments very slowly (e.g. 1 byte every 10 seconds), keeping worker connections occupied until the server runs out of file descriptors.
Tuning client timeouts and buffer sizes cuts off malicious slow connections while protecting legitimate traffic:
# Buffer sizes: prevent buffer overflow attacks client_body_buffer_size 16K; client_header_buffer_size 1k; client_max_body_size 10M; # Adjust if your app accepts large file uploads large_client_header_buffers 4 8k; # Timeouts: drop stalled or slow connections client_body_timeout 12s; client_header_timeout 12s; keepalive_timeout 65s; send_timeout 10s;
5. Implementing Leaky-Bucket Rate Limiting
Nginx includes a built-in implementation of the leaky-bucket algorithm (limit_req) to prevent credential stuffing on login routes and API DDoS flooding:
# Define an in-memory zone: 10MB can track ~160,000 distinct IP addresses
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
server {
location /api/ {
# Allow small bursts up to 20 requests without delaying legitimate users
limit_req zone=api_limit burst=20 nodelay;
proxy_pass http://backend_upstream;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}6. Conclusion & Deployment Checklist
Always run nginx -t to validate your configuration syntax before executing nginx -s reload in production. Testing your public endpoints with tools like SSL Labs (aiming for an A+ grade) ensures all cipher suites and HSTS policies are functioning as expected.