lindev.fr

Aller au contenu | Aller au menu | Aller à la recherche

Mot-clé - php.ini

Fil des billets - Fil des commentaires

07 juin 2017

Environnement de développement complet avec Docker

Qu'allons nous voir

docker-logo.jpg Nous allons voir comment mettre sur pied avec Docker un environnement de développement Web complet ( LAMP ) en quelques minutes ( si l'on compte uniquement le temps de déploiement, et non la lecture de ce post. ).

Mais surtout , rendre cet environnement facilement configurable pour qu'il réponde à vos attentes.

Au programme, nous aurons donc 3 conteneurs


Petit plus, nous aurons à disposition, un fichier de configuration permettant l'utilisation de la fonction mail() de php.

Pour lancer facilement ces conteneurs Docker, nous utiliseront l'outil docker-compose, qui permet en un seul fichier de déclarer notre environnements et bien plus encore.

Pour les plus pressés : Si vous ne souhaitez pas créer les répertoires et fichiers de conf à la main en suivant tout le billet, vous pouvez directement cloner le projet puis lancer ( Après avoir installé Docker sur votre machine évidemment ). Rendez-vous tout en bas de cette page, dans la section Go go go.

Installation de Docker et docker-compose

Franchement, il n'y a rien de compliqué, je ne vais pas détailler spécialement la méthode , juste vous donner les liens pour les différents systèmes.
Après, il suffit de suivre.

Docker CE

Docker-Compose

Bonne nouvelle pour les utilisateurs de Mac & Windows, l'outil est automatiquement installé avec Docker.

Pour les utilisateurs Linux, je conseille la commande pip

sudo pip install docker-compose

Le projet LAMP

Parfait, nous avons tout les outils nécessaires pour atteindre notre objectif.
Commençons par créer un répertoire qui contiendra l’ensemble des fichiers de configuration et le code source de nos futurs projets Web .

mkdir -p dockerlamp/www dockerlamp/docker/apache/vhosts dockerlamp/docker/mysql dockerlamp/docker/php

Voici en résumé ce que ça donne :

dockerlamp
├── docker
│   ├── apache
│   │   └── vhosts
│   ├── mysql
│   ├── php
└── www

Nous aurons donc les fichiers de configuration dans le répertoire docker/ et le code source sera dans le répertoire www/

docker-compose.yml

Je vais pas tourner autour du pot, je vais tout de suite vous donner le contenu complet du fichier docker-compose.yml, nous verrons ensuite les différents points à compléter.

Créez donc le fichier docker-compose.yml à la racine du répertoire dockerlamp/

# Adopt version 2 syntax:
#   https://docs.docker.com/compose/compose-file/#/versioning
version: '2'

volumes:
    database_data2:
        driver: local

services:
###########################
# Setup the Apache container
###########################
    httpd:
        container_name: dockerapache_httpd_1
        restart: always
        image: httpd:2.4.25
        ports:
            - 80:80
        volumes:
            - ./docker/apache/httpd.conf:/usr/local/apache2/conf/httpd.conf
            - ./docker/apache/vhosts/:/usr/local/apache2/conf/vhosts
        volumes_from:
            - php

###########################
# Setup the PHP container
###########################
    php:
        container_name: dockerapache_php_1
        restart: always
        build: ./docker/php/
        expose:
            - 9000
        volumes:
            - ./www/:/usr/local/apache2/htdocs
            - ./docker/php/ssmtp.conf:/etc/ssmtp/ssmtp.conf:ro
            - ./docker/php/php-mail.conf:/usr/local/etc/php/conf.d/mail.ini:ro


###########################
# Setup the Database (MySQL) container
###########################
    mysql:
        container_name: dockerapache_mysql_1
        restart: always
        image: mysql:5.6.36
        expose:
            - 3306
        volumes:
            - database_data2:/var/lib/mysql
            - ./docker/mysql/conf-mysql.cnf:/etc/mysql/mysql.conf.d/conf-mysql.cnf:ro
        environment:
            MYSQL_ROOT_PASSWORD: secret
            MYSQL_DATABASE: project
            MYSQL_USER: project
            MYSQL_PASSWORD: project

Configuration Apache

Afin de configurer finement le service Apache, nous allons récupérer le fichier httpd.conf et le déposer dans le répertoire dockerlamp/docker/apache/

Voici le lien de téléchargement httpd.conf

La seule modification faite à ce fichier ( comparé à la version d'origine ) est la prise en charge des virtualhosts.

Nous allons par conséquent également récupérer le virtualhost par défaut et le placer dans le répertoire dockerlamp/docker/apache/vhosts/

Voici le lien de téléchargement 000-default.conf


Pour les curieux, si vous éditez le fichier 000-default.conf, vous verrez que l'on utilise le module proxy d'apache pour gérer les sources php . Nous passons ces sources au service nommé "php" sur le port 9000.

Nous en avons terminé avec le service apache . Passons au service php.

Configuration php-fpm

Contrairement au service apache, le conteneur php-fpm doit être modifié, pour ne serait-ce qu'installer les extensions.
Nous allons donc créer un fichier Dockerfile, qui contiendra toutes les instructions pour finaliser notre container .

La bonne pratique

J'aurais pu simplement créer une image du container sur dockerHub et la mettre à disposition, mais pour partager une image modifiée, la bonne pratique consiste à utiliser comme base l'image officielle ( php ), puis d'ajouter explicitement les changements à apporter dans un DockerFile.

Ce qui vous permet d'être certain que l'image finale n'est pas corrompue.

Dockerfile

créez le fichier Dockerfile dans le répertoire dockerlamp/docker/php/, comme précisé dans docker-compose.yml.

FROM php:5.6-fpm

# install the PHP extensions we need
RUN set -ex; \
	\
	apt-get update; \
	apt-get install -y \
		libjpeg-dev \
		libpng12-dev \
                libmcrypt-dev \
                ssmtp \
	; \
	rm -rf /var/lib/apt/lists/*; \
	\
	docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr; \
	docker-php-ext-install gd mysqli opcache pdo_mysql json mcrypt; \
        pecl install -o -f xdebug redis \
        && rm -rf /tmp/pear \
        && echo "extension=redis.so" > /usr/local/etc/php/conf.d/redis.ini \
        && echo "zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20131226/xdebug.so" > /usr/local/etc/php/conf.d/xdebug.ini; 
# TODO consider removing the *-dev deps and only keeping the necessary lib* packages

# set recommended PHP.ini settings
# see https://secure.php.net/manual/en/opcache.installation.php
RUN { \
		echo 'opcache.memory_consumption=128'; \
		echo 'opcache.interned_strings_buffer=8'; \
		echo 'opcache.max_accelerated_files=4000'; \
		echo 'opcache.revalidate_freq=2'; \
		echo 'opcache.fast_shutdown=1'; \
		echo 'opcache.enable_cli=1'; \
	} > /usr/local/etc/php/conf.d/opcache-recommended.ini

RUN { \
                echo '[xdebug]'; \
                echo 'xdebug.default_enable = 0'; \
        } >> /usr/local/etc/php/conf.d/xdebug.ini


RUN { \
        echo 'error_reporting  =  E_ALL'; \
        echo 'log_errors = On'; \
        echo 'display_errors = Off'; \
    } > /usr/local/etc/php/php.ini

CMD ["php-fpm"]
EXPOSE 9000

php7-fpm : Si vous préférez une autre version de php, il vous suffit de la changer sur la première ligne ( ex : FROM php:7.1.5-fpm ).
Toutes les versions sont listées ici.

fonction mail()

Puisque nous utilisons le service php à l'intérieur d'un container, seul ce service est disponible ( bien qu'il soit possible de lancer plusieurs services dans un même conteneur, cette méthode n'est pas conseillée ), le service sendmail n'est pas disponible.

Pour palier à ce problème, nous allons utiliser ssmtp. Cet utilitaire ne fait que rediriger les mails vers un serveur SMTP externe.
Pour le configurer ( l'activer au sein de php et définir quel serveur SMTP utiliser ), nous allons ajouter deux fichiers dans le répertoire dockerlamp/docker/php/

  • php-mail.conf
  • ssmtp.conf
php-mail.conf

Ce fichier de configuration ( chargé comme un php.ini supplémentaire ) ne fait que surcharger le chemin de l’exécutable sendmail afin d'utiliser ssmtp.

[mail function]
sendmail_path = "/usr/sbin/ssmtp -t"
ssmtp.conf

Ce fichier vous permet de définir quel serveur SMTP utiliser pour envoyer vos mails.
Par exemple, pour utiliser un compte Gmail:

mailhub=smtp.gmail.com:587
[email protected]
AuthPass=mypassword

FromLineOverride=YES
hostname=dockerdev.foo.net
UseSTARTTLS=YES

Seules les 3 premières lignes sont à adapter selon votre cas.

Nous en avons terminé avec la configuration de php-fpm. Passons à Mysql

Configuration Mysql

C'est presque le service le plus simple... dans le fichier docker-compose, nous avons défini des variables d'environnements, qui spécifient le mot de passe du compte root, une base de données à créer avec un utilisateur associé (login et mot de passe) .

Par la suite, si vous devez ajouter une nouvelle base de données, deux possibilités .

  1. Ajouter les informations dans le fichier docker-compose, et relancer le conteneur
  2. Se connecter en root sur le service mysql et créer manuellement la base de données et son utilisateur .

Nous allons créer le fichier conf-mysql.cnf, dans le répertoire dockerlamp/docker/mysql/ ce fichier est automatiquement monté dans le conteneur Mysql à son démarrage et permet donc de modifier simplement la configuration de mysql .

Par exemple, si l'on souhaite modifier la variable sql_mode

[mysqld]  
sql_mode = "STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

Note : Vous pouvez laisser ce fichier vide si vous n'en avez pas l'utilité pour le moment. Mais il doit être présent dans le répertoire mysql !

Notre environnement LAMP est maintenant prêt !

Lancer l'environnement LAMP

Puisque nous avons configuré notre environnement via un fichier docker-compose.yml, nous allons évidemment utiliser la commande docker-compose pour le lancer.
Placez-vous à la racine du projet dockerlamp/

docker-compose up -d

Cette commande va construire les volumes, les interfaces réseaux, télécharger les images nécessaires, construire les conteneurs si besoin ( via le Dockerfile ) et enfin ... les exécuter en tache de fond . Oui oui .. tout ça en une seule commande .. le pied!

Le test

Nous allons tester notre stack, apache et php.

Créez deux fichiers dans le répertoire www/

  • info.php
  • index.html
info.php
<?php 
echo phpinfo();
index.html
<h1>Hello World</h1>

Enfin ouvrez un navigateur et entrez ces URLs :

Vous devriez normalement voir un magnifique Hello World, et la page d'infos de php ! Selection_999_057_.png

Un vrai projet

Je ne vais pas vous laisser avec un simple phpinfo() et un Hello World !!
Nous allons aller au bout des choses, en installant par exemple un petit Drupal.

L'objectif est d'installer Drupal et qu'il soit accessible ( sur votre machine ) depuis l'url http://drupal.local/


Le Vhost

Afin de pouvoir utiliser un nom de domaine locale, ( drupal.local ), il faut auparavant renseigner le fichier hosts, pour le déclarer .

Linux et Mac
sudo sh -c "echo '127.0.0.1   drupal.local' >> /etc/hosts"
Windows

Pour Windows vous devez ouvrir le fichier c:\Windows\System32\Drivers\etc\hosts en administrateur avec NotePad et y ajouter la ligne :

127.0.0.1   drupal.local

Maintenant, nous allons créer notre vhost afin qu'Apache sache quoi faire lorsqu'il reçoit les requêtes avec le nom de domaine drupal.local.

Editer le fichier dockerlamp/docker/apache/vhosts/drupal.conf

<VirtualHost *:80>
        ServerAdmin [email protected]
        ServerName drupal.local

        <Directory />
            AllowOverride All
            Require all granted
        </Directory>

        DocumentRoot "/usr/local/apache2/htdocs/drupal"
        <Directory "/usr/local/apache2/htdocs/drupal">
                Options Indexes FollowSymLinks
                AllowOverride All
                Require all granted
        </Directory>


    <FilesMatch \.php$>
        # 2.4.10+ can proxy to unix socket
        # SetHandler "proxy:unix:/var/run/php5-fpm.sock|fcgi://localhost/"

        # Else we can just use a tcp socket:
        SetHandler "proxy:fcgi://php:9000"
    </FilesMatch>

</VirtualHost>

On a donc déclaré le nom de domaine à Apache, en lui spécifiant de pointer sur le répertoire drupal/

Les sources

Puisque nous avons demandé à Apache de pointer sur le répertoire drupal/, nous allons télécharger les sources de Drupal dans ce répertoire qui lui-même se trouve dans le répertoire dockerlamp/www/

cd www
wget https://ftp.drupal.org/files/projects/https://ftp.drupal.org/files/projects/drupal-8.3.2.tar.gz
tar xzf drupal-8.3.2.tar.gz 
mv drupal-8.3.2 drupal
mkdir -p drupal/sites/default/files/translations && chmod -R 777 sites/default/files/translations
chmod -R 777 drupal/sites/default/files
touch drupal/sites/default/settings.php && chmod 777 drupal/sites/default/settings.php

Enfin, pour que le conteneur Apache prenne en considération notre nouveau vhost, nous allons redémarrer notre stack

docker-compose restart

L'installation

Pour l'installation, il suffit de pointer sur notre nom de domaine local et suivre les instructions

http://drupal.local/

Arrivé à l'installation de la base de données, remplissez le formulaire comme ceci ( Base de données déclarée dans le fichier docker-compose.yml ),

  • Nom de la base de données : project
  • Utilisateur : project
  • Mot de passe : project
  • Et dans options avancés > Hôte : mysql


Selection_999_058_.png

Après cette étape, Drupal s'installe tranquillement sur votre environnement
Selection_999_059_.png
Remplissez les formulaires durant l'installation, vous devriez rapidement arriver sur la page d'accueil de votre Drupal fraîchement installé .

Selection_999_060_.png Selection_999_061_.png

Conclusion

Vous avez à disposition un environnement de développement complet comme démontré avec Drupal.

Pour chaque projet vous devez donc

  1. Créer un domaine local dans votre fichier hosts
  2. Créer la configuration du virtualHost pour apache
  3. Récupérer les sources et les placer dans le répertoire www/
  4. Relancer la stack LAMP via docker-compose

Voici quelques outils / lignes de commandes pour vous aider à travailler, "debugger".

Vous trouverez ces petits scripts dans le répertoire tools/ du dépôt dockerlamp.

Ces scripts ne représentent qu'une base pour vous aider à travailler, je vous laisse maintenant parcourir la documentation de Docker pour comprendre les différentes commandes / configurations utilisées dans ce billet.

N’hésitez pas à poser des questions si besoin.

Créer un dump d'une base de données

dump_sql.sh

docker exec dockerapache_mysql_1 /usr/bin/mysqldump --databases -uroot -psecret $DATABASE > $DATABASE.sql

Restaurer/Importer une base de donnée depuis un dump sql

restore_sql.sh

cat $DUMP | docker exec -i dockerapache_mysql_1 /usr/bin/mysql -uroot -psecret

Afficher les logs Apache en temps réel ( Pour débugger )

logs.sh

docker logs --tail 100 -f dockerapache_httpd_1 

Afficher les ressources utilisées par les conteneurs sur votre machine

stats.sh

docker stats --format "table {{.Container}}\t{{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}\t{{.NetIO}}\t{{.BlockIO}}\t{{.PIDs}}"

Selection_999_062_.png

Go go go

On clone l'environnement

git clone https://[email protected]/cdesaintleger/dockerlamp.git && cd dockerlamp

On Configure le smtp

cp docker/php/ssmtp.conf.dist docker/php/ssmtp.conf && vim docker/php/ssmtp.conf

On lance la stack

docker-compose up -d

05 avr. 2010

Nginx + php fastcgi + perl

nginx-logo2.pngCa y est , voici la deuxième partie certainement attendu .. non !! ha .. bon .. spa grave ..
Je disais donc , nginx est maintenant en place , mais il faudrait peut être penser à le rendre compatible avec les 90% des sites sur le net aujourd'hui , c'est à dire php .. et pourquoi pas python tant que l'on y est .
Pour mettre en place cette liaison , nous allons utiliser php en fast-cgi .
Nginx ne possédant pas de mod_php comme apache , les requêtes php seronts donc transmises aux process php que nous aurons lancés en tâche de fond .
Je ne vais pas débattre des avantages et des inconvénients d'utiliser php en fastcgi , ce n'est pas le but de ce topic , mais sachez juste qu'aujourd'hui php en fastcgi est très apprécié , pour sa stabilité et sa sécurité , c'est pourquoi l'on retrouve souvent ce mode de fonctionnement chez les hébergeurs aujourd'hui ...
Vous n'étiez pas au courant ? ..

Note du 24/08/10 : Depuis php 5.3.3 il est bien plus simple et performant d'utiliser php-fpm , voir le tuto à ce sujet

PHP compilation

Et oui encore , il nous faut compiler php spécialement pour le mod fast-cgi ( ne vous inquiétez pas , il est maintenant impossible de repasser en mode cgi simple , vous aurez forcement du Fastcgi ).
Comme d'hab voici les étapes ,

  1. Récupération des source
  2. décompactage
  3. création du fichier de config à la compilation
  4. trio : ./configure make / make / install

Récupération de php

Voilà les lignes de commande correspondantes ( PHP 5.3.2 )

wget http://fr2.php.net/get/php-5.3.2.tar.gz/from/this/mirror
tar xzf php-5.3.2.tar.gz
cd /usr/local/src/php-5.3.2/
vim my_configure

Config de compilation

Voici un exemple , de config de php ( celui de ma machine de dev ) je vous laisse ajuster selon vos besoins ..

#!/bin/sh

export OPTIM=-02
./configure --prefix=/usr/local \
        --with-xsl \
        --enable-soap \
        --with-gettext \
        --enable-mbstring --with-mbstring=all \
        --disable-debug \
        --enable-memory-limit \
        --enable-ftp \
        --with-mcrypt \
        --enable-zip \
        --enable-calendar \
        --enable-exif \
        --enable-pdo \
        --with-pdo-mysql \
        --with-mysql \
        --with-pdo-sqlite \
        --with-sqlite \
        --with-zlib \
        --with-jpeg-dir \
        --with-gd \
        --enable-bcmath \
        --with-curl \

Compilation , go go go

make 
make install 

Vérification

Nous voilà avec normalement un exécutable nommé php-cgi dans /usr/local/bin_

Process FastCgi

Nous allons donc maintenant créer un script qui sera chargé de lancer X process , qui ont pour mission de répondre aux requêtes php envoyées par nginx.

Création

cd /etc/init.d/
vim php-fastcgi

Le script peut exister sous des formes plus ou moins différentes , voici celui que j'utilise :

download.pngphp-fastcgiwrapper php-fastcgi

warning.pngLà encore les script est adapté , si vous avez suivi à la lettre mon tutoriel , si vous avez effectué des modification vérifiez les paramètres , notamment:

  • USER
  • PHP_CGI

Ajout au RC

Il faut lui aussi le rendre exécutable , et le mettre dans le RC , afin que les process soient lancés au démarrage de la machine .

chmod 777 php-fastcgi
update-rc.d php-fastcgi defaults

warning.pngConcernant le nombre de process fils lancés , il faudra adapter selon la charge de votre site ... en production , la commande

netstat -atup

Vous donnera des indications sur l'état de vos process , n'en ajoutez pas trop ! travaillez de façon logique .

Vous pouvez démarrer les process :

/etc/init.d/php-fastcgi start

Liaison avec Nginx

Et bien voilà , il ne nous reste plus qu'à lui indiquer de transmettre les requêtes php aux process que nous avons lancés .

fastcgi_params

Dans un premier temps il faudra éditer le fichier de configuration fastcgi_params de nginx .

cd /etc/nginx/
vim fastcgi_params

A la fin de ce fichier , ajouter les lignes suivantes :

fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

Ces lignes permettent entre autre d'indiquer aux process quel script executer , ainsi que son chemin .

Vhost ou Nginx.conf

Selon l'utilisation ou non de vhost , il vous faut ajouter ( en fait elles y sont déjà dans le conf principale si vous avez utilisé mon fichier de config nginx.conf ) les lignes suivantes dans les accolades de server .

location ~ \.php$ {

          include /etc/nginx/fastcgi_params; #or whatever you named it
          fastcgi_pass  127.0.0.1:9000;
	  index index.php;
        }


Exemple d'un vhost:

server{

        listen 8282;

        server_name lindev.fr;

        root /home/apache2/lindev.fr;

        
        location /  {

                index index.php;

        }

        location ~ \.php$ {

          include /etc/nginx/fastcgi_params; #or whatever you named it
          fastcgi_pass  127.0.0.1:9000;
	  index index.php;
        }

}

Et voilà votre serveur peut maintenant gérer les fichiers .php

Restart Nginx

Pour que les modifications prennent effet, il vous faut demander à Nginx de relire sont/ses fichiers de conf .

/usr/local/nginx/sbin -s reload

Et bien voilà pour php .. On fait la même chose avec perl ? aller .. go !

Perl CPAN

Certains sites demandent la gestion de perl , principalement pour des site de graph , tel qu'eluna , je vais donc faire en sorte que notre serveur puisse gérer ce genre de site .. même pas peur !

FCGI

Il nous faut dans un premier temps installer le paquet FCGI par cpan :

perl -MCPAN -e 'install FCGI'

Wrapper perl fastcgi

Il faut ensuite , créer le script qui ( comme pour php ) lance des process en fastcgi en attente de script à traiter .

vim /usr/bin/fastcgi-wrapper.pl

download.pngVoilà le contenu de ce script : fastcgi-wrapper.zip

Il faut maintenant le rendre exécutable

chmod 755 /usr/bin/fastcgi-wrapper.pl

Ok maintenant , nous allons créer le script qui se situe dans le RC , pour lancer les process :

vim /etc/init.d/perl-fastcgi

download.pngVoici le fichier perl-fastcgiperl-fastcgi

On le rend exécutable , et on l'ajoute au RC

chmod 755 /etc/init.d/perl-fastcgi
update-rc.d perl-fastcgi defaults
/etc/init.d/perl-fastcgi start

Liaison perl - Nginx

Nous y voilà , les process perl sont lancés , il écoutent sur le port 8999 , il ne nous reste plus qu'à ajouter dans les Vhost qui en ont besoin , les lignes suivantes :

location ~ \.pl$ {
        gzip off;
        include /etc/nginx/fastcgi_params;
        fastcgi_pass  127.0.0.1:8999;
        fastcgi_index index.pl;
    }

warning.pngCette fois , pas besoin de modifier les fichier fcgi_params car les modifications à apporter sont les même que précédemment avec php .

Nginx restart

Et bien oui comme pour php , on relance la lecture des fichiers de conf de nginx , afin de prendre en compte les modifications .

/usr/local/nginx/sbin/nginx -s reload

Good job

Ca y est , Nginx est maintenant capable de gérer les script php et perl en plus des fichiers statiques ...

Il reste encore quelques petites choses utiles à voir , comme la gestion du SSL , les redirections automatique , les réécritures d'url, pour du 301 ou l'utilisation de framework tel que symphony , Zend ou autre basé sur la réécriture d'url et un peut de sécurité en plus ...

Voilà le programme de la troisième partie sur nginx ..

23 mar. 2010

PHP et Clamav

PHP + Clamav = PHP ClamAV Lib

php-clamav_logo.png Passer les fichiers uploadés par un anti-virus , n'est plus marginal de nos jours . Même sur des systèmes linux , il faut se protéger ...

Etat des lieux

Nous allons donc utiliser un serveur web , avec apache et php5.x d'installé , évidemment clamav sera lui aussi installé et fonctionnel , si ce n'est pas le cas, vous pouvez vous reporter à ce tuto pour son installation .

Dans mon cas , je souhaitai vérifier les fichiers uploadés via un serveur FTP , comme j'ai mis en place un script PHP qui épluche les logs et averti les utilisateurs finaux de l'arrivée d'un nouveau fichier à traiter .

N'ayant finalement pas envi de mettre en place un serveur mandataire FTP transparent pour intégrer l'antivirus , j'ai décider d'utiliser le script de surveillance pour en plus d'avertir les personnes concernés , vérifier les fichiers et les supprimer en cas de détection positive .

PHP ClamAV Lib

Nous allons donc récupérer et décompresser l'archive , sur le site de ClamAV

wget http://sourceforge.net/projects/php-clamav/files/0.15/php-clamav_0.15.2.tar.gz/download
tar xzf php-clamav_0.15.2.tar.gz
rm php-clamav_0.15.2.tar.gz
cd php-clamav_0.15.2/

Compilation

phpize
./configure --with-clamav
make 
make install

PHP.ini

Nous allons donc changer un ou deux petits paramètres dans le php.ini
A commencer par le paramètre extension_dir si ce n'est pas encore fait .
A la fin de la compilation , le chemin à définir vous est indiqué , pour moi , ce sera :

extension_dir = "/usr/lib/php5/20060613/"

Ensuite , il nous faut lier l'extension clamav à php , pour celà nous allons ajouter à la fin du fichier php.ini ces quelques lignes :

extension=clamav.so
[clamav]
clamav.dbpath=/var/lib/clamav
clamav.maxreclevel=0
clamav.maxfiles=0
clamav.archivememlim=0
clamav.maxfilesize=0
clamav.maxratio=0

Enregistrez les fichier et redémarrez apache pour prendre en compte les derniers changements .
Pour vérifier que le module soit bien activé , vous pouvez entrer cette ligne de commande :

php -m | grep clamav

Qui doit normalement vous retourner clamav



Ou alors faire le grand standard echo phpinfo();

Utilisation

Ca y est vous avez fait le plus dur ... avouez que c'était simple !
Bon , ne nous reste plus qu'à utiliser ce module fraichement installé .

Dans les sources , vous avez peut être remarqué la présence d'un fichier php nommé phpclamav_test.php
N'hésitez pas à le tester , et l'ouvrir pour voir les fonctionnalités du module .

Voici son résultat :

test-clamav.jpeg

La fonction la plus utile est bien évidemment cl_scanfile qui prend deux arguments ,

  1. Le chemin vers le fichier à analyser
  2. La variable qui se verra attribué le nom du virus en cas de détection d'infection

La valeur de retour a deux valeur possibles :

  • 1 : détection de virus
  • 0 : pas de détection de virus

Ce qui vous donne donc un script du style , ( à adapter à votre utilisation )

$file = "/var/www/monfichier.zip";

$retcode = cl_scanfile($file, $virusname);
    if ($retcode == CL_VIRUS) {
        echo "<b>File path : </b>".$file."<b>Return code : </b> Virus found name : ".$virusname; 
    } else {
        echo "<b>File path : </b>".$file."<b>Return code : </b> Le fichier est sain"; 
    }

Faites vos test

Il ne vous reste plus qu'à tester vos scripts avec eicar , disponible sur son site.

Ch.

21 sept. 2009

big brother is watching you !

Surveiller la disponibilité d'un site camera.jpg

Rien de bien extraordinaire , mais le principe m'amuse alors autant partager , et pourquoi pas récupérer des idées dans vos commentaires .

Le principe :

L'on me demande un moyen de vérifier si des sites distants sont disponibles , ou non de façon permanente .

J'ai donc décidé de développer un bout de script , qui ne fait ni plus ni moins que:

  • Tester la résolution DNS ( Type A uniquement pour le moment )
  • récupérer les en-têtes envoyés par le serveur en réponse à une requête HTTP.
  • Récupération de ce qui m'intéresse , à savoir le code de status http , et le temps qu'a mis la réponse à me parvenir .

Ensuite , grâce à ces informations , je peux faire toute sorte de graphiques m'indiquant la disponibilité du/des sites surveillés dans le temps .

Exemple :

viewer.png

Le code

pour récupérer des données le plus proche de la réalité possible Comme j'ai dit plus haut , le code est très simple et rapide à mettre en place , il vous faudra cependant activer curl pour l'utiliser .

Vérifier la résolution de nom

Pour cette étape , nous allons utiliser la fonction native à php 4&5 checkdnsrr() :

checkdnsrr($adresse,"A");

Récupérer les entêtes HTTP

Pas besoin de récupérer la totalité , celà surchargerais inutilement les deux cotés , une première solution consiste à utiliser la fonction get_headers() en natif dans php5 :

get_headers  ( "htp://".$adresse  , true );

L'inconvénient de cette fonction , est qu'elle ne possède pas de timeout hormis celui de php , qui est bien trop long et peut pratique .
Les tests avec cette fonction se sont donc révélé bon , mais a généré l'augmentation de la consommation de mémoire de façon spectaculaire , voyez vous-même !

eluna.png

La solution , est donc d'utiliser curl , qui s'est révélé bien plus efficace , voici donc la fonction de remplacement de get_headers() ( sources fr2.php.net )

function get_headers_curl($url)
{
    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL,            $url);
    curl_setopt($ch, CURLOPT_HEADER,         true);
    curl_setopt($ch, CURLOPT_NOBODY,         true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT,        20);

    $r = curl_exec($ch);
    $r = split("\n", $r);
    return $r;
} 

Si vous ne pouvez pas utiliser curl , vous pouvez aussi utiliser la fonction suivante , qui se base sur fsockopen() en natif dans php .

Note:merci à clochix de m'avoir signalé cette autre alternative.

/*
 * Fonction de remplacement de get_headers 
 * Attention à ne pas mettre les http:// devant l'adresse 
 */
function get_headers_sock($adresse, $timeout=15){
    //Tableau qui vat contenir les entêtes
    $Theaders   =   array();
    $UserAgent = "User-Agent : Mozilla/4.0 (compatible; MSIE 5.0; Windows 95)";

    $fp = fsockopen($adresse, 80, $errno, $errstr, $timeout);
    if (!$fp) {
        echo "$errstr ($errno)<br />\n";
    } else {
        $out = "HEAD / HTTP/1.1\r\n";
        $out .= "Host: $adresse\r\n";
        $out .= "$UserAgent\r\n";
        $out .= "Connection : Close\r\n\r\n";

        fwrite($fp, $out);
        while (!feof($fp)) {
            $Theaders[] =   fgets($fp, 128);
        }
        fclose($fp);
    }


    //renvoi des entêtes
    if(!empty($Theaders)){
        return $Theaders;
    }else{
        return null;
    }
    
}

Cette fonction retourne tout comme get_headers() un tableau avec une ligne = une entrée .
Le timeout est ici défini à 20 secondes , car je juge que si l'entête n'est toujours pas là en 20secondes , le site n'est pas navigable normalement , donc indisponible .

Le code de status HTTP

Après avoir reçut la réponse HTTP , l'on décortique l'entrée du tableau n°0 qui correspond normalement à : HTTP/1.1 <code http> <etat>

Une petite expression régulière plus tard , on se retrouve avec le code http seul

//récupération des entêtes
$header = get_headers_curl($adresse);
if(!empty($header){

  //le code http sera disponible dans $retour[1]
  preg_match('#([0-9]{3})#',$header[0],$retour);

}

Le temps pour faire tout ça !

Il ne nous reste plus qu'à récupérer le temps total pour effectuer ces opérations ( temps d'envoi + temps de réception ).
Rien de plus simple , comme dans beaucoup d'exemple sur le net , nous utiliserons microtime()

$debut  = microtime(true);
$header =   get_headers_curl("http://".$adresse) ;
//ou  get_headers_sock($adresse); ( attention à ne pas mettre http devant )
$fin    =  microtime(true);
$temps  =   round($fin-$debut,4);

Et voilà , nous avons toutes les infos nécessaire , ne reste plus qu'à les enregistrer .. en base , fichier .. comme vous voulez .

Exemple de code complet :

<?php
//definition du user_agent

$useragent="Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1";

//adresse à surveiller ( sans les http )
$adresse = "lindev.fr";
        
$retour = array(0,0);
$dns        =   0;
$temps      =   0;

//test du dns
if( checkdnsrr($adresse,"A")){


	$debut  = microtime(true);
        $header =   get_headers_curl("http://".$adresse) ;
        $fin    =  microtime(true);
        $temps  =   round($fin-$debut,4);

        preg_match('#([0-9]{3})#',$header[0],$retour);
        $dns    =   1;

}else{
        echo "Résolution DNS impossible";   
}

//enregistrement des resulats
$result =   array(
   "DNS"           =>     $dns,
   "reponse"       =>  $retour[1],
   "tempsReponse"  =>  $temps
);

//si timeout , impose le code 503
if($result['reponse'] == NULL){
   $result['reponse'] = 503;
}

//enregistrement dans la base de données / ou fichier
        ... ... ...
function get_headers_curl($url)
{
    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL,            $url);
    curl_setopt($ch, CURLOPT_HEADER,         true);
    curl_setopt($ch, CURLOPT_NOBODY,         true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT,        20);

    $r = curl_exec($ch);
    $r = split("\n", $r);
    return $r;
} 
?>

Mise en place

Il faut maintenant lancer ce script de façon régulière afin de surveiller le site de façon précise .
Je vais donc dans mon cas le lancer toutes les 10min , via cron

Vous voilà avec une table qui se remplis toute seule des informations citées ci-dessus , il ne vous reste plus qu'à en faire ce que bon vous semble avec .

Pour info , les graphiques générés ci-dessus sont fait via JPgraph qui fera pourquoi pas l'objet d'un billet pour son initiation .

Conclusion

Voilà une approche d'un outil qui je pense peut s'avérer utile , à partir du moment ou les sites surveillés ne se trouvent pas au même endroit que ce script de monitoring .
Ensuite , n'a de limite que votre imagination pour le faire évoluer , pour par exemple lancer des alertes au bout de X minutes de non-disponibilités , tester d'autres type de services comme les mails , ftp ect ...

J'attends vos retours et vos critiques sur l'idée ou la façon de faire afin d'améliorer tout ça .

A bientôt ,

Ch.

30 oct. 2008

Installation Apache2 Et PHP5 manuellement

Il est conseillé d'installer votre serveur web manuellement afin de l'optimiser au maximum et de ne pas le surcharger avec des extensions inutiles ..

D'autant plus qu'il est assez rapide d'effectuer l'installation .

APACHE2

Commençons par apache ,

Commençons par télécharger les derniéres sources disponibles sur le site d'apache

cd /usr/local/src/
wget http://mirror.mkhelif.fr/apache/httpd/httpd-2.2.10.tar.gz
tar xzf httpd-2.2.10.tar.gz
rm -f httpd-2.2.10.tar.gz
cd httpd-2.2.10/

La question à se poser , faut il installer tous les modules d'apache en static ? La réponse est non , car celà augmenterai la charge d'apache ... Il faut donc choisir les modules à usage intense

Pour plus d'infos entrez cette commande :

./configure --help | less

Ici nous allons commencer par creer un fichier de configuration , qui permettra de refaire l'installation à l'identique en cas de changement de version.

vim conf_install

Voici le contenu :

#!/bin/sh

#Optimisation pour la compilation
export CC="gcc"
export CFLAGS="-02"

#Config des sources pour l'env
./configure --prefix=/usr/local \
	--enable-dav \
	--enable-rewrite \
	--enable-so \
	--enable-proxy \
	--enable-proxy-http \
	--enable-cache \
	--enable-mem-cache \

Nous avons donc précisé le lieu de l'installation /usr/local Activé quelques modules en statique ( dav rewrite ect... ) Et mis en place le systéme de gestion de modules dynamiques --enable.so

Une fois créé , il faut changer le mode du fichier de configuration

chmod 700 conf_install

Vous pouvez alors lancer la configuration d'apache2

./conf_install

En cas d'erreur , il vous faudra peut être installer des librairies supplémentaires , celles-ci seront spécifiés dans le message d'erreur .

Si tout se passe bien , on lance la compilation :

make
make install

Une fois installé , apache se trouve à l'endroit spécifié par la ligne prefix dans le fichier de configuration . Le fichier de configuration d'apache se trouve donc dans :

/usr/local/conf/httpd.conf

Effectuez les premières configurations standard avant de lancer le serveur .

Puis lancez le :

/usr/local/bin/apachectl start

Allez dans votre navigateur et entrez l'adresse suivante :

http://localhost/

Celui-ci doit vous retourner le message suivant :

It Works !

Félicitation , apache est installé et fonctionnel ..

PHP5

Il y a ici deux méthodes pour installer php .. Encore une fois , il y a la méthode statique et dynamique

La plus simple étant la dynamique nous allons donc effectuer celle-ci ... bien que la méthode statique avec apache soit un peut plus performante , elle nécessite une re-compilation d'apache en cas de changement de version de php.

Récupération des sources:

cd /usr/local/src/
wget http://fr.php.net/distributions/php-5.2.6.tar.gz
tar zxf php-5.2.6.tar.gz
rm -f php-5.2.6.tar.gz
cd php-5.2.6/

Ici nous allons effectuer l'installation de la même façon qu'apache Commençons par creer notre fichier de configuration

vim conf_install

Cette fois-ci , voici le contenu :

#!/bin/sh

export OPTIM=-02
./configure --prefix=/usr/local \
	--with-apxs2=/usr/local/bin/apxs \
	--with-inifile=/usr/local/etc/php.ini \
	--with-xsl \
	--enable-soap \
	--with-gettext \
	--with-mysql \
	--enable-mbstring --with-mbstring=all \
	--disable-debug \
	--enable-memory-limit \

Encore une fois pour avoir toutes les infos concernant les options à la configuration , vous pouvez entrer cette commande :

./configure --help | less

Dans ce fichier de configuration , le plus important , est cette ligne :

--with-apxs2=/usr/local/bin/apxs qui correspond au gestionnaire de modules dynamique d'apache . Disponible uniquement si vous avez installé apache avec l'option --enable-so

Comme pour apache la suite est standard :

chmod 700 conf_install
./conf_install

Si tout se passe correctement :

make
make install

Vous voulà maintenant avec php5 d'installé ...

Normalement , l'installation à rajouté pour vous la ligne suivante dans le fichier de configuration d'apache :

LoadModule php5_module modules/libphp5.so

Mais vérifiez quand même ...

vim /usr/local/conf/httpd.conf

Ensuite , ajouter ces parseurs afin qu'apache puisse gérer les fichier php :

AddType application/x-httpd-php .php .phtml
AddType application/x-httpd-php-source .phps

Ici les extentions .php et .phtml sont gérés de la meme façon et .phps affiche une source php coloré

Il vous faut ensuite récupérer php.ini et le mettre à l'endroit spécifié à la configuration de php5

dans notre cas c'est ici : /usr/local/etc/php.ini

Les sources de php vous proposent deux type de fichier php.ini

  • php.ini-dist
  • php.ini-recommended

Nous allons prendre php.ini-dist , car php.ini-recommended change quelques paramétres importants , à étudier donc s'il vous convient .

cp /usr/local/src/php-5.2.6/php.ini-dist /usr/local/etc/php.ini

Voilà nous avons terminé notre installation de base .

Il ne reste plus qu'à relancer apache

/usr/local/bin/apachectl stop
/usr/local/bin/apachectl start

Editez un fichier php dans /usr/local/htdocs afin de vérifier le bon fonctionnement :

exemple :

vim /usr/local/htdocs/phpinfo.php

Avec ce contenu :

<?php

echo phpinfo();

?>

Vous devriez voir apparaître les infos de votre serveur ... comme ci dessous .

Php5 en mode statique

Si nous avions installé php5 en mode statique , voici la procédure :

  • Compilation d'apache avec notre fichier de configuration similaire
  • Compilation de PHP avec aussi notre fichier de configuration en ayant pris soin de retirer la ligne qui contient --with-apxs et en ayant ajouté la ligne suivante :

--with-apache=../apache-2.2.10

  • Recompilation dapache avec le module statique de php ligne suivante dans le fichier de conf de compilation :

--activate-module=src/modules/php5/libphp5.a

En espérant que cet article vous a aidé ...

Nous verrons dans un prochain article quelques notions sur la sécurité à adopter pour ce genre de serveur web .. A bientôt donc ..

Edit 21-sept 2009 ;

A la configuration de php ( V5.3 ) , le module imap , génère une erreur , error: utf8_mime2text() has new signature, but U8T_CANONICAL is missing .
Solution : installer le paquet libc-client-dev

apt-get install libc-client-dev

Edit 4-feb-2010 ;
Si au make de php , un problème concernant une librairie lltdl survient , la solution est la suivante :

apt-get install libtool libtool-ltdl

- page 1 de 2