55 votes

Est-ce qu'il y a un serveur proxy inversé SSH basé sur le nom d'hôte?

J'ai beaucoup apprécié les reverse proxies HTTP dans notre environnement de développement et j'ai trouvé le reverse proxy de virtual host basé sur DNS très utile. Le fait de n'avoir qu'un seul port (et le standard) ouvert sur le pare-feu simplifie beaucoup la gestion.

J'aimerais trouver quelque chose de similaire pour les connexions SSH mais je n'ai pas eu beaucoup de chance. Je préférerais ne pas simplement utiliser le tunneling SSH car cela nécessite l'ouverture de plages de ports autres que le standard. Y a-t-il quelque chose qui peut faire cela ?

Est-ce que HAProxy pourrait faire cela ?

32voto

jammus Points 1796

Je ne crois pas que l'authentification SSH basée sur le nom soit possible étant donné le fonctionnement du protocole.

Voici quelques alternatives.

  • Vous pourriez configurer l'hôte qui répond pour le port 22 pour agir comme une passerelle. Ensuite, vous pouvez configurer le serveur SSH pour transmettre les demandes à l'intérieur en fonction de la clé. Exemple de passeerelle SSH avec des clés

  • Vous pourriez ajuster votre client pour utiliser cet hôte comme proxy. C'est-à-dire, il se connecterait en SSH sur l'hôte passerelle, puis utiliserait cet hôte pour se connecter à l'hôte interne. Configuration de proxy SSH du client ici.

  • Vous pourriez également configurer un simple proxy HTTP sur le bord. Ensuite, utilisez-le pour permettre des connexions entrantes. SSH via un proxy HTTP.

Évidemment, avec toutes les options ci-dessus, il est important de bien configurer et sécuriser la passerelle.

28voto

martin Points 49

J'ai cherché une solution à ce problème de manière intermittente au cours des 16 derniers mois. Mais à chaque fois que je regarde, il semble impossible de faire cela avec le protocole SSH tel que spécifié dans les RFC pertinents et mis en œuvre par les principales implémentations.

Cependant, si vous êtes prêt à utiliser un client SSH légèrement modifié et que vous êtes prêt à utiliser les protocoles d'une manière qui n'était pas exactement prévue lors de leur conception, alors c'est possible d'y parvenir. Plus de détails ci-dessous.

Pourquoi ce n'est pas possible

Le client n'envoie pas le nom d'hôte dans le cadre du protocole SSH.

Il pourrait envoyer le nom d'hôte dans le cadre d'une recherche DNS, mais cela pourrait être mis en cache, et le chemin du client à travers les résolveurs vers les serveurs d'autorité pourrait ne pas traverser le proxy, et même s'il le faisait, il n'y a aucun moyen robuste d'associer des recherches DNS spécifiques à des clients SSH spécifiques.

Il n'y a rien de spécial que vous puissiez faire avec le protocole SSH lui-même non plus. Vous devez choisir un serveur sans même avoir vu la bannière de version SSH du client. Vous devez envoyer une bannière au client avant qu'il n'envoie quoi que ce soit au proxy. Les bannières des serveurs pourraient être différentes, et vous n'avez aucune chance de deviner laquelle est la bonne à utiliser.

Même si cette bannière est envoyée de manière non cryptée, vous ne pouvez pas la modifier. Chaque bit de cette bannière sera vérifié lors de l'établissement de la connexion, donc vous provoqueriez un échec de connexion un peu plus loin.

La conclusion pour moi est assez claire, il faut changer quelque chose du côté client pour que cette connectivité fonctionne.

La plupart des solutions de contournement consistent à encapsuler le trafic SSH dans un autre protocole. On pourrait également envisager une extension du protocole SSH lui-même, dans laquelle la bannière de version envoyée par le client inclut le nom d'hôte. Cela peut rester compatible avec les serveurs existants, puisqu'une partie de la bannière est actuellement spécifiée comme un champ d'identification en forme libre, et bien que les clients attendent généralement la bannière de version du serveur avant d'envoyer la leur, le protocole permet au client d'envoyer sa bannière en premier. Certaines versions récentes du client SSH (par exemple celui sur Ubuntu 14.04) envoient la bannière sans attendre la bannière du serveur.

Je ne connais aucun client qui a pris des mesures pour inclure le nom d'hôte du serveur dans cette bannière. J'ai envoyé un correctif à la liste de diffusion OpenSSH pour ajouter une telle fonctionnalité. Mais il a été rejeté en raison du désir de ne pas révéler le nom d'hôte à quiconque espionne le trafic SSH. Étant donné qu'un nom d'hôte secret est fondamentalement incompatible avec le fonctionnement d'un proxy basé sur le nom, ne vous attendez pas à voir une extension SNI officielle pour le protocole SSH de sitôt.

Une vraie solution

La solution qui a le mieux fonctionné pour moi a en fait été d'utiliser IPv6.

Avec IPv6, je peux attribuer une adresse IP séparée à chaque serveur, de sorte que la passerelle puisse utiliser l'adresse IP de destination pour savoir vers quel serveur envoyer le paquet. Il arrive parfois que les clients SSH fonctionnent sur des réseaux où le seul moyen d'obtenir une adresse IPv6 serait d'utiliser Teredo. Teredo est connu pour être peu fiable, mais seulement lorsque l'extrémité IPv6 native de la connexion utilise un relais Teredo public. On peut simplement mettre un relais Teredo sur la passerelle, où vous exécuteriez le proxy. Miredo peut être installé et configuré comme relais en moins de cinq minutes.

Un contournement

Vous pouvez utiliser un saut hôte/hôte bastion. Cette approche est destinée aux cas où vous ne souhaitez pas exposer le port SSH des serveurs individuels directement à l'internet public. Cela a aussi l'avantage de réduire le nombre d'adresses IP exposées dont vous avez besoin pour SSH, c'est pourquoi il est utilisable dans ce scénario. Le fait que ce soit une solution destinée à ajouter une autre couche de protection pour des raisons de sécurité ne vous empêche pas de l'utiliser lorsque vous n'avez pas besoin de cette sécurité supplémentaire.

ssh -o ProxyCommand='ssh -W %h:%p user1@bastion' user2@target

Un hack sale pour faire fonctionner si la vraie solution (IPv6) est hors de portée

Le hack que je m'apprête à décrire ne doit être utilisé qu'en dernier recours absolu. Avant même de penser à utiliser ce hack, je recommande fortement d'obtenir une adresse IPv6 pour chacun des serveurs auxquels vous souhaitez accéder de manière externe via SSH. Utilisez IPv6 comme méthode principale pour accéder à vos serveurs SSH et n'utilisez ce hack que lorsque vous devez exécuter un client SSH à partir d'un réseau IPv4 où vous n'avez aucune influence sur le déploiement d'IPv6.

L'idée est que le trafic entre le client et le serveur doit être un trafic SSH parfaitement valide. Mais le proxy doit uniquement comprendre suffisamment le flux de paquets pour identifier le nom d'hôte. Comme SSH ne définit pas de moyen d'envoyer un nom d'hôte, vous pouvez envisager d'autres protocoles qui offrent une telle possibilité.

HTTP et HTTPS permettent tous deux au client d'envoyer un nom d'hôte avant que le serveur n'envoie des données. La question maintenant est de savoir s'il est possible de construire un flux d'octets qui est simultanément valide comme trafic SSH et comme HTTP ou HTTPS. HTTPS est quasiment exclu, mais HTTP est possible (pour des définitions suffisamment libérales d'HTTP).

SSH-2.0-OpenSSH_6.6.1 / HTTP/1.1
$: 
Host: example.com

Cela ressemble-t-il à du SSH ou à de l'HTTP pour vous ? C'est du SSH et totalement conforme aux RFC (à l'exception de certains caractères binaires un peu modifiés par le rendu SF).

La chaîne de version SSH inclut un champ de commentaire, qui dans l'exemple ci-dessus a pour valeur / HTTP/1.1. Après le saut de ligne, SSH a des données de paquet binaire. Le premier paquet est un message MSG_SSH_IGNORE envoyé par le client et ignoré par le serveur. La charge à ignorer est :

: 
Host: example.com

Si un proxy HTTP est suffisamment libéral dans ce qu'il accepte, alors la même séquence d'octets serait interprétée comme une méthode HTTP appelée SSH-2.0-OpenSSH_6.6.1 et les données binaires au début du message à ignorer seraient interprétées comme un nom d'en-tête HTTP.

Le proxy ne comprendrait ni la méthode HTTP ni le premier en-tête. Mais il pourrait comprendre l'en-tête Host, ce qui est tout ce dont il a besoin pour trouver l'arrière-plan.

Pour que cela fonctionne, le proxy devrait être conçu sur le principe qu'il n'a besoin de comprendre suffisamment d'HTTP que pour trouver l'arrière-plan, et une fois que l'arrière-plan est trouvé, le proxy transmettra simplement le flux de bytes brut et laissera la véritable terminaison de la connexion HTTP à l'arrière-plan.

Cela peut sembler un peu tiré par les cheveux de faire autant d'hypothèses sur le proxy HTTP. Mais si vous étiez prêt à installer un nouveau logiciel développé dans le but de prendre en charge SSH, alors les exigences pour le proxy HTTP ne semblent pas trop contraignantes.

Dans mon propre cas, j'ai constaté que cette méthode fonctionnait sur un proxy déjà installé sans aucun changement de code, de configuration ou autre. Et cela pour un proxy écrit uniquement avec HTTP en tête, pas SSH.

Preuve de concept client et proxy. (Avis que le proxy est un service exploité par moi-même. N'hésitez pas à remplacer le lien une fois qu'un autre proxy aura été confirmé pour prendre en charge cette utilisation.)

Inconvénients de ce hack

  • Ne l'utilisez pas. Il vaut mieux utiliser la vraie solution, qui est IPv6.
  • Si le proxy tente de comprendre le trafic HTTP, il est sûr de se casser.
  • Compter sur un client SSH modifié n'est pas agréable.

9voto

Király István Points 307

Il y a un nouveau venu dans le quartier. SSH piper va routage votre connexion en fonction des noms d'utilisateur prédéfinis, qui devraient être mappés aux hôtes internes. C'est la meilleure solution dans le contexte de reverse-proxy.

SSh piper sur github

Mes premiers tests ont confirmé, SSH et SFTP fonctionnent tous les deux.

4voto

Vicent Marti Points 2942

Je ne pense pas que cela soit possible, du moins de la manière dont vous l'avez décrit, même si j'adorerais avoir tort. Il ne semble pas que le client envoie le nom d'hôte auquel il souhaite se connecter (du moins en clair). La première étape de la connexion SSH semble être de mettre en place le cryptage.

De plus, vous auriez des problèmes de vérification de la clé hôte. Les clients SSH vérifient les clés en fonction d'une adresse IP ainsi que d’un nom d’hôte. Vous auriez plusieurs noms d'hôtes avec des clés différentes, mais la même adresse IP à laquelle vous vous connectez.

Une solution possible serait d'avoir un hôte 'bastion', où les clients pourraient se connecter en SSH sur cette machine, obtenir un shell normal (ou restreint si désiré), et pourraient ensuite se connecter en SSH sur des hôtes internes à partir de là.

2voto

Kafeine Points 29

Je me demande si Honeytrap (le honeypot à faible interaction) qui a un mode proxy ne pourrait pas être modifié pour y parvenir.

Ce honeypot est capable de transmettre n'importe quel protocole à un autre ordinateur. Ajouter un système de vhost basé sur les noms (comme mis en œuvre par Apache) pourrait en faire un reverse proxy parfait pour n'importe quel protocole, non ?

Je n'ai pas les compétences pour le faire mais peut-être que ce pourrait être un grand projet.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X