Utilice el script wait in bash para proporcionar una contraseña al comando SSH

131

Para aquellos que quieran responder que debo usar las claves SSH, por favor abstenerse

Estoy tratando de usar esperar en un script bash para proporcionar la contraseña SSH. Si la contraseña funciona, pero no termino en la sesión de SSH como debería, se remonta a bash.

Mi guión:

#!/bin/bash

read -s PWD

/usr/bin/expect <<EOD
spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com'
expect "password"
send "$PWD\n" 
EOD
echo "you're out"

El resultado de mi script:

spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com
usr@$myhost.example.com's password: you're out

Me gustaría tener mi sesión SSH y solo cuando salga para volver a mi script bash. La razón por la que estoy usando bash antes de esperar es porque he usado un menú en el que puedo elegir a qué unidad conectarme.

Gracias

Max
fuente
49
vea la primera línea: para aquellos que quieran responder que debo usar las claves SSH, por favor abstenerse
Max
54
Editaría tu primera línea para ser un poco más amigable. Puede considerar algo como "Debido a restricciones, simplemente no puedo usar claves SSH, debo encontrar una manera de hacerlo funcionar con la función de esperar". Debes esperar que la gente sienta curiosidad por qué no estás usando las teclas y solo intentan ser útiles :) @Ignacio no sugirió que las usaras , simplemente lo confirmó como una restricción y no como un descuido.
Tim Post
Intentaría usar kermit en este caso. Tiene un lenguaje de script muy robusto columbia.edu/kermit/skermit.html#scripts
f3xy

Respuestas:

86

Mezclar bash y esperar no es una buena manera de lograr el efecto deseado. Intentaría usar solo Expect:

#!/usr/bin/expect
eval spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com
#use correct prompt
set prompt ":|#|\\\$"
interact -o -nobuffer -re $prompt return
send "my_password\r"
interact -o -nobuffer -re $prompt return
send "my_command1\r"
interact -o -nobuffer -re $prompt return
send "my_command2\r"
interact

La solución de muestra para bash podría ser:

#!/bin/bash
/usr/bin/expect -c 'expect "\n" { eval spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com; interact }'

Esto esperará para ingresar y luego regresar (por un momento) sesión interactiva.

Piotr Król
fuente
1
Funciona muy bien, gracias. ¿Qué sucede si quiero escribir el comando una vez que inicie sesión a través de SSH? ¿Qué debo hacer?
Max
Esta secuencia de comandos debe devolver un shell no activo con el usuario conectado. No entiendo la pregunta. Si absolutamente quiere usar el mismo script en bash, mire la entrada editada.
Piotr Król
De la misma manera que envío la contraseña cuando se me solicita, me gustaría enviar los comandos del sistema una vez que inicie sesión.
Max
El código de Samlple se agregó a la publicación anterior. Por supuesto, esto funcionará hasta que my_commandX no cambie la solicitud devuelta, si esto sucede, la variable de solicitud debe cambiarse.
Piotr Król
@pietrushnic ¿Puedes explicar un poco por qué usar "interact -o -nobuffer -re $ prompt return", en lugar de "esperar $ prompt"? este último parece más utilizado ..
Richard
53

La forma más fácil es usar sshpass . Está disponible en repositorios Ubuntu / Debian y no tiene que lidiar con la integración de esperar con bash.

Un ejemplo:

sshpass -p<password> ssh <arguments>
sshpass -ptest1324 ssh user@192.168.1.200 ls -l /tmp

El comando anterior se puede integrar fácilmente con un script bash.

Nota: Lea la sección Consideraciones de seguridad en man sshpasspara una comprensión completa de las implicaciones de seguridad.

dotnix
fuente
No sé si es una buena solución, pero ciertamente simplifica mucho. Gracias
erikbwork
9
Muy peligroso desde una perspectiva de seguridad: cualquier otro proceso del sistema puede leer los argumentos de la línea de comandos. Es posible sobrescribirlos, y con suerte lo sshpasshace, pero incluso entonces hay un período en el que aún se está iniciando antes de que pueda hacerlo cuando la contraseña esté disponible para que cualquiera de los procesos los vea.
Charles Duffy
1
@CharlesDuffy Por supuesto, tienes razón. sshpassse usa en un escenario donde tiene scripts de prueba simples que se ejecutan en un entorno de red local donde la seguridad no es la principal preocupación. De hecho, hay una sección en la man sshpassque se explica una sección completa sobre Consideraciones de seguridad. Agregó esto para responder, gracias.
dotnix
@ erikb85 Por lo general, un paquete hace todas las cosas sucias por usted, pero, en todos los casos, estos scripts se crean solo para ese uso, entonces sería MEJOR que agregar sus propias cosas. Este comentario trata sobre no reinventar la rueda. Trate las cosas difíciles solo si ninguna persona ha tratado con ellas todavía. sshpass es una buena función.
m3nda
2
Para completar, menciono que "man sshpass" ofrece advertencias de seguridad adecuadas para el posible usuario, señala que "-p" es la forma menos segura de usarlo y ofrece la opción "-e" para tomar la contraseña a través de la variable de entorno , que al menos lo mantiene fuera de la línea de comando.
Ron Burk
22

Agregue el comando de espera 'interactuar' justo antes de su EOD:

#!/bin/bash

read -s PWD

/usr/bin/expect <<EOD
spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com
expect "password"
send "$PWD\n" 
interact
EOD
echo "you're out"

Esto debería permitirle interactuar con la máquina remota hasta que cierre la sesión. Entonces volverás a la fiesta.

dr-jan
fuente
Entra y sale de inmediato. "estás fuera" está impreso.
Emmanuel
8
He reemplazado "interactuar" y "EOD" con "esperar eof" y funcionó para mí. Esto está en una Mac.
Emmanuel
2
Ninguna de las respuestas en esta página funcionó para mí, pero la sugerencia de @ Emmanuel de usar expect eofresolvió el problema.
moertel
Retire el 'de usr@$myhost.example.com'y debería funcionar. Y tal vez es necesario sustituir \ncon \r, pero tu caso es distinto
Tino
20

Después de buscar una respuesta para la pregunta durante meses, finalmente encuentro la mejor solución: escribir un guión simple.

#!/usr/bin/expect

set timeout 20

set cmd [lrange $argv 1 end]
set password [lindex $argv 0]

eval spawn $cmd
expect "Password:"
send "$password\r";
interact

Póngalo en /usr/bin/exp, luego puede usar:

  • exp <password> ssh <anything>
  • exp <password> scp <anysrc> <anydst>

¡Hecho!

maldita sea
fuente
expect "assword:"a que te refieres expect "password:"?
usuario
1
@user "assword"coincidirá con ambos Passwordy password.
Ferdinand.kraft
8

También asegúrese de usar

send -- "$PWD\r" 

en cambio, ya que las contraseñas que comienzan con un guión (-) fallarán de lo contrario.

Lo anterior no interpretará una cadena que comience con un guión como una opción para el comando de envío.

Timmah
fuente
8

Un guión de esperar simple

Remotelogin.exp

    #!/usr/bin/expect
    set user [lindex $argv 1]
    set ip [lindex $argv 0]
    set password [lindex $argv 2]
    spawn ssh $user@$ip
    expect "password"
    send "$password\r"
    interact

Ejemplo:

    ./Remotelogin.exp <ip> <user name> <password>
Vijay SB
fuente
7

Use la herramienta auxiliar fd0ssh(de hxtools, no pmt), funciona sin tener que esperar un aviso particular del programa ssh.

usuario562374
fuente
¡Esto es genial! Es un poco difícil hacerlo funcionar (al menos en el servidor ubuntu) pero funciona sin problemas. La configuración que hicimos: echo "yoursshpass" | fd0ssh ssh -c -L$port:$ip:$remote_port [email protected] & ¡GRACIAS!
JP Illanes
1
Mucho más seguro que pasar la contraseña en la línea de comando como lo sshpasshace.
Charles Duffy
5

Otra forma que encontré útil para usar un script pequeño de esperar de un script bash es la siguiente.

...
bash-script start
bash-commands
...
expect - <<EOF 
spawn your-command-here
expect "some-pattern"
send "some-command"
...
...
EOF
...
more bash commands
...

Esto funciona porque ...If the string "-" is supplied as a filename, standard input is read instead...

Jimbo
fuente
No necesita el -aquí, como se expectlee de stdinforma predeterminada si lo invoca sin argumento. Sin embargo, es útil si desea ejecutarlo interactivamente sin símbolo del sistema ( expectvs. expect -) o en caso de que haga algo como expect -f "$@"donde el primer argumento será un archivo, incluso si parece una opción (comienza con -). En ese caso, si $1(el archivo dado) se -lee esto stdin.
Tino
1

sshpassse rompe si intenta usarlo dentro del objetivo de construcción de Sublime Text, dentro de un Makefile. En lugar de sshpassque pueda usar passh: https://github.com/clarkwang/passh

Contigo sshpassharías:

sshpass -p pa$$word ssh user@host

Contigo passhharías:

passh -p pa$$word ssh user@host

Nota: No olvide usar -o StrictHostKeyChecking=no, de lo contrario la conexión se bloqueará la primera vez que la use. Por ejemplo:

passh -p pa$$word ssh -o StrictHostKeyChecking=no user@host

Referencias

  1. El comando de envío de contraseña no funciona utilizando el script de espera en la conexión ssh
  2. /ubuntu/87449/how-to-disable-strict-host-key-checking-in-ssh
  3. https://linuxcommando.blogspot.com/2008/10/how-to-disable-ssh-host-key-checking.html
  4. /server/330503/scp-without-known-hosts-check
  5. https://debian-administration.org/article/587/pam_mount_and_sshfs_with_password_authentication
usuario
fuente