Contenu principal
Blog Header Design par equinoxe7

PHP-FPM mangerait les entêtes ?

J’ai eu un petit soucis sur le site récemment : malgré toutes mes tentatives, il m’était parfois impossible d’ajouter ou modifier des entêtes depuis le fichier .htaccess. J’ai pu finalement poser un pansement sur ce problème qui me rendait dingue.

Certains le savent, j’ai changé d’hébergeur il y a quelques mois pour aller voir du côté des suisses, chez Infomaniak. Je ne dis pas ça pour jeter la pierre par rapport au soucis abordé aujourd’hui, mais ayant pris une offre classique chez un hébergeur connu, je me dis que je ne suis pas le seul dans cette situation, cela concernera probablement l’un d’entre vous dans le lot.

Symptôme : des entêtes kimarchpa

Dans le fichier .htaccess d’un site, il y a très souvent des manipulations d’entêtes :

Header set XXXXXX
Header unset XXXXXX
Header merge XXXXXX
Header append XXXXXX
Header always set XXXXXX
...

Alors que ceci fonctionne sans soucis avec les fichiers statiques (fichiers images, css, JS, html…), rien à faire du côté des fichiers php.

Au début je n’y ai pas trop prêté attention, quelques header( 'XXXXXX' ); en php et hop, résolu. Et puis avec tous les changements intervenus récemment sur le site (WP Rocket, https), j’ai voulu aller plus loin. Car ces entêtes peuvent être importantes : certaines sont utiles pour les performances du site, d’autres ont attrait à la sécurité.

Source du problème ?

Là ce n’est pas très clair, car on touche un domaine où j’y pipe pas grand chose, la configuration serveur et les technos employées. Après pas mal de recherches et de messages échangés avec le support d’Infomaniak (car on n’a jamais un technicien au bout du mail), j’ai ceci :

Cher client,

Merci pour votre message.

Le souci ne vient pas d’un problème de configuration du serveur mais, cependant, il y a effectivement une particularité de php-fpm qui communique avec apache en cgi.

Pour le php, il faut configurer les headers coté php.
Pour ne le faire qu’une fois il faudrait utiliser, dans un fichier, la fonction php header() et « sourcer » en faisant un require de ce fichier.

Nous vous remercions de votre confiance et vous transmettons nos meilleures salutations.

En résumé, php-fpm/apache/FastCGI, ça fait pas bon ménage ensemble sur ce point et on n’y peut rien, il faut utiliser la fonction php header().
D’ailleurs je n’étais pas le seul surpris, merci Guislain pour ton soutien psychologique ^^’ :

Pansement

Au début j’utilisais une extension pour y mettre mes headers, mais c’était insuffisant. En effet, sans aller dans les détails, il y avait des cas où cela ne marchait pas, et surtout, seul le site en profitait, pas mon installation piwik ou mes outils en ligne.

Quand tout à coup, l’ami Julio marmonne un truc à base de « php.ini, auto prepend« .
Je cherche, et découvre auto_prepend_file, qu’il faut donc placer dans un fichier php.ini.

auto_prepend_file string

Spécifie le nom d’un fichier qui sera automatiquement parcouru avant le fichier principal. Ce fichier est inclus comme s’il l’avait été avec la fonction require, donc include_path est utilisé.

L’idée est donc d’inclure partout un fichier php contenant les header().
Voici par exemple le contenu du mien :

$security_policy  = "default-src 'self'; ";
$security_policy .= "connect-src 'self'; ";
$security_policy .= "script-src 'self' 'unsafe-inline'; ";
$security_policy .= "object-src 'self'; ";
$security_policy .= "style-src 'self' data: 'unsafe-inline'; ";
$security_policy .= "frame-src 'self'; ";
$security_policy .= "media-src 'self'; ";
$security_policy .= "font-src 'self' data:; ";
$security_policy .= "img-src 'self' data: https://*.wp.com https://wordpress.org https://ps.w.org https://*.gravatar.com";

header( 'Cache-Control: public', false );
header( 'Cache-Control: no-transform', false );
header( 'Vary: Accept-Encoding', false );
header( 'X-UA-Compatible: IE=edge' );
header( 'X-Frame-Options: SAMEORIGIN' );
header( 'Content-Security-Policy: '   . $security_policy );
header( 'X-Content-Security-Policy: ' . $security_policy );
header( 'X-WebKit-CSP: '              . $security_policy );
header( 'X-Content-Type-Options: nosniff' );
header( 'X-XSS-Protection: 1; mode=block' );

header_remove( 'Pragma' );
header_remove( 'Last-Modified' );
header_remove( 'X-Powered-By' );
header_remove( 'ETag' );
header_remove( 'Link' );

Ensuite il faut créer le fichier php.ini. Petite particularité chez Infomaniak, ce fichier doit s’appeler .user.ini :

auto_prepend_file="/chemin/absolu/vers/headers.php"

Ces deux fichiers sont bien sûr placés à la racine du site.

L’avantage de cette solution c’est qu’elle va fonctionner pour tous les scripts php de mon coin de serveur, pas seulement WordPress.
L’inconvénient c’est qu’il faut écrire les headers en double : une fois dans le fichier php et une fois dans le fichier .htaccess pour les fichiers statiques.

See ya!

PS : pour ceuzécelles qui ne l’ont pas encore remarqué, le site est passé en https ! \o/