Geben Sie das SSH-Passwort automatisch mit dem Skript ein


193

Ich muss ein Skript erstellen, das automatisch ein Kennwort für den OpenSSH- sshClient eingibt .

Angenommen, ich muss myname@somehostmit dem Passwort SSH a1234b.

Ich habe es schon versucht ...

#~/bin/myssh.sh
ssh myname@somehost
a1234b

... aber das funktioniert nicht.

Wie kann ich diese Funktionalität in ein Skript integrieren?

Antworten:


278

Zuerst müssen Sie sshpass installieren .

  • Ubuntu / Debian: apt-get install sshpass
  • Fedora / CentOS: yum install sshpass
  • Bogen: pacman -S sshpass

Beispiel:

sshpass -p "YOUR_PASSWORD" ssh -o StrictHostKeyChecking=no YOUR_USERNAME@SOME_SITE.COM

Beispiel für einen benutzerdefinierten Port:

sshpass -p "YOUR_PASSWORD" ssh -o StrictHostKeyChecking=no YOUR_USERNAME@SOME_SITE.COM:2400

Anmerkungen:

  • sshpasskann auch ein Passwort aus einer Datei lesen, wenn das -fFlag übergeben wird.
    • Die Verwendung -fverhindert, dass das Kennwort sichtbar wird, wenn der psBefehl ausgeführt wird.
    • Die Datei, in der das Kennwort gespeichert ist, sollte über sichere Berechtigungen verfügen.

12
Dies ist viel besser als die Verwendung von Expect.
Per Mejdal Rasmussen

5
Beachten Sie jedoch, dass sshpass Ihr Kennwort zwar für Befehle wie blockiert ps -aux, Sie jedoch normalerweise keine Befehle ausführen sollten, indem Sie Ihr Kennwort eingeben, da andere Benutzer auf demselben Computer das Kennwort möglicherweise durch Ausführen sehen können ps -aux. Wenn dies sinnvoll ist, möchten Sie stattdessen auch die Authentifizierung mit öffentlichem Schlüssel verwenden, wie in der anderen Antwort erwähnt. Auf diese Weise können Sie Authentifizierungsinformationen von Ihrem Skript trennen, damit Sie Ihr Skript problemlos für andere freigeben und später die Verschlüsselung in Ihrem Ordner ~ / .ssh aktivieren können, ohne auch Ihr Skript zu verschlüsseln.
Alexander Taylor

2
Leider funktioniert dies bei einem Server mit einem benutzerdefinierten SSH-Port nicht. Warum kann SSH uns nicht einfach die Option geben, das Kennwort in die Befehlszeile einzufügen?
Andy

2
Damit der benutzerdefinierte Port funktioniert, fügen Sie am Ende des Befehls "-p Portnummer" hinzu
Ye Lwin Soe


95

Nachdem ich monatelang nach einer Antwort auf die Frage gesucht hatte, fand ich endlich eine bessere Lösung: ein einfaches Skript zu schreiben.

#!/usr/bin/expect

set timeout 20

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

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

Setzen Sie es auf /usr/bin/exp, dann können Sie verwenden:

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

Getan!


2
Diese Antwort sollte imo mehr Stimmen bekommen, es ist ein großartiger Wrapper. Ich habe gerade ein paar gängige Operationen wie Rsyncing mit verschiedenen Flags und Remote-Befehlsausführung ausprobiert und es hat jedes Mal funktioniert. Zu meiner Toolbox mit nützlichen Skripten hinzugefügt, Danke @damn_c!
user2082382

7
Vielleicht hat es nicht mehr positive Stimmen bekommen, weil die Leute es nicht erwartet haben?
klares Licht

7
Der Grund, warum dies IMO keine sehr gute Antwort ist, ist, dass das Passwort in das Skript geschrieben ist, was bei weitem die am wenigsten sichere Methode ist ...
PierreE

8
Das Passwort ist für jeden sichtbar, der ps auf dem Computer ausführt.
Daniel Persson


71

Verwenden Sie die Authentifizierung mit öffentlichem Schlüssel: https://help.ubuntu.com/community/SSH/OpenSSH/Keys

Führen Sie dies auf dem Quellhost nur einmal aus:

ssh-keygen -t rsa # ENTER to every field
ssh-copy-id myname@somehost

Das ist alles, danach können Sie ssh ohne Passwort ausführen.


21
Aha. Aber ich muss mit Passwort ssh. Dies liegt daran, dass "I" das Skript möglicherweise auf einem USB-Stick hat und es von jedem Computer aus ausführen muss. ohne die Notwendigkeit eines Passworts zu deaktivieren.
user1467855

3
@ user1467855, ich denke, Sie müssen Ihre Anforderungen besser erklären. Niemand schlägt vor, dass Sie ein unsicheres Netzwerk haben. Beim Public-Key-Ansatz können sich Benutzer weiterhin mit dem Kennwort anmelden. Sie würden jedoch den privaten Schlüssel auf Ihr USB-Stick kopieren. Dies bedeutet, dass nur das USB-Stick ohne Kennwort angemeldet werden kann.
Aaron McDaid

5
Leider bin ich in einer OP-Situation, da der Systemadministrator die Authentifizierung durch rsa / dsa-Schlüssel nicht zulässt und Passwörter benötigt. Was wirst du tun.
Karel Bílek

26
Abgestimmt, weil dies nicht einmal versucht, die tatsächlich gestellte Frage zu beantworten.
Parthian Shot

2
Dies fordert immer noch zur ersten Anmeldung auf und kann nicht in einem Skript verwendet werden!
Mehrdad Mirreza

29

Sie können ein Expect-Skript verwenden. Ich habe seit einiger Zeit keine mehr geschrieben, aber es sollte wie folgt aussehen. Sie müssen das Skript mit leiten#!/usr/bin/expect

#!/usr/bin/expect -f
spawn ssh HOSTNAME
expect "login:" 
send "username\r"
expect "Password:"
send "password\r"
interact

Ich habe getan, was Sie vorgeschlagen haben, aber die folgenden Fehler erhalten:/bin/myssh.sh: 2: spawn: not found /bin/myssh.sh: 3: expect: not found /bin/myssh.sh: 4: send: not found /bin/myssh.sh: 5: expect: not found /bin/myssh.sh: 6: send: not found
user1467855

Vielen Dank an Aaron, dass er meine Antwort so geändert hat, dass sie korrekt ist. Möglicherweise müssen Sie den folgenden Befehl ausführen, um den richtigen Pfad für die erwartete Eingabe zu finden. which expect
Lipongo

1
Sie können auch diese Shebang-Linie verwenden:#!/usr/bin/env expect
Glenn Jackman

1
Ich interacthabe am Ende hinzugefügt , damit die SSH-Sitzung tatsächlich interaktiv ist
Karel Bílek

-1 für das enorme Sicherheitsrisiko, ein Nur-Text-Passwort in einem Skript zu behalten.
Aaron Digulla

21

Variante I.

sshpass -p PASSWORD ssh USER@SERVER

Variante II

#!/usr/bin/expect -f
spawn ssh USERNAME@SERVER "touch /home/user/ssh_example"
expect "assword:"
send "PASSWORD\r"
interact

Das -pFlag dient zur Angabe einer Portnummer.
Kookerus

4
Nein, sshpass ist nicht ssh. SYNOPSIS sshpass [-ffilename|-dnum|-ppassword|-e] [options] command arguments
RemiZOffAlex

Um sshpass in Linux CentOS auszuführen, müssen Sie yum -y install epel-releaseund dannyum -y install sshpass
Junior Mayhé

In diesem Zusammenhang können diese Daten ignoriert werden
RemiZOffAlex

Obwohl ich weiß, dass dies ein alter Beitrag ist, ist es erwähnenswert, dass die Variant II-Methode das der Sitzung zugewiesene Kennwort in der Bash-Historie anfällig macht, was es höchst nicht ratsam macht.
Kirkland

10

sshpass + autossh

Ein netter Bonus des bereits erwähnten sshpassist, dass Sie es verwenden können autossh, wodurch noch mehr interaktive Ineffizienz beseitigt wird.

sshpass -p mypassword autossh -M0 -t myusername@myserver.mydomain.com

Dies ermöglicht die automatische Wiederverbindung, wenn beispielsweise Ihr WLAN durch Schließen Ihres Laptops unterbrochen wird.


2
Beachten Sie, dass Sie nicht Option hinzufügen können -fzu autossh in dieser Kombination, weil when used with autossh, ssh will be *unable* to ask for passwords or passphrases. harding.motd.ca/autossh/README.txt auch superuser.com/questions/1278583/...
allenyllee

9

sshpass mit besserer Sicherheit

Ich bin auf diesen Thread gestoßen, als ich nach einer Möglichkeit gesucht habe, in einen festgefahrenen Server zu ssh - es dauerte über eine Minute, um den SSH-Verbindungsversuch zu verarbeiten, und es trat eine Zeitüberschreitung auf, bevor ich ein Kennwort eingeben konnte. In diesem Fall wollte ich mein Passwort sofort eingeben können, wenn die Eingabeaufforderung verfügbar war.

(Und wenn es nicht schmerzlich klar ist: Mit einem Server in diesem Zustand ist es viel zu spät, eine Anmeldung mit öffentlichem Schlüssel einzurichten.)

sshpasszur Rettung. Es gibt jedoch bessere Möglichkeiten, dies zu tun alssshpass -p .

Meine Implementierung springt direkt zur interaktiven Kennwortabfrage (keine Zeitverschwendung, um festzustellen, ob ein Austausch öffentlicher Schlüssel möglich ist) und zeigt das Kennwort niemals als einfachen Text an.

#!/bin/sh
# preempt-ssh.sh
# usage: same arguments that you'd pass to ssh normally
echo "You're going to run (with our additions) ssh $@"

# Read password interactively and save it to the environment
read -s -p "Password to use: " SSHPASS 
export SSHPASS

# have sshpass load the password from the environment, and skip public key auth
# all other args come directly from the input
sshpass -e ssh -o PreferredAuthentications=keyboard-interactive -o PubkeyAuthentication=no "$@"

# clear the exported variable containing the password
unset SSHPASS

1
Hinweis für sich selbst: Aktualisieren Sie das Skript, um trapzu verhindern, dass Strg-C die SSHPASSVariable verliert
Ian

1
Ich fand, dass PreferredAuthentications=keyboard-interactivedas nicht funktionierte, aber es durch PreferredAuthentications=passwordfunktionierte zu ersetzen .
Mike Partridge

7

So melde ich mich bei meinen Servern an.

ssp <server_ip>
  • alias ssp = '/ home / myuser / Documents / ssh_script.sh'
  • cat /home/myuser/Documents/ssh_script.sh

#! / bin / bash

sshpass -p mypassword ssh root @ $ 1

Und deshalb...

ssp server_ip

5
# create a file that echo's out your password .. you may need to get crazy with escape chars or for extra credit put ASCII in your password...
echo "echo YerPasswordhere" > /tmp/1
chmod 777 /tmp/1

# sets some vars for ssh to play nice with something to do with GUI but here we are using it to pass creds.
export SSH_ASKPASS="/tmp/1"
export DISPLAY=YOURDOINGITWRONG
setsid ssh root@owned.com -p 22

Referenz: https://www.linkedin.com/pulse/youre-doing-wrong-ssh-plain-text-credentials-robert-mccurdy?trk=mp-reader-card


3
Ich denke, dieser Artikel ist nur sarkastisch!
Yan Foto

5

Ich glaube nicht, dass ich jemanden gesehen habe, der dies vorschlägt, und das OP hat nur "Skript" gesagt, also ...

Ich musste das gleiche Problem lösen und meine bequemste Sprache ist Python.

Ich habe die Paramiko-Bibliothek benutzt. Außerdem musste ich Befehle ausgeben, für die ich eskalierte Berechtigungen benötigen würde sudo. Es stellt sich heraus, dass sudo sein Passwort über stdin über das "-S" -Flag akzeptieren kann! Siehe unten:

import paramiko

ssh_client = paramiko.SSHClient()

# To avoid an "unknown hosts" error. Solve this differently if you must...
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

# This mechanism uses a private key.
pkey = paramiko.RSAKey.from_private_key_file(PKEY_PATH)

# This mechanism uses a password.
# Get it from cli args or a file or hard code it, whatever works best for you
password = "password"

ssh_client.connect(hostname="my.host.name.com",
                       username="username",
                       # Uncomment one of the following...
                       # password=password
                       # pkey=pkey
                       )

# do something restricted
# If you don't need escalated permissions, omit everything before "mkdir"
command = "echo {} | sudo -S mkdir /var/log/test_dir 2>/dev/null".format(password)

# In order to inspect the exit code
# you need go under paramiko's hood a bit
# rather than just using "ssh_client.exec_command()"
chan = ssh_client.get_transport().open_session()
chan.exec_command(command)

exit_status = chan.recv_exit_status()

if exit_status != 0:
    stderr = chan.recv_stderr(5000)

# Note that sudo's "-S" flag will send the password prompt to stderr
# so you will see that string here too, as well as the actual error.
# It was because of this behavior that we needed access to the exit code
# to assert success.

    logger.error("Uh oh")
    logger.error(stderr)
else:
    logger.info("Successful!")

Hoffe das hilft jemandem. Mein Anwendungsfall bestand darin, Verzeichnisse zu erstellen, Dateien zu senden und zu entpacken und Programme auf ~ 300 Servern gleichzeitig zu starten. Daher war die Automatisierung von größter Bedeutung. Ich habe versucht sshpass, expectund dann mit diesem kam.


2

Ich habe das wie folgt funktionieren lassen

.ssh / config wurde geändert, um die Ja / Nein-Eingabeaufforderung zu beseitigen. Ich bin hinter einer Firewall und mache mir keine Sorgen über gefälschte SSH-Schlüssel

host *
     StrictHostKeyChecking no

Erstellen Sie eine Antwortdatei für "Expect", dh "answer.expect"

set timeout 20
set node [lindex $argv 0]
spawn ssh root@node service hadoop-hdfs-datanode restart

expect  "*?assword {
      send "password\r"   <- your password here.

interact

Erstellen Sie Ihr Bash-Skript und rufen Sie in der Datei "require" auf

#!/bin/bash
i=1
while [$i -lt 129]    # a few nodes here

  expect answer.expect hadoopslave$i

  i=[$i + 1]
  sleep 5

done

Ruft 128 Hadoop-Datenknoten ab, die mit der neuen Konfiguration aktualisiert wurden - vorausgesetzt, Sie verwenden einen NFS-Mount für die Hadoop / Conf-Dateien

Hoffe, das hilft jemandem - ich bin eine Windows-Nummer und ich habe ungefähr 5 Stunden gebraucht, um das herauszufinden!


"Ich bin hinter einer Firewall, also mache ich mir keine Sorgen um gefälschte SSH-Schlüssel." Eine Firewall macht in diesem Fall genau nichts. Mit dem HostKeyCheck können Sie überprüfen, ob der Host am anderen Ende kein Trojaner-Host ist. Dh eine, die nur vorgibt, dort zu sein, wo Sie sich verbinden möchten. Wenn Sie eine Verbindung zu einem unbekannten Host herstellen und etwas Sensibles tun, z. B. eine Datei mit Anmeldeinformationen oder einem Token schreiben oder ein Kennwort eingeben, sind diese Informationen nun effektiv öffentlich bekannt. Es ist irrelevant, dass Sie sich hinter einer Firewall befinden.
JCGB

2

Wenn Sie dies auf einem Windows-System tun, können Sie Plink (Teil von PuTTY) verwenden.

plink your_username@yourhost -pw your_password



1

Ich habe es geschafft, damit zu arbeiten:

SSH_ASKPASS="echo \"my-pass-here\""
ssh -tt remotehost -l myusername

0

Im folgenden Beispiel schreibe ich die Lösung, die ich verwendet habe:

Das Szenario: Ich möchte eine Datei mit einem sh-Skript von einem Server kopieren:

#!/usr/bin/expect
$PASSWORD=password
my_script=$(expect -c "spawn scp userName@server-name:path/file.txt /home/Amine/Bureau/trash/test/
expect \"password:\"
send \"$PASSWORD\r\"
expect \"#\"
send \"exit \r\"
")

echo "$my_script"

-2

Verwenden Sie dieses Skript innerhalb des Skripts. Das erste Argument ist der Hostname und das zweite das Kennwort.

#!/usr/bin/expect
set pass [lindex $argv 1]
set host [lindex $argv 0]
spawn ssh -t root@$host echo Hello
expect "*assword: " 
send "$pass\n";
interact"

Was zeigt dies zusätzlich zu den vorhandenen Antworten? Besonders die von damn_c, Lipongo oder RemiZOffAlex und anderen ...
Martin Prikryl

Skriptausführung zusammen mit ssh #! / usr / bin / erwarten set pass [lindex $ argv 1] set host [lindex $ argv 0] spawn ssh -t root @ $ host sh /tmp/anyscript.sh erwarten "* assword:" sende "$ pass \ n"; interagieren "
Shivam Mehrotra

-3

Verwenden Sie den folgenden Befehl, um eine Remote-Maschine über Shell-Skripte zu verbinden:

sshpass -p PASSWORD ssh -o StrictHostKeyChecking=no USERNAME@IPADDRESS

wo IPADDRESS, USERNAMEund PASSWORDsind Eingangsgrößen , die in Skript zur Verfügung stellen müssen, oder wenn wir in Runtime Verwendung zur Verfügung stellen möchten „lesen“ Befehl.


5
Was zeigt diese Antwort zusätzlich zu den vorhandenen Antworten? + Schlagen Sie niemals jemandem vor, StrictHostKeyChecking=noohne die Konsequenzen zu erklären.
Martin Prikryl

-5
sudo ssh username@server_ip_address -p port_number

Drücken Sie die Eingabetaste und geben Sie dann das Kennwort Ihres Systems und schließlich Ihr Serverkennwort ein

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.