« Installation de configuration du serveur web Apache 2.4 sous Debian Bullseye » : différence entre les versions

Aller à la navigation Aller à la recherche
 
(46 versions intermédiaires par le même utilisateur non affichées)
Ligne 4 : Ligne 4 :
=Les différents mpm=
=Les différents mpm=


Les différents mpm de apache sont fournis sous forme de modules et ce dès l'installation du paquet <code>apache2</code>. Sous Debian pré-Bullseye, la seule exception était le mpm ITK qui nécessitait l'installation du paquet <code>libapache2-mpm-itk</code>. Ce n'est plus le cas depuis Bullseye.
Les différents mpm de apache sont fournis sous forme de modules et ce dès l'installation du paquet <code>apache2</code>. La seule exception reste le mpm ITK qui nécessite l'installation du paquet <code>libapache2-mpm-itk</code>.


=Installation=
=Installation=
Ligne 71 : Ligne 71 :


Nous allons créer un fichier afin d'interdire l'accès à certains dossiers qu'apache autorise en général par défaut. Notez qu'activer ces options empêchera la configuration par défaut de nombreux paquets debian de fonctionner.<br>
Nous allons créer un fichier afin d'interdire l'accès à certains dossiers qu'apache autorise en général par défaut. Notez qu'activer ces options empêchera la configuration par défaut de nombreux paquets debian de fonctionner.<br>
Créez le fichier <code>/etc/apache2/conf-available/zzz_localsecurity.conf</code> (le faire commencer par zzz devrait vous assurer qu'il soit lu en dernier)
Créez le fichier <code>/etc/apache2/conf-available/zzz-local-security.conf</code> (le faire commencer par zzz devrait vous assurer qu'il soit lu en dernier) contenant :
<pre>
<pre>
# Disable access to / by default
<Directory />
        Options -Includes -IncludesNOEXEC -ExecCGI -Indexes -FollowSymLinks -SymLinksIfOwnerMatch -MultiViews
        AllowOverride None
        Require all denied
</Directory>
# Disable access to /usr/share by default
# Disable access to /usr/share by default
<Directory /usr/share>
<Directory /usr/share/>
        Options -Includes -IncludesNOEXEC -ExecCGI -Indexes -FollowSymLinks -SymLinksIfOwnerMatch -MultiViews
         AllowOverride None
         AllowOverride None
         Require all denied
         Require all denied
Ligne 81 : Ligne 89 :
# Disable access to /usr/lib/cgi-bin/ by default (will override conf-enabled/serve-cgi-bin.conf if enabled)
# Disable access to /usr/lib/cgi-bin/ by default (will override conf-enabled/serve-cgi-bin.conf if enabled)
<Directory /usr/lib/cgi-bin/>
<Directory /usr/lib/cgi-bin/>
        Options -Includes -IncludesNOEXEC -ExecCGI -Indexes -FollowSymLinks -SymLinksIfOwnerMatch -MultiViews
         AllowOverride None
         AllowOverride None
         Require all denied
         Require all denied
</Directory>
</Directory>


# Disable access to svt tree
# Disable access to svn tree
<DirectoryMatch "/\.svn">
<DirectoryMatch "/\.svn">
  Require all denied
        Require all denied
</DirectoryMatch>
</DirectoryMatch>


# Disable access to git tree
# Disable access to git tree
<DirectoryMatch "/\.git">
<DirectoryMatch "/\.git">
  Require all denied
        Require all denied
</DirectoryMatch>
</DirectoryMatch>


Ligne 100 : Ligne 109 :
</FilesMatch>
</FilesMatch>


# Disable access to htpasswd and htdigest files as some user don't make them hidden
# Disable access to htpasswd and htdigest files as some users don't make them hidden
<FilesMatch "htpasswd">
<Files htpasswd>
         Require all denied
         Require all denied
</FilesMatch>
</Files>
<FilesMatch "htdigest">
<Files htdigest>
        Require all denied
</Files>
 
# Disable access to .user.ini (used by php for local config)
<Files .user.ini>
        Require all denied
</Files>
 
# Deny access to most php project configuration files (localsettings.php, config.php but also things like config.anything.php
<FilesMatch "(?i)^(config-db|wp-config|commonsettings|localsettings|config)(\.([a-z]|[0-9])+)*\.ph(ar|p|tml)$">
         Require all denied
         Require all denied
</FilesMatch>
</FilesMatch>
Ligne 110 : Ligne 129 :
# Enforce a restricted open_basedir if php7 module is loaded
# Enforce a restricted open_basedir if php7 module is loaded
<IfModule php7_module>
<IfModule php7_module>
  php_admin_value open_basedir /var/www/
        php_admin_value open_basedir /var/www/
</IfModule>
</IfModule>


Ligne 123 : Ligne 142 :
         EnableCapabilities on
         EnableCapabilities on
</IfModule>
</IfModule>
</pre>


</pre>
Vous pouvez noter que les sections concernant <code>/usr/lib/cgi-bin/</code> et <code>/usr/share/</code> sont superflues étant données que la section concernant <code>/</code> couvre déjà ces répertoires. Il est néanmoins pratique d'avoir prédéfini des règles pour ces deux dossiers car ce sont ceux pour lesquels vous risquez le plus d'avoir à assouplir les règles de sécurité à l'échelle du serveur entier.


Activez ce fichier de configuration :  
Activez le fichier de configuration avec <code>a2enconf</code> :  
<pre>a2enconf zzz_localsecurity.conf
<pre>a2enconf zzz-local-security.conf
/etc/init.d/apache2 reload</pre>
/etc/init.d/apache2 reload</pre>


Ligne 140 : Ligne 160 :
</pre>
</pre>


Pour les alias et les proxy, le mappage se fait dans le sens inverse, du plus spécifique au moins spécifique :
Pour les <code>Alias</code> et les proxy (<code>ProxyPass</code>), le mappage se fait dans le sens inverse, du plus spécifique au moins spécifique :
<pre>
<pre>
Alias "/foo/bar" "/srv/www/uncommon/bar"
Alias "/foo/bar" "/srv/www/uncommon/bar"
Ligne 174 : Ligne 194 :


Ce mode de fonctionnement est plus complexe, mais augmente les performances et permet d'utiliser les mpm worker et event (eux même plus performants que prefork et itk).<br>
Ce mode de fonctionnement est plus complexe, mais augmente les performances et permet d'utiliser les mpm worker et event (eux même plus performants que prefork et itk).<br>
Le principe est d'avoir un daemon php-fpm exécutant les scripts php. Apache s'y connecte au moyen d'un socket.<br>
Le principe est d'avoir un daemon php-fpm exécutant les scripts php. Apache s'y connecte en fcgi au moyen d'un socket.<br>
Chaque daemon php-fpm existe au sein d'un pool qui a son propre socket. Pour des raisons de sécurité, il est conseillé d'utiliser un pool (donc un socket) différent pour chaque site. En effet, si un script malveillant est exécuté au sein d'un pool, il a le potentiel de contaminer l'ensemble du pool et donc l'ensemble des sites utilisant le pool. Il est également possible d'attribuer un utilisateur/groupe spécifique à chaque pool ce qui compense l'impossibilité d'utiliser mpm-itk.
Chaque daemon php-fpm existe au sein d'un pool qui a son propre socket. Pour des raisons de sécurité, il est conseillé d'utiliser un pool (donc un socket) différent pour chaque site. En effet, si un script malveillant est exécuté au sein d'un pool, il a le potentiel de contaminer l'ensemble du pool et donc l'ensemble des sites utilisant le pool. Il est également possible d'attribuer un utilisateur/groupe spécifique à chaque pool ce qui compense l'impossibilité d'utiliser mpm-itk.


Ligne 209 : Ligne 229 :


La première méthode consiste à modifier directement le fichier de configuration principal de php/fpm : <code>/etc/php/7.4/fpm/php.ini</code>.<br>
La première méthode consiste à modifier directement le fichier de configuration principal de php/fpm : <code>/etc/php/7.4/fpm/php.ini</code>.<br>
Les options appliquées le seront à l'ensemble des scripts lancé par php/fpm et ce quelque soit le pool utilisé. '''Cela n'est donc viable que pour une configuration "par défaut" valable pour l'ensemble de vos sites (ou que vous modifierez par d'autre méthode décrites plus bas).'''
Les options appliquées le seront à l'ensemble des scripts lancé par php/fpm et ce quelque soit le pool utilisé. '''Cela n'est donc viable que pour une configuration "par défaut" valable pour l'ensemble de votre serveur et quelque soit le site (ou que vous modifierez par d'autre méthode décrites plus bas).'''


===php-fpm.conf===
===php-fpm.conf===
Ligne 282 : Ligne 302 :
Les fichiers php exécuté dans /srv/admin/ auront la timezone définie à Europe/London et ceux dans /srv/admin/main/ auront la timezone Europe/Paris.
Les fichiers php exécuté dans /srv/admin/ auront la timezone définie à Europe/London et ceux dans /srv/admin/main/ auront la timezone Europe/Paris.


Si la même valeur est définie dans le pool.d et dans un .user.ini, c'est celle de .user.ini qui sera appliquée.
Si la même valeur est définie dans le pool.d et dans un .user.ini, c'est celle de .user.ini qui sera appliquée. Attention quand même à quelques spécificités, par exemple, la valeur de open_basedir locale ne peut-être définie que dans des sous-dossiers de la valeur globale de pool.d.


Vous pouvez désactiver cette fonctionnalité (par sécurité et si vous n'en avez pas besoin) en vidant la variable suivante dans <code>user_ini.filename</code> :
Vous pouvez désactiver cette fonctionnalité (par sécurité et si vous n'en avez pas besoin) en vidant la variable suivante dans <code>/etc/php/7.4/php.ini</code> :
<pre>user_ini.filename =</pre>
<pre>user_ini.filename =</pre>
==Attribuer un pool a une vhost==
<pre>
# PHP-FPM admin sock
<FilesMatch ".+\.ph(ar|p|tml)$">
        SetHandler "proxy:unix:/run/php/php7.4-fpm-poolname.sock|fcgi://localhost"
</FilesMatch>
</pre>


=Note on PHP=
=Note on PHP=
Ligne 316 : Ligne 345 :
Notez qu'il est important de faire terminer le path par un <code>/</code> (le path <code>/votre/documentroot</code> est considéré comme <code>/votre/documentroot*</code>
Notez qu'il est important de faire terminer le path par un <code>/</code> (le path <code>/votre/documentroot</code> est considéré comme <code>/votre/documentroot*</code>


===AllowOverride===
===AllowOverride et .htaccess===


AllowOverride permet de définir les règles autorisées à être modifiées par un fichier <code>.htaccess</code><br>
AllowOverride permet de définir les règles autorisées à être modifiées par un fichier <code>.htaccess</code><br>
Notez que cette directive doit obligatoirement être définie dans un champ <Directory><br>
La configuration apache que nous avons vu plus tôt désactive complètement les fichiers <code>.htaccess</code> dans la totalité du système de fichier. Le problème de ce comportement est que les fichiers htaccess seront tout simplement ignoré, or, de nombreux projets utilisent les fichiers htaccess pour protéger de la lecture certains répertoires sensibles (fichiers de configurations, etc).<br>
La configuration apache que nous avons vu plus tôt désactive complètement les fichiers <code>.htaccess</code> dans la totalité du système de fichier. Le problème de ce comportement est que les fichiers htaccess seront tout simplement ignoré, or, de nombreux projets utilisent les fichiers htaccess pour protéger de la lecture certains répertoires sensibles (fichiers de configurations, etc).<br>
'''Si vous êtes certain que votre projet n'utilise pas de fichiers .htaccess, la question ne se pose même pas, gardez les fichiers htaccess désactivés''' ! Même s'ils sont pratiques, ils restent des fichiers relativement faciles à modifier (un peu de code foireux dans un module externe d'un CMS par exemple) et offrent donc une sécurité bien moindre que les directives définies directement dans la configuration de votre virtualhost apache ! Ils ont par ailleurs un impact sur les performances de apache.<br>
Plusieurs options s'offrent à vous :
Notez que cette directive doit obligatoirement être définie dans un champ <Directory>
* '''Si vous êtes certain que votre projet n'utilise pas de fichiers .htaccess, la question ne se pose même pas, gardez les fichiers htaccess désactivés''' ! Même s'ils sont pratiques, ils restent des fichiers relativement faciles à modifier (un peu de code foireux dans un module externe d'un CMS par exemple) et offrent donc une sécurité bien moindre que les directives définies directement dans la configuration de votre virtualhost apache ! Ils ont également un impact sur les performances de apache (nécessité pour apache de remonter l'arborescence à la recherche d'un .htaccess à chaque requête).<br>
 
* Si votre projet utilise des fichiers .htaccess, il est possible d'intégrer leur contenu à la configuration de votre virtualhost. Vous y gagniez ainsi en sécurité et en performances tout en limitant un vecteur d'attaque.
 
* Si votre projet utilise des fichiers .htaccess mais qu'ils ne peuvent pas être intégrés à la configuration de votre virtualhost (fichiers générés par un client dans le cadre d'une activité de hosting, fichier dynamique généré par le projet lui même, etc), l'idéal est de restreindre les capacités des fichiers .htaccess, ce que vous allons voir plus loin.
<br \>
Dans tous les cas :
Dans tous les cas :
* Évitez absolument d'allowoverride fileinfo (permet de modifier l'handler par défaut d'un fichier)
* Évitez absolument d'allowoverride fileinfo (permet de modifier l'handler par défaut d'un fichier)
* Évitez si possible d'allowoverride options (car permet principalement d'activer l'execution CGI)
* Évitez si possible d'allowoverride options (car permet principalement d'activer l'execution CGI)
* Si vous êtes certains que votre projet n'utilise pas de fichiers .htaccess :
* Si vous êtes certains que votre projet n'utilise pas de fichiers .htaccess ou que vous pouvez les intégrer à la configuration de la virtualhost :
<pre>
<pre>
AllowOverride none
AllowOverride none
Ligne 336 : Ligne 367 :
AllowOverrideList Require
AllowOverrideList Require
</pre>
</pre>
* Si jamais le projet en question necessite les directives d'authentifications, on pourra définir comme cela :
* Si jamais le projet en question nécessite les directives d'authentifications, on pourra définir comme cela :
<pre>
<pre>
AllowOverride Limit AuthConfig
AllowOverride Limit AuthConfig
Ligne 409 : Ligne 440 :
* Sans spécifier un header Host : le serveur sert le contenu de admin.domain.tld.conf
* Sans spécifier un header Host : le serveur sert le contenu de admin.domain.tld.conf
* En spécifiant un header Host (n'importe lequel) : le serveur sert le contenu de admin.domain.tld.conf
* En spécifiant un header Host (n'importe lequel) : le serveur sert le contenu de admin.domain.tld.conf
==Activer la vhost par défaut==
Cette vhost sera utilisé pour toute requête n'en matchant aucune autre.
<pre>a2ensite 000-default</pre>
Pour la vhost SSL, c'est un peu plus complexe.<br>
Commencez par ré-générez votre certificat machine :
<pre>
make-ssl-cert generate-default-snakeoil --force-overwrite
</pre>
Puis renommez le fichier de configuration de la vhost par défaut SSL, et ce afin qu'il soit toujours lu en premier :
<pre>
cp /etc/apache2/sites-available/default-ssl.conf /etc/apache2/sites-available/000-default-ssl.conf
</pre>
Puis chargez le :
<pre>a2ensite 000-default-ssl</pre>
Après tout ça, relancez apache :
<pre>/etc/init.d/apache2 restart</pre>
Notez que ces vhosts ne spécifient pas de <code>ServerName</code>, il sera donc déduit du nom d'hôte FQDN de la machine (<code>hostname -f</code>).<br>
'''Attention, cela implique que vous ne créez aucune autre virtualhost ayant "simplement" le nom d'hôte de la machine comme ServerName''', sinon vous aurez 2 virtualhost avec le même nom d'hôte, et la première chargée en configuration (ordre alphamumérique) sera celle présentée au client (mais pas forcément celle que vous souhaitez).


==Activer server-status / vhost d'admin==
==Activer server-status / vhost d'admin==
===Création d'une vhost d'administration===
<pre>
<VirtualHost 192.168.10.1:80>
        ServerName admin.server.localdomain
        ServerAlias admin_alt.server.localdomain
        DocumentRoot /path/to/admin/interface/
        #AssignUserId www-data www-data # Décommentez uniquement si vous utilisez mpm-itk
        ErrorLog ${APACHE_LOG_DIR}/admin.server.localdomain.error.log
        CustomLog /var/log/apache2/admin.server.localdomain.access.log vhost_combined
</VirtualHost>
</pre>
Pour sécuriser l'accès, et n'autorisant par exemple que les IPs 192.168.50.0/24 :
<pre>
<Directory /path/to/admin/interface/>
        Options +Indexes
        IndexOptions FancyIndexing FoldersFirst IgnoreCase NameWidth=* Charset=UTF-8 XHTML
        # Allow only VPN and nancy-lan
        Require all denied
        Require ip 192.168.50.0/24
</Directory>
</pre>
====PhpMyAdmin====
<pre>
# phpmyadmin installed from package
include /etc/phpmyadmin/apache.conf
<Directory /usr/share/phpmyadmin/>
        Require all denied
        Require ip 192.168.50.0/24
</Directory>
<Directory /usr/share/phpmyadmin/setup>
        Require all denied
</Directory>
<Directory /usr/share/phpmyadmin/templates>
        Require all denied
</Directory>
<Directory /usr/share/phpmyadmin/libraries>
        Require all denied
</Directory>
</pre>
Notez que <code>/etc/phpmyadmin/apache.conf</code> défini les valeurs php <code>open_basedir</code> et <code>upload_tmp_dir</code> pour PhpMyAdmin. Cela ne fonctionnera néanmoins qu'avec mod-php, pas avec php-fpm (pour cela il faudra créer un fichier .user.ini à la racine de phpmyadmin dans <code>/usr/share/phpmyadmin/</code> contenant <code>open_basedir =</code> suivi des mêmes arguments que dans <code>/etc/phpmyadmin/apache.conf</code>
====phpsysinfo====
<pre>
# phpsysinfo from packages
alias /phpsysinfo /usr/share/phpsysinfo/
<Directory /usr/share/phpsysinfo/>
        <IfModule php7_module>
            php_admin_value open_basedir none
        </IfModule>
        Require all denied
        Require ip 192.168.50.0/24
</Directory>
</pre>
====apache Status====
Activez le module status
<pre>a2enmode status</pre>
Observez le fichier <code>mods-enabled/status.conf</code>. Par défaut il active les options de status sur tous les sites (en dehors d'un virtualhost), mais avec une sécurité suffisante (requière une IP locale pour y accéder). Cette configuration est également nécessaire pour permettre à certains binaires d'accéder au status d'apache (par exemple <code>apache2ctl status</code>.
Afin d'éviter de modifier directement ce fichier de configuration, nous allons réactiver le module status dans votre vhost d'admin :
<pre>
# apache status page at /server-status
# ensure mods-enabled/status.conf does not allow an insecured /server-status
# mods-enabled/status.conf needs to be kept activated for apache local process like apache2ctl status
<Location /main/server-status>
        SetHandler server-status
        Require all denied
        Require local
        Require ip 192.168.50.0/24
</Location>
</pre>
Notez que les valeurs <code>ExtendedStatus On</code> ou <code>ProxyStatus On</code> issue de <code>mods-enabled/status.conf</code> sont appliqués automatiquement dans cette vhost également (vous ne pouvez pas les re-préciser dans une vhost).
====server info====
'''Je déconseille d'activer le module info en prod, car il donne beaucoup d'informations sur la configuration du serveur, et en cas de faille (si quelqu'un peut y accéder) cela peut être délétère.'''
Pour information, pour activer le module info :
<pre>a2enmode info</pre>
Le fichier <code>mods-enabled/info.conf/</code> active les options d'information sur tous les sites (en dehors d'un virtualhost), mais avec une sécurité renforcée (requière une IP locale pour y accéder).
====FPM Status====
Si vous utilisez php-fpm :
<pre>
# fpm status page
<Location "/fpm-status">
        Require all denied
        Require ip 192.168.50.0/24
        ProxyPass "unix:/run/php/php7.4-fpm.sock|fcgi://localhost/fpm-status"
</Location>
</pre>
Et dans <code>/etc/php/7.4/fpm/pool.d/<votre pool>.conf</code> (par défaut dans le cas présent ça devrait être le pool <code>www</code> !
<pre>pm.status_path = /fpm-status</pre>
Notez que vous pouvez créer autant de page fpm-status que de pool. Il faudra juste veiller à ce que le chemin (ici <code>/fpm-status</code> soit différent pour chaque pool (il faut donc éditer la configuration de apache et celle du pool).
Pour plus d'information : https://www.php.net/manual/fr/fpm.status.php


=Authentification=
=Authentification=
4 231

modifications

Menu de navigation