Monthly Archives: August 2012

Mediatomb sur Ubuntu avec support du javascript

Après avoir essayé plusieurs serveurs DLNA, j’ai finalement porté mon choix sur Mediatomb car il permet d’organiser ses fichiers grâce à des scripts javascript.

Malheureusement la version de Mediatomb disponible dans les dépôts Ubuntu n’a pas été compilée avec le javascript activé.

Voici donc la manipulation à suivre pour recompiler une version de Mediatomb avec le support du Javascript.

Tout d’abord, il faut supprimer les librairies libmoz185 présentes par défaut dans Ubuntu puis installer des librairies nécessaires à la compilation:

sudo apt-get remove libmozjs185*
sudo apt-get install build-essential libnspr4-0d

Ensuite téléchargez les librairies libmozjs2d et  libmozjs-dev initialement développées pour Debian Squeeze. Pensez à prendre les versions correspondant à votre architecture et celle pour Debian Squeeze (c’est important).

Une fois téléchargées, vous pouvez les installer:

sudo dpkg -i libmoz*.deb

Récupérez ensuite les sources de Mediatomb:

sudo apt-get build-dep mediatomb
sudo apt-get source mediatomb

Puis éditez le fichier “debian/rules” pour activer le javascript:

sudo nano <mediatombfolder>/debian/rules

Recherchez –disable-libjs et remplacez le par –enable-libjs.

Vous pouvez également changer le numéro de version dans <mediatombfolder>/debian/changelog et dans le fichier “mediatomb.dsc” afin d’éviter les écrasements suite à des mises à jour.

Il ne vous reste plus qu’à lancer la configuration de Mediatomb:

cd <mediatombfolder>
sudo ./configure

Si tout c’est bien déroulé, vous devriez voir “libjs : yeslibjs : yes”.

Désormais vous pouvez lancer la compilation grâce à la commande:

sudo fakeroot debian/rules binary

Une fois la compilation terminée (cela peut prendre plusieurs minutes),  vous devriez avoir 3 fichiers .deb dans le répertoire parent.

Il ne reste plus qu’à les installer:

sudo apt-get install libjs-prototype
sudo dpkg -i mediatomb*.deb

Voilà, votre serveur Mediatomb est installé et il supporte le javascript 🙂

[.Net] Serveur TCP Asynchrone et Client Tcp Asynchrone

J’utilise énormément les deux classes suivantes qui permettent d’instancier en asynchrone des serveurs TCP ou des clients TCP.

La classe ASyncTcpServer m’a permis ainsi de faire un serveur Web, un serveur FTP, un serveur de données et tout cela de manière asynchrone.

La classe ASyncTcpClient quant à elle permet de se connecter à des serveurs TCP divers et variés.

Je tiens à préciser que j’ai juste convertit ces classes en Vb.Net et qu’elles ont été développées à l’origine par Rob Davey.

Imports System.Net.Sockets
Imports System.Net
Imports System.Text
Imports System.Linq
Imports System.Threading
 
Module AsyncTcp
 
    ''' <summary>
    ''' An Asynchronous TCP Server that makes use of system managed threads
    ''' and callbacks to stop the server ever locking up.
    ''' </summary>
    Public Class AsyncTcpServer
 
#Region "Properties"
        Private TcpListener As TcpListener
        Private Clients As New List(Of Client)
 
        ''' <summary>
        ''' The encoding to use when sending / receiving strings.
        ''' </summary>
        Public Property Encoding As Encoding
 
        ''' <summary>
        ''' The data received.
        ''' </summary>
        Public Event DataReceived(ByRef Data() As Byte, ByRef DataLength As Integer, ByRef RemoteIP As String)
 
        ''' <summary>
        ''' An enumerable collection of all the currently connected tcp clients
        ''' </summary>
        Public ReadOnly Property TcpClients As IEnumerable(Of TcpClient)
            Get
                Return From x In Clients Select x.TcpClient
            End Get
        End Property
#End Region
 
#Region "Constructeurs"
        ''' <summary>
        ''' Constructor for a new server using an IPAddress and Port
        ''' </summary>
        ''' <param name="localaddr">The Local IP Address for the server.</param>
        ''' <param name="port">The port for the server.</param>
        Public Sub New(ByVal localaddr As IPAddress, ByVal port As Integer)
            Me.New()
            TcpListener = New TcpListener(localaddr, port)
        End Sub
 
        ''' <summary>
        ''' Constructor for a new server using an end point
        ''' </summary>
        ''' <param name="localEP">The local end point for the server.</param>
        Public Sub New(ByVal localEP As IPEndPoint)
            Me.New()
            TcpListener = New TcpListener(localEP)
        End Sub
 
        ''' <summary>
        ''' Private constructor for the common constructor operations.
        ''' </summary>
        Private Sub New()
            Me.Encoding = Encoding.Default
            Me.Clients = New List(Of Client)
        End Sub
#End Region
 
#Region "Start / Stop"
        ''' <summary>
        ''' Starts the TCP Server listening for new clients.
        ''' </summary>
        Public Sub Start()
            Me.TcpListener.Start()
            Me.TcpListener.BeginAcceptTcpClient(AddressOf AcceptTcpClientCallback, Nothing)
        End Sub
 
        ''' <summary>
        ''' Stops the TCP Server listening for new clients and disconnects
        ''' any currently connected clients.
        ''' </summary>
        Public Sub [Stop]()
            Me.TcpListener.Stop()
            SyncLock Me.Clients
                For Each c As Client In Me.Clients
                    c.TcpClient.Client.Disconnect(False)
                Next
                Me.Clients.Clear()
            End SyncLock
        End Sub
#End Region
 
#Region "Write"
        ''' <summary>
        ''' Writes a string to a given TCP Client
        ''' </summary>
        ''' <param name="tcpClient">The client to write to</param>
        ''' <param name="data">The string to send.</param>
        Public Sub Write(ByVal tcpclient As TcpClient, ByVal data As String)
            Dim bytes() As Byte = Me.Encoding.GetBytes(data)
            Write(tcpclient, bytes)
        End Sub
 
        ''' <summary>
        ''' Writes a string to all clients connected.
        ''' </summary>
        ''' <param name="data">The string to send.</param>
        Public Sub Write(ByVal data As String)
            For Each c As Client In Me.Clients
                Write(c.TcpClient, data)
            Next
        End Sub
 
        ''' <summary>
        ''' Writes a byte array to all clients connected.
        ''' </summary>
        ''' <param name="bytes">The bytes to send.</param>
        Public Sub Write(ByVal bytes() As Byte)
            For Each c As Client In Me.Clients
                Write(c.TcpClient, bytes)
            Next
        End Sub
 
        ''' <summary>
        ''' Writes a byte array to a given TCP Client
        ''' </summary>
        ''' <param name="tcpClient">The client to write to</param>
        ''' <param name="bytes">The bytes to send</param>
        Public Sub Write(ByVal tcpClient As TcpClient, ByVal bytes() As Byte)
            Dim networkStream As NetworkStream = tcpClient.GetStream()
            networkStream.BeginWrite(bytes, 0, bytes.Length, AddressOf WriteCallback, tcpClient)
        End Sub
 
        ''' <summary>
        ''' Callback for the write opertaion.
        ''' </summary>
        ''' <param name="result">The async result object</param>
        Private Sub WriteCallback(ByVal result As IAsyncResult)
            Dim tcpClient As TcpClient = CType(result.AsyncState, TcpClient)
            Dim networkStream As NetworkStream = tcpClient.GetStream()
            networkStream.EndWrite(result)
        End Sub
#End Region
 
        ''' <summary>
        ''' Callback for the accept tcp client opertaion.
        ''' </summary>
        ''' <param name="result">The async result object</param>
        Private Sub AcceptTcpClientCallback(ByVal result As IAsyncResult)
            Dim tcpClient As TcpClient = TcpListener.EndAcceptTcpClient(result)
            Dim buffer(tcpClient.ReceiveBufferSize) As Byte
            Dim client As New Client(tcpClient, buffer)
            SyncLock Me.Clients
                Me.Clients.Add(client)
            End SyncLock
            Dim networkStream As NetworkStream = client.NetworkStream
            networkStream.BeginRead(client.Buffer, 0, client.Buffer.Length, AddressOf ReadCallback, client)
            TcpListener.BeginAcceptTcpClient(AddressOf AcceptTcpClientCallback, Nothing)
        End Sub
 
        ''' <summary>
        ''' Callback for the read opertaion.
        ''' </summary>
        ''' <param name="result">The async result object</param>
        Private Sub ReadCallback(ByVal result As IAsyncResult)
            Dim client As Client = CType(result.AsyncState, Client)
            If client Is Nothing Then Exit Sub
            Try
                Dim networkStream As NetworkStream = client.NetworkStream
                Dim read As Integer = networkStream.EndRead(result)
 
                If read = 0 Then
                    SyncLock Me.Clients
                        Me.Clients.Remove(client)
                        Exit Sub
                    End SyncLock
                End If
                Dim data As String = Me.Encoding.GetString(client.Buffer, 0, read)
                'Do something with the data object here.
                RaiseEvent DataReceived(client.Buffer, read, CType(client.TcpClient.Client.LocalEndPoint, IPEndPoint).Address.ToString())
                'Then start reading from the network again.
                networkStream.BeginRead(client.Buffer, 0, client.Buffer.Length, AddressOf ReadCallback, client)
            Catch ex As Exception
            End Try
        End Sub
 
#Region "Class Client"
        ''' <summary>
        ''' Internal class to join the TCP client and buffer together
        ''' for easy management in the server
        ''' </summary>
        Class Client
            ''' <summary>
            ''' Constructor for a new Client
            ''' </summary>
            ''' <param name="tcpClient">The TCP client</param>
            ''' <param name="buffer">The byte array buffer</param>
            Public Sub New(ByVal tcpClient As TcpClient, ByVal buffer() As Byte)
                If tcpClient Is Nothing Then
                    Throw New ArgumentNullException("tcpClient")
                End If
                If buffer Is Nothing Then
                    Throw New ArgumentNullException("buffer")
                End If
                Me.TcpClient = tcpClient
                Me.Buffer = buffer
            End Sub
 
            ''' <summary>
            ''' Gets the TCP Client
            ''' </summary>
            Public Property TcpClient As TcpClient
 
            ''' <summary>
            ''' Gets the Buffer.
            ''' </summary>
 
            Public Property Buffer As Byte()
 
            ''' <summary>
            ''' Gets the network stream
            ''' </summary>
 
            Public ReadOnly Property NetworkStream As NetworkStream
                Get
                    Return TcpClient.GetStream()
                End Get
            End Property
        End Class
#End Region
 
    End Class
 
    ''' <summary>
    ''' An Asynchronous TCP Client
    ''' </summary>
    Public Class AsyncTcpClient
 
#Region "Properties"
        Private Addresses As IPAddress()
        Private Port As Integer
        Private AddressesSet As WaitHandle
        Private TcpClient As TcpClient
        Private FailedConnectionCount As Integer
        Public Property Encoding As Encoding
        Public Event DataReceived(ByRef Data() As Byte, ByRef DataLength As Integer)
#End Region
 
#Region "Constructeurs"
        ''' <summary>
        ''' Construct a new client from a known IP Address
        ''' </summary>
        ''' <param name="address">The IP Address of the server</param>
        ''' <param name="port">The port of the server</param>
        Public Sub New(ByVal address As IPAddress, ByVal port As Integer)
            Me.New(New IPAddress() {address}, port)
        End Sub
 
        ''' <summary>
        ''' Construct a new client where multiple IP Addresses for
        ''' the same client are known.
        ''' </summary>
        ''' <param name="addresses">The array of known IP Addresses</param>
        ''' <param name="port">The port of the server</param>
        Public Sub New(ByVal addresses As IPAddress(), ByVal port As Integer)
            Me.New(port)
            Me.Addresses = addresses
        End Sub
 
        ''' <summary>
        ''' Construct a new client where the address or host name of
        ''' the server is known.
        ''' </summary>
        ''' <param name="hostNameOrAddress">The host name or address of the server</param>
        ''' <param name="port">The port of the server</param>
        Public Sub New(ByVal hostNameOrAddress As String, ByVal port As Integer)
            Me.New(port)
            AddressesSet = New AutoResetEvent(False)
            Dns.BeginGetHostAddresses(hostNameOrAddress, AddressOf GetHostAddressesCallback, Nothing)
        End Sub
 
        ''' <summary>
        ''' Private constuctor called by other constuctors
        ''' for common operations.
        ''' </summary>
        ''' <param name="port"></param>
        Private Sub New(ByVal port As Integer)
            If port < 0 Then
                Throw New ArgumentException()
            End If
            Me.Port = port
            Me.TcpClient = New TcpClient()
            Me.Encoding = Encoding.Default
        End Sub
#End Region
 
#Region "Connect"
        ''' <summary>
        ''' Attempts to connect to one of the specified IP Addresses
        ''' </summary>
        Public Sub Connect()
            If AddressesSet IsNot Nothing Then
                'Wait for the addresses value to be set
                AddressesSet.WaitOne()
            End If
            'Set the failed connection count to 0
            Interlocked.Exchange(FailedConnectionCount, 0)
            'Start the async connect operation
            TcpClient.BeginConnect(Addresses, Port, AddressOf ConnectCallback, Nothing)
        End Sub
 
        ''' <summary>
        ''' Callback for Connect operation
        ''' </summary>
        ''' <param name="result">The AsyncResult object</param>
        Private Sub ConnectCallback(ByVal result As IAsyncResult)
            Try
                TcpClient.EndConnect(result)
            Catch ex As Exception
                'Increment the failed connection count in a thread safe way
                Interlocked.Increment(FailedConnectionCount)
                If (FailedConnectionCount >= Addresses.Length) Then
                    'We have failed to connect to all the IP Addresses connection has failed overall.
                    Exit Sub
                End If
            End Try
            'We are connected successfully.
            Dim networkStream As NetworkStream = TcpClient.GetStream()
            Dim buffer(TcpClient.ReceiveBufferSize) As Byte
            'Now we are connected start asyn read operation.
            networkStream.BeginRead(buffer, 0, buffer.Length, AddressOf ReadCallback, buffer)
        End Sub
#End Region
 
#Region "Write"
        ''' <summary>
        ''' Writes a string to the network using the defualt encoding.
        ''' </summary>
        ''' <param name="data">The string to write</param>
        ''' <returns>A WaitHandle that can be used to detect
        ''' when the write operation has completed.</returns>
        Public Sub Write(ByVal data As String)
            Dim bytes() As Byte = Encoding.GetBytes(data)
            Write(bytes)
        End Sub
 
        ''' <summary>
        ''' Writes an array of bytes to the network.
        ''' </summary>
        ''' <param name="bytes">The array to write</param>
        ''' <returns>A WaitHandle that can be used to detect
        ''' when the write operation has completed.</returns>
        Public Sub Write(ByVal bytes() As Byte)
            Dim networkStream As NetworkStream = TcpClient.GetStream
            'Start async write operation
            networkStream.BeginWrite(bytes, 0, bytes.Length, AddressOf WriteCallback, Nothing)
        End Sub
 
        ''' <summary>
        ''' Callback for Write operation
        ''' </summary>
        ''' <param name="result">The AsyncResult object</param>
        Private Sub WriteCallback(ByVal result As IAsyncResult)
            Dim networkStream As NetworkStream = TcpClient.GetStream
            networkStream.EndWrite(result)
        End Sub
#End Region
 
#Region "Read"
        ''' <summary>
        ''' Callback for Read operation
        ''' </summary>
        ''' <param name="result">The AsyncResult object</param>
        Private Sub ReadCallback(ByVal result As IAsyncResult)
            Dim read As Integer
            Dim networkStream As NetworkStream
            Try
                networkStream = TcpClient.GetStream()
                read = networkStream.EndRead(result)
            Catch ex As Exception
                'An error has occured when reading
                Exit Sub
            End Try
 
            If read = 0 Then
                Exit Sub
            End If
 
            Dim buffer() As Byte = CType(result.AsyncState, Byte())
            Dim data As String = Me.Encoding.GetString(buffer, 0, read)
            'Do something with the data object here.
            RaiseEvent DataReceived(buffer, read)
            'Then start reading from the network again.
            networkStream.BeginRead(buffer, 0, buffer.Length, AddressOf ReadCallback, buffer)
        End Sub
 
#End Region
 
#Region "Diverses fonctions"
        ''' <summary>
        ''' Callback for Get Host Addresses operation
        ''' </summary>
        ''' <param name="result">The AsyncResult object</param>
        Private Sub GetHostAddressesCallback(ByVal result As IAsyncResult)
            Addresses = Dns.EndGetHostAddresses(result)
            'Signal the addresses are now set
            CType(AddressesSet, AutoResetEvent).Set()
        End Sub
#End Region
    End Class
 
End Module

[DIY] Fabriquer un tap Ethernet pour moins de 20€

Qu’est-ce qu’un Tap Ethernet ?

Un tap réseau, ou tap Ethernet, est un équipement physique (ordinateur, sonde, …) qui se branche entre plusieurs équipements (serveurs, ordinateurs, routeurs, imprimantes, …) afin de pouvoir capturer le trafic.

Dans la majorité des cas, un tap permet de capturer le trafic entre deux points d’un réseau afin de pouvoir l’analyser pour trouver des anomalies (intrusion, virus), pour enregistrer des données VoIp, pour sniffer des paquets, pour faire de la détection d’intrusion (IDS) ou bien encore pour recetter une installation (adsl bien calibré).

Un tap est généralement utilisé avec des logiciels de monitoring et de supervision de réseau. Personnellement j’utilise WireShark et TCPDump (sur lesquels je définis des filtres).

Un tap sera utilisé afin d’améliorer la sécurité de votre architecture réseau. En effet, un tap est non intrusif, indétectable sur le réseau car aucune adresse ip ne lui est assignée.

Un tap peut être utilisé pour:

  • capturer le trafic entre 2 équipements de votre réseau informatique (bypass et passthrough)
  • agréger les données provenant de plusieurs équipements

Il existe plusieurs sortes de tap: fibre, ethernet, usb, etc…

Personnellement j’ai eu l’occasion de tester un ProfiTap qui se connecte en USB sur le pc d’analyse et qui prend 2 ports Ethernet en entrée. Ce type de sonde est simple à utiliser et fonctionne bien mais contrairement à des sondes plus performante, elle se limite à du 100Mb.

Parmis toutes les sondes professionnelles, c’est une des moins chers mais il faudra quand même déboursé 1000€.

Bien sûr, ce n’est pas grand chose comparé à certaines probes (sondes) fibres peuvent être vendues plusieurs dizaines de milliers d’euros.

N’ayant pas un budget illimité (malheureusement :-(), j’ai décidé de me lancer dans la réalisation d’un tap ethernet homemade et low cost.

Fabriquer un Tap Ethernet: difficile ?

En me lançant dans ce projet, j’étais plutôt pessimiste car je suis novice en électronique, et pas forcément super manuel.

J’ai donc effectué plusieurs recherches et j’ai trouvé toutes les informations nécessaires à la réalisation d’un tap Ethernet.

Parmis toutes mes lectures, l’élément le plus important est sans aucun doute le schéma suivant (trouvé sur Snort).

Ce schéma est très simple à comprendre. On dispose de 2 hosts et de 2 taps qui permettent de monitorer chacun des hosts.

On notera que 2 paires de fils (4-5 et 7-8) ne passent pas par les taps. C’est tout à fait normal car les câbles éthernet n’utilisent que 2 paires de fils: (1-2 pour transmettre les datas et 3-6 pour recevoir les datas).

C’est pourquoi pour pouvoir monitorer les transmissions de chaque host, il nous faudra une tap par host (une pour le traffic entrant et une pour le trafic sortant).

Le tap que nous allons fabriquer sera conforme à ce schéma: 2 ports pour les hosts et 2 ports pour les tap.

J’ai tout de même essayé de faire un tap à 3 ports (2 hosts et 1 tap) en mirrorant les fils sur les 3 connecteurs éthernet mais j’ai eu un résultat bizarre au niveau de WireShark.

Fabriquer un Tap Ethernet pour moins de 20€

Vous l’aurez compris: mon objectif est de fabriquer un tap ethernet avec un budget relativement bas. Comme je suis assez maniac, j’ai opté pour des composants de qualité mais il est possible de faire un tap ethernet avec uniquement 2 câbles éthernet, un fer à souder et un peu de patience.

Tout d’abord voici le matériel nécessaire:

  • 4 RJ45 KeyStone Jack Catégorie 5: 8€
  • 1 Wall Plate 4 ports RJ45: 5€
  • 1 Back Plate: 5€
  • 1 câble éthernet catégorie 5 de 20cm: 2€ (vous pouvez utiliser un vieux câble)

On arrive donc à un total de 20€. Les frais de ports sont inclus et tout le matériel a été acheté sur Ebay car ce sont les meilleurs tarifs que j’ai trouvé.

La première étape consiste à couper le câble ethernet, le dénuder puis séparer les 4 paires de fils:

Rangez les câbles par paires de couleur:

 

Vous remarquerez que sur chaque keystone, il y a un code couleur qui va vous aider dans votre cablage:

Désormais nous allons cabler le Host A. Prenez un keystone puis connectez les 8 fils en vous aidant d’un puncher (trouvable sur Ebay à 2€) ou d’un petit tournevis plat:

Coupez l’excédent au ciseau à ras bord du keystone puis mettez les bouchons de fixations:

Prenez un second keystone qui sera notre Host B puis connectez y les paires bleues et marrons:

A présent nous allons connecter le Host A à la tap A puis à l’Host B. Nous allons donc prendre un troisième keystone, y brancher les cables orange et orange rayés. Ensuite l’excédent sera branché sur l’Host B.

Puis l’on fera la même chose avec le quatrième keystone et les câbles vert puis on branche les keystones sur le wall plate:

Je vous conseille de tester si les connexions fonctionnent avant de mettre les caches de keystones.

Il ne vous reste plus qu’à mettre le tout dans le back plate et votre tap éthernet sera terminée:

 

 

 

Comment utiliser le Tap Ethernet ?

Pour utiliser le Tap éthernet c’est simple: il suffit de brancher deux équipements sur les ports de Hosts (par exemple une freebox sur HostsA et un routeur sur HostB).

Ensuite, brancher TapA ou TapB ou les deux sur votre machine d’analyse (dans mon cas un RaspBerryPi), configurer vos interfaces en mode promiscuous puis lancer votre outil de capture (Snort, Wireshark ou TCPDump par exemple).

Pour passer une interface en mode promiscuous, il faut taper la commande suivante:

ifconfig eth0 promisc

Pour supprimer le mode promiscuous, il faut utiliser la commande:

ifconfig eth0 -promisc

Si vous souhaitez analyser le trafic entrant et le trafic sortant simultanément, il faudra brancher les taps sur une machine disposant de 2 ports éthernet et lancer 2 outils de capture.

Dans le cas où vous souhaiteriez capturer les 2 taps avec un seul WireShark, il vous faudra créer un pont (Bridge) entre vos 2 interfaces.

Pour cela, il faut installer le paquet bridget-utils:

apt-get install bridge-utils

Puis créer le pont avec la commande suivante (br0 est le nom de l’interface de bridge):

brctl addif br0 eth0 eth1

Enfin pensez que si vous souhaitez connecter votre ordinateur de capture sur votre réseau de manière classique (afin de se connecter en ssh par exemple), alors il vous faudra un troisième port ethernet.

Si vous souhaitez utiliser le tap éthernet sous Windows, il faut faire quelques modifications dans les paramètres de votre carte Ethernet: il faut supprimer l’ip fixe si vous en avez une et désactiver le contrôle de flux:

Il ne vous reste plus qu’à lancer WireShark pour capturer le trafic 🙂

Vous voila désormais prêt à vous lancer dans l’aventure de la réalisation d’un Tap Ethernet Homemade :).

RaspBerry Pi et afficheur LCD Hitachi HD44780 1602 [PART 1]

Comme vous le savez j’ai récemment récupéré un RaspBerry Pi et du coup je me suis dis pourquoi ne pas essayé d’intéragir avec les pins GPIO (General Purpose Input Output).

Je me suis donc donné pour projet de réaliser un petit programme qui affiche des informations systèmes sur un écran LCD connecté via les ports GPIO de mon RaspBerry Pi.

Les GPIO du RaspBerry Pi

Un RaspBerry Pi possède 26 pins GPIO qui permettent de connecter une multitude d’équipement et périphériques: LED, transistor, radio, cerveeau, afficheur lcd, dalle tactile, …

Le schéma suivant détail l’utilisation de chacun des pins.

La première chose à voir est la numérotation des ports GPIO. Celle-ci est relativement importante notamment lorsqu’on commencera à programmer dessus.

On note donc qu’il y a 2 pins servant à l’alimentation électrique (en 3.3V et en 5V) et un pin servant à la masse (en noir sur le schéma).

Les pins en blanc ne doivent JAMAIS être utilisé.

Les pins en vert sont les ports GPIO utilisables. Il y en a 8 en tout.

Les pins en violet sont des ports SPI (Serial Peripheral Interface) qui sont utilisables dans certains cas précis.

Il en est de même pour les ports jaunes UART (Universal Asynchronous Receiver Transmitter) et les ports bleu I²C.

Vous allez me dire que c’est dommage que seuls 8 ports GPIO soient utilisable directement. Rassurez vous, il est tout à fait possible de reconfigurer les ports UART, I²C et SPI afin de pouvoir utiliser les 17 ports GPIO de votre RaspBerry Pi.

Ainsi la librairie WiringPi, permet de les utiliser facilement.

Choisir un afficheur LCD pour RaspBerry Pi ?

Il existe une infinité de références d’afficheur LCD. Il en existe de toutes les tailles, toutes les formes et tous les prix.

Après plusieurs recherches, j’ai porté mon choix sur un afficheur LCD Hitachi HD44780 1602.

J’ai choisi cet afficheur LCD car le contrôleur HD44780 est un des plus couramment utilisé, il y a donc énormément de documentation technique.
De plus il ne nécessite pas énormément de pins pour être connecté et il fonctionne en 5V.

Et enfin, il est relativement peu coûteux (j’ai trouvé le mien à 3€ livré sur Ebay :-))

A la découverte du LCD HD44780 1602

Présentation du LCD HD44780 1602

L’afficheur est d’une taille compacte (ce qui est pratique pour l’intégrer dans un boitier de RaspBerry Pi).

Il dispose de deux lignes de 16 caractères chacune. Il existe également des versions à 3 lignes et 4 lignes.

Le brochage du LCD HD44780 1602

Une des notions fondamentales lorsque l’on souhaite utiliser un afficheur LCD est la connexion et le brochage.

Le chipset HD44780 étant relativement simple, les afficheurs se basant dessus utilisent en général 16 broches, la branche 1 étant la broche la plus a gauche.

Voici le détail de l’utilisation de chaque broche:

  • la broche 1 (VSS) sera reliée à la masse.
  • la broche 2 (VDD) sera reliée à l’alimentation positive de 5V.
  • la broche 3 (V0) est une entrée analogique qui permet de régler le contraste de l’afficheur. Il faut savoir qu’une tension de 5V correspondra au contraste le plus faible alors qu’une mise à la masse correspondra au contraste le plus élevé. Je vous conseille d’utiliser un potentiomètre pour gérer le contraste (nous verrons cela plus tard).
  • la broche 4 (RS pour Register Select) est une entrée numérique qui sert à sélectionner le registre. Cela permettra à l’afficheur de déterminer si une commande (signal niveau bas) ou une donnée (signal niveau haut) lui est envoyée.
  • la broche 5 (R/W pour Read/Write) est une entrée numérique qui sert à lire (niveau haut) ou écrire (niveau bas).
  • la broche 6 (E pour Enable) est une entrée numérique qui valide la lecture ou l’écriture. La validation est active sur le front descendant d’une impulsion, dont la durée de l’état haut doit être au moins de 450 ns.
  • les broches 7 à 14 sont des entrées numériques. Ce sont des bus de données bidirectionnels qui servent à envoyer ou à recevoir les données ou les commandes via l’afficheur LCD.
  • les broches 15 et 16 servent à alimenter le rétroéclairage (backlight). La broche 15 (l’anode) doit être alimentée en +5V et la broche 16 (la cathode) doit être mise à la masse.

Les modes d’utilisation du LCD HD44780 1602

Il existe deux modes possibles pour utiliser le LCD HD44780 1602:

  • le mode 8 bits où les données et les commandes sont envoyées grâce aux broches D0 à D7 (broches 7 à 14).
  • le mode 4 bits qui limite le nombre de broches nécessaire pour commander l’afficheur. Juste les broches D4 à D7 sont utilisées sur le LCD, les broches D3 à D0 étant mises à la masse.

Personnellement je vous conseille d’utiliser le mode 4 bits car le RaspBerry Pi est limité en ports GPIO.

En effet, le mode 4 bits demande sept broches (voire six si l’on ne fait qu’écrire) alors que le mode huit bits en requiert 11.

Pour envoyer les différents bits représentant les caractères, on transmet séquentiellement les quatre bits de poids forts suivis des quatre bits de poids faibles.

Une impulsion de minimum 450 ns séparant chaque demi-octet est envoyée sur l’entrée E pour valider ces derniers.

Les mémoires et registres du LCD HD44780 1602

Les afficheurs basé sur le chipset HD44780 utilisent 2 types de mémoire:

  • La DDRAM qui stocke les caractères que l’on veut afficher à l’écran.
  • La CGRAM qui contient le jeu de caractères affichables. Elle permet d’afficher 200 caractères différents dont huit peuvent être définis par l’utilisateur.

Les afficheurs basé sur le chipset HD44780 utilisent 3 types de registre:

  • le registre d’instruction (unidirectionnel) qui reçoit des commandes venant de l’utilisateur. Il est utilisable uniquement en écriture et permettra de déplacer le curseur ou effacer l’afficheur.
  • le registre d’état (unidirectionnel) qui est utilisé uniquement en lecture et qui sert à indiquer lorsque l’afficheur est prêt à recevoir une instruction ou une donnée. La demande d’état se fait grâce à la broche R/W (R/W = 0, lorsque l’on écrit et R/W = 1, lorsque l’on veut lire l’état).
  • le registre de données (bidirectionnel) qui permet de recevoir les caractères à afficher ou à envoyer les caractères stockés dans la DDRAM.

 

Optimiser la consommation CPU et mémoire de votre RaspBerry Pi

Aujourd’hui j’ai cherché plusieurs façons d’optimiser la consommation de mon RaspBerry Pi.

En effet, votre rpi ne possède pas de ressources illimités, c’est pourquoi il faut absolument gérer sa consommation (mémoire et CPU).

Au fil des pages, j’ai trouvé plusieurs astuces que je regroupe ici.

J’espère que cela vous sera pratique.

Remplacer OpenSSH avec DropBear

Le simple fait de remplacer OpenSSH avec DropBear vous permettra de gagner environ 10Mb de mémoire. Il faut tout de même savoir que cette manipulation supprime le logging SSH ainsi que le port forwarding.

Tout d’abord, on installe le client openssh et DropBear puis on arrête le service SSH

apt-get install dropbear openssh-client
/etc/init.d/ssh stop

Puis on lance DropBear au démarrage du RaspBerryPi

sed -i 's/NO_START=1/NO_START=0/g' /etc/default/dropbear

Optionnel: prevenir des connections root

sed -i 's/DROPBEAR_EXTRA_ARGS=/DROPBEAR_EXTRA_ARGS="-w"/g' /etc/default/dropbear

Optionnel: prévenir des connections et des mots de passe root

sed -i 's/DROPBEAR_EXTRA_ARGS=/DROPBEAR_EXTRA_ARGS="-w -s"/g' /etc/default/dropbear

Optionnel: changer le port d’écoute

sed -i 's/DROPBEAR_PORT=22/DROPBEAR_PORT=2222/g' /etc/default/dropbear

Ensuite il suffit de démarrer DropBear et de supprimer OpenSSH Server

/etc/init.d/dropbear start
apt-get purge openssh-server

Supprimer extra tty / getty

Cette manipulation va désactiver tty2-tty6, vous laissant uniquement tty1 et vous fera gagner environ 4Mb de RAM.

sed -i '/[2-6]:23:respawn:\/sbin\/getty 38400 tty[2-6]/s%^%#%g' /etc/inittab

Optionnel: vous pouvez également désinstaller getty

sed -i '/T0:23:respawn:\/sbin\/getty -L ttyAMA0 115200 vt100/s%^%#%g' /etc/inittab

Remplacer Bash Shell avec Dash Shell

Le fait de remplacer votre shell Bash par le Dash va améliorer les performances de votre machine et vous faire gagner environ 1Mb de mémoire.

De plus, votre RaspBerry démarrera plus rapidement et votre utiliserez moins d’espace disque.

dpkg-reconfigure dash
 
Use dash as the default system shell (/bin/sh)? Yes

Utiliser 512Mb de Swap

Plusieurs tests ont révélés que votre RaspBerry Pi est le plus performant lorsqu’il utilise 512 Mb de swap.

echo "CONF_SWAPSIZE=512" > /etc/dphys-swapfile

Ensuite il suffit de l’initialiser et de l’activer:

dphys-swapfile setup
dphys-swapfile swapon

Optionnel: vous pouvez améliorer les performances de votre swap grâce à la commande suivante:

sed -i 's/sortstrategy = 3/sortstrategy = 0/g'  /etc/preload.conf

Optimiser le montage du système

Pour optimiser le temps de montage du système installé sur votre RaspBerry Pi, vous pouvez utiliser la commande suivante:

sed -i 's/defaults,noatime/defaults,noatime,nodiratime/g' /etc/fstab

Désactiver IPv6

Si vous n’utilisez pas les fonctionnalités d’IPv6, vous pouvez le désactiver ce qui économisera les ressources de votre RaspBerry Pi et qui améliorera ses vitesses de connection.

echo "net.ipv6.conf.all.disable_ipv6=1" > /etc/sysctl.d/disableipv6.conf
echo 'blacklist ipv6' >> /etc/modprobe.d/blacklist 
sed -i '/::/s%^%#%g' /etc/hosts

Pensez à redémarrer votre RaspBerry:

shutdown -r now

Remplacer le Deadline Scheduler avec le NOOP Scheduler

Le plannificateur NOOP est plus approprié lorsque l’on utilise un disque SSD ou une carte Flash pour stocker le système d’exploitation:

sed -i 's/deadline/noop/g' /boot/cmdline.txt
shutdown -r now

Remplacer rsyslogd par inetutils-syslogd

Le remplacement de rsyslogd par inetutils-syslogd et la suppression des logs inutiles permet la consommation mémoire et l’utilisation cpu.

apt-get -y remove --purge rsyslog
apt-get -y install inetutils-syslogd 
service inetutils-syslogd stop

Vous pouvez supprimer les fichiers de logs obsolètes:

for file in /var/log/*.log /var/log/mail.* /var/log/debug /var/log/syslog; do [ -f "$file" ] && rm -f "$file"; done
for dir in fsck news; do [ -d "/var/log/$dir" ] && rm -rf "/var/log/$dir"; done

Il faut ensuite créer une fichier de configuration puis de démarrer le service:

echo -e "*.*;mail.none;cron.none\t -/var/log/messages\ncron.*\t -/var/log/cron\nmail.*\t -/var/log/mail" > /etc/syslog.conf
 
mkdir -p /etc/logrotate.d
echo -e "/var/log/cron\n/var/log/mail\n/var/log/messages {\n\trotate 4\n\tweekly\n\tmissingok\n\tnotifempty\n\tcompress\n\tsharedscripts\n\tpostrotate\n\t/etc/init.d/inetutils-syslogd reload >/dev/null\n\tendscript\n}" > /etc/logrotate.d/inetutils-syslogd
service inetutils-syslogd start

Passer en IP Fixe et supprime le DHCP-Client

Passer en IP Fixe réduira votre consommation mémoire et cpu.

Tout d’abord créez un fichier de backup:

cp -f /etc/network/interfaces /etc/network/interfaces.dhcp-backup

Ensuite éditez le fichier /etc/network/interfaces et remplacez:

iface eth0 inet dhcp

par:

iface eth0 inet static
#set your static IP below
address 192.168.1.107
#set your default gateway IP here
gateway 192.168.1.1
netmask 255.255.255.0
network 192.168.1.0
broadcast 192.168.1.255

Pour que les changements soient effectifs, il suffit de redémarrer votre RaspBerry Pi:

shutdown -r now

Overclocker la CPU, RAM et GPU de votre RaspBerry Pi

Voici une petite astuce pour overclocker la cpu, la ram et la puissance GPU de votre RaspBerry Pi sans pour autant en augmenter le voltage.

echo -e "arm_freq=800\nsdram_freq=450\ncore_freq=350" >> /boot/config.txt

Notez que pour utiliser la commande suivante, il est préférable d’utiliser un dissipateur thermique sur la puce de votre RaspBerry. On peut en trouver pour 3€ sur ebay 🙂

echo -e "arm_freq=850\nsdram_freq=500\ncore_freq=450" >> /boot/config.txt

Pour que les modifications prennent effet, il suffit de redémarrer votre RaspBerry Pi:

shutdown -r now

 

Mise à jour du firmware de votre Raspberry Pi

Voilà comment procéder pour mettre à jour votre RaspBerry Pi sans risquer d’endommager votre Rpi.

sudo apt-get install ca-certificates git-core
sudo wget http://goo.gl/1BOfJ -O /usr/bin/rpi-update
sudo chmod +x /usr/bin/rpi-update
sudo rpi-update

Si vous rencontrez une erreur n’y pretez pas attention, ce n’est pas gênant.

Il ne vous reste plus qu’à exécuter les commandes suivantes:

sudo ldconfig
sudo rpi-update

Pour terminer la mise à jour du firmware de votre RaspBerry Pi, il ne vous reste plus qu’à le redémarrer.

Optimisez votre Raspberry Pi pour une utilisation en serveur

J’ai acheté récemment un RaspBerry Pi (RPI) sur lequel je me suis mis à développer des scripts python afin de faire de l’analyse de trames réseau.

N’ayant pas besoin du mode graphique, j’ai trouvé plusieurs astuces afin d’optimiser mon RaspBerry Pi qui tourne sur une version de Debian.

Après avoir installé un serveur SSH, vous pouvez donc désinstaller certains paquets servant uniquement à l’utilisation graphique.

sudo apt-get update
sudo apt-get -y remove aspell hunspell-en-us iptraf libaspell15 libhunspell-1.2-0 lxde lxsession lxtask lxterminal squeak-vm whiptail zenity gdm
sudo apt-get -y autoremove

De plus si lorsque vous vous logguez en SSH, la connection prend 10 secondes, vous pouvez desactiver la résolution DNS:

echo UseDNS no >> /etc/ssh/sshd_config
service ssh restart

Nouveau plugin de coloration syntaxique

Comme vous avez pu le remarquer, le blog a connu quelques souci avec la coloration syntaxique. Du coup nous avons changé de plugin et nous utilisons désormais WP-SynHighlight qui semble fonctionner mieux.

Tous les vieux messages sont par contre impactés par ce changement et ils perdront leur coloration.

Mais c’est un mal pour un bien 🙂

Exécuter un script PHP dans un shell sous Linux

Aujourd'hui j'ai voulu exécuté un script php dans un shell sur mon serveur Linux.

Pour cela, c'est simple il suffit de rajouter la ligne suivante en haut de votre fichier php:

#!/path/to/php

Notez que !/path/to/php est le répertoire dans lequel est installé php sur votre machine linux.

Pour trouver ce path, utilisez la commande:

which php

Ce qui retournera quelque chose comme çà:

/usr/bin/php

Votre fichier php ressemblera alors à:

#!/usr/bin/php

Il suffit de rendre votre script exécutable via la commande:

chmod +x hello.php

Puis d'exécuter votre script en tapant:

./hello.php