1. Script en lui-même

Le script en lui-même - getLogsFtps.php - est écrit en PHP et contient les éléments suivants:

  • Aucune limite de temps n’est définie, afin que le script puisse tourner en boucle en continu
  • Trois variables principales sont utilisées:
    • $BASEPATHFTPS pour indiquer le chemin pour le téléchargement FTPS, y compris le username et password
    • $BASEPATHLOCAL pour définir dans quel répertoire les logs seront sauvés
    • $listOfFiles pour la liste des fichiers à télécharger. PHP n’arrivant pas à lire la liste des fichiers présents dans un répertoire, il faut explicitement définir quels fichiers téléchargés. Ce n’est pas un grand problème dans ce cas, car les fichiers ont toujours la même structure, à savoir web.log, web.log.0, web.log.1.gz à web.log.6.gz, ftp.log et finalement ftp.log.0 à ftp.log.30
  • Chaque fichier dans la variable $listOfFiles sera téléchargé et sauvé dans un sous-répertoire de $BASEPATHLOCAL
  • A la fin de la boucle, le script PHP se met en veille (fonction sleep) jusqu’au lendemain à 9h00

<?php

    set_time_limit(0);
   
    while (true) {
        $BASEPATHFTPS = 'ftps://USER:PASSWORD@HOSTNAME/logs/';
        $BASEPATHLOCAL = '/shares/PathTo/Logs/SiteX/';
        $stream_options = array('ssl' => array('verify_peer' => false, 'ciphers' => 'HIGH'));
        $stream_context = stream_context_create($stream_options);
       
        $listOfFiles = array_merge(
                            array('web.log', 'web.log.0', 'ftp.log'),
                            generateFilenameRange('web.log.', 1, 7, '.gz'),
                            generateFilenameRange('ftp.log.', 0, 31, '')
                        );
       
        $currTimeFolder = strftime('%Y-%m-%d_%H-%M-%S');
        mkdir($BASEPATHLOCAL . $currTimeFolder);
        foreach ($listOfFiles as $f)
            downloadFile($BASEPATHLOCAL . $currTimeFolder . '/', $f);
           
        sleepUntilNextDay();
    }
   
    function generateFilenameRange($basename, $fromIncluded, $toExcluded, $suffix) {
        $diff = $toExcluded - $fromIncluded;
        $result = array();
       
        for($i = 0; $i < $diff; $i++) {
            $result[$i] = $basename . ($i + $fromIncluded) . $suffix;
        }
       
        return $result;
    }
   
    function downloadFile($saveDir, $dlFile) {
        global $BASEPATHFTPS, $stream_options, $stream_context;

        $fsave = fopen($saveDir . $dlFile, 'w', 0);
        if ($fdl = fopen($BASEPATHFTPS . $dlFile, 'r', 0, $stream_context))
        {
            while (!feof($fdl)) {
                fwrite($fsave, fread($fdl, 8192));
            }
          
            // Closes the file handle
            fclose($fdl);
            fclose($fsave);
        }
        else
        {
            die('Could not open file.');
        }
    }
   
    function sleepUntilNextDay() {
        $nextDay = strtotime('next day 9am');
        $sleepTime = ($nextDay-time());
        sleep($sleepTime);
    }
?> 

2. Mise en place du script

Le script peut être lancé très facilement via la commande suivante:

php -q getLogsFtps.php &

Pour une solution légèrement plus élégante, j’ai préféré créer dans le répertoire /root/ un sous-dossier /root/scripts/ où tous les scripts sont stockés. /root/scripts/getLogsFtps.php n’est cependant qu’un lien symbolique vers /share/logs/scripts/getLogsFtps.php où le fichier original est conservé.

3. Problèmes restants

Malheureusement ce script contient encore quelques imperfections tels que la non-vérification du certificat SSL ('verify_peer' = false).

Bien qu’au début je pensais que le problème venait du certificat SSL servi (un certificat *.infomaniak.ch valide étant présenté pour l’accès à ftp.mondomain.ch), un second test en référençant directement le hostname du provider (imuXX.infomaniak.ch) affichait la même erreur. Il s’avère qu’aucune liste de certificats approuvée (CAs) n’est présent sur le NAS MyBookWorld, ce qui fait qu’aucune vérification ne peut avoir lieu!

Bien que la non-validation n’est pas belle, cela évite néanmoins qu’un attaquant seulement capable de lire le trafic puisse intercepter mon mot de passe.