Comme vous ne l'ignorez peut-être pas, X11 est une technologie client/serveur. C'est à
dire que lorsqu'une application est lancée, elle n'écrit jamais directement sur le
périphérique graphique mais se connecte, par l'intermédiaire d'un kit graphique (Qt, GTK,
etc) à un serveur d'affichage, le fameux Xorg exploitant le protocole X11.
Ainsi, à chaque fois qu'une application X11 veut afficher un rectangle, ou une image,
c'est à ce serveur que cette demande est transmise et c'est lui qui effectue le rendu
visuel. Dans l'autre sens, le serveur recueille les entrées telles la souris ou le clavier
pour retransmettre cela à l'application.
Alors évidemment lorsque le client et le serveur sont sur une même machine, tout ceci ne
va pas sans une certaine perte de performance. Cependant les impacts sur la vitesse sont limités à plusieurs étages comme par l'utilisation de sockets rapides (sockets UNIX) au lieu des classiques sockets sur IP, ou encore par un accès direct au GPU dans des cas critiques comme la 3D ou la vidéo.
Maintenant cette toute relative perte de performance ne doit pas faire oublier les immenses avantages de cette solution : la transparence réseau. En effet déporter l'affichage d'une application sur une machine distante, exécuter sur son écran local une application qui se trouve sur un serveur distant, tout cela et bien d'autres choses encore sont rendues possibles grâce au X11.
Pour la petite histoire il faut bien comprendre que cette transparence réseau n'est pas un
coquetterie d'Unixien. En effet, à son origine, une architecture UNIX classique se
composait d'un ou plusieurs serveur "puissant" et d'une myriade de petits terminaux graphiques causant couramment le X11 "en dur", le tout sur un LAN 1Mb/s.
Aujourd'hui la transparence réseau offerte par X11 n'est même pas soupçonnée la majorité
des utilisateurs de Linux qui ne travaillent que sur une et une seule machine. Mais X11
permet de couvrir un vaste ensemble de cas d'usage allant du pratique à l'indispensable.
- ouvrir une session graphique complète sur une machine distante. Tout ce qui sera
exécuté tournera sur la machine distante et s'affichera via le serveur X11 de la machine
locale.
- ouvrir juste une application graphique, généralement via SSH, sur la machine distante.
Dans tous les cas le principe sera le même, une application est lancée à distance et se
connecte à votre serveur X11 local. Voyons cela de plus près.
L'option "native"
Comme nous l'avons vu, un serveur X11 utilise les sockets pour communiquer avec le client. Et pour que cette communication soit la plus rapide possible, il en utilise deux types : des sockets "lents" TCP/IP, et des sockets "rapides" UNIX. Dans le cas d'un serveur local parlant à une application locale, le socket utilisé est systématiquement de type UNIX.
Pour des raisons de sécurité, il y a de forte chance que votre serveur X soit paramétré de sorte à ne pas utiliser les sockets TCP/IP, et donc de ne pas permettre son utilisation par une machine distante. Nous allons donc changer cela en ayant conscience que cette manipulation n'est sure que sur un réseau local de confiance et protégé du réseau public.
Le lancement de votre serveur X11 est effectué par l'intermédiaire d'un gestionnaire de session, par exemple GDM pour Gnome. Pour autoriser les clients distant à utiliser ce serveur X11 via TCP, il faut donc lancer en tant que root l'outil gdmsetup, aller dans l'onglet sécurité, et décocher la ligne Refuser les connexions TCP au serveur X. Ceci fait vous pouvez fermer gdmsetup et relancer votre serveur X. Au retour, le port 6000 correspondant à l'écran X11 :0.0 (si c'est :1.0 le port sera 6001, et ainsi de suite) devrait être écouté par le serveur :
rootnetstat -anlp | grep X | grep -v STREAM
tcp 0 0 0.0.0.0:6000 0.0.0.0:* LISTEN 5667/X
vérification du serveur X11 en écoute
Ceci fait, nous allons pouvoir nous connecter sur la machine distante, par exemple avec SSH, et y lancer une commande graphique, par exemple evolution :
gastonssh machine_distante
gaston@machine_distante>DISPLAY=mon_desktop:0.0 evolution
Utilisation de la transparence native de X11
C'est aussi simple que cela. Tout passe par l'utilisation de la variable DISPLAY qui indique à l'application où se trouve le serveur X11 à utiliser. En local, votre variable DISPLAY est sûrement :0.0. Le fait qu'il n'y ait rien devant le : indique au client que le serveur est local. Dans notre exemple il va donc aller sur la machine mon_desktop. 0.0 indique d'utiliser l'écran .0 de la carte 0.
Si tout a fonctionné, c'est nickel. Il est possible que votre serveur soit configuré pour refuser les connexions externes et vous aurez alors obtenez l'erreur suivante :
gastonssh machine_distante
gaston@machine_distante>DISPLAY=mon_desktop:0.0 evolution
No protocol specified
Impossible d'ouvrir l'affichage :
Exécuter « evolution --help » pour obtenir la liste complète des options en ligne de commande.
Erreur d'autorisation
Ce qui compte ici c'est le No protocol specified qui dit, à qui sait le comprendre, que vous devez d'abord autoriser les connexions et lançant sur la machine secondaire la commande suivante :
gastonxhost +
access control disabled, clients can connect from any host
gastonssh machine_distante
gaston@machine_distante>DISPLAY=mon_desktop:0.0 evolution&
Autorisation de tous les accès à la machine secondaire
Et là, ça marche... Ceci étant, dans la mesure où nous passons par SSH pour aller sur la
machine distante, il existe une méthode plus simple consistant fournie par SSH lui-même.
L'option SSH
SSH permet la redirection de ports), et plus particulièrement
est capable de rediriger le socket UNIX d'un serveur distant sur un socket TCP/IP local.
Cette caractéristique nous permet en toute simplicité de faire la même chose que
précédemment, mais à travers une connexion chiffrée convenant mieux à un réseau LAN moins
sécurisé et ce, sans aucun changement des paramétrage de sécurité.
Ainsi, utilisé avec l'option -X (certaines configuration font cela par défaut), ssh va ainsi automatiquement changer la variable DISPLAY pour pointer sur son "faux" serveur X11 local :
gastonssh -X machine_distante
gaston@machine_distante>echo $DISPLAY
localhost:11.0
gaston@machine_distante>evolution&
lancement d'évolution à travers SSH
Là, plus besoin d'autorisation via xhost ni d'écoutes de port TCP/IP, tout se fait
automatiquement par la grâce de SSH. Maintenant cette méthode n'est pas sans défaut. En
effet, si la machine distante est un peu légère, le chiffrement temps réel de toutes les
données circulant dans le tuyau SSH vont un peu pénaliser les performances. Mais sur un
LAN moderne cela reste acceptable.
Concernant un réseau distant, par exemple à travers internet, c'est le volume de données
échangé qui va pénaliser les performances. Il est donc plus sage dans ce cas d'opter sur
une version compressée du protocole X11, comme
nomachine/freeNX.
Un bureau distant complet
Pour vous donner un cas d'usage, mon bureau est relié à mon logement par une série de 3
switch Gigabit. Chez moi j'ai un petit portable très léger. Au bureau se trouve la grosse
machine de développement. Pour travailler soir et week-end (oui, je sais ;-), je me
connecte en mode session sur ma machine de bureau et tout ce que je lance est ainsi routé
vers mon portable. A savoir en général firefox, chrome, une dizaine de GVIM, thunderbird,
pidgin, skype, etc... Tout ce joli monde tourne donc dans mon bureau et communique avec le
serveur X11 de mon portable en mode bi-écran... Et bien croyez moi, je ne vois strictement
aucune différence entre cet usage, et le fait de bosser directement dans mon bureau.
J'arrive même à lancer une vidéo sans soucis... Voyons donc comme faire pour lancer ainsi
une session entière à distance.
Pour d'évidentes raisons de performances, ajouté du fait que je travaille sur un LAN
sécurisé, l'approche SSH n'apporte ici que peu d'avantage. Autant donc attaquer nativement
le serveur X11 de sorte à bénéficier des meilleurs performances.
Dans mon cas le gestionaire de fenêtre est l'excellent
awesome. Le principe va donc être de créer un fichier
xinitrc-distant qui va lancer à distance le gestionnaire de fenêtre.
xhost +
ssh ma-machine "DISPLAY=mon-portable:0.0 awesome"
Pour ceux qui ne sont pas à l'aise avec xinitrc, allez jeter oeil à cet article
là. Pour les autres, il ne reste plus qu'à lancer
la session dans la console linux :
xinit xinitrc-distant
Et hop, je suis sur ma machine distante, dans mon gestionnaire de fenêtres préféré et je
peux dés lors lancer les applications que je veux. Voyons maintenant un peu ce que nous
avons fait.
Le contenu de xinitrc-distant ne devrais plus vous surprendre outre mesure. On y
retrouve déjà le xhost + pour autoriser les accès distants au serveur X11 local.
Attention, comme indiqué au premier chapitre, il est nécessaire pour que tout ceci
fonctionne que fous ayez activé le mode TCP/IP sur votre serveur X11 !!
Ensuite il s'agit de se connecter via SSH sur la machine distante pour lancer awesome. Le
DISPLAY injecté en variable va quant à lui indiquer à awesome d'aller parler au
serveur X11 de mon portable, et le tour est joué.
La syntaxe de lancement de X11 est en revanche un peu nouvelle, mais pas tant que cela en
réalité. En effet, lorsque vous tapez startx dans la console Linux, c'est comme si vous
aviez tapé xinit ~/.xinitrc. C'est commande xinit qui va concrètement lancer le
serveur X11 et qui va ensuite exécuter le script xinitrc. Ici nous indiquons donc juste
un script alternatif à xinit.
Et le son alors ??
Tout ceci est en effet bien sympa. Nous avons pour nos applications un affichage local, un
clavier local, une souris locale, mais quid du son ? Et c'est là que PulseAudio va enfin
servir à quelque chose. En effet, comme X11, PulseAudio bénéficie d'une transparence
réseau qui par défaut est limité à un socket UNIX. Comme pour X11 nous allons donc
commencer par activer le mode TCP/IP allant modifier le fichier /etc/pulse/default.pa.
En cherchant dedans vous devez trouvez une ligne normalement commentée
load-module module-native-protocol-tcp. Décommentez la ligne, sauvez le fichier et
redémarrez la machine. Ceci fait, PulseAudio devrait être en écoute du port 4713 de la
machin locale.
Nous devons maintenant modifier notre fichier xinitrc-distant pour
injecter dans l'environnement d'awesome la référence au serveur PulseAudio :
xhost +
ssh ma-machine "DISPLAY=mon-portable:0.0 PULSE_SERVER=mon-portable:4713 awesome"
Ceci fait, il ne reste plus qu'à relancer xinit ~/xinit-distant pour avoir maintenant
accès à l'audio tant pour les entrées que les sorties. Cela fonctionne tellement bien que
j'utilise régulièrement skype de cette manière.
Conclusion
Comme à l'accoutumée, les outils SSH et X11 démontre leur plasticité et leur capacité à
s'adapter à toutes les situations tordues auxquelles vous voudrez les plier. Happy
Networking :)