Security should be a top priority for any production Nginx server. Here’s how to harden your Nginx configuration against common vulnerabilities and threats.
Restrict Information Disclosure
Prevent leaking server information:
nginxhttp {
server_tokens off; # Hide Nginx version
# Custom error pages
error_page 401 403 404 /custom_error.html;
}
Implement Strong SSL/TLS Configuration
Use modern, secure TLS settings:
nginxserver {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
# Modern SSL configuration
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:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# DH parameters for DHE ciphersuites
ssl_dhparam /path/to/dhparam.pem;
# HSTS (15768000 seconds = 6 months)
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload" always;
}
Force HTTPS Redirection
Ensure all traffic uses HTTPS:
nginxserver {
listen 80;
server_name example.com;
# Redirect all HTTP traffic to HTTPS
return 301 https://$host$request_uri;
}
Add Security Headers
Implement modern security headers:
nginxhttp {
# Security headers
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.google-analytics.com; img-src 'self' data: https://www.google-analytics.com; style-src 'self' 'unsafe-inline'; font-src 'self'; connect-src 'self'; frame-ancestors 'self'; form-action 'self';" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=(), payment=()" always;
}
Rate Limiting
Protect against brute force and DDoS attacks:
nginxhttp {
# Define rate limiting zones
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
limit_req_zone $binary_remote_addr zone=api:10m rate=5r/s;
server {
# Apply rate limiting to login page
location /login {
limit_req zone=login burst=5 nodelay;
# Rest of configuration...
}
# Apply rate limiting to API
location /api/ {
limit_req zone=api burst=10;
# Rest of configuration...
}
}
}
Block Suspicious User Agents and Requests
Filter out malicious requests:
nginxhttp {
# Block bad bots and crawlers
map $http_user_agent $bad_bot {
default 0;
"~*Baiduspider" 1;
"~*Exabot" 1;
"~*Indy Library" 1;
"~*Alexa Crawler" 1;
"~*AhrefsBot" 1;
"~*curl" 1;
"~*MJ12bot" 1;
"~*Wget" 1;
}
server {
if ($bad_bot) {
return 403;
}
# Block suspicious requests
location ~ (\.git|\.htaccess|\.env|wp-config\.php) {
deny all;
return 404;
}
}
}
File Upload Protection
If your server accepts file uploads, secure them:
nginxlocation /uploads {
# Only allow specific file types
location ~* \.(jpg|jpeg|png|gif)$ {
# Allow these file types
}
# Deny all other file types
location ~* \. {
deny all;
}
client_max_body_size 10M; # Limit upload size
# Prevent script execution
location ~* \.(php|pl|py|jsp|asp|sh|cgi)$ {
deny all;
}
}
Regular Security Updates
Keep up with Nginx security updates:
bash# For Debian/Ubuntu
apt update
apt-get install --only-upgrade nginx
# For CentOS/RHEL
yum update nginx
Implement Fail2Ban
Use Fail2Ban to block repeat offenders:
# Example Fail2Ban configuration for Nginx
[nginx-http-auth]
enabled = true
port = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
maxretry = 5
By implementing these security measures, you can significantly reduce the attack surface of your Nginx web server and protect against common vulnerabilities.