Posso fazer com que o SSH use um programa askpass mesmo que tenha sido executado em um terminal?

9

man ssh diz:

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.

Eu gostaria que o SSH usasse um programa askpass, mesmo que fosse executado em um terminal.

Ocasionalmente, tenho que me conectar a servidores, onde há algum atraso na exibição de um prompt de senha (talvez devido a problemas de rede, talvez devido a tentativas de pesquisas reversas no DNS, ...). Fico aborrecido e mudo para outra coisa, e esqueço a tentativa de conexão. (Insira uma piada sobre o tempo de atenção de um peixe dourado.) Quando finalmente volto a ele, o prompt excede o tempo limite e até mesmo uma senha correta resultaria em uma conexão fechada.

As chaves seriam uma solução, mas nem todo sistema que eu uso possui minhas chaves SSH habituais. No entanto, eu costumo usar sistemas Ubuntu, e o Ubuntu tem um programa askH SSH instalado por padrão.

Se uma janela askpass aparecer, eu ficaria imediatamente ciente disso. Esse é um compromisso bom o suficiente para mim, se eu conseguir fazê-lo funcionar.

muru
fonte
Boa pergunta. Ao olhar para o código fonte, não parece. Você teria que enganá-lo para não abrir /dev/tty( LD_PRELOAD?).
Celada 27/03
@ Celada isso causaria problemas ao iniciar o shell?
Muru
Provavelmente não ...
Celada 27/03

Respostas:

7

Isso será um pouco mais complicado, mas a combinação de várias peças fará com que funcione:

Explicação

  1. Para forçar ssha usar o $SSH_ASKPASSprograma, você não pode permitir sshver o real tty. É apenas condição. Isso pode ser feito usando setside usando -nalternar para ssh.

    Este caso iniciaria a conexão, mas você não conseguiria interagir com o shell, o que provavelmente também é seu requisito;) (e também interrompe seu TTY local).

    Mas você pode desistir da "primeira sessão". Você também deve adicionar a -Nopção, que suprimirá o comando remoto e fará apenas a autenticação .

    Além disso, o possível "lixo" de saída pode ser redirecionado &> /dev/nullse você não estiver interessado nele.

  2. Configurar ControlMasterem ssh_config. É um recurso interessante e uma vez que a conexão é estabelecida, você pode "iniciar" as sessões rapidamente. Este trecho ~/.ssh/configdeve fazer o seguinte:

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

    Você pode adicionar isso a alguns hostblocos que listam seus "candidatos lentos" ou em qualquer lugar. É quase sem sobrecarga.

Linha final

Então você deve conseguir se conectar dessa maneira ao host que espera que demore um pouco:

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

Todo o processo pode ser simplificado pela aliasfunção bash, executando as duas coisas em uma única etapa, mas é deixado na imaginação dos leitores.

Somente argumentos de linha de comando

Você pode unir as duas coisas na linha de comando sem ssh_configparte:

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

A seguinte função deve funcionar quando as opções SSH não são especificadas:

ssh() {
    if ! command ssh -o PasswordAuthentication=no "$1" true
    then
        setsid -w ssh -fnN "$1"
    fi
    command ssh "$@"
}
  • -f instrui o SSH a ir para o plano de fundo imediatamente antes da execução do programa, após a obtenção da senha.
  • -wdiz setsidpara aguardar o término do programa. Nesse caso, isso acontece quando o SSH fica em segundo plano. Combinado com ssh -f, a espera manual entre os dois comandos SSH pode ser eliminada.
  • A função assume que o primeiro argumento é o nome do host.
  • O teste é apenas para evitar conexões SSH desnecessárias.
Jakuje
fonte
ControlMasterjá está configurado, justamente porque é difícil digitar senhas nesses casos. Não deve ser difícil escrever uma função que teste um mestre existente e use o askpass se não conseguir encontrar um. Obrigado!
muru 27/03
3

Um por manual SSH ( man ssh):

Se sshnão houver um terminal associado, mas DISPLAY e SSH_ASKPASS estiverem configurados, ele executará o programa especificado por SSH_ASKPASS.

Portanto, você precisa desassociar o terminal (por exemplo, adicionando um tubo) e verifique se DISPLAYnão está definido (se você deseja usar o terminal para sua senha).

Exemplo simples:

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

O mesmo com ssh-add:

$ echo foo | SSH_ASKPASS=/my/cmd DISPLAY= ssh-add id_rsa
ssh_askpass: exec(/my/cmd): No such file or directory
kenorb
fonte
Infelizmente isso não funciona para mim. Diz Pseudo-terminal will not be allocated because stdin is not a terminal, então parece que o cachimbo está fazendo alguma coisa. ssh </dev/nullteve o mesmo efeito. No entanto, nos dois casos, ele ainda pede uma senha e ainda posso digitar uma. Tentei no Linux e Mac. Eu tentei, ssh -vvvmas não diz nada de útil.
Timmmm 18/12/19
1
SSH_ASKPASS=/foo DISPLAY= setsid ssh hostfunciona embora.
Timmmm 18/12/19