Puis-je demander à SSH d'utiliser un programme askpass même s'il a été exécuté à partir d'un terminal?

9

man ssh dit:

SSH_ASKPASS
   If  ssh needs a passphrase, it will read the passphrase from the
   current terminal if it was run from a terminal.  If ssh does not
   have  a  terminal associated with it but DISPLAY and SSH_ASKPASS
   are set, it will execute the program  specified  by  SSH_ASKPASS
   and open an X11 window to read the passphrase.

J'aimerais que SSH utilise un programme askpass même s'il était exécuté à partir d'un terminal.

À l'occasion, je dois me connecter à des serveurs, où il y a un certain retard dans l'affichage d'une invite de mot de passe (peut-être en raison de problèmes de réseau, peut-être en raison de tentatives de recherches DNS inversées,…). Je suis agacé et je passe à autre chose, et j'oublie la tentative de connexion. (Insérez une blague sur la durée d'attention d'un poisson rouge.) Quand j'y reviens enfin, le délai d'attente de l'invite et même un mot de passe correct entraîneraient simplement une connexion fermée.

Les clés seraient une solution, mais tous les systèmes que j'utilise n'ont pas mes clés SSH habituelles. Cependant, j'utilise généralement des systèmes Ubuntu et Ubuntu a un programme askpass SSH installé par défaut.

Si une fenêtre askpass apparaissait, cependant, j'en serais immédiatement conscient. C'est un assez bon compromis pour moi, si seulement je peux le faire fonctionner.

muru
la source
Bonne question. En regardant le code source, il ne lui ressemble pas. Il faudrait le piéger pour ne pas ouvrir /dev/tty( LD_PRELOAD?).
Celada
@Celada est-ce que cela causerait des problèmes lors du démarrage du shell?
muru
Probablement pas ...
Celada

Réponses:

7

Ce sera un peu plus compliqué, mais la combinaison de plusieurs pièces le fera fonctionner:

Explication

  1. Pour forcer sshà utiliser le $SSH_ASKPASSprogramme, vous ne pouvez pas permettre sshde voir le réel tty. C'est juste une condition. Cela peut être fait en utilisant setsidet en utilisant le -ncommutateur vers ssh.

    Ce cas initierait la connexion, mais vous ne seriez pas en mesure d'interagir avec le shell, ce qui est probablement aussi votre exigence;) (et rompt également votre ATS local).

    Mais vous pouvez renoncer à la "première session". Vous devez également ajouter un -Ncommutateur, qui supprimera la commande à distance et effectuera uniquement l'authentification .

    La sortie "indésirable" peut également être redirigée &> /dev/nullsi vous n'êtes pas intéressé.

  2. Installer ControlMasterdans ssh_config. C'est une fonctionnalité intéressante et une fois la connexion établie, vous pouvez "lancer" des sessions assez rapidement. Cet extrait ~/.ssh/configdevrait faire cela:

    ControlPath ~/.ssh/controlmasters/%r@%h:%p
    ControlMaster auto
    ControlPersist 5m
    

    Vous pouvez ajouter cela dans un hostbloc répertoriant vos "candidats lents", ou juste partout. Ce ne sont presque pas des frais généraux.

Ligne finale

Ensuite, vous devriez pouvoir vous connecter de cette manière à l'hôte que vous attendez, cela prendra un certain temps:

setsid ssh -nN host
# wait, insert password in the X11 prompt
ssh host
# will bring you directly to your session

L'ensemble du processus peut être simplifié par aliasou bash fonction faisant les deux en une seule étape, mais il est laissé à l'imagination des lecteurs.

Uniquement les arguments de ligne de commande

Vous pouvez joindre les deux choses ensemble sur la ligne de commande sans ssh_configpartie:

setsid ssh -nNMS ~/.ssh/masters/%C host
# wait, insert password in the X11 prompt
ssh -S ~/.ssh/masters/%C host
# will bring you directly to your session

La fonction suivante devrait fonctionner lorsque les options SSH ne sont pas spécifiées:

ssh() {
    if ! command ssh -o PasswordAuthentication=no "$1" true
    then
        setsid -w ssh -fnN "$1"
    fi
    command ssh "$@"
}
  • -f indique à SSH de passer en arrière-plan juste avant l'exécution du programme, c'est-à-dire après avoir obtenu le mot de passe.
  • -windique setsidd'attendre la fin du programme. Dans ce cas, cela se produit lorsque SSH passe en arrière-plan. Combiné avec ssh -f, l'attente manuelle entre les deux commandes SSH peut être éliminée.
  • La fonction suppose que le premier argument est le nom d'hôte.
  • Le test vise simplement à empêcher les connexions SSH inutiles.
Jakuje
la source
ControlMasterest déjà configuré, précisément parce qu'il est si difficile de saisir des mots de passe dans de tels cas. Il ne devrait pas être difficile d'écrire une fonction qui teste un maître existant et utilise le askpass s'il n'en trouve pas. Merci!
muru
3

Un par manuel SSH ( man ssh):

Si sshaucun terminal n'est associé mais DISPLAY et SSH_ASKPASS sont définis, il exécutera le programme spécifié par SSH_ASKPASS.

Par conséquent, vous devez dissocier le terminal (par exemple en ajoutant un tube) et vous assurer qu'il DISPLAYn'est pas défini (si vous souhaitez utiliser le terminal pour votre phrase secrète à la place).

Exemple simple:

echo foo | SSH_ASKPASS=/my/cmd DISPLAY= ssh ...

La même chose avec ssh-add:

$ echo foo | SSH_ASKPASS=/my/cmd DISPLAY= ssh-add id_rsa
ssh_askpass: exec(/my/cmd): No such file or directory
kenorb
la source
Malheureusement, cela ne fonctionne pas pour moi. Cela dit Pseudo-terminal will not be allocated because stdin is not a terminal, il semble donc que la pipe fasse quelque chose. ssh </dev/nulleu le même effet. Cependant, dans les deux cas, il demande toujours un mot de passe, et je peux toujours en saisir un. J'ai essayé sur Linux et Mac. J'ai essayé ssh -vvvmais ça ne dit rien d'utile.
Timmmm
1
SSH_ASKPASS=/foo DISPLAY= setsid ssh hostfonctionne bien.
Timmmm