Niveau :      
Résumé :alias ssh='ssh macommande && ssh'

Aujourd'hui interceptons les commandes ssh. Alors ne commencez pas à penser que je suis passé du côté obscur de la force. Il y a des usage bien pratique ce script et je vous en proposerai un dans le prochain article.

Tout d'abord le problème : on veut pouvoir intercepter une commande ssh de façon silencieuse pour pouvoir utiliser la connexion qui va s'établir et lancer les commandes qu'on veut sur la machine distante. Cela implique une acceptation implicite de l'utilisateur puisqu'on va utiliser un simple alias pour "intercepter" la commande. Bien sûr rien ne vous empêche de modifier l'alias d'un ami selon les moyens qui sont à votre disposition ;-)

Principe de fonctionnement

Vous vous dites qu'il suffit de reprendre les paramètres de la commande et de la relancer. Non, habitués que vous êtes à l'agent ssh, vous avez oublié qu'en son absence l'utilisateur devra taper un mot de passe pour que la commande passe.

Pour récupérer la connexion ssh, openssh met à notre disposition tout ce qu'il faut. L'option s'appelle ControlMaster, elle crée une socket sur laquelle ssh peut ensuite se connecter pour ouvrir un nouveau terminal sans repasser toute la chaine de connexion au serveur.

La méthode est donc fait simple :

  • on intercepte la commande ssh (alias)
  • on lance notre script en background ($0 &)
  • on ajoute un option -M et -S si besoin à la commande ssh pour créer la socket
  • on garde les options originales et le processus original (exec ssh -M -S "$@")
  • dans le script en background on peut ensuite utiliser directement la socket en question pour faire ce qu'on veut

Résultat

Donc résumons : un alias

alias ssh='~/.sshalias'

Et un script nommé ~/.sshalias (commentaires en anglais par habitude). Modifiez la commande run pour metre ce que vous voulez dedans

#!/bin/sh

# GPLv2 
# author : peck

#  command tu run via the ssh socket
run()
{
        # example ssh command
        ssh -S "$1" XXX 'hostname'
}

# test if we are the child which can connect via the master
if [ "$1" == "-=0" ]
then
    go=0
    # limit to 60 retries x 1s
    for i in $(seq 1 60)
    do
        sleep 1
        # try to connect via master
        ssh -S "$2" -O check xxx 2>/dev/null
        if [ $? -eq 0 ]
        then
            go=1
            break
        fi
    done
    # run the stealth command
    if [ $go -eq 1 ]
    then
        sleep 1 # bug if we go too fast
        run "$2"
    fi
    # remove master socket if we created it
    if [ "$3" == "0" ]
    then
        rm -f "$2"
    fi
    exit 0
fi

# we are in a real ssh command
master=0
sock=""
for i in "$@"
do
    # test if master is already provided
    if [ "$i" == "-M" ]
    then
        master=1
    fi
    # retrieve socket if provided
    if [ "$i" == "-S" ]
    then
        sock=".";
    fi
    if [ "$i" == "." ]
    then
        sock="$i"
    fi
done

# create socket name if needed
if [ "$sock" == "" ]
then
    sock=$(mktemp -u -t sshx.XXXXXX)
fi

# launch child which will use our master socket
$0 -=0 "$sock" "$master" &

# run original command adding a master socket
if [ $master -eq 1 ]
then
    exec ssh "$@"
else
    exec ssh -S "$sock" -M "$@"
fi