Create easily your SNI (multiple hostname on one IP) certificates for HTTPS with OpenSSL

Prerequisites :

  • A Linux box (tested on Ubuntu Server 14.04)
  • OpenSSL installed

What we will do :

  • Create our own certificate authority – you will need to deploy it to clients in order to avoid browser warnings.
  • Create a SNI certificate.

Let’s Start :

Create a folder for your authority, in this folder, create two files with following content, make them eXecutables :

gen_root_ca.sh : (create an authority valid for 3650 days)

#!/bin/bash

openssl genrsa -out rootCA.key 2048
openssl req -x509 -new -nodes -key rootCA.key -days 3650 -out rootCA.pem -sha256

gen_cert_sni.sh : (create a sni certificate valid for 1460 days)

#!/bin/bash
echo sample subject /C=FR/ST=France/L=YourCity/O=YourOrganisation/CN=$1
echo input your subject below :
read SUBJ
echo sample : subjectAltName=DNS:mydomain.com,DNS:www.mydomain.com,DNS:www.mydomain2.org
echo input your domain names like in sample :
read ALTNAME
if [[ "$1" = ??* ]] && [[ "$SUBJ" = /C=*/ST=*/L=*/O=*/CN=* ]]; then
mkdir $1
 cp /etc/ssl/openssl.cnf $1/
 echo [ v3_req ] >> $1/openssl.cnf
 echo $ALTNAME >> $1/openssl.cnf
 openssl genrsa -out $1/$1_cert.key 2048
 openssl req -new -key $1/$1_cert.key -out $1/$1_cert.csr -sha256 -nodes -subj "$SUBJ" -config $1/openssl.cnf -extensions v3_req -reqexts v3_req
 openssl x509 -req -in $1/$1_cert.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out $1/$1_cert.crt -days 1460 -sha256 -extfile $1/openssl.cnf -extensions v3_req
echo Done
else
 echo Incorrect certificate name or incorrect subject name
fi

Now execute ./gen_root_ca.sh, fill in carefully your authority informations. OK, now you’re done with your authority, copy rootCA.pem to rootCA.crt and deploy it to your clients : on a windows box, double click on rootCA.crt, install certificate, Next, Check “Place all certificates in the following store”, browse for “Trusted Root Certification Authorities”, OK, Next, Finish. Your done !

Let’s create our SNI Certificate :
Choose a “certificate_name”
Execute ./gen_cert_sni.sh my_certificate_name, i recommand you prepare your subject line and domain names line on text editor, then fill data on the command line.

The script will create a folder my_certificate_name with a .crt and .key file. Use it with your favorite Web server (apache, nginx, nodejs…).

Now test your certificate, on a client where authority cert is installed you will get a beautifull :

cert cert2

 

 

Hyper-V Web Interface

Il y a un manque d’interfaces Web non professionnelle pour Hyper-V. Pour évaluer NodeJS, j’ai fait une interface Web pour Hyper-V permettant d’effectuer les fonctions de base (Démarrer, Arréter, mettre en pause) sur une machine virtuelle.

There’s a lack of Hyper-V Web interface for non professional users (I mean students, home users). In order to test NodeJS, i’ve made this minimalist web interface allowing to Start, Pause and Stop VirtualMachines.

HyperVNodeJS

Feal free to download it :

HyperV 2008 : HyperV NodeJS

HyperV 2012 : HyperV NodeJS 2012

Production debugging : 100% CPU dans une application ASP.NET

Le but de cet article est de donner deux méthodes (la simple, l’avancée) permettant de trouver la cause d’un 100% CPU qui ne se produit que sur un environnement de production sur lequel nous n’avons pas toute la panoplie d’outils nous permettant de trouver rapidement la cause.

(Les ecrans qui suivent sont sur Windows 2008 R2)

Diagnostiques de base

Avant de passer dans les diagnostiques avancés, nous allons commencer par essayer d’isoler une URL qui génère ce probleme.

A l’aide de l’outil d’administration de IIS, au niveau serveur, on peut afficher la liste des processus généré par IIS.

Pour chaque process, il est possible de voir la liste des Requetes.

Et de trouver ainsi celle qui pose probleme dans un cas particulier.

A l’aide de ces requetes on a un déjà une bonne idée d’ou peut se situer le probleme.

Diagnostiques avancés

Connaitre la liste des requetes ne résoud pas pour autant le probleme dans tous les cas (cas ou cela ne depend pas de la requete mais d’un evenement exterieur…). Et il faudrait au minimum savoir quel bout de code génère ce 100% CPU. S’il n’est pas facile de le connaitre de prime abord, il est possible à l’aide de la stack trace des thread en cours d’execution de savoir approximativement ou se trouve le probleme.

Le principe qui va etre appliqué pour ce diagnostique avancé, sera de prendre des images du processus en cours et de regarder dans quel partie du code se trouve le programme. A l’aide de plusieurs de ces images prises a des moments différents, on va pouvoir grossierement déterminer ou se trouve le bout de code en cause.

Prérequis

Il faut commencer par télécharger les debugging tools pour windows et les installer sur le serveur ou le problème se produit : (Voir plus bas une méthode par le gestionnaire de tache ne nécessitant pas ce prérequis sur le serveur)

http://msdn.microsoft.com/en-us/windows/hardware/gg463009.aspx

Une fois installé dans le dossier de destination vous devez avoir l’outils adplus.exe :

Récupération du Process ID

Repérer le PID du processus ASP.NET qui pose problème à l’aide du gestionnaire de taches (Menu View > Select columns) :

Enregistrement d’images mémoires (Dumps)

Nous allons utiliser adplus.exe pour générer un Dump complet du processus que nous pourrons analyser à l’aide de l’outil WinDbg.

Prenons comme exemple ou le processus w3wp.exe utilisant la majorité du CPU est le PID : 3376, et nous crérons un dossier c:\dumps qui contiendra l’ensemble des dumps du processus.

adplus.exe -hang -p 3376 -quiet -o c:\dumps

Patienter environ 10s après que le programme vous ait rendu la main.

Il vous faudra reproduire cette actions plusieurs fois lorsque le probleme se produit. Attention le process est mis en pause (freezer) pendant les quelques secondes du Dump mémoire et ne répondra donc plus aux requetes utilisateurs pendant cette durée.

Dump sans ADPlus

Si vous n’avez pas le temps d’installer ADPlus, vous pouvez tout de même effectué des dumps directement depuis le gestionnaire des taches (TaskManager). Pour cela, dans l’onglet process, faites un clic droit sur le process en question, puis Create Dump File.

Analyse d’une image mémoire (dump)

En plus de AdPlus, les debugging tools incluent l’outils WinDbg que vous trouverez dans votre menu démarrer.

Lancez cet outil. (attention à executer celui correspondant à votre architecture à debugger : x64 ou x86)

Ouvrez le Dump en utilisant : File > Open Crash Dump et en allant chercher le dump qui a été généré dans le dossier que vous avez fournit à adplus lors de l’étape précédente.

Pour qu’il soit capable de transformer des adresses dans des DLLs en Nom de méthode, vous allez devoir charger les symbols. Le plus simple est de laisser WinDbg le faire tout seul en lui indiquant le serveur de Microsoft adapté.

SRV*c:\temp*http://msdl.microsoft.com/download/symbols

Adapter WinDbg aux diagnostiques de code .NET :

dans la fenêtre command :

.loadby sos clr

Maintenant il ne reste plus qu’a lister la pile des appels (call stack) de l’ensemble des threads pour récupérer l’emplacement d’execution à l’instant de ce dump mémoire.

Pour cela la commande ci-dessous a exécuter dans la fenêtre de commande va lister l’ensemble des piles d’appels dans les processus et threads en cours d’execution dans ce dump :

~* e !clrstack

Maintenant, il reste a partir de ces informations a en déduire le problème.

plus d’informations :

Filtrer les logs Azure (WADWindowsEventLogTable) depuis VisualStudio

Quand vous n’avez pas la possibilité d’avoir un outil dédié, vous pouvez utiliser Visual Studio pour visualiser les Event Logs stockés dans Azure.

Il faut pour cela écrire une requête de filtrage de la table : WADWindowsEventLogTable :

J’ai cherché la syntaxe pour faire des requêtes, La syntaxe comme l’indique visual studio est basé sur la syntaxe des WCF Data Service qui elle même est issue du standard “Open Data Protocol”.

exemple de cette syntaxe :

(EventId eq 0) and (Timestamp gt datetime'2012-02-03')

Ce qu’il y a a retenir de cette syntaxe :

La syntaxe est case sensitive (timestamp != Timestamp) !

Les opérateurs :
eq : égal
ne : not equal
lt : plus petit que
gt : plus grand que

la liste complete est disponible à cette URL :
Filtres Open Data

Types :
Lorsque vous spécifiez un type précis, par exemple dateTime, binary, il va falloir le spécifier en préfixant le type :
datetime’2012-02-03′
la liste complète accompagné d’une colonne d’exemples est disponible à cette URL :
Types de données

Voila ! vous etes maintenant paré à filtrer les logs à l’aide de VisualStudio.

ASP.NET MVC3 et le ValidateInput(false)

Qui n’a pas rencontré le problème de validation sur ASP.NET MVC3 : A potentially dangerous Request.Form value was detected from the client.

En WebForm il est simple de corriger ce problème et je ne m’étendrait pas dessus de nombreux site décrive comment procéder.

En ASP.NET MVC3, l’attribut [ValidateInput(false)] sur la méthode de votre controlleur est sensé régler le problème.

Mais dans ce cas :

Test.cshtml

@{
    ViewBag.Title = "Test";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Test</h2>

<p>@Html.Raw( ViewBag.k)</p>

@using (Html.BeginForm())
{
<span style="font-size: 12px; line-height: 18px;">
</span>    <p><input type="text" name="toto" ><input type="submit" /></p>;
}

HomeController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MvcApplication1.Controllers
{
    [ValidateInput(false)]
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.Message = "Welcome to ASP.NET MVC!"+ Server.MachineName;

            return View();
        }

        public ActionResult About()
        {
            return View();
        }

        [ValidateInput(false)]
        public ActionResult Test()
        {
            string k = "";

            foreach (string key in Request.Form.Keys)
            {
                k += key + " : " + Request.Form[key] + "; ";

            }
            ViewBag.k = k;

            return View();
        }
    }
}

si vous entrez le texte : ” coucou <br/> bonjour” dans le champ texte, et que vous soumettez le formulaire par un clic sur le bouton Valider, Malgré l’utilisation des attributs [ValidateInput(false)], Vous aurez la page habituelle d’erreure…

[HttpRequestValidationException (0x80004005): A potentially dangerous Request.Form value was detected from the client (toto="<fdfdsdf>").]
   System.Web.HttpRequest.ValidateString(String value, String collectionKey, RequestValidationSource requestCollection) +8812804
   Microsoft.Web.Infrastructure.DynamicValidationHelper.<>c__DisplayClass12.<ReplaceCollection>b__d(String value, String key) +79
   Microsoft.Web.Infrastructure.DynamicValidationHelper.LazilyEvaluatedNameObjectEntry.ValidateObject() +89
   Microsoft.Web.Infrastructure.DynamicValidationHelper.LazilyValidatingHashtable.get_Item(Object key) +54

La solution :

Utilisez la classe System.Web.Helpers.Validation :

foreach (string key in System.Web.Helpers.Validation.Unvalidated(Request).Form.Keys)
{
     k += key + " : " + System.Web.Helpers.Validation.Unvalidated(Request).Form[key] + "; ";
}

Vous n’aurez ainsi plus d’erreurs de validation.

VirtualBox et le problème du “Cannot register hard disk because … UUID … already exists”

Lorsque vous dupliquez un disque virtuel (copier/coller d’un fichier vdi ou vhd) pour l’utiliser dans virtualbox, vous allez être confronté au problème de l’identifiant du disque qui doit être unique.

Pour éviter d’être confronté au problème vous pouvez utiliser la commande permettant de cloner un disque fournie dans l’outil VBoxManage en ligne de commande. Cette commande lors de la copie du disque va changer l’UUID du disque de manière à ne pas avoir ce problème.

VBoxManage clonehd chemin_disque_source chemin_disque_a_copier

Mais bien souvent on effectue d’abord la copie du disque et ensuite on se rend compte du problème. Le plus simple est alors de changer cet UUID sur la copie, ce qui est souvent bien moins long que de lancer une commande ‘clonehd’ du disque. Et la encore une commande existe pour simplement changer l’UUID d’un disque existant :

VBoxManage internalcommands sethduuid chemin_du_disque_copié

Sharepoint 2010 : WebPart Générique pour charger des Contrôles ASP.NET

Le modèle de création de WebPart Sharepoint poussé par Microsoft est de faire contenir dans une WebPart un contrôle ASP.NET. Le contenu du WebPart étant assez simple, on peut en faire un générique dont un paramètre permettra de définir le contrôle ASP.NET à charger.

L’intérêt, bien que limité, permet de créer des interfaces qui ne seront pas disponible directement à travers l’ajout de WebPart mais en connaissant le chemin du contrôle ASP.NET uniquement. Cela peut être pratique lorsqu’on a quelques contrôles ASP.NET de debug qu’on ne souhaite pas faire apparaitre dans la liste des WebPart disponibles.

Elle permettra aussi de déployer des contrôles (dépourvus de code behind) en uploadant des contrôles dans Sharepoint.

Il conviendra de vérifier que seuls les administrateurs aient le droit de modifier le chemin car dans le cas contraire cela pourrait entrainer une faille de sécurité.

[ToolboxItemAttribute(false)]
 public class LoadUserControl : Microsoft.SharePoint.WebPartPages.WebPart
 {
 [WebBrowsable(true),
 Category("WebPart Configuration"),
 WebPartStorage(Storage.Shared),
 FriendlyName("ASCX"),
 Description("Chemin du controle ASP.NET."),
 Personalizable(true)]
 public string ascx { get; set; }

 protected override void CreateChildControls()
 {
 if (!string.IsNullOrEmpty(ascx))
 {
 Control control = Page.LoadControl(ascx);
 Controls.Add(control);
 }
 }
 }

Exemple d’exploitation pour charger un contrôle :

<webParts>
 <webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
 <metaData>
 <type name="MyNameSpace.LoadUserControl.LoadUserControl, MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0000000000000000" />
 <importErrorMessage>$Resources:core,ImportErrorMessage;</importErrorMessage>
 </metaData>
 <data>
 <properties>
 <property name="Title" type="string">Titre publique de la WebPart</property>
 <property name="Description" type="string">My WebPart</property>
 <property name="ascx" type="string">~/_CONTROLTEMPLATES/Exemple/Exemple.ascx</property>
 </properties>
 </data>
 </webPart>
</webParts>

Regarder la Télé Free derriere un Routeur Linux sans fastidieuse configuration des clients

Free utilise le protocole RTSP pour faire transiter le signal TV, dans le cadre du multiposte.

L’inconvénient du protocole RTSP est similaire à celui du FTP, un canal de commande sous forme d’une connexion TCP permet de définir un canal de données qui sera situé sur une autre connexion TCP.

Mais le protocole FTP à un avantage que n’a pas directement le RTSP, le mode Passif qui règles les principaux problèmes du FTP derrière un NAT.

Mais revenons au protocole RTSP : la solution que j’utilisais jusqu’à présent était de définir dans VLC un port statique différent sur chaque machine cliente et de définir des règles de port forwarding sur le routeur. Solution peu pratique lorsque la plupart des machines sont en DHCP ou lorsque des machines ne font que passer dans le réseau.

En recherchant un Proxy RTSP pour éviter cette configuration plus que fastidieuse, je suis tombé sur le travail de plusieurs développeurs à l’adresse http://mike.it-loops.com/, ou encore https://github.com/maru-sama/rtsp-linux-v2.6

Ils ont développé un filtre a intégrer au noyau Linux du routeur comme il en existe pour le protocole FTP.

Le code source est fournit, il ne vous reste qu’a le compiler. Cela vous donne un module à installer et à charger dans le noyau. (module nf_nat_rtsp). Tous les détails sont dans le fichier README.RST fournit avec le package.

Maintenant, n’importe quel PC présent sur le réseau peut accéder à la TV Free sans avoir a configurer, ni le routeur, ni le client.

VirtualBox Headless et ajouter des périphériques USB sous Windows

Un petit script pour répondre a une problématique, comment ajouter en script un périphérique USB à une machine Virtuelle à l’aide de VirtualBox ?

Si vous exploitez une machine déportée pour héberger vos machines virtuelles, vous utilisez sans doute VBoxHeadless et un accès TSE pour accéder à ces dernières.

Mais comment connecter vos périphériques USB lorsque vous n’avez plus d’interface graphique ? Dans VirtualBox une série d’exécutables en ligne de commande est prévu pour effectuer des actions sur ces machines.

Dans ce cas précis, VBoxManage va nous servir.

Voici les commandes que vous utiliserez :


C:\VBox>VBoxManage list usbhost

Host USB Devices:

UUID: 00f631b2-118c-40f3-a5b6-9c5cc654c743
VendorId: 0x041e (041E)
ProductId: 0x401d (401D)
Revision: 0.1 (0001)
Manufacturer: Creative
Product: Creative WebCam NX Ultra
Current State: Available

l’utilisation de la commande :

VBoxManage controlvm "nom de ma vm" usbattach 00f631b2-118c-40f3-a5b6-9c5cc654c743

permet d’attacher la webcam à la machine virtuelle. Mais cet UUID change régulièrement donc difficile de créer un script simple.

J’ai donc créé un javascript vous permettant à partir du nom du produit d’ajouter le périphérique usb à la machine virtuelle.


cscript InstallByUUID.wsf "Creative WebCam NX Ultra" "nom de ma vm"

Contenu du script ( InstallByUUID.wsf ) :

<job>
<script language="JScript">

        var tmppath = "c:\\temp";
        var wtattach = "";

        var lastUUID = "";
        var producttofind = "";
        var found = false;

        function FindUUID(lineinfo)
        {
                if (lineinfo.indexOf('UUID:')==0)
                {
                        lastUUID = lineinfo.substring(20,56);
                }
                if (lineinfo.indexOf('Product:')==0)
                {
                        var product = lineinfo.substring(20);
                        if (product == producttofind)
                                found = true;
                }
        }

        if (WScript.Arguments.length<2)         {                 WScript.echo("InstallByUUID.wsf [ProductNameofUSBItem] [NameOfVmToAttach]");                 exit(0);         }                  producttofind = WScript.Arguments(0);                          var objShell = WScript.CreateObject("WScript.Shell");         objShell.Run('cmd /C ""c:\\Program Files\\Oracle\\VirtualBox\\VBoxManage.exe" list usbhost > '+tmppath+'\\usbatach.txt"', 0, 1);

        var objFileSystem = WScript.CreateObject("Scripting.FileSystemObject");
        var objFile = objFileSystem.OpenTextFile(tmppath+'\\usbatach.txt');
        while ((!objFile.AtEndOfStream)&&(!found))
        {
                FindUUID( objFile.ReadLine( ));
        }
        objFile.Close();

        objFileSystem.DeleteFile(tmppath+'\\usbatach.txt');

        if (!found)
        {
                WScript.echo(producttofind +' n\'a pas été trouvé');
        }

        var runcmd = 'cmd /C ""c:\\Program Files\\Oracle\\VirtualBox\\VBoxManage.exe" controlvm "'+WScript.Arguments(1)+'" usbattach '+lastUUID+'"';
        objShell.Run(runcmd, 0, 1);
        //WScript.echo(runcmd);
</script>
</job>

Mon routeur x86 Low Power

Dans le but de diminuer mon impact énergétique, j’ai cherché a remplacer mon routeur qui se présentait sous la forme d’un PC classique équipé de deux cartes réseau par une machine x86 a base de processeur basse consommation.

Après une longue recherche, j’ai finalement trouvé une machine adéquate : Le Compulab Fit-PC2i.

On trouve facilement des PCs basse consommation depuis que le processeur ATOM d’Intel est sorti (grand fan des Acer REVO), sans compter les équivalents AMD, mais difficile d’en trouver ayant deux interfaces réseau.

J’ai installé le système d’exploitation (noyau Linux) sur une clef USB et monté certains points de montage directement en RAM de manière a optimiser le nombre d’écriture sur la clef USB.

/etc/fstab :

UUID=fcxxx... /               ext4    noatime,errors=remount-ro 0       1
tmpfs /tmp tmpfs defaults 0 0
tmpfs /var/tmp tmpfs defaults 0 0
tmpfs /var/log tmpfs defaults 0 0
tmpfs /var/www tmpfs defaults 0 0

On remarquera la présence du noatime sur le root pour éviter la mise a jour des dates d’accès au fichier qui écrirait sur la clef usb à chaque accès fichier.

A cela s’ajoute des scripts au démarrage du système pour remplir ces dossiers en RAM, d’autres s’exécutant a intervalle régulier (tous les jours par exemple) pour prévenir la perte de données lors d’arrêt non souhaité du routeur, ainsi que des scripts de sauvegarde au moment de l’arrêt du serveur.

Consommation :

Mesure avant : 70wh, Mesure après : 10wh

Autres alternatives :

J’avais auparavant tenté d’utiliser un routeur matériel (Linksys WRT-150N), compatible avec la distribution DD-WRT, mais malgré la grande ouverture du système, on se trouve vite limité par les capacité matérielles du routeur.