Se connecter en ssh sur une machine derrière un pare-feu

Qui ne s'est jamais fait avoir à vouloir se connecter en ssh à une machine qui est inaccessible derrière un pare-feu? Ou alors de vouloir accéder à un des services hébergés sur cette machine sans pouvoir ouvrir de port public?

Alors bien entendu, on pourrait mettre en place un vpn, qu’il soit intégré dans le routeur ou en installant un serveur OpenVpn sur le réseau. Seulement ce n’est pas toujours possible, et ce n’est pas toujours utile non plus…

Ici je vais vous présenter une solution qui nécessite uniquement un serveur ssh avec un port ouvert sur le wan. Les autres machines pourrons se connecter à celle ci, qui centralisera alors les connexions.

En se connectant, les machines vont créer une connexion persistante sur un port spécifique (nous aurons à la relancer si elle est coupée pour une raison x ou y), et c’est à travers cette connexion que les autres machines pourrons se connecter.

Voici un schéma de ce à quoi cela devrait ressembler:

Schéma réseau - connexion ssh derrière un pare-feu

Nous avons ici deux sites distants :

  • Le site A :
    • Qui possède deux machines sur son réseau, auxquelles nous voulons accéder pour la démonstration
    • Tout les ports sont bloqués en entrée par le pare-feu
  • Le site B :
    • Possède un serveur (machine 2) sur lequel nous redirigeons le port 22 du routeur
    • Possède deux machines qui doivent accéder aux machines du site A en ssh. Actuellement elles ne peuvent donc pas.

Maintenant que nous connaissons un peu la topographie du réseau que nous avons en face, nous pouvons passer à la mise en place de notre solution.

Mise en place du serveur SSH qui fera office de proxy

Pour ce serveur, j’ai choisi une Debian qui sera dédiée à cet usage, mais n’importe quel système linux avec openssh fera l’affaire. Nous allons aussi créer un utilisateur qui n’aura aucun privilège sur lequel nos machines vont se connecter. Cet utilisateur s’appellera tunnel.

# Ajout de l’utilisateur
adduser tunnel

# Génération de clé ssh
ssh-keygen

# Installation du serveur ssh, si ce n’est pas déjà fait
apt-get install -y openssh-server
systemctl enable sshd && systemctl start sshd

# Si vous voulez pouvoir utiliser les ports liés aux machines distantes directement sur l’ip publique de votre proxy ssh:
sed -i 's/#GatewayPorts.*/GatewayPorts yes/g' /etc/ssh/sshd_config

Et voilà, votre proxy ssh est désormais fonctionnel. Voyons à présent comment créer une connexion depuis les machines du Site A, avant de s’y connecter depuis le Site B.

Vous aurez remarqué que nous avons laissé l’authentification par mot de passe actif: pour des raisons de sécurité je vous recommande de le supprimer par la suite. Mais dans un premier temps cela va nous permettre de procéder à nos échanges de clés ssh plus facilement.

Pour la suite de cet article, nous assumerons que cette machine est disponible à l’adresse suivante : proxy.siteb.domain

Se connecter sur le serveur proxy depuis n’importe où.

Sur votre / vos machines cibles, vous aurez besoin d’avoir un serveur ssh actif, et… bah c’est tout en fait.

# Si vous n’avez pas généré de clé ssh
ssh-keygen

# Échange de clé ssh avec notre proxy
ssh-copy-id tunnel@proxy.siteb.domain

# Création de la connexion
ssh -fN -R 0.0.0.0:2000:localhost:22 tunnel@proxy.siteb.domain

Ça y est, votre machine est connectée au proxy!

Regardons de plus prêt cette commande :

  • ssh -fN :
    • l’option f nous permet de lancer la commande ssh en mode background
    • l’option N n’exécute aucune commande sur la machine distante, cette option est prévue pour le port forwarding (ce qui est justement notre cas)
  • -R 0.0.0.0:2000:localhost:22
    • cette partie nous permet de binder un port local sur le port distant. Ici, nous ouvrons le port 2000 sur la machine distante et le redirigeons vers notre port 22 en local
    • attention, la partie 0.0.0.0 correspond au masque d’addresses sur lequel nous voulons que notre port distant réponde. Si vous voulez limiter uniquement aux utilisateurs connectés à la machine proxy, vous devez remplacer cette adresse par localhost. Ou alors plus court: 2000:localhost:22 . Nous en reparlerons plus bas.
  • tunnel@proxy.siteb.domain
    • Notre machine et utilisateur distant

Se connecter à notre machine reliée au proxy

Nous pouvons désormais nous connecter en ssh à nos machines du site A depuis le site B.

Nous allons voir deux manières de le faire: en utilisant le port de la machine distant sur l’adresse publique de notre proxy, ou en se connectant en premier à notre proxy pour ensuite se connecter à la machine voulue.

Nous assumerons que les machines 1 et 2 du site A utilisent respectivement les ports 2000 et 2001.

Se connecter depuis l’ip publique du proxy

A travers cette solution, nous pouvons nous connecter en une simple ligne de commande depuis non seulement notre lan, mais aussi depuis depuis le wan à condition que les ports en questions soient redirigé vers le proxy.

ssh utilisateur-de-la-machine@proxy.siteb.domain -p 2000

# Je vous recommande aussi de faire un échange de clé ssh avant de bloquer l’authentification par mot de passe
ssh-copy-id utilisateur-de-la-machine@proxy.siteb.domain -p 2000

Se connecter d’abord au proxy, avant de rebondir sur la machine souhaitée

Il est possible que vous ne souhaitiez pas que les ports des machines soient accessible depuis l’adresse publique de votre proxy. Par exemple, pour être sûr que l’utilisateur s’authentifie d’abord sur le proxy avant de rebondir sur la machine voulue.

Dans ce cas là nous procéderions ainsi :

# Depuis notre machine
ssh tunnel@proxy.siteb.domain

# Depuis le proxy en tant qu’utilisateur tunnel (mais n’importe quel utilisateur fonctionnerais du moment qu’il est autorisé à se connecter sur la machine distante via le mot de passe ou une clé ssh)
ssh utilisateur-de-la-machine@localhost -p 2000

# En une seule ligne de commande
ssh -t tunnel@proxy.siteb.domain ssh utilisateur-de-la-machine@localhost -p 2000

Dans ce cas présent nous voudrions alors ne pas activer la redirection publique de ports dans notre proxy (cf : sed -i 's/#GatewayPorts.*/GatewayPorts yes/g' /etc/ssh/sshd_config).

Nous voudrions aussi initialiser la connexion comme ceci: ssh -fN -R 2000:localhost:22 tunnel@proxy.siteb.domain

Conclusion

Vous voici donc connecté en ssh à une machine qui était injoignable il y a encore peu de temps depuis votre réseau. Cette technique est très simple à mettre en place, et permet en plus de centraliser vos connexions en un seul endroit.

L’avantage de cette technique, est qu’elle ne permet pas uniquement de mapper des ports ssh sur notre proxy, mais tout port dont nous aurions besoin.

Je suis sûr que ceci vous sera utile un jour où l’autre,

Enjoy!