nlc Le mieux est l'ennemi du bien | Bonsoir à tous ! J'ai un petit casse tête à résoudre pour les pros ou les passionnés réseaux ! Pour ceux que ça intéresse prenez le temps de bien comprendre ce que j'explique, c'est assez technique ! J'ai déjà parlé de ça à quelques "admin" réseau, et ils n'ont pas bien compris ma requête et m'ont même pris pour un fou. Bon faut avouer que c'est pas évident à comprendre, mais je vais essayer d'être le plus clair possible, attention suivez bien c'est parti :
Je développe des systèmes électroniques embarqués communicants, qui fonctionnent sous linux embarqué. Ces systèmes sont installés sur le réseau local de mes clients, ou "des clients de mes clients".
Ces systèmes électroniques embarquent entre autres un serveur web, ainsi qu'un serveur ssh. Le serveur web c'est pour que le client puisse accéder à l'interface de configuration/supervision de l'appareil, et le serveur ssh c'est uniquement pour moi, pour me logguer depuis mon bureau sur les systèmes afin d'en effectuer la maintenance.
La contrainte principale qui implique la complexité qui va suivre, c'est donc que :
1) Le client doit pouvoir accéder à l'interface web du système depuis son réseau local.
2) Le client doit également pouvoir accéder à l'interface web du système depuis l'extérieur de son réseau, depuis Internet en fait (quand il est en déplacement par exemple).
3) Je dois pouvoir me logguer en SSH sur le système depuis l'extérieur de son réseau, donc depuis Internet (à partir de mon bureau par exemple).
Tout cela est normalement très simple :
- Pour le point 1, il suffit de configurer le serveur dhcp du réseau pour qu'il attribue toujours la même IP au système en fonction de son adresse mac. Il accède alors à l'interface web du système avec son navigateur en l'ouvrant directement sur l'ip, par exemple http://192.168.1.123. On peut également configurer le système électronique pour qu'il ait directement une IP fixe.
- Pour les points 2 et 3, ce n'est guère plus compliqué, il suffit de créer des règles de redirection NAT sur le routeur/modem qui gère l'accès internet du client. Ensuite soit l'IP publique du client est fixe et on accède à l'interface par exemple par http://ip.pu.bli.que:1234, ou l'IP publique n'est pas fixe et il suffit de mettre en place un système de dyndns dans mon système embarqué.
Seulement voilà, tout cela ne fonctionne très bien et n'est envisageable QUE si l'utilisateur du système électronique a les moyens de configurer le réseau de son entreprise à sa guise ! Et en fait, dans 99% des cas, ce n'est pas possible car :
- Personne ne s'y connaît en réseau et les explications que je donne ou qui sont décrites dans la notice c'est du chinois, du coup ça leur parait super compliqué et ne veulent pas aller plus loin
- Mon interlocuteur n'y connaît rien en réseau et fait passer les demandes de configuration réseau à l'administrateur réseau, qui a les compétences pour faire la configuration, mais ne veut pas les faire, soit par ce que ça le fait chier ou qu'il veut montrer que c'est lui le chef, soit parce qu'il est persuadé qu'ouvrir des ports depuis l'extérieur c'est horriblement dangereux car ça ouvre des failles de sécurités.
- Soit l'admin réseau n'est pas super compétent, veut bien jouer le jeu mais ne comprend pas trop ce qu'il fait ou ce que je lui demande, et là je passe des heures à essayer d'expliquer au téléphone. Du coup du côté des clients, on pense que le système que je fournis est une usine à gaz et que c'est beaucoup trop compliqué à utiliser.
- Soit la gestion réseau est sous traitée à une entreprise extérieure, et là je crois que c'est pire que tout, en général j'abandonne de suite....
Donc j'ai beaucoup réfléchi au problème, et j'ai trouvé une solution élégante, qui "fonctionnellement" est compliquée mais qui fait qu'au niveau de l'utilisation c'est totalement plug and play et transparent pour le client.
En fait, le souci principal c'est pour rentrer sur le réseau du client depuis l'extérieur. Par contre dans l'autre sens, sortir du réseau du client pour aller sur Internet c'est beaucoup plus facile !
Du coup je procède de la sorte, attention c'est là que ça se complique un peu Mes systèmes électroniques, à chaque mise sous tension et à chaque fois que le lien est rompu, ouvrent une connexion sortante vers un de mes serveurs quelque part sur internet, qui possède une IP fixe et un nom de domaine. Ce lien, ou cette "socket" si vous préférez, est donc continuellement ouvert et joue le rôle de "tunnel". D'ailleurs, la carte et le serveur s'échangent des petites données de temps en temps pour vérifier leur présence respective et garder le tunnel ouvert (car sinon au bout d'un certain temps d'inactivité, les routeurs et passerelles NAT coupent la socket pour libérer de la place dans la table de routage).
Ensuite, quand je veux atteindre un de mes systèmes électroniques, je passe par mon serveur, qui fait office de passerelle/point d'entrée, et redirige mes requêtes dans le bon tunnel, vers le système électronique qui se trouve à l'autre bout, chez le client.
Du coup pour le client c'est du vrai plug and play : il branche le système sur son réseau, dans 99% du temps il y a un serveur DHCP actif, du coup le système chope une IP, l'adresse de la passerelle, et peut se connecter sur internet et ouvrir son tunnel vers mon serveur. En fait, vous l'aurez compris, j'en ouvre 2, un tunnel pour le serveur HTTP (interface web de configuration/supervision), et un tunnel pour le serveur ssh (prise de main à distance pour la maintenance).
Pour ceux qui n'ont pas abandonné la lecture, je continue :
Pour mettre en place ce système de tunnel, en fait je n'ai rien fait de particulier, j'exploite juste des options pas forcément très connus de ssh, qui permettent de faire des redirections de ports distantes :
- J'ai mon serveur sur Internet avec IP fixe + nom de domaine sur lequel tourne un serveur ssh
- Le système électronique chez le client ouvre une première connexion sortante ssh avec le serveur, et demande au serveur de rediriger le port distant XXXXX vers le port local 80 (interface web). Et en parallèle le système ouvre une 2eme connexion sortante ssh vers le serveur, en lui demandant de rediriger le port distant YYYYY vers le port local 22 (prise de main à distance).
Du coup, pour accéder à l'interface web du système (depuis l'extérieur du réseau client mais même depuis l'intérieur), il suffit de saisir dans son navigateur http://mon_serveur.com:XXXXX
La requête http est alors faite sur le port XXXX de mon serveur, qui redirige alors les paquets vers le port 80 de mon système électronique en passant par le tunnel SSH ! Génial non !? Et moi pour prendre la main à distance en ssh sur mon système électronique, il me suffit d'ouvrir ma connexion ssh vers le port qui va bien sur le serveur, en faisant : ssh -p YYYYY root@mon_serveur_com
Même principe que ci dessus, le serveur va alors rediriger tous les paquets vers le port 22 de mon système électronique en passant par le tunnel SSH existant entre le système électronique et le serveur. C'est terriblement efficace.
Vous l'aurez compris, chaque système électronique que je fournis utilise des numéros de ports différents, ce qui permet d'accéder à tous mes systèmes en me connectant uniquement sur mon serveur mais en spécifiant le port en fonction du système que je veux joindre, par exemple :
ssh -p 12345 root@mon_serveur_com
ssh -p 12346 root@mon_serveur_com
ssh -p 12347 root@mon_serveur_com
ssh -p 12348 root@mon_serveur_com
etc...
Et pour le client, c'est tout pareil, il peut accéder à son ou ses systèmes en boormarquant simplement les url correspondantes (et permanentes) à chacun des systèmes :
http://mon_serveur_com:23456
http://mon_serveur_com:23457
http://mon_serveur_com:23458
http://mon_serveur_com:23459
etc...
Avec ce système je frise la perfection, je n'ai quasiment plus de souci, vu que du côté du client, en principe il n'a qu'à brancher le système sur son réseau, et il n'a même pas besoin de connaître l'IP qui a été attribuée au système, c'est moi qui lui donne directement le lien permanent permettant d'accéder au système (http://mon_serveur.com:XXXXX).
Mais ça ne fait que friser la perfection, j'ai encore des petits soucis malheureusement Et oui, il arrive (de plus en plus fréquemment malheureusement) que sur certain réseaux l'admin ait verrouillé tous les ports en sortie, en ne laissant ouverts que les ports strictement nécessaires : http, https, pop3, etc...
Du coup, mon système utilisant le port 22 pour se connecter en ssh vers mon serveur pour ouvrir le tunnel et lancer la redirection de port distante, ne peut pas se connecter et ouvrir le tunnel si le port 22 est verrouillé en sortie ! Pour résoudre ce problème, j'ai trouvé une astuce qui consiste à ne plus utiliser le port 22, mais le port 80 ou 443 qui sont habituellement forcément ouverts en sortie.
Mais du coup, l'autre souci c'est que le client ne peut pas utiliser le lien direct et permanent vers son système (http://mon_serveur.com:XXXXX) depuis l'intérieur de son réseau, puisque le port XXXXX est bloqué en sortie !!!!
Du coup j'ai une idée pour résoudre ce problème, mais je ne sais pas si c'est faisable : il faudrait que le lien direct permanent vers les systèmes installés chez les clients ne soient plus sous la forme http://mon_serveur.com:XXXXX, mais sous la forme :
http://systeme1.mon_serveur.com
http://systeme2.mon_serveur.com
http://systeme3.mon_serveur.com
http://systeme4.mon_serveur.com
etc...
Du coup ça passerait par le port 80 et le client aurait accès à l'interface du système. Mais techniquement, ça implique que sur mon serveur j'ai plusieurs virtual host (un par système en fait), mais que le serveur web du serveur ne réponde pas lui même à la requête, mais ne fasse que la rediriger vers localhost:XXXXX, de manière à ce que la requête puisse alors partir vers le bon système en passant par le bon tunnel ssh.
Ou alors de faire un peu comme un proxy, le client accède à son système par l'adresse http://systeme1.mon_serveur.com, et sur mon serveur, dans le virtual host correspondant, je charge en réalité la page demandée mais sur l'adresse localhost:XXXXX, puis je recopie la réponse faite par le système à l'autre bout du tunnel vers le navigateur du client.
Est-ce que vous pensez qu'un système comme ça soit envisageable, et comment je pourrai mettre ça en place sur mon serveur ?
Si vous m'avez lu jusqu'au bout et que vous ne vous êtes pas endormi : merci, bonne nuit, et bon week end à tous Message édité par nlc le 02-08-2010 à 10:42:17 ---------------
char table[] = {112,114,105,110,116,102,40,34,37,99,37,99,37,99,34,44,49,49,48,44,49,48,56,44,57,57,41,59,0}; char* tablePtr = table; while(*tablePtr) printf( "%c",*tablePtr++ );
|