Могу ли я заставить SSH использовать программу askpass, даже если она запускалась из терминала?

9

man ssh говорит:

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.

Я бы хотел, чтобы SSH использовал программу askpass, даже если она запускалась из терминала.

Иногда мне приходится подключаться к серверам, где появляется некоторая задержка при отображении запроса пароля (возможно, из-за проблем с сетью, может быть из-за попыток обратного поиска DNS,…). Я раздражаюсь и переключаюсь на что-то другое, и забываю о попытке соединения. (Вставьте шутку о концентрации внимания золотой рыбки.) Когда я, наконец, вернусь к ней, время ожидания подсказки истекло, и даже правильный пароль привел бы к закрытому соединению.

Ключи были бы одним решением, но не каждая система, которую я использую, имеет мои обычные ключи SSH. Однако я обычно использую системы Ubuntu, и в Ubuntu по умолчанию установлена ​​программа SSH askpass.

Однако если всплывет окно «Аскпас», я сразу узнаю об этом. Это достаточно хороший компромисс для меня, если только я смогу заставить его работать.

Мур
источник
Хороший вопрос. Если посмотреть на исходный код, это не похоже на это. Вы должны обмануть его, чтобы не открыть /dev/tty( LD_PRELOAD?).
Селада,
@Celada это может вызвать проблемы при запуске оболочки?
Муру
Вероятно, нет ...
Селада

Ответы:

7

Это будет немного сложнее, но сочетание нескольких частей сделает его работоспособным:

объяснение

  1. Чтобы заставить sshиспользовать $SSH_ASKPASSпрограмму, вы не можете позволить sshувидеть реальное tty. Это просто состояние. Это можно сделать, используя setsidи используя -nпереключатель в ssh.

    Этот случай может инициировать соединение, но вы не сможете взаимодействовать с оболочкой, что, вероятно, также является вашим требованием;) (а также нарушает ваш локальный TTY).

    Но вы можете отказаться от «первого сеанса». Вы также должны добавить -Nпереключатель, который подавляет удаленную команду и выполняет только аутентификацию .

    Также возможный вывод «мусор» может быть перенаправлен, &> /dev/nullесли вы не заинтересованы в нем.

  2. Установить ControlMasterв ssh_config. Это отличная функция, и как только соединение установлено, вы можете довольно быстро «запустить» сеанс. Этот фрагмент ~/.ssh/configдолжен сделать это:

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

    Вы можете добавить это в некоторый hostблок, перечисляющий ваших «медленных кандидатов», или просто везде. Это почти без накладных расходов.

Финальная линия

Тогда вы сможете подключиться к хосту, который, как вы ожидаете, займет некоторое время:

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

Весь процесс можно упростить, aliasили функция bash выполняет оба действия за один шаг, но это остается на воображение читателей.

Только аргументы командной строки

Вы можете объединить обе вещи в командной строке без ssh_configчасти:

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

Следующая функция должна работать, если не указаны параметры SSH:

ssh() {
    if ! command ssh -o PasswordAuthentication=no "$1" true
    then
        setsid -w ssh -fnN "$1"
    fi
    command ssh "$@"
}
  • -f инструктирует SSH перейти в фоновый режим непосредственно перед выполнением программы, то есть после получения пароля.
  • -wговорит setsidждать окончания программы. В этом случае это происходит, когда SSH переходит в фоновый режим. В сочетании с ssh -fэтим ручное ожидание между двумя командами SSH может быть исключено.
  • Функция предполагает, что первым аргументом является имя хоста.
  • Тест только для предотвращения ненужных соединений SSH.
Jakuje
источник
ControlMasterуже настроен именно потому, что в таких случаях вводить пароли очень сложно. Не должно быть сложно написать функцию, которая тестирует существующий мастер и использует askpass, если он не может его найти. Спасибо!
Муру
3

Руководство по SSH ( man ssh):

Если с ним sshне связан терминал, но установлены DISPLAY и SSH_ASKPASS, он выполнит программу, указанную SSH_ASKPASS.

Поэтому вам необходимо отключить терминал (например, путем добавления канала) и убедиться, что DISPLAYон не установлен (если вы хотите использовать терминал для своей фразы-пароля).

Простой пример:

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

То же самое с ssh-add:

$ echo foo | SSH_ASKPASS=/my/cmd DISPLAY= ssh-add id_rsa
ssh_askpass: exec(/my/cmd): No such file or directory
kenorb
источник
К сожалению, это не работает для меня. Это говорит Pseudo-terminal will not be allocated because stdin is not a terminal, так что кажется, что труба что-то делает. ssh </dev/nullимел тот же эффект. Однако в обоих случаях он все еще запрашивает пароль, и я все еще могу ввести его. Я пробовал на Linux и Mac. Я пытался, ssh -vvvно это не говорит ничего полезного.
Timmmm
1
SSH_ASKPASS=/foo DISPLAY= setsid ssh hostработает хотя.
Timmmm