Utilisation sans tête du Raspberry Pi
par Benoit, 2014-09-26

Cet article présente quelques manipulations importantes pour utiliser un micro-ordinateur Raspberry Pi sans tête, c’est-à-dire sans y connecter de moniteur, de clavier ou de souris. En outre, j’explique comment accéder au Raspberry Pi depuis un réseau local lorsqu’il y accède lui-même par l’intercession du Partage Internet d’un ordinateur sous Mac OS X.

Raspberry Pi? Sans tête?

Le Raspberry Pi est un mignon micro-ordinateur basé sur la plate-forme ARM. Il n’a besoin d’énergie que ce que donne un port USB et roule un système d’exploitation chargé à partir d’une carte SD (typiquement une variante GNU/Linux). C’est une bébelle idéale pour expérimenter tant avec des idées de haut niveau, comme un serveur d’application web maison, qu’avec des trucs de bas niveau, comme attaquer des vulnérabilités de gestion de pile ou de tas.

Incidemment, je dois donner un workshop sur le sujet des exploits de pile et de tas sur la plate-forme ARM à l’Université du Nouveau-Brunswick la semaine prochaine. Je veux faire de ce workshop un tutoriel interactif, aussi désirai-je utiliser mon Raspberry Pi comme hôte des programmes ciblés par de tels exploits. Cependant, deux obstacles se dressaient devant ce dessein:

  1. Je n’ai pas de périphériques adéquats pour contrôler le Pi directement. Je veux donc l’utiliser à travers une connexion réseau, présumément par un accès SSH.
  2. Le Pi ne comporte pas d’antenne pour accéder à un réseau sans fil 802.11; son accès réseau est un unique port Ethernet. Bien qu’on puisse y adjoindre une interface 802.11 par un port USB, je désirais minimiser les accessoires. Je désire donc accéder au Pi par une connexion Ethernet directe avec mon portable (MacBook Pro). D’une part, le Pi gagne accès à l’Internet à l’aide du Partage Internet offert par Mac OS X. D’autre part, je veux que les pairs sur le même réseau local que moi puissent aussi accéder au Pi, via mon portable.

Le reste de l’article présente les approches simples que j’ai mises en oeuvre pour franchir ces obstacles.

Préparation du système d’exploitation du Raspberry Pi

J’ai suivi les étapes de ce tutoriel de Tristan Collins pour installer le système d’exploitation Raspbian, un port de Debian Linux au Raspberry Pi. En bref, une fois qu’on a téléchargé l’image disque de Raspbian, on doit la décompresser et la transmettre à la carte SD.

Pour ma part, j’ai d’abord eu quelques problèmes avec ma carte SD. Mes tentatives d’utiliser la commande dd indiquée ci-dessous ne réussissaient pas: le message d’erreur suggérait que la carte était en lecture seule. Je crois que des grains de poussière se sont déposés près du commutateur de verrouillage de la carte.

Commutateur de verrouillage de carte SD

Commutateur de verrouillage de la carte SD.

En faisant bouger le petit levier gris et en soufflant dans la petite cavité où le commutateur glisse, je pense avoir été en mesure de libérer la poussière qui faisait croire au lecteur que la carte était verrouillée. Après ces manipulations, j’ai pu procéder à la transmission de l’image disque.

Les instructions qui suivent valent pour un ordinateur sous Mac OS X; sur GNU/Linux, la commande dd est disponible, mais le device correspondant à la carte SD doit être identifié d’une autre manière. Sur un Mac, on déterminer d’abord le device correspondant à la carte SD, à l’aide de la commande diskutil.

$ diskutil list
...
/dev/disk7
#:                       TYPE NAME                    SIZE       IDENTIFIER
0:     FDisk_partition_scheme                       *31.9 GB     disk7
1:                      FAT32 NO NAME                31.9 TB     disk7s1

Dans mon cas, la carte SD a pour device /dev/disk7. Sachant cela, je démonte les partitions que OS X avait cru bon monter lorsque j’ai inséré la carte dans le lecteur.

$ diskutil unmountDisk disk7

Unmount of all volumes on disk7 was successful

Finalement, je décompresse et je transmets l’image Raspbian que j’ai téléchargée. La dernière opération (commande dd) s’exécute en quelque 25 minutes: excellent moment pour aller préparer une bonne tasse de chaud.

$ cd Downloads
$ unzip 2014-09-09-wheezy-raspbian.zip
$ sudo dd bs=1m if=2014-09-09-wheezy-raspbian.img of=/dev/disk7
3125+0 records in
3125+0 records out
3276800000 bytes transferred in 1584.555457 secs (2067962 bytes/sec)

On insère ensuite la carte dans la fente appropriée du Raspberry Pi et on branche le micro-ordinateur à un port USB. En principe, tout va bien: le voyant rouge PWR s’allume et le voyant ACT clignote au rythme des entrées/sorties à la carte SD. Si on ne voit pas ce clignotement, c’est vraisemblablement à cause d’une panique de noyau, entraînant l’arrêt des calculs. Vérifiez que votre carte SD fonctionne bien, et répétez les instructions ci-haut au besoin.

Partage Internet

On branche maintenant le Pi au MacBook, qui lui partagera sa connexion Internet sans fil via son interface Ethernet. Il faut vraiment faire cette étape en premier, alors je le répète:

Branchez d’abord le Raspberry Pi et le MacBook Pro avec le câble Ethernet.

Si on démarre d’abord le Partage Internet et que les câbles ne sont pas branchés, il m’est arrivé que le serveur DHCP du MacBook Pro ne démarre pas, de sorte que le pauvre Pi, une fois branché, ne recevra jamais d’adresse IP, malgré ses incessantes supplications.

On démarre ensuite le Partage Internet, à partir de l’onglet Partage des Réglages du MacBook Pro:

OS X: Partage Internet

Réglages de Partage Internet, sur Mavericks (OS X 10.9).

Avant de cliquer sur la case démarrant le partage, on s’assure que la source du partage est la connexion sans fil et que l’interface Ethernet est choisie parmi les destinations du partage.

Découverte de l’adresse du Raspberry Pi

Le partage Internet implanté sur Mac OS X n’est pas conçu pour donner une adresse à un appareil sans tête. Par conséquent, le serveur DHCP qu’il démarre ne peut être ni configuré, ni interrogé. J’ai découvert deux méthodes pour découvrir l’adresse du Pi branché au Mac. Dans les deux cas, il faut d’abord établir quel numéro de réseau le Partage Internet retient. On y parvient en examinant l’ensemble des interfaces réseau sur le Mac, via la commande ifconfig:

$ ifconfig
...
bridge100: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        options=3<RXCSUM,TXCSUM>
        ether ca:2a:14:51:e5:64
        inet 192.168.2.1 netmask 0xffffff00 broadcast 192.168.2.255
        Configuration:
                id 0:0:0:0:0:0 priority 0 hellotime 0 fwddelay 0
                maxage 0 holdcnt 0 proto stp maxaddr 100 timeout 1200
                root id 0:0:0:0:0:0 priority 0 ifcost 0 port 0
                ipfilter disabled flags 0x2
        member: en0 flags=3<LEARNING,DISCOVER>
                ifmaxaddr 0 port 4 priority 0 path cost 0
        media: autoselect
        status: active

Le partage Internet a donc lieu via l’interface Ethernet sur le réseau 192.168.2/24. On sait d’ailleurs que la distribution Raspbian comporte un usage nommé pi, dont le mot de passe est raspberry. Ainsi, la première approche à laquelle j’ai pensé a été la force brute: essayer les adresses sur le réseau 192.168.2/24 une après l’autre (en omettant 192.168.2.1, réservée au MacBook Pro). Lorsqu’une tentative de connexion prend plus de quelques secondes, je l’abandonne et j’essaie l’adresse suivante.

$ ssh pi@192.168.2.2
^C
$ ssh pi@192.168.2.3
^C
$ ssh pi@192.168.2.4
The authenticity of host '192.168.2.4 (192.168.2.4)' can't be established.
RSA key fingerprint is d0:d8:f4:d0:2e:1b:a9:3e:e2:97:6a:42:5e:a8:7b:b0.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.2.4' (RSA) to the list of known hosts.
pi@192.168.2.4's password:
Linux raspberrypi 3.12.28+ #709 PREEMPT Mon Sep 8 15:28:00 BST 2014 armv6l

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.

NOTICE: the software on this Raspberry Pi has not been fully configured.
Please run 'sudo raspi-config'

pi@raspberrypi ~ $

Naturellement, cette approche prendrait un temps fou si le serveur DHCP du MacBook Pro ne donnait pas une adresse proche de 192.168.2.1 au Raspberry Pi. Une approche plus élégante pour découvrir les hôtes sur un certain réseau est d’utiliser nmap. Cet outil n’est pas installé par défaut sur Mavericks: on le télécharge d’ici. nmap est un balayeur réseau: il peut découvrir les hôtes appartenant à un réseau ou les ports ouverts sur ces hôtes. Dans le cas présent, on cherche seulement les hôtes valides, donc on peut éviter le coûteux balayage des ports:

$ nmap -sn 192.168.2.*

Starting Nmap 6.47 ( http://nmap.org ) at 2014-09-26 20:55 EDT
Nmap scan report for 192.168.2.1
Host is up (0.00081s latency).
Nmap scan report for 192.168.2.4
Host is up (0.0016s latency).
Nmap done: 256 IP addresses (2 hosts up) scanned in 19.59 seconds

Comme il ne peut y avoir que deux adresses sur ce réseau et qu’on sait que 192.168.2.1 correspond au MacBook Pro, on bien découvert le Raspberry Pi.

Accès au Raspberry Pi depuis le réseau local

Ceci résout le premier obstacle mentionné ci-haut. Cependant, réseauter le Raspberry Pi à travers le Mac par une adresse non routable le rend inaccessible depuis le reste du réseau local auquel le MacBook Pro participe (le réseau sans fil).

L’approche la plus simple que j’ai trouvée pour permettre cet accès implique d’utiliser le serveur SSH du MacBook Pro comme proxy SOCKS, via sa fonctionnalité de redirection de ports dynamique. Un serveur SOCKS articule une sorte de réseau virtuel privé au niveau application: un client de ce proxy peut initier des échanges IP qui émanent du serveur, lequel redirige les réponses à ces échanges au client. Ces transactions sur le protocole IP sont résolues par le serveur: ainsi, bien que l’adresse 192.168.2.4 soit généralement non routable, le MacBook Pro qui réalise le partage Internet sait comment la router. En passant par ce MacBook Pro comme proxy SOCKS, on permet donc l’accès au Raspberry Pi à tous les clients SOCKS.

Serveur

Pour réaliser cette approche, il faut démarrer le serveur SSH du MacBook Pro. Cela est implicite à l’activation des Sessions à distance, qu’on réalise depuis l’onglet Partage de l’application de Réglages. Cela fait, on démarre un serveur SOCKS qui sera accessible pour tout participant au réseau local:

$ ssh -D *:1080 -fN localhost

Le paramètre *:1080 qui suit l’option -D indique que le serveur SOCKS est accessible depuis toutes les interfaces réseau du Mac, sur le port 1080 (défaut pour les serveurs SOCKS). Les options -fN font en sorte que la connexion SSH ne démarre pas de shell ni de commande client, et démarre en arrière-plan, libérant le terminal. On pourra interrompre le serveur SOCKS en éliminant le client SSH par la commande kill.

Client

De manière générale, seules les applications gérant explicitement la connexion à un proxy SOCKS (comme un navigateur Internet) peuvent bénéficier de l’accès prolongé par un tel serveur. Heureusement, j’ai découvert l’utilitaire GNU/Linux tsocks, qui utilise de la magie noire de librairies dynamiques pour emballer toutes les fonctions de programmation IP (socket, connect, etc.) dans un tunnel SOCKS. Sur Ubuntu/Debian, on installe ce programme à l’aide de apt-get:

$ sudo apt-get install tsocks

On doit ensuite configurer les serveurs SOCKS que tsocks peut utiliser pour accéder à telle ou telle adresse. Les échanges IP impliquant seulement certains intervalles d’adresses seront ainsi relayés au serveur SOCKS. Voici le contenu de /etc/tsocks.conf pour une machine virtuelle connectée au même réseau local que le MacBook Pro (192.168.1/24), à partir de laquelle je veux accéder au Raspberry Pi:

# Réseaux "locaux", accédés sans relai à un proxy SOCKS.
local = 192.168.1.0/255.255.255.0
# Accès à 192.168.2/24
path {
  reaches = 192.168.2.0/255.255.255.0
  server = 192.168.1.154   # Adresse du MacBook Pro.
  server_port = 1080
  server_type = 5
}
# Serveur par défaut.
server = 192.168.1.154
server_type = 5
server_port = 1080 

Sur cette machine virtuelle, j’accède au Pi par la commande

$ tsocks ssh pi@192.168.2.4
pi@192.168.2.4's password:

Cette approche ajoute un peu de complexité au niveau des clients, mais l’alternative que je perçois est de mettre en oeuvre un réseau virtuel privé. Ce déploiement d’un proxy SOCKS est trop simple pour que je m’en passe.

Commentaires