Partie 1 - Serveur: Installation et Sécurisation

Partie 1 - Serveur: Installation et Sécurisation

howto admin system

Le but final de ce tuto est de configurer un serveur qui hébergera plusieurs domaines avec leurs propres sites ainsi que les mails correspondants à chacun, de manière sécurisée.Vu la longueur du tuto, je l'ai découpé en plusieurs articles afin de le rendre plus lisible.

Pour remplir cet objectif on va utiliser apache et php et s'appuyer sur des outils comme suPHP suexec pour les sécuriser. Le \"serveur mail\" sera propulsé par le couple Postfix et Dovecot, sur lesquels on installera des outils comme spamassins, postgrey, amavis et clamAV.

  • Ce tuto a été réalisé sur une dédibox (offre online.net).
  • La distribution est une ubuntu serveur 14.04, j'ai choisi cette distribution pour deux raisons, la première c'est que c'est une base Debian que je commence à bien connaître et que c'est LA distribution où je trouve le plus d'infos pertinente en anglais ET en français, ce qui peut être très utile dans certains cas.
  • Tout le tuto considère que vous êtes en root (sudo -s).

Une fois l'installation de la distribution réalisée via l'interface d'admin de votre serveur, on va procéder à quelques réglage de base afin d'apporter un peu de sécurité. Bien sur, le minimum est d'avoir un mdp de passe fort sur votre compte utilisateur, sinon, tout ceci ne sert à rien.

Sécurisation Basique

Sécuriser SSH

Il faut en premier lieu modifier le port par défaut, le 22 étant une cible privilégiée en éditant le fichier /etc/ssh/sshd_config comme suit :

Port xxxx (le modifier pour ne pas utiliser le port par défaut 22)
PermitRootLogin no
PermitEmptyPasswords no
Protocol 2

On va profiter du fait que ssh remplace avantageusement le protocole FTP pour le configurer de manière à ce que l'on puisse se servir de cette fonction sans permettre aux utilisateur SFTP de se logguer sur la machine en console. On va donc ajouter à la fin du fichier les lignes suivantes :

        Match Group ftponly
                ChrootDirectory /var/www/%u
                ForceCommand internal-sftp
                AllowTcpForwarding no
                X11Forwarding no

Tout utilisateur faisant parti du groupe ftponly (qu'il faudra donc créer sur votre serveur) sera donc chroot au dossier /var/www/nom_de_l_utilisateur/ et ne pourra pas utiliser la console, pour plus de sureté je vous invite à remplacer le shell de l'utilisateur par /usr/sbin/nologin Puis relancer ssh :

service ssh reload

 

Mise en place d'UFW

La gestion d'iptables est extrêmement simplifié avec cet outil, donc profitons en. On va commencer par lui indiquer sa configuration par défaut puis le port SSH, histoire de pouvoir se connecter au serveur après l'activation, on va également ouvrir tout les ports nécessaire au service installé tout au long de ce tuto. Activation des règles par défaut:

ufw default deny incoming
ufw default deny outgoing

Ports entrants:

XXXX (port SSH défini précédement)
ufw allow 25/tcp #smtp
ufw allow 80/tcp #http
ufw allow 110/tcp #pop3
ufw allow 143/tcp #imap
ufw allow 443/tcp #https
ufw allow 465/tcp #smtps
ufw allow 993/tcp #imaps
ufw allow 995/tcp #pop3s
ufw allow XXXXXX/tcp #webmin 10000 par défaut
ufw allow 2812 #Monit par défaut

Ports sortants:

ufw allow out ftp #FTP
ufw allow out 25/tcp #smtp
ufw allow out 80/tcp #HTTP
ufw allow out 53 #DNS
ufw allow out 110/tcp #pop3
ufw allow out 143/tcp #imap
ufw allow out 443/tcp #HTTPS
ufw allow out 465/tcp #smtps
ufw allow out 993/tcp #imaps
ufw allow out 995/tcp #pop3s

Assurez vous bien d'avoir correctement configuré la règle concernant le serveur SSH, sinon, vous serez coincé.

ufw enable

Si tout va bien lorsque vous faites :

ufw status numbered

Vous devriez obtenir ça :

État : actif

     Vers                       Action      De
     ----                       ------      --
[ 1] XXXX                       ALLOW IN    Anywhere
[ 2] 80/tcp                     ALLOW IN    Anywhere
[ 3] 80/tcp                     ALLOW OUT   Anywhere (out)
[ 4] 443/tcp                    ALLOW OUT   Anywhere (out)
[ 5] 53                         ALLOW OUT   Anywhere (out)
[ 6] 443/tcp                    ALLOW IN    Anywhere
[ 7] 25/tcp                     ALLOW OUT   Anywhere (out)
[ 8] 25/tcp                     ALLOW IN    Anywhere
[ 9] 110/tcp                    ALLOW IN    Anywhere
[10] 110/tcp                    ALLOW OUT   Anywhere (out)
[11] 143/tcp                    ALLOW OUT   Anywhere (out)
[12] 143/tcp                    ALLOW IN    Anywhere
[13] 465/tcp                    ALLOW OUT   Anywhere (out)
[14] 465/tcp                    ALLOW IN    Anywhere
[15] 993/tcp                    ALLOW IN    Anywhere
[16] 993/tcp                    ALLOW OUT   Anywhere (out)
[17] 995/tcp                    ALLOW OUT   Anywhere (out)
[18] 995/tcp                    ALLOW IN    Anywhere
[19] XXXX/tcp                  ALLOW IN    Anywhere
[20] 2812                       ALLOW IN    Anywhere
[21] XXXX(v6)                  ALLOW IN    Anywhere (v6)
[22] 80/tcp (v6)                ALLOW IN    Anywhere (v6)
[23] 80/tcp (v6)                ALLOW OUT   Anywhere (v6) (out)
[24] 53/tcp (v6)                ALLOW OUT   Anywhere (v6) (out)
[25] 443/tcp (v6)               ALLOW OUT   Anywhere (v6) (out)
[26] 53 (v6)                    ALLOW OUT   Anywhere (v6) (out)
[27] 443/tcp (v6)               ALLOW IN    Anywhere (v6)
[28] 25/tcp (v6)                ALLOW OUT   Anywhere (v6) (out)
[29] 25/tcp (v6)                ALLOW IN    Anywhere (v6)
[30] 110/tcp (v6)               ALLOW IN    Anywhere (v6)
[31] 110/tcp (v6)               ALLOW OUT   Anywhere (v6) (out)
[32] 143/tcp (v6)               ALLOW OUT   Anywhere (v6) (out)
[33] 143/tcp (v6)               ALLOW IN    Anywhere (v6)
[34] 465/tcp (v6)               ALLOW OUT   Anywhere (v6) (out)
[35] 465/tcp (v6)               ALLOW IN    Anywhere (v6)
[36] 993/tcp (v6)               ALLOW IN    Anywhere (v6)
[37] 993/tcp (v6)               ALLOW OUT   Anywhere (v6) (out)
[38] 995/tcp (v6)               ALLOW OUT   Anywhere (v6) (out)
[39] 995/tcp (v6)               ALLOW IN    Anywhere (v6)
[40] XXXX/tcp (v6)             ALLOW IN    Anywhere (v6)
[41] 2812 (v6)                  ALLOW IN    Anywhere (v6)

Vous remarquerez qu'UFW à automatiquement créé les règles en IPV6. Si vous voulez supprimer une règle, le plus simple est d'utiliser la commande suivante :

ufw delete XX # numéro de la règle

Pour autoriser le ping depuis votre serveur (utile pour les tests), il faut ajouter les lignes suivantes dans votre fichier /etc/ufw/befores.rules

# allow outbound icmp
-A ufw-before-output -p icmp -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
-A ufw-before-output -p icmp -m state --state ESTABLISHED,RELATED -j ACCEPT

Voila, votre serveur est déjà un petit peu moins \"Open Bar\"

Mise en place du socle de base du serveur

Installation du serveur LAMP

On va commencé par installer tout le necessaire

apt-get install --assume-yes lamp-server^

Pendant l'installation, MySQL vous demandera d'indiquer un mdp pour l'utilisateur root, cet utilisateur ayant accés à toutes vos bases MySQL, le mot de passe (complexe) doit être conservé en lieu sur. On va en profiter pour installer les modules dont on aura besoin plus tard et qui sont, de toute manière, requis pour beaucoup de CMS (phpBB, Prestashop, Wordpress...)

apt-get install --assume-yes \
  php-apc \
  php5-mcrypt \
  php5-memcache \
  php5-curl \
  php5-gd \
  php-xml-parser

Il manque un lien symbolique pour le bon fonctionnement de php5-mcrypt, qu'a cela ne tienne on va l'ajouter :

ln -sf ../../mods-available/mcrypt.ini /etc/php5/apache2/conf.d/20-mcrypt.ini

On enclenche le module SSL

a2enmod rewrite ssl

On va procéder à deux trois petit réglage afin de minimiser les informations donner par php et apache. On édite /etc/php5/apache2/php.ini

; Decides whether PHP may expose the fact that it is installed on the server
; (e.g. by adding its signature to the Web server header).  It is no security
; threat in any way, but it makes it possible to determine whether you use PHP
; on your server or not.
; http://php.net/expose-php
expose_php = Off

puis /etc/apache2/conf-enabled/security.conf

#
# ServerTokens
# This directive configures what you return as the Server HTTP response
# Header. The default is 'Full' which sends information about the OS-Type
# and compiled in modules.
# Set to one of:  Full | OS | Minimal | Minor | Major | Prod
# where Full conveys the most information, and Prod the least.
#
ServerTokens Prod

#
# Optionally add a line containing the server version and virtual host
# name to server-generated pages (internal error documents, FTP directory
# listings, mod_status and mod_info output etc., but not CGI generated
# documents or custom error documents).
# Set to "EMail" to also include a mailto: link to the ServerAdmin.
# Set to one of:  On | Off | EMail
#
ServerSignature Off

On va configurer les fichiers Vhost par défauts d'Apache, on édite donc /etc/apache2/sites-available/000-default.conf

<VirtualHost IP_EXTERNE:80>
        # The ServerName directive sets the request scheme, hostname and port that
        # the server uses to identify itself. This is used when creating
        # redirection URLs. In the context of virtual hosts, the ServerName
        # specifies what hostname must appear in the request's Host: header to
        # match this virtual host. For the default virtual host (this file) this
        # value is not decisive as it is used as a last resort host regardless.
        # However, you must set it for any further virtual host explicitly.
        # ServerName example.com

        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html/

      <Directory />
              Options FollowSymLinks
              AllowOverride none
      </Directory>
      <Directory /var/www/html/>
              Options Indexes FollowSymLinks MultiViews
              #Active la prise en compte du .htaccess
              AllowOverride All
      </Directory>
        # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
        # error, crit, alert, emerg.

Puis on fait la même chose pour le Vhost SSL par défaut. Normalement le fichier s'appelle default-ssl.conf, il est selon moi plus judicieux de leur donner un nom avec ce type car apache, va tester les configurations et s'arreter sur celle qui correspond à la demande soumise par le navigateur, il est donc intéressant que les fichiers par défaut soit les premiers Donc on renomme en premier le fichier

mv /etc/apache2/sites-available/default-SSL.conf /etc/apache2/sites-available/000-default-SSL.conf

On génère le certificat SSL auto-signé

apt-get install --assume-yes ssl-cert
make-ssl-cert generate-default-snakeoil --force-overwrite
#On sécurise la clé
chmod 600 /etc/ssl/private/*.key

et on l'édite pour avoir la configuration suivante :

<IfModule mod_ssl.c>
        <VirtualHost IP_EXTERNE:443>
                ServerAdmin webmaster@localhost

                DocumentRoot /var/www/html
                <Directory "/">
                Options FollowSymLinks
                AllowOverride None
                </Directory>

                <Directory "/var/www/html">
                Options FollowSymLinks
                AllowOverride All
                </Directory>

                # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
                # error, crit, alert, emerg.
                # It is also possible to configure the loglevel for particular
                # modules, e.g.
                #LogLevel info ssl:warn

                ErrorLog ${APACHE_LOG_DIR}/error.log
                CustomLog ${APACHE_LOG_DIR}/access.log combined

                # For most configuration files from conf-available/, which are
                # enabled or disabled at a global level, it is possible to
                # include a line for only one particular virtual host. For example the
                # following line enables the CGI configuration for this host only
                # after it has been globally disabled with "a2disconf".
                #Include conf-available/serve-cgi-bin.conf

                #   SSL Engine Switch:
                #   Enable/Disable SSL for this virtual host.
                SSLEngine on

                #   A self-signed (snakeoil) certificate can be created by installing
                #   the ssl-cert package. See
                #   /usr/share/doc/apache2/README.Debian.gz for more info.
                #   If both key and certificate are stored in the same file, only the
                #   SSLCertificateFile directive is needed.
                SSLCertificateFile      /etc/ssl/certs/ssl-cert-snakeoil.pem
                SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key

                #   Server Certificate Chain:
                #   Point SSLCertificateChainFile at a file containing the
                #   concatenation of PEM encoded CA certificates which form the
                #   certificate chain for the server certificate. Alternatively
                #   the referenced file can be the same as SSLCertificateFile
                #   when the CA certificates are directly appended to the server
                #   certificate for convinience.
                #SSLCertificateChainFile /etc/apache2/ssl.crt/server-ca.crt

                #   Certificate Authority (CA):
                #   Set the CA certificate verification path where to find CA
                #   certificates for client authentication or alternatively one
                #   huge file containing all of them (file must be PEM encoded)
                #   Note: Inside SSLCACertificatePath you need hash symlinks
                #                to point to the certificate files. Use the provided
                #                Makefile to update the hash symlinks after changes.
                #SSLCACertificatePath /etc/ssl/certs/
                #SSLCACertificateFile /etc/apache2/ssl.crt/ca-bundle.crt

                #   Certificate Revocation Lists (CRL):
                #   Set the CA revocation path where to find CA CRLs for client
                #   authentication or alternatively one huge file containing all
                #   of them (file must be PEM encoded)
                #   Note: Inside SSLCARevocationPath you need hash symlinks
                #                to point to the certificate files. Use the provided
                #                Makefile to update the hash symlinks after changes.
                #SSLCARevocationPath /etc/apache2/ssl.crl/
                #SSLCARevocationFile /etc/apache2/ssl.crl/ca-bundle.crl

                #   Client Authentication (Type):
                #   Client certificate verification type and depth.  Types are
                #   none, optional, require and optional_no_ca.  Depth is a
                #   number which specifies how deeply to verify the certificate
                #   issuer chain before deciding the certificate is not valid.
                #SSLVerifyClient require
                #SSLVerifyDepth  10

                #   SSL Engine Options:
                #   Set various options for the SSL engine.
                #   o FakeBasicAuth:
                #        Translate the client X.509 into a Basic Authorisation.  This means that
                #        the standard Auth/DBMAuth methods can be used for access control.  The
                #        user name is the `one line' version of the client's X.509 certificate.
                #        Note that no password is obtained from the user. Every entry in the user
                #        file needs this password: `xxj31ZMTZzkVA'.
                #   o ExportCertData:
                #        This exports two additional environment variables: SSL_CLIENT_CERT and
                #        SSL_SERVER_CERT. These contain the PEM-encoded certificates of the
                #        server (always existing) and the client (only existing when client
                #        authentication is used). This can be used to import the certificates
                #        into CGI scripts.
                #   o StdEnvVars:
                #        This exports the standard SSL/TLS related `SSL_*' environment variables.
                #        Per default this exportation is switched off for performance reasons,
                #        because the extraction step is an expensive operation and is usually
                #        useless for serving static content. So one usually enables the
                #        exportation for CGI and SSI requests only.
                #   o OptRenegotiate:
                #        This enables optimized SSL connection renegotiation handling when SSL
                #        directives are used in per-directory context.
                #SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
                <FilesMatch "\.(cgi|shtml|phtml|php)$">
                                SSLOptions +StdEnvVars
                </FilesMatch>
                <Directory /usr/lib/cgi-bin>
                                SSLOptions +StdEnvVars
                </Directory>
                <Directory />
                                SSLOptions +StdEnvVars
                </Directory>
                <Directory /var/www/html>
                                SSLOptions +StdEnvVars
                </Directory>

                #   SSL Protocol Adjustments:
                #   The safe and default but still SSL/TLS standard compliant shutdown
                #   approach is that mod_ssl sends the close notify alert but doesn't wait for
                #   the close notify alert from client. When you need a different shutdown
                #   approach you can use one of the following variables:
                #   o ssl-unclean-shutdown:
                #        This forces an unclean shutdown when the connection is closed, i.e. no
                #        SSL close notify alert is send or allowed to received.  This violates
                #        the SSL/TLS standard but is needed for some brain-dead browsers. Use
                #        this when you receive I/O errors because of the standard approach where
                #        mod_ssl sends the close notify alert.
                #   o ssl-accurate-shutdown:
                #        This forces an accurate shutdown when the connection is closed, i.e. a
                #        SSL close notify alert is send and mod_ssl waits for the close notify
                #        alert of the client. This is 100% SSL/TLS standard compliant, but in
                #        practice often causes hanging connections with brain-dead browsers. Use
                #        this only for browsers where you know that their SSL implementation
                #        works correctly.
                #   Notice: Most problems of broken clients are also related to the HTTP
                #   keep-alive facility, so you usually additionally want to disable
                #   keep-alive for those clients, too. Use variable "nokeepalive" for this.
                #   Similarly, one has to force some clients to use HTTP/1.0 to workaround
                #   their broken HTTP/1.1 implementation. Use variables "downgrade-1.0" and
                #   "force-response-1.0" for this.
                BrowserMatch "MSIE [2-6]" \
                                nokeepalive ssl-unclean-shutdown \
                                downgrade-1.0 force-response-1.0
                # MSIE 7 and newer should be able to use keepalive
                BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown

        </VirtualHost>
</IfModule>

Pour forcer les users à utiliser le SSL, vous pouvez ajouter ça à votre
fichier .htaccess que vous placerez à la racine du site (/var/www/html/
par exemple)

RewriteEngine On

# Redirect all HTTP traffic to HTTPS.
RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]

Installation de suexec et de suPHP

Le couple suexec et suPHP permettent de cloisonner l'exécution de chaque site dans l'environnement d'un utilisateur propre à chaque hébergement, ce qui permet d'éviter qu'un site compromis puisse altérer les autres. Mise en place des paquets:

apt-get install --assume-yes apache2-suexec \
apache2-suexec-custom \
libapache2-mod-suphp

Dans le dossier /etc/apache2/suexec vous trouverez un ficher www-data
contenant les lignes suivantes :

/var/www
public_html/cgi-bin
# The first two lines contain the suexec document root and the suexec userdir
# suffix. If one of them is disabled by prepending a # character, suexec will
# refuse the corresponding type of request.
# This config file is only used by the apache2-suexec-custom package. See the
# suexec man page included in the package for more details.

Il faudra créer un fichier similaire pour chaque utilisateur différent où, bien sur, il faudra remplacer le chemin /var/www par celui menant au site (/var/www/nom_de_l_utilisateur) Il faut ensuite éditer le fichier de configuration de suPHP /etc/suphp/suphp.conf comme suit :

[global]
;Path to logfile
logfile=/var/log/suphp/suphp.log

;Loglevel
loglevel=info

;User Apache is running as
webserver_user=www-data

;Path all scripts have to be in
docroot=/var/www:${HOME}/httpdocs:/usr/share

;Path to chroot() to before executing script
;chroot=/mychroot

; Security options
allow_file_group_writeable=false
allow_file_others_writeable=false
allow_directory_group_writeable=false
allow_directory_others_writeable=false

;Check wheter script is within DOCUMENT_ROOT
check_vhost_docroot=false

;Send minor error messages to browser
errors_to_browser=false

;PATH environment variable
env_path=/bin:/usr/bin

;Umask to set, specify in octal notation
umask=0022

; Minimum UID
min_uid=33

; Minimum GID
min_gid=33

[handlers]
;Handler for php-scripts
application/x-httpd-suphp="php:/usr/bin/php-cgi"

;Handler for CGI-scripts
x-suphp-cgi="execute:!self"

La valeur umask 0022 permet de limiter les permissions des fichiers, avec cette configuration seul les permissions 755 pour les dossiers et 644 pour les fichiers sont autorisées. Dans docroot, on indique les dossier /usr/share pour pouvoir faire fonctionner les scripts comme phpmyadmin. Les valeurs min_uid et min_gid, sont celles de l'utilisateur www-data (consultable à l'aide la commande \"id www-data\"), personnellement, une fois que le serveur est fonctionnel, je crée un utilisateur www-public qui remplacera www-data, afin de ne permettre qu'au process utilisateur (avec un id superieur à 1000) l'exécution de ces scripts, cependant, la configuration étant assez sensible à mettre en place, je ne le fais qu'une fois que je sais que tout marche dans la configuration de base. On désactive php5, on active suPHP et suexec

a2dismod php5
a2enmod suexec
a2enmod suphp

On verra plus loin dans ce tuto comment créer les différent utilisateur et les modifications à apporter au fichier de conf des différents vhost pour prendre en compte se fonctionnement.

Installation de memcache

Mise en place des paquets :

apt-get install --assume-yes memcached

on edite /etc/memcached.conf

# Start with a cap of 64 megs of memory. It's reasonable, and the daemon default
# Note that the daemon will grow to this size, but does not start out holding this much
# memory
-m 64

La valeur par défaut est de 64, vous pouvez l'augmenter, il s'agit de la valeur maximum qu'atteindra memcache, donc si il n'en a pas besoin il occupera moins de mémoire.

Installation des paquets mail-server

Afin d'assurer le service mail, il faut que le nom de votre serveur soit FQDN, on va donc commencer par le nommer correctement, par convention le nom du serveur sera mail.example.com.

hostname mail.example.com
echo "mail.example.com" > /etc/hostname

On édite /etc/hosts comme suit :

127.0.0.1 mail.example.com localhost
IP_EXTERNE mail.example.com mail

Mise en place des paquets :

apt-get install --assume-yes mail-server^

Pendant l'installation il vous faudra configurer Postfix, vous devez indiquez \"Internet Site\" pour le type d'utilisation, puis pour le nom, cela doit être le nom FQDN de votre serveur (mail.example.com), ne générer pas les certificat SSL pour dovecot. On modifiera la configuration pour prendre en compte les certificats généré précédemment plus tard. On va ensuite installer les paquets encessaire à la gestion de MySQL par dovecot et postfix ainsi que différent outils nécessaire à al sécurisation des mails:

apt-get install --assume-yes \
  postfix-mysql \
  dovecot-mysql \
  postgrey \
  amavis \
  clamav \
  clamav-daemon \
  spamassassin \
  php5-imap

Tout comme tout à l'heure pour mcrypt on rajoute le lien manquant pour php5-imap et on l'active :

ln -sf ../../mods-available/imap.ini /etc/php5/apache2/conf.d/20-imap.ini
php5enmod imap

Ce paquet va nous être utile pour l'utilisation de postfix admin et la plupart des script webmail comme roundcube ou autre. Ensuite afin de rendre les modules antispam et antivirus performant on va installer les paquets suivants :

apt-get install --assume-yes \
  pyzor \
  razor \
  arj \
  cabextract \
  lzop \
  nomarch \
  p7zip-full \
  ripole \
  rpm2cpio \
  tnef \
  unzip \
  unrar-free \
  zip \
  zoo

On termine par un

service apache2 restart

Et voila, le socle du serveur est installé, maintenant que la base est là, il va falloir passer à la configuration, le plus long étant celle du serveur mail en lui même. Mais ce sera dans une seconde partie. N'hésitez pas poser des questions, j'essaierai d'y répondre si je peux.

Add a comment

Previous Post Next Post