% Tunnel SSH avec reverse # Introduction L'idée est d'ouvrir un tunnel SSH qui passe par un serveur relai. Le poste de travail (poste) se connecte à la cible via le relai. ``` ____________ ____________ poste -------------->[ relai ]-------------> cible p_tun >> Tunnel(L) >> p_relai << Tunnel(R) <> Tunnel(L) >> port serveur SSH ``` ## Définition d'un tunnel `reverse from server` : ``` port client SSH << Tunnel(R) << port serveur SSH ``` ## Exemple ``` __________ _________ poste ------------>[ relai ]-----------> cible 6122>> Tunnel(L) >>6022<< Tunnel(R) <<22 __________ _________ ``` - 6122 port d'entrée (1 = in) - 6022 port de sortie du tunnel poste > relai (0 = out) - 22 port SSH de la cible # Mise en application ## IPI - ``: mon poste de travail (port 6122 sera relié au port 22 de la cible) - ``: `luke` - (port `6022` reliera la sortie du tunnel entrant (poste > relai) à l'entrée du tunnel reverse (relai > cible)) - ``: `proxmox-patrick` Exemple serveur IPI: adresse publique: `185.64.149.17` ## Création d'une paire de clé sur la cible En tant qu'utilisateur standard (nom = `u_ssh_cible`) Générer une paire de clé privé/publique sur la `` **SANS** *passphrase*. Copier la clé publique (elle sera copiée dans le fichier `authorized_keys` de l'utilisateur `tunnel@`) ## Mise en place du relai ### Création d'un utilisateur `tunnel` sur `` #### Fichier `authorized_keys` pour l'utilisateur `tunnel` Préfixe: ``` from="185.64.149.17",no-agent-forwarding,no-pty,no-X11-forwarding,permitopen="localhost:6022",command="/home/tunnel/bin/tunnelcheck" ``` Copie de la clé publique de la ``: ``` from="185.64.149.17",no-agent-forwarding,no-pty,no-X11-forwarding,permitopen="localhost:6022",command="/home/tunnel/bin/tunnelcheck" ssh-ed25519 AAAACccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc u_ssh_cible@cible ``` #### Création du script de vérification du tunnel ```bash mkdir bin touch bin/tunnelcheck chmod +x bin/tunnelcheck ``` Copier le code suivant dans `bin/tunnelcheck` : ```bash #!/bin/bash set -Eeuo pipefail parameters=(${SSH_ORIGINAL_COMMAND-}) if [[ ${#parameters[@]} -gt 1 ]] then server_response=$(ssh -o PasswordAuthentication=no -p ${parameters[1]} -n -f localhost exit 2>&1 | cut -c1-17 || echo "") if [[ ${server_response:-} = "Permission denied" ]] then echo TUNNEL_OK exit 0 else echo TUNNEL_KO exit 1 fi fi ``` ## Mise en place du reverse tunnel sur `` ### Lancement initial ```bash ssh -f -T -N -R 6022:localhost:22 tunnel@relai.aezi.fr ``` #### Vérification depuis le `` Depuis le `` en tant qu'utilisateur `tunnel`, lancer: ```bash SSH_ORIGINAL_COMMAND="tunnel_check 6022" /home/tunnel/bin/tunnelcheck ``` Vérifier les *fingerprint* si nécessaire ### Mise en place du `crontab` Sur la machine `` (en tant qu'`u_ssh_cible` ): ```bash crontab -e ``` Coller la ligne suivante: ``` */30 * * * * /usr/bin/ssh tunnel@relai.aezi.fr /home/tunnel/bin/tunnelcheck 6022 && echo OK || /usr/bin/ssh -f -T -N -R 6022:localhost:22 tunnel@relai.aezi.fr ``` ## Depuis le `` de travail Ouverture du tunnel vers le `` ``` ssh -f -T -N -L 6122:localhost:6022 tunnel@relai.aezi.fr ``` ### Connection ```bash ssh -p 6122 u_ssh_cible@localhost ``` ### ```bash # Sur ma machine ssh -f -T -N -L 6122:localhost:6022 tunnel@relai.aezi.fr ssh -L 55522:localhost:55555 tunnel@relai.aezi.fr # Pour se connecter ssh -p 55522 laurent@127.0.0.1 ``` ## IMPORTANT: à la première connection Vérifier les *fingerprint* # Finalisation de la sécurisation Désactiver l'utilisateur `tunnel` ### Sur le serveur cible ```bash #!/bin/bash #autossh -f -M 0 -N -o "ServerAliveInterval 10" -o "ServerAliveCountMax 3" -T -N -R 22:localhost:55555 tunnel@relai.aezi.fr #autossh -v -M 0 -o "ServerAliveInterval 10" -o "ServerAliveCountMax 3" -T -N -f -R 55555:localhost:22 tunnel@relai.aezi.fr autossh -v -M 55556 -T -N -f -R 55555:localhost:22 tunnel@relai.aezi.fr #ssh -v -f -N -T -R 55555:localhost:22 tunnel@relai.aezi.fr ``` # Solution Maison Côté serveur ``` ssh tunnel@relai.aezi.fr /home/tunnel/bin/tunnelcheck 55555 && echo OK || ssh -f -T -N -R 55555:localhost:22 tunnel@relai.aezi.fr ``` Côté relai ```bash $ cat bin/tunnelcheck #!/bin/bash set -Eeuo pipefail parameters=(${SSH_ORIGINAL_COMMAND-}) if [[ ${#parameters[@]} -gt 1 ]] then server_response=$(ssh -o PasswordAuthentication=no -p ${parameters[1]} -n -f localhost exit 2>&1 | cut -c1-17 || echo "") if [[ ${server_response:-} = "Permission denied" ]] then echo TUNNEL_OK exit 0 else echo TUNNEL_KO exit 1 fi fi ``` Pour tester côté relai: ```bash $ SSH_ORIGINAL_COMMAND="tunnel_check 55555" bin/tunnelcheck ``` # Sources Gestion des sessions et du contrôle - [shell script - Getting a pid for an ssh process that backgrounded itself - Unix & Linux Stack Exchange](https://unix.stackexchange.com/questions/389014/getting-a-pid-for-an-ssh-process-that-backgrounded-itself) - [linux - How to tell if an ssh ControlMaster connection is in use - Server Fault](https://serverfault.com/questions/211213/how-to-tell-if-an-ssh-controlmaster-connection-is-in-use)