Securitate WordPress Avansată: Nginx, Apache și Fail2Ban – Protejează wp-admin și xmlrpc.php
WordPress rămâne cel mai popular CMS, dar și unul dintre cele mai atacate. Pe lângă plugin-uri de securitate, blocarea accesului la zonele sensibile direct la nivel de server și utilizarea Fail2Ban poate face site-ul mult mai sigur.
Mai jos găsești un exemplu de configurare Nginx și Apache, cu restricții pentru IP-urile de admin și protecții împotriva atacurilor comune (XSS, SQL injection, enumerare de autori etc.)..
Principii folosite
✔ acces la admin doar din IP-uri de încredere
✔ admin-ajax.php și admin-post.php rămân publice (necesar pentru frontend)
✔ dezactivare XML‑RPC
✔ blocare enumerare autori
✔ blocare PHP în uploads
✔ blocare fișiere sensibile
✔ protecție XSS / SQLi la nivel de webserver
✔ Fail2Ban ca layer suplimentar (firewall automat
Nginx – WordPress Security Block (per site)
Înlocuiește IP‑urile dummy cu IP‑urile reale de admin.
############################################
# WORDPRESS SECURITY BLOCK (PER-SITE)
############################################
# --- Trusted admin IPs ---
set $wp_admin_allowed 0;
# Admin IPs (dummy)
if ($remote_addr = 123.123.123.123) { set $wp_admin_allowed 1; }
if ($remote_addr = 111.111.111.111) { set $wp_admin_allowed 1; }
if ($remote_addr = 222.222.222.222) { set $wp_admin_allowed 1; }
# Server itself
if ($remote_addr = 127.0.0.1) { set $wp_admin_allowed 1; }
# PHP socket per site - CHNAGE SOCKET
set $php_sock unix:/run/php/161626534612882.sock;
#or use set $php_sock 127.0.0.1@843; f
############################################
# BLOCK PHP EXECUTION IN wp-content
############################################
location ~* ^/wp-content/.*\.php$ {
return 403;
}
############################################
# ADMIN AREA: /wp-admin
############################################
# Allow static assets for all
location ~ ^/wp-admin/.*\.(css|js|png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot|ico)$ {
access_log off;
log_not_found off;
}
# Essential PHP scripts allowed for everyone
location ~ ^/wp-admin/(admin-ajax\.php|admin-post\.php)$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass $php_sock;
}
# WP Login - trusted IPs only
location = /wp-login.php {
if ($wp_admin_allowed = 0) { return 403; }
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass $php_sock;
}
# All other PHP files in admin areas - trusted IPs only
location ~ ^/wp-admin/.*\.php$ {
if ($wp_admin_allowed = 0) { return 403; }
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass $php_sock;
}
# Protect folders themselves (index.php)
location ~ ^/wp-admin/?$ {
if ($wp_admin_allowed = 0) { return 403; }
index index.php;
try_files $uri $uri/ /index.php?$args;
}
############################################
# AUTHOR ENUMERATION
############################################
location ~* ^/author/ { return 403; }
if ($args ~* "author=\d+") { return 403; }
location ~* ^/wp-json/wp/v2/users { return 403; }
############################################
# DISABLE XML-RPC
############################################
location = /xmlrpc.php { return 403; }
############################################
# COMMON XSS / SQL INJECTION / MALICIOUS REQUESTS
############################################
location ~* "(eval\(|base64_|<script|union.*select|insert.*into|drop.*table|sleep\(|benchmark\(|information_schema|load_file|outfile|concat\()" {
return 403;
}
############################################
# SENSITIVE FILES
############################################
location ~* ^/(wp-config\.php|readme\.html|license\.txt|\.env|composer\.json|package\.json) { return 403; }
############################################
# PHP IN UPLOADS
############################################
location ~* ^/wp-content/uploads/.*\.php$ { return 403; }
############################################
# DOTFILES & BACKUPS
############################################
location ~ /\. { return 403; }
location ~* \.(bak|old|orig|swp|sql|zip|tar|gz)$ { return 403; }
############################################
# SEO SAFE
############################################
location = /robots.txt { allow all; log_not_found off; access_log off; }
location = /sitemap.xml { allow all; log_not_found off; access_log off; }
############################################
# END WORDPRESS SECURITY BLOCK
############################################
Apache – WordPress Security Block
Funcționează pentru Apache + PHP‑FPM sau mod_php.
# -------------------------------------------
# WORDPRESS SECURITY BLOCK
# -------------------------------------------
<FilesMatch "wp-config.php|readme.html|license.txt|\.env|composer.json|package.json">
Require all denied
</FilesMatch>
<FilesMatch "\.(bak|old|orig|swp|sql|zip|tar|gz)$">
Require all denied
</FilesMatch>
<FilesMatch "\.php$">
SetEnvIf Remote_Addr "^(123\.123\.123\.123|111\.111\.111\.111|222\.222\.222\.222|127\.0\.0\.1)$" WP_ADMIN_ALLOWED
</FilesMatch>
<Directory "/var/www/html/wp-admin">
<Files "admin-ajax.php">
Require all granted
</Files>
<Files "admin-post.php">
Require all granted
</Files>
<FilesMatch "\.php$">
Require env WP_ADMIN_ALLOWED
</FilesMatch>
</Directory>
<Directory "/var/www/html/wp-content/uploads">
<FilesMatch "\.php$">
Require all denied
</FilesMatch>
</Directory>
# Disable XML-RPC
<Files "xmlrpc.php">
Require all denied
</Files>
# Disable author enumeration
RewriteEngine On
RewriteCond %{QUERY_STRING} author=\d [NC]
RewriteRule ^ /? [L,R=403]
Layer suplimentar de securitate: Fail2Ban
Nginx sau Apache pot proteja site-ul, dar atacurile brute force pot veni rapid și masiv. Fail2Ban poate monitoriza logurile web și bloca automat IP-urile care încearcă login-uri repetate sau exploit-uri.
Exemplu jail WordPress:
# /etc/fail2ban/jail.local
[wordpress]
enabled = true
port = http,https
filter = wordpress
logpath = /var/log/nginx/access.log
maxretry = 5
bantime = 3600
Astfel, chiar dacă cineva evită Nginx sau Apache, Fail2Ban blochează IP-urile suspecte la nivel de firewall.
Concluzie
🔐 Securitatea reală începe la nivel de server, nu în plugin-uri
🧱 Nginx / Apache = primul zid
🔥 Fail2Ban = al doilea zid
🧠 WordPress vede doar trafic deja filtrat
