[NAS 2/x] Installation

Dans le premier article de cette série, je vous annoncais que j’avais choisi le HP Proliant MicroServer Gen8 pour en faire un NAS. Une fois la machine reçue, il convient de faire quelques adaptations pour rendre son utilisation, et son administration, plus agréable. Pour ces quelques opérations, je me suis à nouveau basé sur l’article très complet de L’Atelier du Geek traitant de l’installation d’OpenMediaVault sur cette machine.

En partant des informations de l’article, je me suis moi aussi doté d’un câble SATA, d’un câble adaptateur d’alimentation floppy vers SATA et d’un disque SSD sur lequel sera installé le système.

nas_1
Le disque SSD placé sur le haut du NAS

On connecte le câble d’alimentation sur une broche d’alimentation libre et au SSD. Pour le câble SATA, rien de bien compliqué, la machine dispose d’un port libre sur l’un de ses côtés. En mettant en place les différents éléments, j’ai constaté que la machine semble également disposer d’un emplacement pour carte SD. Il pourrait donc être intéressant d’effectuer l’installation du système sur une carte SD, plutôt que sur le disque SSD. Ainsi, le pourcentage d’utilisation de l’espace disque serait bien plus optimisé qu’avec le SSD où plusieurs dizaines de gigaoctets sont inutilisés.

nas_2
Câble SATA connecté sur le port libre de la carte mère

Au niveau matériel, notre NAS est donc prêt à fonctionner. Il reste une petite subtilité à effectuer afin de s’assurer que le NAS démarrera sur le SSD. Pour cela, il convient de créer un Array RAID contenant notre disque et de demander au BIOS de booter dessus. Voir l’étape 2 de l’article de L’Atelier du Geek pour tous les détails.

nas_3
Préparation du boot sur le SSD

Une fois ces opérations effectuées, on peut se tourner vers l’installation du système d’exploitation du NAS. J’ai moi aussi choisi OpenMediaVault. On récupère l’ISO, un coup de dd pour créer une clé USB d’installation et le tour est joué, l’installation peut commencer.

Pas de difficultés particulières de ce côté là, des questions classiques pour qui aura déjà installé un système GNU/Linux. Une fois l’installation terminée et le NAS éteint, on peut se tourner vers la mise en place des disques de données.

Unity3D : gestion des bords de l’écran

Définition du problème

J’ai passé quelques temps à comprendre comment gérer la détection des bords de l’écran pour ne pas que mon gameobject en sorte.

Dans mon cas le gameobject dirigé par le joueur est un cube auquel on ajoute un BoxCollider, la caméra est fixe.

Dans Unity on gère la position d’un objet par son attribut position (un Vector3 donnant le positionnement du centre de l’objet).

Malheureusement pour moi le composant camera de Unity permet seulement de trouver la taille en pixels de l’écran (maCamera.pixelHeight et maCamera.pixelWidth) et donc je me suis mis à chercher un moyen de déterminer en pixel l’endroit où se trouve mon cube afin de savoir si celui-ci est en dehors ou en dedans de l’écran. En gros si mon cube est entièrement visible ou non !

De l’intérêt d’utiliser un BoxCollider

Pour déterminer le centre de mon cube ainsi que sa taille j’utilise les valeurs récupérables dans l’attribut bounds du composant :

//dans start()
joueurX = this.GetComponent<Collider>().bounds.size.x/2;
joueurY = this.GetComponent<Collider>().bounds.size.y/2;

//dans update()  centreJoueurX = this.GetComponent<Collider> ().bounds.center.x; centreJoueurY = this.GetComponent<Collider> ().bounds.center.y; 

Aux tests à effectuer

if (maCamera.WorldToScreenPoint(new Vector3(0,(centreJoueurY+joueurY),0)).y > pixelHeight) {
//on stop le déplacement
directionJoueur = 0;
this.gameObject.transform.localPosition += (-mouvementY * speed * Time.deltaTime);
} 
else if (maCamera.WorldToScreenPoint(new Vector3(0,(centreJoueurY-joueurY),0)).y  < 0) {
directionJoueur = 0;            this.gameObject.transform.localPosition += (mouvementY * speed * Time.deltaTime);
} 
else if (maCamera.WorldToScreenPoint(new Vector3((centreJoueurX+joueurX),0,0)).x > pixelWidth) {
directionJoueur = 0;             this.gameObject.transform.localPosition += (-mouvementX * speed * Time.deltaTime);
}
else if (maCamera.WorldToScreenPoint(new Vector3((centreJoueurX-joueurX),0,0)).x < 0) {
directionJoueur = 0;                                           this.gameObject.transform.localPosition += (mouvementX * speed  * Time.deltaTime);
}


Voilà pour le système utilisé actuellement, on peut bien entendu imaginer un système pour ne pas refaire les tests à chaque update() mais uniquement au moment voulu.

WordPress, xmlrpc et déni de service

Certains d’entre vous l’ont peut-être constaté, il était plutôt compliqué d’accéder à unicoda.com durant les dernières 48h. En effet, il se trouve que le site a été la cible d’une attaque de type brute force qui l’a mis à mal. Résultat, un processus apache qui décolle et accapare toutes les ressources de la machine jusqu’au déni de service. Retour sur la folle vie d’un serveur attaqué.

Tout commence le 25 août 2016 aux alentours de 19h, la première requête de la série apparaît à 18 heures 46 minutes et 25 secondes pour être précis.

191.96.249.54 - - [25/Aug/2016:18:46:25 +0200] "POST /xmlrpc.php HTTP/1.0" 200 579 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
191.96.249.54 - - [25/Aug/2016:18:46:25 +0200] "POST /xmlrpc.php HTTP/1.0" 200 579 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
191.96.249.54 - - [25/Aug/2016:18:46:25 +0200] "POST /xmlrpc.php HTTP/1.0" 200 579 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"

À cette heure-là, pas de problème, le serveur fonctionne correctement. La première alerte sera levée par le système de monitoring d’OVH à 22h54 ce même jour. Le serveur a déclaré forfait et ne répond plus au ping. Quelques minutes plus tard, le support intervient et redémarre le serveur. Une nouvelle alerte sera levée vers 4h du matin, avec intervention du support. En découvrant les mails le matin, je ne flaire pas immédiatement l’attaque. Le support est intervenu, il n’y a pas de précision indiquant si le problème vient du logiciel ou du matériel côté hébergeur, le site ne s’affichant pas, j’effectue à mon tour un redémarrage du serveur et m’assure que les différents services sont bien repartis. Tout semble fonctionner… Pourtant, même scénario dans la nuit de vendredi à samedi avec deux interventions du support. Quelque chose cloche, je continue de vaquer à mes occupations lorsque le serveur devient une nouvelle fois inaccessible samedi vers midi. Pas doute il y a un problème, je vais devoir effectuer des vérifications dès que possible.

Continuer la lecture de « WordPress, xmlrpc et déni de service »

dd ? Et pourquoi pas, dcfldd ?

Si vous avez un peu joué avec le Raspberry Pi, vous êtes certainement familier avec la commande dd, en particulier si vous avez installé l’OS sur carte SD depuis GNU/Linux. Peut-être avez-vous même effleuré sa consœur, j’ai nommé: dcfldd.

J’ai découvert cette version du programme dd lors de ma dernière installation de Raspbian. Bien que celle-ci soit un peu ancienne et peu mise à jour, nous pouvons tout de même parler de version améliorée du programme d’origine. L’outil est développé par le « laboratoire des investigations informatiques » américain (Defense Computer Forensics Lab), aussi abrévié DCFL, d’où le nom de l’outil: dcfldd.

Du côté des fonctionnalités, on notera la possibilité d’effacer un disque en utilisant des motifs connus, ou encore celle de vérifier qu’une image est identique à l’originale bit à bit. dcfldd propose également un suivi de la quantité de donnée traitée au fur et à mesure de son avancement.

La dernière version stable date du 19 décembre 2006. Les dernières modifications sont à peine plus récentes et datent quant à elle du 4 décembre 2007. En comparaison, les dernières modifications du programme original ont eu lieu en janvier 2016, dcfldd ne dispose donc pas de toutes les améliorations qui ont pu être apportées à dd depuis 2008. Une mise à jour du code serait donc appréciable, mais l’opération ne serait pas forcément aisée.

Ces derniers temps, j’ai principalement utilisé dcfldd plutôt que dd afin de profiter de l’information d’avancement du travail en cours donnée par défaut par la commande. Néanmoins, à l’avenir, dd devrait faire l’affaire, puisqu’il existe une option status=progress permettant de suivre l’avancement de l’opération. Le comportement par défaut de dd étant de ne rien afficher avant que la tâche soit terminée. Ce sera donc un retour probable à dd pour les prochaines opérations.

 

Voir aussi : http://forensicswiki.org/wiki/Dcfldd

Rafraichir la page parente à la fermeture de la page fille

Derrière ce titre alambiqué se cache un besoin particulier que j’ai cherché (et réussi) à résoudre dernièrement. La situation est la suivante : un utilisateur arrive sur une page, celle-ci effectue un appel ajax afin de connaître l’état d’un paramètre utilisateur. Pour illustrer, nous dirons donc que la page interroge une api pour répondre à la question : l’utilisateur a-t-il une image de profil enregistrée ?

Si l’utilisateur possède une image enregistrée, on la lui affiche ainsi qu’un message pour lui permettre de la supprimer. Si aucune image n’est présente, l’utilisateur peut choisir d’en ajouter une. L’acquisition de l’image s’effectue dans une page dédiée, que nous appellerons la page fille. Cette acquisition est réalisée à l’aide de la bibliothèque Cropper.js.

Une fois l’image acquise, l’utilisateur valide la sélection via un bouton. Au niveau de la page fille, un appel est donc réalisé vers une api pour sauvegarder l’image. Si l’appel est une réussite, nous fermons la page fille. À ce stade, l’utilisateur se retrouve sur la page parente qui lui propose toujours d’ajouter une image, ce qu’il vient de faire, nous allons donc recharger la page parente à la fermeture de la page fille.

J’illustre ce processus dans le code HTML en fin de page. Lorsque la page parente est chargée, celle-ci affiche en alert(), le message « Page chargée ! » afin de matérialiser le rechargement de la page. En cliquant sur le lien, une nouvelle page s’ouvre. Lorsqu’on clique sur le bouton de cette page, on va déclencher la fermeture de la page courante (la page fille) et le rechargement de la page parente. De plus, afin de matérialiser l’action de la page fille dans la page parente, de rendre l’exemple plus intéressant et de matérialiser ce qui correspondrait dans mon cas pratique à la mise à jour de l’information par le premier appel ajax (celui sur la page parente), le texte saisi dans le formulaire sur la page fille est transféré à la page parente et affiché par un alert().

Par ailleurs, le test du booléen pageFille.fermeture dans la fonction de l’événement unload de la page fille permet de s’assurer que la page parente ne sera rechargée que si le traitement est réussi sur la page fille où window.fermeture vaudra alors true. En effet, si on enlève le test du booléen, on constate qu’un événement unload a lieux dès l’ouverture de la page fille, ce qui aurait donc pour effet de recharger immédiatement la page parente. Le test du booléen permet de palier à ce « problème ».

Page Parente (pageParente.html)

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
  </head>
  <body>
    <p>
      <a href="javascript:ouvrirPageFille();">cliquez ici</a>
    </p>

    <script>
      function ouvrirPageFille() {
        var pageFille = window.open('pageFille.html', 'Titre', 'top=42,left=42,height=800,width=600,scrollbars=yes,status=no,toolbar=yes');
        //Recharge la page parente à la fermeture de la page fille 
        pageFille.onunload = function() {
          if(pageFille.fermeture) {
            alert(pageFille.message);
            //Rechargement
            location.reload();
          }
        }
      }

      window.onload = alert('Page chargée !');
    </script>
  </body>
</html>

Page Fille (pageFille.html)

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
  </head>
  <body>
    <form>
      <label for="message">Message :</label>
      <input id="message" type="text" name="message">
      <input type="submit" value="Valider et quitter" onclick="quitterPage();">
    </form>

    <script>
      function quitterPage() {
        window.message = document.getElementById('message').value;
        window.fermeture = true;
        window.close();
      }
    </script>
  </body>
</html>

Voilà pour l’exemple. Il reste maintenant quelques limitations à préciser pour finir cet article. Si l’utilisateur ferme la fenêtre du navigateur via le bouton prévu à cet effet (la croix rouge généralement en haut à droite), la page parente n’est pas rechargée. Dans mon cas pratique, cela fait sens car l’utilisateur n’aura alors pas soumit d’image; il n’y a donc aucun raison de rafraîchir la page. Autre point, si l’utilisateur rafraîchit la page fille, cela a pour effet de casser la liaison existante entre les deux pages et le rechargement de la page parente n’aura pas lieux.

Voici donc une manière de rafraîchir une page parente à la fermeture de sa page fille en restant dans les fonctionnalités de base du navigateur et des langages. D’autres façons de faire sont très certainement possibles (avec des événements) et certains framework js seraient à même de simplifier le problème, en permettant de ne mettre à jour dynamiquement qu’une partie de l’interface.