Accueil / Tutoriels Serveur / Apache2 Hardening pour WordPress — Headers, CSP, IP réelle, .htaccess

Apache2 Hardening pour WordPress — Headers, CSP, IP réelle, .htaccess

Apache2 Hardening pour WordPress — Headers, CSP, IP réelle, .htaccess

Durcir Apache2 pour WordPress : en-têtes de sécurité, CSP pragmatique, IP réelle derrière Cloudflare/Reverse proxy, règles .htaccess et bonnes pratiques 2025.

Prérequis & principes

  • Ubuntu 22.04/24.04 avec Apache2, WordPress installé (/var/www/html/wordpress à adapter).
  • Accès sudo/root.
  • Objectif : sécurité pragmatique (ne pas casser l’admin WP), durcissement incrémental.

Modules requis : headers, rewrite, ssl, remoteip (si proxy/CDN).

sudo a2enmod headers rewrite ssl remoteip
sudo systemctl reload apache2

En-têtes HTTP de sécurité (Apache)

Créez une configuration dédiée aux en-têtes. Cette baseline est prudente et compatible WordPress par défaut (front et admin). Ajustez-la selon vos extensions/CDN.

# /etc/apache2/conf-available/security-headers.conf
<IfModule mod_headers.c>
  Header always set X-Content-Type-Options "nosniff"
  Header always set X-Frame-Options "SAMEORIGIN"
  Header always set Referrer-Policy "strict-origin-when-cross-origin"
  Header always set Permissions-Policy "accelerometer=(), geolocation=(), microphone=(), camera=()"
  Header always set X-XSS-Protection "1; mode=block"
</IfModule>
sudo a2enconf security-headers
sudo systemctl reload apache2

Réduisez la verbosité serveur :

# /etc/apache2/conf-available/security-tuning.conf
ServerTokens Prod
ServerSignature Off
sudo a2enconf security-tuning
sudo systemctl reload apache2

CSP (Content-Security-Policy) : baseline front & admin

Une CSP stricte casse facilement l’admin WP. On propose donc deux politiques : front (plus stricte) et admin (plus permissive). Commencez en mode Report-Only si besoin.

Front (pages publiques)

# /etc/apache2/conf-available/csp-front.conf
<IfModule mod_headers.c>
  <LocationMatch "^/(?!wp-admin|wp-login\.php)">
    Header always set Content-Security-Policy "default-src 'self'; img-src 'self' data: https:; style-src 'self' 'unsafe-inline' https:; script-src 'self' 'unsafe-inline' https:; font-src 'self' data: https:; frame-ancestors 'self';"
  </LocationMatch>
</IfModule>

Admin (wp-admin)

# /etc/apache2/conf-available/csp-admin.conf
<IfModule mod_headers.c>
  <Location /wp-admin>
    Header always set Content-Security-Policy "default-src 'self'; img-src 'self' data: https:; style-src 'self' 'unsafe-inline' https:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; font-src 'self' data: https:; frame-ancestors 'self';"
  </Location>
</IfModule>

Activez puis testez (si votre thème/plug-ins chargent des ressources externes, ajoutez leurs domaines aux directives img-src, script-src, style-src, etc.).

sudo a2enconf csp-front csp-admin
sudo systemctl reload apache2

IP réelle client (Cloudflare / reverse proxy)

Derrière Cloudflare/proxy, Apache voit l’IP du proxy. Activez mod_remoteip pour consigner l’IP client réelle et fiabiliser vos règles (WAF/ban, logs, analytics).

# /etc/apache2/conf-available/remoteip-cloudflare.conf
RemoteIPHeader CF-Connecting-IP
# Ajoutez les ranges Cloudflare v4 / v6 (extrait)
RemoteIPTrustedProxy 173.245.48.0/20
RemoteIPTrustedProxy 103.21.244.0/22
RemoteIPTrustedProxy 103.22.200.0/22
RemoteIPTrustedProxy 103.31.4.0/22
# ... (complétez avec toutes les plages officielles CF)

Optionnel : remplacez %h par %a pour que les logs utilisent l’IP client réelle :

sudo sed -i 's/LogFormat "%h %l %u/LogFormat "%a %l %u/' /etc/apache2/apache2.conf
sudo a2enconf remoteip-cloudflare
sudo systemctl reload apache2

.htaccess : protections utiles pour WordPress

Conservez d’abord le bloc WordPress, puis ajoutez des règles de protection. Évitez de surcharger : le gros des règles doit vivre en /etc/apache2/ côté vhost/conf.

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

# Bloquer fichiers sensibles
<FilesMatch "(^\.|wp-config\.php|readme\.html|license\.txt|composer\.(json|lock))">
  Require all denied
</FilesMatch>

# Interdire exécution PHP dans uploads (créez aussi .htaccess sous /uploads)
# (double filet : utile si AllowOverride)
<Directory "wp-content/uploads">
  <FilesMatch "\.php$"> Require all denied </FilesMatch>
</Directory>

# Limiter XML-RPC (si non utilisé). Préférez règles WAF CF si possible.
<Files xmlrpc.php>
  Require all denied
</Files>

HTTPS / HSTS (rappel rapide)

Forcez le HTTPS et activez HSTS uniquement si tout le site est servi en HTTPS sans contenu mixte.

# VHost 80 > redirection HTTPS
<VirtualHost *:80>
  ServerName example.com
  ServerAlias www.example.com
  Redirect permanent / https://example.com/
</VirtualHost>

# VHost 443 (Let’s Encrypt)
<IfModule mod_headers.c>
  # Activez HSTS quand vous êtes prêt (testez avant preload)
  Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains"
</IfModule>

Validation & debug

  • Vérifier en-têtes : curl -sI https://example.com | less
  • Tester la CSP : passez d’abord en Report-Only, analysez la console navigateur, ajustez les domaines autorisés.
  • Confirmer IP réelle : regardez vos logs Apache (le premier champ doit afficher l’IP client réelle, pas celle de Cloudflare).

Maillage interne

FAQ

Puis-je activer une CSP très stricte sans casser WordPress ?

WordPress et certains thèmes/plug-ins utilisent des scripts et styles inline. Une CSP trop stricte (sans 'unsafe-inline' ni nonces) casse souvent l’admin. Commencez avec une politique pragmatique, puis durcissez progressivement en listant précisément les domaines de confiance.

Faut-il bloquer totalement xmlrpc.php ?

Si vous n’utilisez pas de services qui en dépendent (ex. anciennes apps mobiles), oui : bloquez-le côté Apache ou via Cloudflare (règle WAF). Sinon, limitez par IP et surveillez via un IDS comme CrowdSec.

Comment vérifier que l’IP réelle client est bien consignée ?

Après configuration de mod_remoteip, vérifiez les logs d’accès Apache : la première colonne doit afficher l’IP publique du visiteur (pas l’IP Cloudflare). Vous pouvez tester en visitant le site depuis une connexion 4G/5G et en consultant la dernière entrée de log.

HSTS peut-il casser mon site ?

HSTS force le navigateur à utiliser HTTPS. Si une partie du site n’est pas prête (contenu mixte, sous-domaines non SSL), vous risquez des erreurs. Activez-le uniquement lorsque tout est en HTTPS correct, puis augmentez progressivement la durée (max-age).

Conclusion

Le durcissement Apache2 pour WordPress repose sur des en-têtes solides, une CSP progressive, la bonne IP client quand on est derrière Cloudflare, et des règles .htaccess simples mais efficaces. Appliquez, testez, itérez : la sécurité est un processus continu.

Étiquetté :