I’ll help analyze and explain these WordPress Nginx security settings, highlighting the key security measures and optimizations. Here’s a breakdown of the most important security features:
- Basic Access Security
# Disable logging for system files
location = /favicon.ico {
try_files /favicon.ico @empty;
access_log off;
log_not_found off;
expires max;
}
This reduces log clutter and prevents unnecessary logging of common file requests.
- Upload Protection
# Deny access to archives in wp-content
location ~* ^/(wp-content)/(.*?)\.(zip|gz|tar|bzip2|7z)$ {
deny all;
}
# Prevent PHP execution in uploads
location /wp-content/uploads/ {
location ~ \.php$ {
deny all;
}
}
Critical security measure that prevents attackers from executing malicious uploaded files.
- Script Execution Protection
# Disable execution of potentially dangerous scripts
location ~* .(pl|cgi|py|sh|lua|asp)$ {
return 444;
}
Blocks execution of non-PHP scripts that could be used for attacks.
- Configuration Protection
# Protect sensitive files
location ~* /(wp-config.php|readme.html|license.txt|nginx.conf) {
deny all;
}
Prevents access to sensitive WordPress configuration files.
- SQL Injection Protection
location ~* "(\'|\")(.*)(drop|insert|md5|select|union)" {
deny all;
}
Blocks common SQL injection patterns.
- Performance Optimizations
# Cache settings for static files
location ~* \.(?:css|js)$ {
expires 1y;
access_log off;
add_header Cache-Control "public";
}
# Media file caching
location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|webm)$ {
expires max;
access_log off;
add_header Cache-Control "public";
}
Implements aggressive caching for static resources.
- Backup File Protection
# Deny backup extensions
location ~* ^.+\.(bak|log|old|orig|original|php#|php~|php_bak|save|swo|swp|sql)$ {
deny all;
access_log off;
log_not_found off;
}
Prevents access to backup files that might contain sensitive information.
- XSS Protection
location ~* "(<|%3C).*script.*(>|%3)" {
deny all;
}
Blocks common XSS attack patterns.
- Path Traversal Protection
location ~ "(\\|\.\.\.|\.\./|~|`|<|>|\|)" {
deny all;
}
Prevents directory traversal attacks.
- Additional Security Headers
add_header Permissions-Policy "geolocation=(),midi=(),sync-xhr=(),microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=(self),payment=()";
Implements modern security headers to control browser features.
Key Security Benefits:
- Prevents unauthorized access to sensitive files
- Blocks common attack vectors (SQL injection, XSS, etc.)
- Protects upload directories from code execution
- Implements proper caching for better performance
- Reduces server load by blocking malicious requests
- Prevents information disclosure through backup files
- Protects against path traversal attacks
- Implements modern security headers
Best Practices Added:
- WWW redirect for consistent domain access
- Extended timeouts for large file uploads
- Proper caching headers for different file types
- Logging optimizations to reduce disk I/O
- Protection against common WordPress vulnerabilities
This configuration provides a strong security baseline while maintaining good performance through proper caching and resource handling. It’s particularly well-suited for high-traffic WordPress sites that need extra security measures.
Remember to:
- Test thoroughly before implementing in production
- Keep regular backups
- Monitor logs for blocked attacks
- Update WordPress core, themes, and plugins regularly
- Consider implementing a WAF (Web Application Firewall) for additional protection
# WordPress Enhanced Security Configuration
# Optimized for security and performance
# Last updated: 2024-11-18
#################### BASIC SETTINGS ####################
# Limit Buffer Overflow attacks
client_body_buffer_size 10K;
client_header_buffer_size 1k;
client_max_body_size 32m;
large_client_header_buffers 2 1k;
# Timeouts
client_body_timeout 12;
client_header_timeout 12;
keepalive_timeout 15;
send_timeout 10;
# Global Security Headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Permissions-Policy "geolocation=(),midi=(),sync-xhr=(),microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=(self),payment=()";
#################### WORDPRESS SPECIFIC ####################
# Disable WordPress content directory browsing
autoindex off;
# Disable logging for favicon and robots.txt
location = /favicon.ico {
try_files /favicon.ico @empty;
access_log off;
log_not_found off;
expires max;
}
location @empty {
empty_gif;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
try_files $uri /index.php?$args;
}
# Brute Force Protection for wp-login.php
# Add this to nginx.conf: limit_req_zone $binary_remote_addr zone=wplogin:10m rate=1r/s;
location = /wp-login.php {
limit_req zone=wplogin burst=2 nodelay;
include fastcgi_params;
fastcgi_pass unix:/var/run/php-fpm.sock; # Adjust based on your PHP-FPM setup
}
#################### SECURITY RULES ####################
# Block PHP execution in uploads directory
location /wp-content/uploads {
location ~ \.php$ {
deny all;
}
# WebP support
location ~ \.(png|jpe?g)$ {
add_header Vary "Accept-Encoding";
add_header "Access-Control-Allow-Origin" "*";
add_header Cache-Control "public, no-transform";
access_log off;
log_not_found off;
expires max;
try_files $uri $uri.webp $uri =404;
}
}
# Block access to sensitive WordPress files
location ~* wp-config.php$ {
deny all;
}
# Block access to sensitive directories
location ~* ^/(wp-content)/(.*?)\.(zip|gz|tar|bzip2|7z)$ {
deny all;
}
location ~ ^/wp-content/(updraft|uploads/sucuri) {
deny all;
}
# Block non-PHP script execution
location ~* \.(pl|cgi|py|sh|lua|asp|aspx)$ {
return 444;
}
# Block access to hidden files and directories
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# Block sensitive content
location ~* ^/(license|readme|README|wp-config-sample)\.(txt|html|md)$ {
deny all;
access_log off;
log_not_found off;
}
#################### SECURITY PATTERNS ####################
# Block SQL injections
location ~* "(\'|\")(.*)(drop|insert|md5|select|union)" {
deny all;
}
# Block XSS
location ~* "<(/*|%)*(script|object|embed|applet|meta|iframe|frame|frameset|style|img|onmouseover)" {
deny all;
}
# Block common exploits
location ~* "(eval\(|base64_encode|base64_decode|\(null\)|javascript\:|escape\(|\%|\$|localhost|loopback|127\.0\.0\.1)" {
deny all;
}
# Block directory traversal
location ~ "(\\|\.\.\.|\.\./|~|`|<|>|\|)" {
deny all;
}
#################### PERFORMANCE OPTIMIZATION ####################
# Cache static files
location ~* \.(ogg|ogv|svg|svgz|eot|otf|woff|woff2|ttf|m4a|mp4|ttf|rss|atom|jpe?g|gif|cur|heic|png|tiff|ico|zip|webm|mp3|aac|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
expires max;
log_not_found off;
access_log off;
add_header Cache-Control "public";
}
# Cache CSS and JS files
location ~* \.(css|js)$ {
expires 1y;
access_log off;
add_header Cache-Control "public, no-transform";
}
# Cache HTML and XML files
location ~* \.(html|xml)$ {
expires 7d;
add_header Cache-Control "public, no-transform";
}
#################### WORDPRESS PERMALINKS ####################
# WordPress permalinks configuration
location / {
try_files $uri $uri/ /index.php?$args;
}
# Pass PHP scripts to PHP-FPM
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php-fpm.sock; # Adjust based on your setup
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_intercept_errors on;
fastcgi_buffer_size 128k;
fastcgi_buffers 256 16k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
}
#################### DENY ACCESS TO SPECIAL FILES ####################
# Block access to backup and source files
location ~* \.(bak|config|sql|fla|ini|log|sh|inc|swp|dist|engine|install|old|orig|psd|tar|tpl|info|json|md|theme|yml|yaml)$ {
deny all;
}
#################### COMPRESSION ####################
# Enable GZIP compression
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_min_length 256;
gzip_types
application/atom+xml
application/geo+json
application/javascript
application/x-javascript
application/json
application/ld+json
application/manifest+json
application/rdf+xml
application/rss+xml
application/vnd.ms-fontobject
application/wasm
application/x-web-app-manifest+json
application/xhtml+xml
application/xml
font/eot
font/otf
font/ttf
image/bmp
image/svg+xml
text/cache-manifest
text/calendar
text/css
text/javascript
text/markdown
text/plain
text/xml
text/vcard
text/vnd.rim.location.xloc
text/vtt
text/x-component
text/x-cross-domain-policy;
#################### SSL CONFIGURATION ####################
# Recommended SSL configuration
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
# Modern 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;
#################### ERROR PAGES ####################
# Custom error pages
error_page 403 /error/403.html;
error_page 404 /error/404.html;
error_page 500 502 503 504 /error/50x.html;
#################### END ####################
# Redirect from www to non-www
if ($host ~ ^www\.(?<domain>.+)$) {
return 301 $scheme://$domain$request_uri;
}