Systèmes d'exploitation — fondations · L2 · Section 8/12
Sockets et IPC réseau
Progression
#Communications entre processus par sockets
Prérequis
- Introduction aux réseaux: adresses IP, ports, TCP vs UDP.
- C: sockets et gestion d'erreurs basique (descripteur, -1, errno).
Objectifs d'apprentissage
- Écrire la chorégraphie serveur (socket, bind, listen, accept) et client (connect).
- Choisir TCP ou UDP, AF_INET ou AF_UNIX, selon le besoin.
- Passer à des sockets non bloquantes avec select pour servir plusieurs clients.
Les sockets offrent une API uniforme pour relier deux processus, que ce soit sur la même machine (sockets Unix, AF_UNIX) ou à travers un réseau (sockets IP, AF_INET). Un serveur installe un point d'écoute; un client s'y connecte; des octets transitent dans les deux sens.
#0. Ce que le cours met sous les sockets
Les sockets ne sont pas tombées du ciel: le cours d'Unix les présente comme la couche sur laquelle repose toute une famille de protocoles, et il en donne la genèse. telnet est un outil général de connexion à distance qui s'appuie sur TCP et IP, utilise son propre protocole, et sert de support à la plupart des protocoles de plus haut niveau. La liste du cours mérite d'être connue, car elle montre ce qui tourne au-dessus d'une simple connexion:
- FTP sur le port 21, Telnet sur le port 23, SMTP sur le port 25, DNS sur le port 53, HTTP sur le port 80, POP3 sur le port 110, NNTP sur le port 119, NTP sur le port 123, IRC sur le port 194.
Ce que ces protocoles ont en commun, c'est exactement ce que l'API socket fournit: un flux bidirectionnel entre deux processus identifiés par une adresse et un port, sur lequel on écrit et lit du texte. La commande telnet machine port est donc le meilleur débogueur de protocole qui existe: elle ouvre la socket à la main et laisse l'utilisateur taper les commandes du protocole une par une. Le cours en donne une trace complète pour SMTP, et le TP 4 fait précisément envoyer un courrier électronique à la main par ce moyen.
Le fossé entre sockets sécurisées et non sécurisées. Le cours insiste sur le fait que les connexions ordinaires entre machines ne sont pas cryptées et que « la transmission par diffusion permet d'intercepter des paquets assez facilement ». Il détaille même le mécanisme de sécurité d'un service distant: rlogin et rsh acceptent un fichier $HOME/.rhosts qui autorise la connexion sans mot de passe, si bien que « dès qu'on est parvenu à se connecter sur une des machines, on a accès à toutes les autres où un fichier .rhosts le permet pour cet utilisateur ». Cette solution n'est donc acceptable qu'à l'intérieur d'un réseau local.
SSH est la réponse à ce problème, et sa description par le cours est un excellent complément au chapitre: authentification du client par le serveur, cryptage de la transmission, garantie d'intégrité. Le mécanisme de clés publiques/privées s'établit en quatre temps — le serveur envoie sa clé publique en clair, le client génère une clé symétrique qu'il chiffre avec cette clé publique, il l'envoie, le serveur la déchiffre avec sa clé privée — et les deux extrémités partagent alors la même clé symétrique. C'est exactement le schéma qu'une bibliothèque TLS reproduit au-dessus d'une socket TCP.
Copie et montage. À ce niveau, le cours cite trois familles d'outils: rcp (copie distante à la mode rlogin, donc non sécurisée), scp (même forme d'appel, sécurité de SSH), et NFS pour le montage de volumes distants — l'ordinateur distant exporte le volume, le client le monte sur un répertoire local, la transmission se faisant en UDP. Samba joue le même rôle face à Windows en implémentant SMB/CIFS.
#1. Cycle serveur-client
Côté serveur, la chorégraphie suit toujours la même séquence: socket crée le point de terminaison, bind l'attache à une adresse et un port, listen déclare la file d'attente des connexions, puis une boucle accept récupère les connexions entrantes. Côté client, un simple connect suffit à établir le canal. Une fois la poignée de main terminée, les deux extrémités disposent d'un flux bidirectionnel que send/recv ou read/write peuvent manipuler. Les tampons noyau stockent temporairement les données; si le lecteur ne suit pas, l'écrivain est bloqué ou reçoit EWOULDBLOCK en mode non bloquant.
1int server = socket(AF_INET, SOCK_STREAM, 0);2if (server < 0) { perror("socket"); return 1; }3bind(server, (struct sockaddr *)&addr, sizeof addr);4listen(server, SOMAXCONN);5for (;;) {6 int client = accept(server, NULL, NULL);7 if (client < 0) { perror("accept"); continue; }8 handle(client);9 close(client);10}Ce squelette constitue la base d'innombrables serveurs, du démon SSH au proxy HTTP. Trois codes d'erreur à savoir lire sur bind: EADDRINUSE (le port est déjà pris; l'option SO_REUSEADDR permet de réattacher après un redémarrage rapide du serveur), EACCES (port inférieur à 1024 sans privilèges), EINVAL (adresse incohérente avec la famille).
#2. TCP, UDP, sockets Unix
TCP (SOCK_STREAM) offre un flux fiable et ordonné: un dialogue continu, parfait pour un protocole requête-réponse. UDP (SOCK_DGRAM) ne crée pas de connexion persistante. Chaque datagramme transporte sa propre adresse source; l'application doit gérer les pertes éventuelles. Le choix dépend de la tolérance à la perte et du besoin de latence minimale: interrogation DNS, flux temps réel.
À l'opposé, les sockets Unix (AF_UNIX) ne sortent pas de la machine locale: elles désignent leur homologue par un chemin de système de fichiers, transmettent même des descripteurs de fichiers (SCM_RIGHTS) et offrent de meilleures performances pour l'IPC interne. La comparaison mesurable le montre: sur une même machine, une socket Unix fait souvent jeu égal ou mieux qu'une boucle TCP sur localhost, et évite pile, ports et permissions réseau.
Les serveurs à grande échelle utilisent souvent des sockets non bloquantes combinées à select, poll, epoll ou kqueue pour surveiller plusieurs connexions sans monopoliser des threads: un seul thread descripteur par descripteur, réveillé quand un descripteur est prêt.
#3. Protocoles applicatifs
Construire une API par-dessus des sockets nécessite de définir un format de message (texte, binaire), un cadrage (longueur en tête, séparateur), un protocole d'erreur et, idéalement, une observabilité (journaux structurés, métriques). Sans ces éléments, le moindre problème réseau devient difficile à diagnostiquer: qui a écrit quoi, où était le curseur dans le flux quand la connexion s'est coupée? Les sockets TLS viennent ajouter une couche de chiffrement et d'authentification (identité du serveur, secret partagé après poignée de main), mais la logique applicative reste identique.
#Atelier: serveur d'heure, en trois paliers
Palier 1 (bloquant): implémentez un serveur TCP qui accepte un client, lui envoie l'heure courante (time, strftime) et ferme. Testez avec nc localhost 12345. Observation attendue: une ligne d'heure s'affiche côté nc, puis la connexion se ferme.
Palier 2 (serveur naïf): lancez deux clients simultanés contre ce serveur mono-client: le second attend que le premier ait fini. Correction: fork après accept (ou un thread), le parent referme le descripteur client et reboucle. Observation: les deux clients sont servis simultanément. Collectez bien les enfants (wait ou signal(SIGCHLD, SIG_IGN)) pour ne pas fabriquer de zombies, en écho au chapitre Processus.
Palier 3 (non bloquant): refaites le même service avec une socket en O_NONBLOCK et select sur l'ensemble des descripteurs ouverts. Observation: un seul processus, aucun fork, et les connexions simultanées progressent entrelacées. En variante, mesurez la latence d'une version AF_UNIX face à la version TCP: la même étude, sur la machine locale, donnera la hiérarchie présentée plus haut.
#Exercices
1. Citer quatre protocoles de haut niveau avec leur numéro de port. Sur quoi s'appuient-ils tous?
2. Quelle commande permet de dialoguer « à la main » avec un serveur SMTP, et pourquoi est-ce utile?
3. Quels sont les trois avantages de SSH sur rlogin et rsh? Comment le canal sécurisé s'établit-il?
4. Pourquoi le fichier $HOME/.rhosts est-il dangereux? Dans quel cadre seulement est-il acceptable?
5. Quelle commande copie un fichier sur une machine distante de façon sécurisée, et quelle commande permet de monter un volume distant?
6. Écrire la chorégraphie serveur d'une socket TCP, en nommant les quatre appels dans l'ordre.
Corrections détaillées
1. Par exemple: FTP sur le port 21, Telnet sur le 23, SMTP sur le 25, DNS sur le 53, HTTP sur le 80, POP3 sur le 110, NNTP sur le 119, NTP sur le 123, IRC sur le 194. Tous s'appuient sur TCP et IP, et la plupart sont accessibles par telnet, qui est l'outil général de connexion à distance servant de support aux protocoles de plus haut niveau.
2. telnet machine port, par exemple telnet echo.unice.fr 25. C'est utile parce que la commande ouvre la connexion et laisse l'utilisateur taper les commandes du protocole une par une: on voit les réponses du serveur, on comprend la grammaire du protocole, et on diagnostique une panne de service sans dépendre d'un client particulier. C'est aussi la démonstration la plus directe de l'absence d'authentification dans SMTP: l'expéditeur déclaré dans MAIL FROM n'est vérifié par personne.
3. SSH apporte l'authentification du client par le serveur, le cryptage de la transmission et la garantie d'intégrité de cette transmission — trois choses que rlogin et rsh n'offrent pas. L'établissement du canal se fait en quatre temps: le serveur envoie sa clé publique en clair au client; le client génère une clé de chiffrement symétrique et la chiffre avec cette clé publique; il envoie la clé symétrique chiffrée au serveur; le serveur la déchiffre avec sa clé privée. Les deux extrémités partagent alors la même clé symétrique, et la session peut être chiffrée.
4. Parce qu'il autorise la connexion sans mot de passe depuis les machines qui y sont listées. Le cours en tire la conséquence: « dès qu'on est parvenu à se connecter sur une des machines, on a accès à toutes les autres où un fichier .rhosts le permet pour cet utilisateur ». La propagation d'une seule compromission devient donc totale. Cette solution n'est acceptable qu'à l'intérieur d'un réseau local, et le cours note que le protocole est souvent refusé par les administrateurs pour des connexions à travers les réseaux.
5. scp effectue la copie sécurisée, en utilisant le protocole de SSH; sa forme d'appel est identique à celle de rcp, avec des références distantes de la forme [utilisateur]@machine:[chemin]. Le montage de volumes distants se fait par NFS: l'ordinateur distant exporte le volume, le client demande le montage sur un répertoire local, et la transmission se fait en UDP. Samba remplit le même rôle face à Windows, en implémentant SMB/CIFS.
6.
1int server = socket(AF_INET, SOCK_STREAM, 0);2bind(server, (struct sockaddr *)&addr, sizeof addr);3listen(server, SOMAXCONN);4for (;;) {5 int client = accept(server, NULL, NULL);6 handle(client);7 close(client);8}Les quatre appels sont, dans l'ordre: socket, qui crée le point de terminaison; bind, qui l'attache à une adresse et un port; listen, qui déclare la file d'attente des connexions; et accept, qui récupère une connexion entrante et rend un nouveau descripteur pour dialoguer avec ce client. Côté client, un simple connect suffit à établir le canal.