Amaury.net
Accueil Liste articles Forum Ma liste de cadeaux Contact

Dédibox : install et config

12 septembre 2006

J'ai loué une machine en hébergement dédié. Ca n'intéresse pas grand-monde, parce que le sujet est très technique. Mais bref.

Mon ami Olivier m'avait fait remarqué l'offre Dédibox, une offre d'hébergement de machine dédiée montée par la maison-mère du fournisseur d'accès à Internet Free. Cette offre possède un très bon rapport qualité-prix.

Je vais donc détailler ici les différentes action que j'ai effectué sur ce serveur après son installation. Cela pourrait servir à d'autres personnes qui voudraient faire la même chose.

J'ai acheté la Dédibox le 02 août. Le lendemain, tôt dans la matinée, la machine était livrée. Après installation d'un système Ubuntu server 6.06 (système bluffant d'installation automatique des OS, propre à Dédibox), pas de réponse SSH. J'effectue via l'interface d'administration une mise-à-jour du BIOS, qui se déroule sans problème. Je lance un test matériel, qui freeze la machine ; je sollicite le support technique, qui relance le teste.
Je fais une réinstallation du système, en choisissant une Dedibox-Ubuntu. L'installation est OK, le SSH et le Web répondent. Je réinstalle à nouveau une Ubuntu server 6.06. Installation OK, mais toujours pas de réponse SSH.
J'effectue un reboot de la machine, et là le Web et le SSH répondent correctement.

- Commençons par une mise-à-jour de la base du système :

$ apt-get update
$ apt-get dist-upgrade

- Installons ensuite inetd, le super-démon qui sera nécessaire au fonctionnement de plusieurs serveurs :

$ apt-get install inetd

Firewall

Première chose à faire, protéger le serveur des intrusions en configurant le firewall.
- Ecriture du fichier /etc/init.d/firewall

#!/bin/sh
# vidage des regles
iptables -F
iptables -X
iptables -t nat -F
# chargement des modules kernel necessaires au FTP
/sbin/modprobe ip_nat_ftp
/sbin/modprobe ip_conntrack_ftp
# garde les connexions ouvertes
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
# autorise les connexions SSH entrantes
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# autorise le ping (décommenter la ligne ci-dessous)
# iptables -A INPUT -p icmp -j ACCEPT
# autorise les connexions HTTP entrantes
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# autorise les connexions SMTP et POP entrantes
iptables -A INPUT -p tcp --dport 25 -j ACCEPT
iptables -A INPUT -p tcp --dport 110 -j ACCEPT
# bloque les connexions entrantes
iptables -P INPUT DROP
iptables -P FORWARD DROP
# bloque les connexions sortantes
iptables -P OUTPUT DROP
# autorise loopback
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
# connexions sortantes autorisees (FTP, DNS, HTTP, HTTPS) pour les mises-a-jour
iptables -A OUTPUT -p tcp --dport 20 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 21 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 443 -j ACCEPT
# connexions SMTP, POP et IMAP sortantes autorisees
iptables -A OUTPUT -p tcp --dport 25 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 110 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 143 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 220 -j ACCEPT
# connexions NTP sortantes autorisees
iptables -A OUTPUT -p tcp --dport 123 -j ACCEPT
iptables -A OUTPUT -p udp --dport 123 -j ACCEPT
# connexions SSH sortantes autorisees
iptables -A OUTPUT -p tcp --dport 22 -j ACCEPT
iptables -A OUTPUT -p udp --dport 22 -j ACCEPT
# connexions WHOIS sortantes autorisees
iptables -A OUTPUT -p tcp --dport 43 -j ACCEPT
# connexions USENET sortantes autorisees
iptables -A OUTPUT -p tcp --dport 119 -j ACCEPT

- Puis faisons en sorte que ce fichier soit exécuté automatiquement au démarrage de la machine :

$ chmod +x /etc/init.d/firewall
$ update-rc.d firewall start 01 2 .

Serveur mail

Nous allons ensuite faire en sorte que le serveur puisse recevoir des e-mails, et en envoyer.
- Installation des logiciels :

$ apt-get install exim
$ apt-get install qpopper

- Edition de /etc/exim/exim.conf

rfc1413_query_timeout = 0s
local_domains = localhost:amaury.net:pandocreon.fr:...
trusted_users = mail:uucp:www-data

- Edition de /etc/qpopper.conf

set trim-domain              = true

Nous verrons plus loin comme se protéger des spams. Ensuite, nous passons aux choses sérieuses, l'installation et la configuration du serveur pour en faire un serveur LAMP (Linux Apache MySQL PHP) convenable.

Base de données

- Commençons avec l'installation de MySQL :

$ apt-get install mysql-server
$ mysql_secure_installation

- Je configure MySQL pour lui laisser plus de liberté dans la consommation mémoire. C'est parfois pratique avec l'outil en ligne de commande. Edition du fichier /etc/mysql/my.cnf

key_buffer            = 32M
max_allowed_packet    = 900M
max_allowed_packet    = 900M
key_buffer            = 32M

- Ajout simpliste d'utilisateurs MySQL

$ mysql -u root -p
$ grant usage on *.* to 'utilisateur'@'localhost' identified by '***';
$ create database base_de_donnee;
$ grant all privileges on base_de_donnee.* to 'utilisateur'@'localhost';

Requêtes lentes

Pour optimiser les requêtes SQL qui s'exécutent sur le serveur, on peut demander à MySQL de logguer spécifiquement les requêtes qui mettent plus de X secondes à s'exécuter, ainsi que celles qui n'utilisent pas d'index.

Edition du fichier /etc/mysql/my.cnf :

log-slow-queries = /var/log/mysql/mysql-slow.log
log-long-format
long-query-time = 10

Attention, en ajoutant des logs on ralentit MySQL. Il faut penser à ne pas mettre un seuil de déclenchement trop faible (valeur de la variable long-query-time ; le mieux est de mettre une grosse valeur, puis de diminuer progressivement), et retirer à terme ces logs.

Logs binaires

Toujours concernant le serveur MySQL, j'ai décidé de retirer les logs binaires. Ceux-ci prennent beaucoup de place (13 GO pour ma part en un mois et demi !), et ont peu d'utilité lorsque le serveur n'est pas répliqué, et qu'on fait des sauvegardes quotidiennes.

On commence par se logguer en root à la base de données, puis on vide les logs existants :

FLUSH LOGS;
PURGE MASTER LOGS BEFORE NOW();

Edition du fichier /etc/mysql/my.cnf, pour commenter les lignes qui correspondent aux logs binaires :

#log-bin = /var/log/mysql/mysql-bin.log
#expire-logs-days = 20
#max_binlog_size = 104857600

Il faut ensuite redémarrer le serveur :

$ /etc/init.d/mysql restart

PHP 5

- Installation de Apache (version 2) et PHP (version 5) :

$ apt-get install apache2 libxml2 xml-core
$ apt-get install php5 php5-mysql php5-mcrypt php5-gd php5-dev php5-curl php5-imap php5-json php5-cli php-pear

Il faut remarquer que j'installe PHP aussi bien dans sa version intégrée à Apache, qu'en version "ligne de commande", me permettant de créer des petits programmes autonomes. Pour mes besoins particuliers, j'ai décidé de permettre à PHP de consommer plus de mémoire que ne l'autorise l'installation de base. Pour celà :
- Edition du fichier /etc/php5/apache2/php.ini

max_execution_time = 120
max_input_time = 180
memory_limit = 600M
register_globals = Off
register_long_arrays = Off
register_argc_argv = Off
post_max_size = 12M
upload_max_filesize = 10M

- Edition du fichier /etc/php5/cli/php.ini

max_execution_time = 7200
memory_limit = 600M
extension=mysql.so
extension=gd.so

Magic quotes

Il faut savoir que, par défaut, les données textuelles reçues par un formulaire Web sont "échappées", en ajoutant des backslashs devant les caractères qui pourraient poser problème à l'insertion des textes en bases de données. C'était peut-être une bonne idée à une époque, mais plusieurs raisons s'opposent à son utilisation maintenant :

  • Ce n'est pas portable. On n'est jamais certain de l'activation ou non de cette option d'un serveur à l'autre.
  • Ca consomme des ressources. L'ajout de backslashs sur les données prend un certain temps d'exécution, pour des données qui n'en ont pas forcément besoin. Dans ce cas, il faut même perdre du temps à les retirer par la suite.
  • C'est une protection imparfaite. Il vaut mieux récupérer des données "claires", et leur appliquer un traitement approprié (fonction mysql_real_escape_string par exemple) au besoin.
  • PHP6 abandonnera ce comportement par défaut, preuve s'il en est que cette idée n'est pas utile.

Pour cela, il faut modifier le fichier /etc/php5/apache2/php.ini :

magic_quotes_gpc = Off

Outils annexes

Un gros morceau a été fait. Avant de passer à la configuration d'Apache, on va se détendre un peu en s'occupant de quelques petits autres trucs.

- J'ai décidé d'installer un certain nombre d'outils utiles :

$ apt-get install lynx
$ apt-get install mutt
$ apt-get install emacs
$ apt-get install iftop
$ apt-get install screen
$ apt-get install hexedit
$ apt-get install mtop
$ apt-get install make
$ apt-get install whois

NTP

- Pour que la machine se tienne toujours à l'heure, on va installer le démon openntpd :

$ apt-get install openntpd

On édite ensuite le fichier /etc/openntpd/ntpd.conf :

server ntp.dedibox.fr
#servers

VI

J'utilise principalement l'éditeur de texte vi.
Pour que la coloration syntaxique soit active par défaut, je crée un fichier .vimrc à ma racine, qui contient une seule ligne :

syntax enable

Petite chose à savoir : sur les version plus récentes de la Ubuntu (version 7.04 par exemple), la version installée de vi est vraiment très basique. Pour avoir la version complète (avec coloration sytaxique, etc.), il faut installer un package particulier :

$ apt-get install vim-full

Serveur Web

Youpla, passons maintenant à Apache.
- Edition du fichier /etc/apache2/sites-available/default

NameVirtualHost *:80
NameVirtualHost *:443

- Pour mes sites www.amaury.net et perso.amaury.net, j'ajoute le fichier /etc/apache2/sites-available/amaury.net

# amaury.net
<VirtualHost *:80>
    ServerAdmin amaury@amaury.net
    ServerName amaury.net
    ServerAlias www.amaury.net
    DocumentRoot /home/http/amaury.net/www
    <Directory>
        Options FollowSymLinks
        AllowOverride None
    </Directory>
    LogLevel warn
    ErrorLog /var/log/apache2/amaury.net-error.log
    CustomLog /var/log/apache2/amaury.net-access.log combined
</VirtualHost>
# perso.amaury.net
<VirtualHost *:80>
    ServerAdmin amaury@amaury.net
    ServerName perso.amaury.net
    DocumentRoot /home/http/amaury.net/perso
    <Directory>
        Options FollowSymLinks
        AllowOverride None
    </Directory>
    LogLevel warn
    ErrorLog /var/log/apache2/perso.amaury.net-error.log
    CustomLog /var/log/apache2/perso.amaury.net-access.log combined
</VirtualHost>

- Enregistrement de ces sites auprès d'Apache, et redémarrage

$ a2ensite oabp.org
$ /etc/init.d/apache2 reload

Cette opération est à renouveller et/ou compléter évidemment en fonction des sites à héberger.

HTTPS

Je vais aussi permettre la connexion au serveur Web en HTTPS (version sécurisée).
- Ajout du support SSL dans Apache :

$ a2enmod ssl

- Creation d'un certificat :

$ apache2-ssl-certificate

- On dit à Apache d'écouter sur les ports 80 et 443. Edition du fichier /etc/apache2/ports.conf :

Listen 80
Listen 443

- Prise en charge du certificat. Edition du fichier /etc/apache2/sites-available/default :

NameVirtualHost *:80
NameVirtualHost *:443

SSLCertificateFile /etc/apache2/ssl/apache.pem

- Pour que le SSL soit pris en compte sur un domaine (par exemple www.amaury.net), j'ajoute les lignes suivantes au fichier /etc/apache2/sites-available/amaury.net :

# amaury.net
<VirtualHost *:443>
    ServerAdmin amaury@amaury.net
    ServerName amaury.net
    ServerAlias www.amaury.net
    DocumentRoot /home/http/amaury.net/www
    <Directory>
        Options FollowSymLinks
        AllowOverride None
    </Directory>
    LogLevel warn
    ErrorLog /var/log/apache2/amaury.net-error.log
    CustomLog /var/log/apache2/amaury.net-access.log combined
    SSLEngine On
</VirtualHost>

Ensuite on relance le serveur Apache :

$ /etc/init.d/apache2 reload

Gestion des sauvegardes

Nous allons maintenant nous occuper de la sauvegarde de la machine, en utilisant le logiciel backup-manager
- Installation de backup-manager :

$ apt-get install backup-manager

- Edition du fichier de configuration /etc/backup-manager.conf. Pour la documentation, je vous suggère fortement d'aller voir sur le site du logiciel.
Le programme backup-manager se place tout seul dans /etc/cron.daily/ donc il n'y a rien de plus a faire, il s'exécutera automatiquement tous les matins à 06h25 (heure par défaut).

Gestion des spams

Pour la gestion des spams, nous allons utiliser Bogofilter, qui est un filtre qui "apprend" à reconnaître les bons messages des mauvais.

$ apt-get install procmail
$ apt-get install bogofilter

Procmail est un programme qui permet de faire passer les emails entrants par tout un tas de règles de filtrage, et même à travers le programme Bogofilter. Bogofilter de son côté est un logiciel qui apprend à différencier les spams des vrais messages.

Pour faire simple, voici le fichier .procmailrc présent à la racine du répertoire de mon utilisateur :

# ############# Effacer silencieusement les emails asiatiques ##############
UNREADABLE='[^?"]*big5|iso-2022-jp|ISO-2022-KR|euc-kr|gb2312|ks_c_5601-1987'
:0:
* 1^0 $ ^Subject:.*=\?($UNREADABLE)
* 1^0 $ ^Content-Type:.*charset="?($UNREADABLE)
Mail/spam-unreadable
:0:
* ^Content-Type:.*multipart
* B?? $ ^Content-Type:.*^?.*charset="?($UNREADABLE)
Mail/spam-unreadable
# ############# Vire les mails avec piece-jointe suspecte ############
:0 H
*^Content-Type: (multipart/mixed)
{
    :0 B
    *     name=.*\.(ocx\"|vbs\"|wsf\"|wsh\"|shs\"|com\"|bat\"|bas\"|chm\"|pif\"|vbe\"|hta\"|scr\"|dll\")
    {
        :0
        Mail/suspicious
    }
}
#:0:
#* ^Content-Type:.*multipart
#* B?? $ ^Content-Type:.*application/octet-stream
#Mail/suspicious
# ################ Supprime les message d'erreur ############
:0 H
* ^From.*MAILER-DAEMON
Mail/error-daemon
# ################ Supprime les differentes ecritures de "Viagra" ##########
:0 H
* ^Subject.*[WwVv][1JjIil\|][aAoO\@0][Gg][Rr][AaoO\@0]
Mail/suspicious
# ################ Supprime les differentes ecritures de "Valium" ##########
:0 H
* ^Subject.*[WwVv][aAoO\@0][1JjIil\|][1JjIilL\|][UuWwVv][MmWw]
Mail/suspicious
# ################ Supprime les differentes ecritures de "Vicodin" ##########
:0 H
* ^Subject.*[WvVv][1JjIil][Cc][aAoO\@0][Dd][1JjIil][Nn]
Mail/suspicious
# ############### Supprime les differentes ecritures de "Prozac" #########
:0 H
* ^Subject.*[Pp][Rr][oO0][zZ][Aa\@][cCkK]
Mail/suspicious
# ###########################################################
# ############## Filtre les mails par bogofilter ############
# ###########################################################
:0fw
| bogofilter -u -e -p
:0:
* ^X-Bogosity: Spam, tests=bogofilter
Mail/filtred

Pour que Bogofilter fonctionne correctement, il faut lui apprendre à faire la différence entre les bons mails et les spams. Pour cela, il va falloir lui en faire ingurgiter le plus possible (des milliers si possible).
Pour lui faire apprendre qu'un message est un spam :

$ cat le_message_de_spam | bogofilter -s -v

Pour lui faire apprendre qu'un message est correct :

$ cat le_message_correct | bogofilter -n -v

Si un spam se retrouve dans vos emails corrects, il faut le lui dire :

$ cat le_message_qui_est_finalement_du_spam | bogofilter -N -s -v

Si un bon email se retrouve dans vos spams :

$ cat le_message_qui_est_finalement_correct | bogofilter -S -n -v

Unicode

J'essaye de garder tous les textes au format Unicode (UTF-8 pour être exact), qui permet un traitement de tous les caractères de la planète, sans risque de problèmes d'internationalisation.

Pour cela, il faut faire quelques ajustements. Pour Apache, c'est assez simple : par défaut, il utilise UTF-8 comme type d'encodage des caractères. Concernant MySQL, les choses sont un peu plus complexes, car la version packagée par Ubuntu garde un certain nombre de réglages dont l'encodage vaut latin1. Il faut donc modifier cela dans le fichier /etc/mysql/my.cnf :

[client]
default-character-set = utf8
[mysqld]
default-character-set = utf8
default-collation = utf8_general_ci

Au niveau de PHP, il faut indiquer au système que tous les encodages sont maintenant basés sur UTF-8. Il faut donc éditer le fichier /etc/php5/apache2/php.ini :

mbstring.language = uni
mbstring.internal_encoding = UTF-8
mbstring.http_input = UTF-8
mbstring.http_output = UTF-8
mbstring.encoding_translation = Off
mbstring.detect_order = auto

Rien d'autre à modifier, car Ubuntu utilise déjà l'Unicode comme encodage par défaut, par exemple pour l'édition de fichiers texte.

PECL et PEAR

Ce sont deux types d'extensions pour PHP. PECL fourni des extensions compilées, alors que PEAR contient du code pur PHP. A priori, le système contient d'origine tout ce qui est nécessaire.

$ apt-get install php-pear php5-dev

ZIP

Par exemple, pour utiliser l'extension ZIP :

$ pecl install zip

Puis on édite le fichier /etc/php5/apache2/php.ini pour y ajouter une ligne :

extension=zip.so

Au passage, j'ajoute aussi cette même ligne au fichier /etc/php5/cli/php.ini. Il ne reste plus qu'à redémarrer Apache. Si vous ne pouvez/voulez pas installer cette extension, il est possible de faire la même chose en pur PHP.

FileInfo

Pour détecter proprement le type d'un fichier, on peut utiliser l'extension PECL FileInfo.
On commence par installer les librairies nécessaires :

$ apt-get install re2c
$ apt-get install libmagic-dev

On installe l'extension :

$ pecl install fileinfo

Ensuite, il faut ajouter une ligne à la fin du fichier /etc/php5/apache2/php.ini :

extension=fileinfo.so

Et enfin on redémarre Apache :

$ apache2ctl restart

HTTP_Request

J'ai besoin de deux modules PEAR supplémentaires :

$ pear install Crypt_HMAC
$ pear install Http_Request

Malheureusement, il y a un petit soucis avec le module HTTP_Request. Dans un environnement complètement Unicode comme le mien, les en-têtes HTTP Content-Length envoyés sont erronés. L'origine du problème : l'utilisation de la fontion strlen() pour obtenir la taille des données. L'ennui, c'est que cette fonction compte 1 seul caractère pour les données multi-octet, ce qui arrive souvent en Unicode.

Il faut donc remplacer tous les appels à :

strlen($variable)

par :

mb_strlen($variable, "ASCII")

dans le fichier /usr/share/php/HTTP/Request.php.

PHPDoc

Une petite installation du programme PHPDocumentor, qui permet de géréner de la documentation de script PHP.

$ pear install --alldeps PhpDocumentor

APC

APC (Advanced PHP Cache) est un système qui garde en mémoire les pages PHP en version compilée, ce qui fait gagner en performances. J'ai trouvé sur les sites PrendreUnCafé et Un électron libre des informations concernant son installation.

$ apt-get install apache2-prefork-dev
$ ln -s /usr/bin/apxs2 /usr/bin/apxs
$ pecl install apc

Répondre "yes" à toutes les questions posées lors de l'exécution de la dernière commande devrait être bon.

Ensuite, il faut ajouter une ligne à la fin du fichier /etc/php5/apache2/php.ini :

extension=apc.so

Il ne reste plus qu'à redémarrer Apache :

$ apache2ctl restart