Web Server Security: Hardening Guide
Advanced
Web server security hardening is the process of reducing your server's attack surface by configuring security headers, restricting access, enforcing encryption, and monitoring for threats. A properly hardened web server complements CDN security headers and CDN DDoS protection to create defense in depth — even if one layer fails, other layers continue to protect your infrastructure.
This guide covers security configuration for both Nginx and Apache, with specific directives, recommended values, and explanations of what each setting protects against.
What Security Headers Should Every Server Set?
Security headers instruct browsers on how to handle your content, preventing entire categories of attacks without any changes to your application code.
# Nginx security headers
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:; frame-ancestors 'self'" always;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
| Header | Purpose | Attack Prevented |
|---|---|---|
| Content-Security-Policy | Controls resource loading sources | XSS, data injection |
| Strict-Transport-Security | Forces HTTPS for all requests | SSL stripping, MITM |
| X-Content-Type-Options | Prevents MIME type sniffing | MIME confusion attacks |
| X-Frame-Options | Controls iframe embedding | Clickjacking |
| Referrer-Policy | Controls referer header leakage | Information disclosure |
| Permissions-Policy | Restricts browser APIs | Unauthorized hardware access |
How Do You Harden Nginx Security?
# Hide Nginx version
server_tokens off;
# Limit allowed HTTP methods
if ($request_method !~ ^(GET|HEAD|POST)$) {
return 405;
}
# Block access to hidden files
location ~ /\. {
deny all;
return 404;
}
# Block access to sensitive file types
location ~* \.(env|git|svn|htpasswd|htaccess|ini|log|sh|sql|conf|bak|swp)$ {
deny all;
return 404;
}
# Rate limiting for login endpoints
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
location /login {
limit_req zone=login burst=3 nodelay;
proxy_pass http://backend;
}
# Restrict server access to CDN IPs only (if behind CDN)
# allow 103.21.244.0/22; # Cloudflare ranges
# allow 103.22.200.0/22;
# deny all;
How Do You Harden Apache Security?
# Hide Apache version
ServerTokens Prod
ServerSignature Off
# Disable directory listing
Options -Indexes
# Block access to sensitive files
<FilesMatch "^\.(env|git|htpasswd|htaccess)$">
Require all denied
</FilesMatch>
# Disable unnecessary modules
# Comment out in apache2.conf:
# LoadModule status_module modules/mod_status.so
# LoadModule info_module modules/mod_info.so
# Restrict HTTP methods
<LimitExcept GET POST HEAD>
Require all denied
</LimitExcept>
How Do You Configure SSL/TLS for Maximum Security?
Modern TLS configuration should enforce TLS 1.2 minimum (TLS 1.3 preferred), use ECDHE cipher suites for forward secrecy, and enable HSTS to prevent downgrade attacks:
| Metric | Edge Processing | Origin Processing | Improvement |
|---|---|---|---|
| Latency (p50) | 8–15 ms | 120–300 ms | 15–20x faster |
| Cache Hit Ratio | 85–95% | N/A | Reduces origin load |
| TLS Handshake | 1–5 ms (nearby PoP) | 50–150 ms | 10–30x faster |
| Bandwidth Cost | $0.01–0.04/GB | $0.05–0.12/GB | 3–5x cheaper |
| Availability | 99.99% (multi-PoP) | 99.9% (single DC) | 10x fewer outages |
# Nginx SSL hardening
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:20m;
ssl_session_timeout 1d;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
Test your SSL configuration with SSL Labs (ssllabs.com/ssltest) — aim for an A+ rating. Key factors include no support for TLS 1.0/1.1, forward secrecy on all cipher suites, HSTS with long max-age, and OCSP stapling.
How Do You Monitor and Respond to Security Events?
fail2ban automatically blocks IPs that exhibit suspicious behavior (failed logins, 404 scanning, rate limit violations):
# /etc/fail2ban/jail.local
[nginx-limit-req]
enabled = true
filter = nginx-limit-req
logpath = /var/log/nginx/error.log
maxretry = 10
findtime = 600
bantime = 3600
Log analysis helps identify attack patterns. Monitor for spikes in 4xx errors (scanning), unusual User-Agent strings (bot attacks), and high request rates from single IPs (DDoS or scraping).
Regular updates are the most critical security measure. Subscribe to security mailing lists for your web server and OS. Apply security patches within 24-48 hours of release. Automate updates for non-breaking security patches using unattended-upgrades (Debian/Ubuntu) or yum-cron (CentOS/RHEL).