Kann ich SSH dazu bringen, ein Askpass-Programm zu verwenden, selbst wenn es von einem Terminal ausgeführt wurde?

9

man ssh sagt:

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.

Ich möchte, dass SSH ein Askpass-Programm verwendet, auch wenn es von einem Terminal ausgeführt wurde.

Gelegentlich muss ich eine Verbindung zu Servern herstellen, bei denen es zu Verzögerungen beim Anzeigen einer Kennwortabfrage kommt (möglicherweise aufgrund von Netzwerkproblemen, möglicherweise aufgrund versuchter Reverse-DNS-Suchvorgänge usw.). Ich ärgere mich und wechsle zu etwas anderem und vergesse den Verbindungsversuch. (Fügen Sie einen Witz über die Aufmerksamkeitsspanne eines Goldfisches ein.) Wenn ich endlich darauf zurückkomme, läuft die Eingabeaufforderung ab und sogar ein korrektes Passwort würde nur zu einer geschlossenen Verbindung führen.

Schlüssel wären eine Lösung, aber nicht jedes System, das ich verwende, verfügt über meine üblichen SSH-Schlüssel. Normalerweise verwende ich jedoch Ubuntu-Systeme und Ubuntu hat standardmäßig ein SSH-Askpass-Programm installiert.

Wenn jedoch ein Askpass-Fenster auftauchte, würde ich es sofort bemerken. Das ist ein guter Kompromiss für mich, wenn ich ihn nur zum Laufen bringen kann.

muru
quelle
Gute Frage. Wenn man sich den Quellcode ansieht, sieht es nicht so aus. Sie müssten es dazu bringen, nicht zu öffnen /dev/tty( LD_PRELOAD?).
Celada
@ Celada würde das Probleme beim Starten der Shell verursachen?
Muru
Wahrscheinlich nicht ...
Celada

Antworten:

7

Dies wird etwas komplizierter sein, aber die Kombination mehrerer Teile wird es funktionieren lassen:

Erläuterung

  1. Um sshdie Verwendung des $SSH_ASKPASSProgramms zu erzwingen , können Sie nicht zulassen ssh, dass das Original angezeigt wird tty. Es ist nur Bedingung. Dies kann durch Verwenden setsidund Verwenden von -nswitch to erfolgen ssh.

    Dieser Fall würde eine Verbindung initiieren, aber Sie könnten nicht mit der Shell interagieren, was wahrscheinlich auch Ihre Anforderung ist;) (und auch Ihre lokale TTY unterbricht).

    Sie können aber die "erste Sitzung" aufgeben. Sie sollten auch einen -NSchalter hinzufügen , der den Remote-Befehl unterdrückt und nur die Authentifizierung durchführt .

    Auch die mögliche Ausgabe "Junk" kann umgeleitet werden, &> /dev/nullwenn Sie nicht daran interessiert sind.

  2. Einrichten ControlMasterin ssh_config. Es ist eine coole Funktion und sobald die Verbindung hergestellt ist, können Sie Sitzungen ziemlich schnell "starten". Dieser Ausschnitt ~/.ssh/configsollte das tun:

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

    Sie können das in einen hostBlock einfügen, in dem Ihre "langsamen Kandidaten" aufgeführt sind, oder einfach überall. Es ist fast kein Overhead.

Letzte Zeile

Dann sollten Sie in der Lage sein, auf diese Weise eine Verbindung zu dem Host herzustellen, von dem Sie erwarten, dass er eine Weile dauert:

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

Der gesamte Prozess kann durch die aliasBash-Funktion vereinfacht oder beides in einem Schritt ausgeführt werden, bleibt jedoch der Vorstellungskraft des Lesers überlassen.

Nur Befehlszeilenargumente

Sie können beide Dinge in der Befehlszeile ohne ssh_configTeil zusammenfügen:

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

Die folgende Funktion sollte funktionieren, wenn keine SSH-Optionen angegeben sind:

ssh() {
    if ! command ssh -o PasswordAuthentication=no "$1" true
    then
        setsid -w ssh -fnN "$1"
    fi
    command ssh "$@"
}
  • -f weist SSH an, kurz vor der Programmausführung in den Hintergrund zu treten, nachdem das Kennwort erhalten wurde.
  • -wweist setsidan, auf das Ende des Programms zu warten. In diesem Fall geschieht dies, wenn SSH in den Hintergrund tritt. In Kombination mit ssh -fkann das manuelle Warten zwischen den beiden SSH-Befehlen vermieden werden.
  • Die Funktion geht davon aus, dass das erste Argument der Hostname ist.
  • Der Test dient nur dazu, unnötige SSH-Verbindungen zu vermeiden.
Jakuje
quelle
ControlMasterist bereits eingerichtet, gerade weil es in solchen Fällen so schwierig ist, Passwörter einzugeben. Es sollte nicht schwierig sein, eine Funktion zu schreiben, die einen vorhandenen Master testet und den Askpass verwendet, wenn er keinen findet. Vielen Dank!
Muru
3

A gemäß SSH-Handbuch ( man ssh):

Wenn sshkein Terminal zugeordnet ist, aber DISPLAY und SSH_ASKPASS gesetzt sind, wird das von SSH_ASKPASS angegebene Programm ausgeführt.

Daher müssen Sie das Terminal trennen (z. B. durch Hinzufügen einer Pipe) und sicherstellen, dass DISPLAYes nicht festgelegt ist (wenn Sie stattdessen das Terminal für Ihre Passphrase verwenden möchten).

Einfaches Beispiel:

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

Das gleiche mit ssh-add:

$ echo foo | SSH_ASKPASS=/my/cmd DISPLAY= ssh-add id_rsa
ssh_askpass: exec(/my/cmd): No such file or directory
Kenorb
quelle
Leider funktioniert das bei mir nicht. Es heißt Pseudo-terminal will not be allocated because stdin is not a terminal, also scheint die Pfeife etwas zu tun. ssh </dev/nullhatte den gleichen Effekt. In beiden Fällen wird jedoch immer noch nach einem Kennwort gefragt, und ich kann immer noch eines eingeben. Ich habe es unter Linux und Mac versucht. Ich habe es versucht, ssh -vvvaber es sagt nichts Nützliches aus.
Timmmm
1
SSH_ASKPASS=/foo DISPLAY= setsid ssh hostfunktioniert aber.
Timmmm