Почему sshpass все равно запрашивает пароль?

Вопрос или проблема

Контекст:

  • Рабочая станция Debian Stretch, пытающаяся установить SSH-соединение с многочисленными серверами GNU/Linux (в основном RH и Debian)
  • Я не могу изменить SSH-конфигурацию удаленных серверов
  • Я понимаю, что это далеко не идеально, но мне необходимо входить в систему с помощью логина и пароля. Без SSH-ключа, просто старый добрый логин/пароль. Я не могу изменить это (не нужно предлагать использование ключей + фраз-паролей)
  • sshpass -V : “sshpass 1.06”

Этот ответ дает интересный намек на использование ‘sshpass’.

Что я настроил в ‘~/.ssh/config’ :

Host myServer
    HostName 12.34.56.78
    User bob
    ProxyCommand sshpass -v -pmyPassword ssh %r@%h -W localhost:%p

Примечание: параметр ‘-v’ sshpass используется только для получения подробностей при задавании этого вопроса

Когда я пытаюсь подключиться через SSH:

me@myWorkstation$ ssh myServer
SSHPASS searching for password prompt using match "assword"
SSHPASS read: [email protected]'s password:
SSHPASS detected prompt. Sending password.
SSHPASS read:

[email protected]'s password:

И это ждет бесконечно 🙁

Если я редактирую ‘~/.ssh/config’ и заменяю ‘myPassword’ (который является реальным паролем для этого входа в SSH, он работает при ручном вводе):

Host myServer
    HostName 12.34.56.78
    User bob
    ProxyCommand sshpass -v -pnotMyPasswordAnymoreOhNo ssh %r@%h -W localhost:%p

что дает:

me@myWorkstation$ ssh myServer
SSHPASS searching for password prompt using match "assword"
SSHPASS read: [email protected]'s password:
SSHPASS detected prompt. Sending password.
SSHPASS read:

Permission denied, please try again.
SSHPASS read: [email protected]'s password:
SSHPASS detected prompt, again. Wrong password. Terminating.
ssh_exchange_identification: Connection closed by remote host

На самом деле я получаю ответ (хотя и отрицательный). Можете объяснить, почему?

документация к sshpass говорит:

ВОПРОСЫ БЕЗОПАСНОСТИ

  В первую очередь, пользователи sshpass должны понимать, что требование ssh к интерактивному вводу пароля не случайно. Почти
   невозможно безопасно хранить пароль, и пользователи sshpass должны рассмотреть возможность использования аутентификации по
   открытому ключу, которая обеспечивает тот же опыт пользователя и при этом безопаснее и доставляет меньше хлопот.

  Опция -p должна рассматриваться как наименее безопасная из всех опций sshpass. Все пользователи системы могут видеть
   пароль в командной строке при помощи простого "ps" команды. Sshpass делает минимальную попытку скрыть пароль, но
   такие попытки обречены создавать условия гонок и не решать проблему. Пользователи sshpass рекомендуются использовать один
   из других методов передачи пароля, которые более безопасны.

  В частности, людям, пишущим программы, которые должны передавать пароль программно, рекомендуется использовать 
   безымянный канал и передавать конец чтения канала в sshpass с помощью опции -d.

Вы можете попробовать сохранить переменную ENV и хранить пароль там, но это плохая практика.

Если кому-то интересно заставить ssh запрашивать пароль один раз, т.е. в то время, когда sshpass предоставляет пароль и завершает работу в случае его неправильности, то что-то вроде этого работает отлично

sshpass -e ssh [email protected] -o NumberOfPasswordPrompts=1 whoami

Объяснение:

  • sshpass берет пароль из переменной окружения $SSHPASS при использовании опции -e
  • ssh использует пароль, предоставленный sshpass, и если он успешный, то выполняет команду whoami на удаленном сервере
  • если пароль неверный, то он не запрашивает повторно пароль благодаря -o NumberOfPasswordPrompts=1, что заставляет ssh запрашивать только один раз, и этим 1 разом был уже использованный неправильный пароль, предоставленный sshpass, поэтому фокус возвращается к терминалу

Не совсем та же проблема, но это был один из немногих связанных пунктов, с которыми я столкнулся во время недавнего поиска.

Столкнулся с совершенно другой причиной, связанной с использованием Cygwin из-за расположения файла known_hosts. При входе с помощью ssh всё вёл себя нормально, но при входе через sshpass всё происходило ошибка, и при выполнении sshpass -v появлялась ошибка:

bash$ ./sshpass -v -p PASSWORD ssh REMOTEUSER@ADDRESS
SSHPASS searching for password prompt using match "assword"
The authenticity of host 'ADDRESS (ADDRESS)' can't be established.
ED25519 key fingerprint is SHA256:h5Pmc4/GLFmGXvZl3oPadzvAgmOVW5tD9hSOKRCfKes.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/n
SSHPASS detected host authentication prompt. Exiting.
bash$ 

Наконец, удалось обнаружить это, добавив также -vvv к команде ssh, что выявило следующее:

bash$ ./sshpass -v -p PASSWORD ssh -vvv REMOTEUSER@ADDRESS
OpenSSH_9.9p1, OpenSSL 3.0.15 3 Sep 2024
debug2: resolve_canonicalize: hostname ADDRESS is address
debug3: expanded UserKnownHostsFile '~/.ssh/known_hosts' -> '/home/USER/.ssh/known_hosts'
debug3: expanded UserKnownHostsFile '~/.ssh/known_hosts2' -> '/home/USER/.ssh/known_hosts2'
debug3: channel_clear_timeouts: clearing
debug3: ssh_connect_direct: entering
debug1: Connecting to ADDRESS [ADDRESS] port 22.
debug3: set_sock_tos: set socket 4 IP_TOS 0x48
debug1: Connection established.

...

debug1: Remote protocol version 2.0, remote software version OpenSSH_8.9
debug1: compat_banner: match: OpenSSH_8.9 pat OpenSSH* compat 0x04000000
debug2: fd 4 setting O_NONBLOCK
debug1: Authenticating to ADDRESS:22 as 'REMOTEUSER'
debug1: load_hostkeys: fopen /home/USER/.ssh/known_hosts: No such file or directory
debug1: load_hostkeys: fopen /home/USER/.ssh/known_hosts2: No such file or directory
debug1: load_hostkeys: fopen /etc/ssh_known_hosts: No such file or directory
debug1: load_hostkeys: fopen /etc/ssh_known_hosts2: No such file or directory
debug3: order_hostkeyalgs: no algorithms matched; accept original
debug3: send packet: type 20
debug1: SSH2_MSG_KEXINIT sent
debug3: receive packet: type 20

...

debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug3: receive packet: type 31
debug1: SSH2_MSG_KEX_ECDH_REPLY received
debug1: Server host key: ssh-ed25519 SHA256:h5Pmc4/GLFmGXvZl3oPadzvAgmOVW5tD9hSOKRCfKes
debug1: load_hostkeys: fopen /home/USER/.ssh/known_hosts: No such file or directory
debug1: load_hostkeys: fopen /home/USER/.ssh/known_hosts2: No such file or directory
debug1: load_hostkeys: fopen /etc/ssh_known_hosts: No such file or directory
debug1: load_hostkeys: fopen /etc/ssh_known_hosts2: No such file or directory
debug3: hostkeys_find_by_key_hostfile: trying user hostfile "/home/USER/.ssh/known_hosts"
debug1: hostkeys_find_by_key_hostfile: hostkeys file /home/USER/.ssh/known_hosts does not exist
debug3: hostkeys_find_by_key_hostfile: trying user hostfile "/home/USER/.ssh/known_hosts2"
debug1: hostkeys_find_by_key_hostfile: hostkeys file /home/USER/.ssh/known_hosts2 does not exist
debug3: hostkeys_find_by_key_hostfile: trying system hostfile "/etc/ssh_known_hosts"
debug1: hostkeys_find_by_key_hostfile: hostkeys file /etc/ssh_known_hosts does not exist
debug3: hostkeys_find_by_key_hostfile: trying system hostfile "/etc/ssh_known_hosts2"
debug1: hostkeys_find_by_key_hostfile: hostkeys file /etc/ssh_known_hosts2 does not exist
SSHPASS searching for password prompt using match "assword"
The authenticity of host 'ADDRESS (ADDRESS)' can't be established.
ED25519 key fingerprint is SHA256:h5Pmc4/GLFmGXvZl3oPadzvAgmOVW5tD9hSOKRCfKes.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/n
SSHPASS detected host authentication prompt. Exiting.
bash$ 

Однако, подключение непосредственно с помощью ssh вместо sshpass делало следующее:

bash$ ssh -vvv remoteuser@ADDRESS
OpenSSH_for_Windows_9.5p1, LibreSSL 3.8.2
debug3: Failed to open file:C:/Users/USER/.ssh/config error:2
debug3: Failed to open file:C:/ProgramData/ssh/ssh_config error:2
debug2: resolve_canonicalize: hostname ADDRESS is address
debug3: expanded UserKnownHostsFile '~/.ssh/known_hosts' -> 'C:\\Users\\USER/.ssh/known_hosts'
debug3: expanded UserKnownHostsFile '~/.ssh/known_hosts2' -> 'C:\\Users\\USER/.ssh/known_hosts2'
debug3: ssh_connect_direct: entering
debug1: Connecting to ADDRESS [ADDRESS] port 22.
debug1: Connection established.

...

debug1: Local version string SSH-2.0-OpenSSH_for_Windows_9.5
debug1: Remote protocol version 2.0, remote software version OpenSSH_8.9
debug1: compat_banner: match: OpenSSH_8.9 pat OpenSSH* compat 0x04000000
debug2: fd 3 setting O_NONBLOCK
debug1: Authenticating to ADDRESS:22 as 'remoteuser'
debug3: record_hostkey: found key type ED25519 in file C:\\Users\\USER/.ssh/known_hosts:3
debug3: record_hostkey: found key type RSA in file C:\\Users\\USER/.ssh/known_hosts:4
debug3: record_hostkey: found key type ECDSA in file C:\\Users\\USER/.ssh/known_hosts:5
debug3: load_hostkeys_file: loaded 3 keys from ADDRESS
debug3: Failed to open file:C:/Users/USER/.ssh/known_hosts2 error:2
debug1: load_hostkeys: fopen C:\\Users\\USER/.ssh/known_hosts2: No such file or directory
debug3: Failed to open file:C:/ProgramData/ssh/ssh_known_hosts error:2
debug1: load_hostkeys: fopen __PROGRAMDATA__\\ssh/ssh_known_hosts: No such file or directory
debug3: Failed to open file:C:/ProgramData/ssh/ssh_known_hosts2 error:2
debug1: load_hostkeys: fopen __PROGRAMDATA__\\ssh/ssh_known_hosts2: No such file or directory
debug3: order_hostkeyalgs: have matching best-preference key type [email protected], using HostkeyAlgorithms verbatim
debug3: send packet: type 20
debug1: SSH2_MSG_KEXINIT sent
debug3: receive packet: type 20

...

debug3: send packet: type 30
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug3: receive packet: type 31
debug1: SSH2_MSG_KEX_ECDH_REPLY received
debug1: Server host key: ssh-ed25519 SHA256:h5Pmc4/GLFmGXvZl3oPadzvAgmOVW5tD9hSOKRCfKes
debug3: record_hostkey: found key type ED25519 in file C:\\Users\\USER/.ssh/known_hosts:3
debug3: record_hostkey: found key type RSA in file C:\\Users\\USER/.ssh/known_hosts:4
debug3: record_hostkey: found key type ECDSA in file C:\\Users\\USER/.ssh/known_hosts:5
debug3: load_hostkeys_file: loaded 3 keys from ADDRESS
debug3: Failed to open file:C:/Users/USER/.ssh/known_hosts2 error:2
debug1: load_hostkeys: fopen C:\\Users\\USER/.ssh/known_hosts2: No such file or directory
debug3: Failed to open file:C:/ProgramData/ssh/ssh_known_hosts error:2
debug1: load_hostkeys: fopen __PROGRAMDATA__\\ssh/ssh_known_hosts: No such file or directory
debug3: Failed to open file:C:/ProgramData/ssh/ssh_known_hosts2 error:2
debug1: load_hostkeys: fopen __PROGRAMDATA__\\ssh/ssh_known_hosts2: No such file or directory
debug1: Host 'ADDRESS' is known and matches the ED25519 host key.
debug1: Found key in C:\\Users\\USER/.ssh/known_hosts:3
debug3: send packet: type 21
debug1: ssh_packet_send2_wrapped: resetting send seqnr 3
debug2: ssh_set_newkeys: mode 1
debug1: rekey out after 134217728 blocks

...

debug3: receive packet: type 80
debug1: client_input_global_request: rtype [email protected] want_reply 0
debug3: client_input_hostkeys: received RSA key SHA256:gRIZdS/NcmA7JC7vxBDG63uhjuE9ZuKadl9XKU1yC0A
debug3: client_input_hostkeys: received ECDSA key SHA256:TJCsTQVSHrxE5DuWpG65F7tr3P7qDfknz9NLBQ/W+o0
debug3: client_input_hostkeys: received ED25519 key SHA256:h5Pmc4/GLFmGXvZl3oPadzvAgmOVW5tD9hSOKRCfKes
debug1: client_input_hostkeys: searching C:\\Users\\USER/.ssh/known_hosts for ADDRESS / (none)
debug3: hostkeys_foreach: reading file "C:\\Users\\USER/.ssh/known_hosts"
debug3: hostkeys_find: found ssh-ed25519 key at C:\\Users\\USER/.ssh/known_hosts:3
debug3: hostkeys_find: found ssh-rsa key at C:\\Users\\USER/.ssh/known_hosts:4
debug3: hostkeys_find: found ecdsa-sha2-nistp256 key at C:\\Users\\USER/.ssh/known_hosts:5
debug1: client_input_hostkeys: searching C:\\Users\\USER/.ssh/known_hosts2 for ADDRESS / (none)
debug3: Failed to open file:C:/Users/USER/.ssh/known_hosts2 error:2
debug1: client_input_hostkeys: hostkeys file C:\\Users\\USER/.ssh/known_hosts2 does not exist
debug3: client_input_hostkeys: 3 server keys: 0 new, 3 retained, 0 incomplete match. 0 to remove
debug1: client_input_hostkeys: no new or deprecated keys from server
debug3: client_repledge: enter
debug3: receive packet: type 91
debug2: channel_input_open_confirmation: channel 0: callback start
debug2: fd 3 setting TCP_NODELAY
debug2: client_session2_setup: id 0
debug2: channel 0: request pty-req confirm 1
debug3: send packet: type 98
debug2: channel 0: request shell confirm 1
debug3: send packet: type 98
debug3: client_repledge: enter
debug1: pledge: fork
debug2: channel_input_open_confirmation: channel 0: callback done
debug2: channel 0: open confirm rwindow 0 rmax 32768
debug3: receive packet: type 99
debug2: channel_input_status_confirm: type 99 id 0
debug2: PTY allocation request accepted on channel 0
debug2: channel 0: rcvd adjust 2097152
debug3: receive packet: type 99
debug2: channel_input_status_confirm: type 99 id 0
debug2: shell request accepted on channel 0
Last login: Tue Feb 11 15:40:24 2025 from HOST
REMOTEHOST$$ 

Обратите внимание, как логин ssh использует Windows-домашний каталог для директории пользователя .ssh, но sshpass использует домашний каталог Cygwin.

Просто предположение, но это похоже на то, что они по-разному обрабатывают начальный ~/ в пути.

В любом случае, проблема была решена путем создания символеического ссылки для .ssh в домашней директории Cygwin /home/USER на Windows-домашний каталог C:\Users\USER.

bash$ cd
bash$ ls -l .ssh
lrwxrwxrwx 1 USER Domain Users 29 Feb 11 15:56 .ssh -> /cygdrive/c/Users/USER/.ssh

Ответ или решение

Основной вопрос, который поднимается в этом обсуждении, заключается в том, почему sshpass продолжает запрашивать пароль, несмотря на явное указание такового через команду или конфигурацию. Чтобы полностью понять эту проблему, надо рассмотреть несколько аспектов работы SSH и sshpass.

Теория

SSH — это протокол для безопасного доступа к удалённым серверам, который в первую очередь рассчитан на использование ключевой авторизации. Однако, когда использование ключей невозможно, приходится работать с текстовыми паролями. Протокол SSH имеет определённые механизмы защиты, связанные с аутентификацией, включая необходимость ручного ввода пароля, чтобы уменьшить вероятность его компрометации.

sshpass — это утилита, которая позволяет передавать пароль для SSH-сессии через командную строку или другие менее безопасные механизмы. Важно понимать, что она была создана для минимальной автоматизации процессов в обход стандартных требований безопасности SSH и несёт с собой определённые уязвимости.

Примеры

В рассматриваемом случае на Debian Stretch рабочей станции используется конфигурация с sshpass для подключения без использования SSH-ключей. Конфигурация ~/.ssh/config выглядит следующим образом:

Host myServer
    HostName 12.34.56.78
    User bob
    ProxyCommand sshpass -v -pmyPassword ssh %r@%h -W localhost:%p

Когда попытка подключения осуществляется с помощью ssh myServer, sshpass должен автоматически передавать пароль, но этого не происходит.

Причины и решения

  1. Проблемы с ProxyCommand: Анализ сообщений отладки показывает, что sshpass не всегда корректно справляется с ProxyCommand, что часто связано с тем, что данная команда выполняется фактически как подзапрос, а не основное подключение, из чего могут возникать ошибки обработки.

  2. Проблемы с известными хостами:

    • Проверка подлинности удаленного хоста может быть блокирующим фактором. Если хост неизвестен, ssh может остановить выполнение до тех пор, пока пользователь не подтвердит доверие к новому хосту, как это видно из логов отладки, где происходит неожиданный выход sshpass при наличии запроса на установление подлинности хоста.
  3. Проблемы с обнаружением приглашения к вводу пароля:

    • sshpass полагается на шаблон для обнаружения приглашения к вводу пароля (обычно "assword"). Если формулировка приглашения отличается или появляется неожиданное сообщение, sshpass может не распознать момент для ввода пароля.

Применение решений

Настройка аутентификации хоста:

Убедитесь, что аутентификация хоста выполняется корректно. Для этого можно предварительно вручную подключиться к серверу, чтобы добавить хост в known_hosts, что избавит sshpass от необходимости обрабатывать дополнительные запросы.

Альтернативные флаги и параметры:

  • Используйте -o StrictHostKeyChecking=no в команде SSH, чтобы отключить проверку ключа хоста для тестовых или менее защищённых сред. Это может устранить блокировку на этапе подлинности хоста.

  • Применение -o NumberOfPasswordPrompts=1 в комбинированной команде с sshpass может заставить SSH прервать попытку ввода правильного пароля после первой неудачной попытки, что избавит от излишних запросов.

Проблемы с Переменными Окружения:

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

export SSHPASS='myPassword'
sshpass -e ssh -o StrictHostKeyChecking=no bob@12.34.56.78

Таким образом, такая сложная конфигурация SSH требует комплексного подхода и внимания к деталям, которые могут варьироваться от неудачи обработки аутентификации хоста до проблем с обнаружением приглашения к вводу пароля. Надёжное понимание механизмов работы позволит наиболее эффективно адаптировать инструменты для выполнения поставленной задачи.

Оцените материал
Добавить комментарий

Капча загружается...