Automatycznie wprowadź hasło SSH za pomocą skryptu

194

Muszę utworzyć skrypt, który automatycznie wprowadza hasło do OpenSSH ssh klienta .

Powiedzmy, że muszę myname@somehostwprowadzić hasło SSHa1234b .

Próbowałem już ...

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

... ale to nie działa.

Jak mogę wprowadzić tę funkcjonalność do skryptu?

użytkownik 1467855
źródło

Odpowiedzi:

278

Najpierw musisz zainstalować sshpass .

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

Przykład:

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

Przykład niestandardowego portu:

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

Uwagi:

  • sshpassmoże również odczytać hasło z pliku po przekazaniu -fflagi.
    • Użycie -fzapobiega wyświetleniu hasła, jeśli pspolecenie zostanie wykonane.
    • Plik, w którym przechowywane jest hasło, powinien mieć bezpieczne uprawnienia.
abbotto
źródło
12
Jest to o wiele lepsze niż używanie funkcji Expect.
Per Mejdal Rasmussen
5
pamiętaj tylko, że podczas gdy sshpass blokuje twoje hasło przed takimi poleceniami ps -aux, nie powinieneś normalnie uruchamiać poleceń, wpisując swoje hasło, ponieważ inni użytkownicy na tym samym komputerze mogą zobaczyć hasło po uruchomieniu ps -aux. jeśli jest to praktyczne, zamiast tego należy również użyć uwierzytelniania za pomocą klucza publicznego, jak wspomniano w drugiej odpowiedzi. pozwala to oddzielić informacje uwierzytelniające od skryptu, abyś mógł bez obaw udostępniać skrypt innym użytkownikom, a następnie zdecydować się na włączenie szyfrowania w folderze ~ / .ssh bez szyfrowania skryptu.
Alexander Taylor
2
Niestety, to nie działa dla mnie na serwerze z niestandardowym portem ssh ... dlaczego ssh nie może po prostu dać nam opcji wstawienia hasła w wierszu poleceń?
Andy,
2
aby niestandardowy port działał, dodaj „-p numer portu” na końcu polecenia
Ye Lwin Soe
95

Po miesiącach szukania odpowiedzi na pytanie, w końcu znalazłem lepsze rozwiązanie: napisanie prostego skryptu.

#!/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

Włóż to /usr/bin/exp, a następnie możesz użyć:

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

Gotowe!

cholera
źródło
2
Ta odpowiedź powinna uzyskać więcej głosów imo, jest to świetne opakowanie. Właśnie wypróbowałem kilka typowych operacji, takich jak rsyncing z różnymi flagami i zdalne wykonywanie poleceń i zadziałało za każdym razem. Dodano do mojego zestawu przydatnych skryptów, dzięki @damn_c!
user2082382
7
Może nie zyskał więcej głosów, ponieważ ludzie się tego nie spodziewali?
jasne
7
Powodem, dla którego IMO nie jest zbyt dobrą odpowiedzią, jest to, że hasło jest zapisane w skrypcie, który jest zdecydowanie najmniej bezpieczną metodą ...
PierreE
8
Hasło będzie widoczne dla każdego, kto uruchomi ps na maszynie.
Daniel Persson
22
„assword” jest niesamowity :-)
Ciro Santilli 29 冠状 病 六四 事件 法轮功
71

Użyj uwierzytelniania za pomocą klucza publicznego: https://help.ubuntu.com/community/SSH/OpenSSH/Keys

Na hoście źródłowym uruchom to tylko raz:

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

To wszystko, po czym będziesz mógł robić ssh bez hasła.

Diego Woitasen
źródło
21
Widzę. Ale jestem WYMAGANY, aby ssh z hasłem. Wynika to z faktu, że „I” może mieć skrypt na dysku USB i trzeba go uruchomić z dowolnego komputera; nie wyłączając potrzeby hasła.
user1467855,
3
@ user1467855, myślę, że musisz lepiej wyjaśnić swoje wymagania. Nikt nie sugeruje, że masz niezabezpieczoną sieć. W podejściu opartym na kluczu publicznym użytkownicy nadal będą mogli logować się przy użyciu hasła. Ale skopiowałbyś klucz prywatny na dysk USB, co oznacza, że ​​dysk USB byłby jedyną rzeczą, która może zalogować się bez hasła.
Aaron McDaid
5
Niestety jestem w sytuacji OP, ponieważ sysadmin nie zezwala na uwierzytelnianie za pomocą kluczy rsa / dsa i wymaga haseł. Co zrobisz.
Karel Bílek,
26
Zagłosowano, ponieważ nawet nie próbuje odpowiedzieć na zadane pytanie.
Parthian Shot
2
Nadal pojawia się monit o pierwsze logowanie i nie można go użyć w skrypcie!
Mehrdad Mirreza
29

Możesz użyć skryptu oczekuje. Od jakiegoś czasu nie napisałem żadnego, ale powinien wyglądać jak poniżej. Musisz kierować skryptem#!/usr/bin/expect

#!/usr/bin/expect -f
spawn ssh HOSTNAME
expect "login:" 
send "username\r"
expect "Password:"
send "password\r"
interact
Lipongo
źródło
Zrobiłem tak, jak zasugerowałeś, ale dostaję następujące błędy:/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
Dzięki Aaron za zmianę mojej odpowiedzi, aby była poprawna. Może być konieczne uruchomienie poniższej komendy, aby znaleźć poprawną ścieżkę do wprowadzenia w oczekiwaniu. which expect
Lipongo,
1
Możesz także użyć tej linii #!/usr/bin/env expect
shebang
1
Dodałem interactdo końca, aby sesja ssh była interaktywna
Karel Bílek,
-1 dla ogromnego ryzyka bezpieczeństwa związanego z utrzymywaniem hasła w postaci zwykłego tekstu w skrypcie.
Aaron Digulla
21

Wariant I

sshpass -p PASSWORD ssh USER@SERVER

Wariant II

#!/usr/bin/expect -f
spawn ssh USERNAME@SERVER "touch /home/user/ssh_example"
expect "assword:"
send "PASSWORD\r"
interact
RemiZOffAlex
źródło
-pFlaga jest do określania numeru portu.
Kookerus,
4
Nie. Sshpass nie jest ssh. SYNOPSIS sshpass [-ffilename|-dnum|-ppassword|-e] [options] command arguments
RemiZOffAlex,
Aby uruchomić sshpass w Linux CentOS, musisz, yum -y install epel-releasea następnieyum -y install sshpass
Junior Mayhé
W tym kontekście te dane można zignorować
RemiZOffAlex
Chociaż wiem, że jest to stary post, warto zauważyć, że metoda Wariant II pozostawiłaby hasło podane do sesji narażone na atak w historii basha, co czyni go wysoce niewskazanym.
Kirkland,
10

sshpass + autossh

Jedną z miłych zalet wspomnianego wyżej sshpassjest to, że można go używać autossh, eliminując jeszcze więcej interaktywnej nieefektywności.

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

Umożliwi to automatyczne połączenie, jeśli np. Twoje Wi-Fi zostanie przerwane przez zamknięcie laptopa.

Sridhar Sarnobat
źródło
2
Zauważ, że nie możesz dodać opcji -fdo autossh w tej kombinacji, ponieważ when used with autossh, ssh will be *unable* to ask for passwords or passphrases. harding.motd.ca/autossh/README.txt także superuser.com/questions/1278583/…
allenyllee 23.08.18
9

sshpass z lepszym bezpieczeństwem

Natknąłem się na ten wątek, szukając sposobu, aby ssh przełączyć się na zawieszony serwer - przetworzenie próby połączenia SSH zajęło ponad minutę i upłynął limit czasu, zanim mogłem wprowadzić hasło. W takim przypadku chciałem móc podać hasło natychmiast po pojawieniu się monitu.

(A jeśli nie jest to boleśnie jasne: z serwerem w tym stanie jest o wiele za późno, aby skonfigurować login klucza publicznego.)

sshpassna pomoc. Istnieją jednak lepsze sposoby na rozwiązanie tego problemusshpass -p .

Moja implementacja przechodzi bezpośrednio do interaktywnego monitu o hasło (nie tracę czasu na sprawdzenie, czy może nastąpić wymiana klucza publicznego) i nigdy nie ujawnia hasła jako zwykłego tekstu.

#!/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
Ian
źródło
1
uwaga do siebie: zaktualizuj skrypt, aby użyć, trapaby zapobiec wyciekaniu ctrl-C ze SSHPASSzmiennej
Ian
1
Okazało się, że PreferredAuthentications=keyboard-interactiveto nie działa, ale zastąpienie go działaniem PreferredAuthentications=password.
Mike Partridge,
8

W ten sposób loguję się na moje serwery.

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

#! / bin / bash

sshpass -p mojehasło ssh root @ 1 $

I dlatego...

ssp server_ip
DimiDak
źródło
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

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

RmccurdyDOTcom
źródło
3
Myślę, że ten artykuł jest po prostu sarkastyczny!
Yan Foto
5

Chyba nie widziałem, żeby ktokolwiek to sugerował, a OP powiedział po prostu „skrypt”, więc ...

Musiałem rozwiązać ten sam problem, a moim najwygodniejszym językiem jest Python.

Użyłem biblioteki paramiko. Ponadto musiałem wydawać polecenia, dla których potrzebowałbym eskalowanych uprawnień sudo. Okazuje się, że sudo może zaakceptować swoje hasło poprzez stdin poprzez flagę „-S”! Patrz poniżej:

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!")

Mam nadzieję, że to komuś pomoże. Moim przypadkiem użycia było tworzenie katalogów, wysyłanie i rozpakowywanie plików oraz uruchamianie programów na ~ 300 serwerach. Dlatego automatyzacja była najważniejsza. Próbowałem sshpass, expecta potem to wymyśliłem.

John Carrell
źródło
2

Mam to działa w następujący sposób

.ssh / config został zmodyfikowany w celu wyeliminowania monitu o tak / nie - jestem za firewallem, więc nie martwię się o sfałszowane klucze ssh

host *
     StrictHostKeyChecking no

Utwórz plik odpowiedzi dla expect, tj. 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

Utwórz skrypt bash i po prostu wywołaj expect w pliku

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

  expect answer.expect hadoopslave$i

  i=[$i + 1]
  sleep 5

done

Pobiera 128 kodów danych hadoop odświeżonych dzięki nowej konfiguracji - przy założeniu, że używasz podłączenia NFS dla plików hadoop / conf

Mam nadzieję, że to komuś pomoże - jestem Windows numpty i zajęło mi to około 5 godzin!

WT29
źródło
„Jestem za firewallem, więc nie martwię się o sfałszowane klucze ssh”. W tym przypadku zapora nie robi nic. HostKeyCheck umożliwia sprawdzenie, czy host na drugim końcu nie jest hostem trojańskim. Tj., Który udaje, że jest tam, gdzie chcesz się połączyć. Jeśli łączysz się z nieznanym hostem i robisz coś delikatnego, na przykład piszesz plik z poświadczeniami lub tokenem lub wpisujesz hasło, informacje te są teraz skutecznie znane opinii publicznej. Bycie za zaporą ogniową nie ma znaczenia.
JCGB
2

Jeśli robisz to w systemie Windows, możesz użyć Plink (część PuTTY).

plink your_username@yourhost -pw your_password
Marko Vranjkovic
źródło
1

Udało mi się z tym pracować:

SSH_ASKPASS="echo \"my-pass-here\""
ssh -tt remotehost -l myusername
Konstantin Ineshin
źródło
0

W poniższym przykładzie napiszę rozwiązanie, którego użyłem:

Scenariusz: chcę skopiować plik z serwera za pomocą skryptu sh:

#!/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"
BERGUIGA Mohamed Amine
źródło
-2

Użyj tego skryptu w skrypcie, Pierwszy argument to nazwa hosta, a drugi to hasło.

#!/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"
Shivam Mehrotra
źródło
Co to pokazuje oprócz istniejących odpowiedzi? Szczególnie te autorstwa damn_c, Lipongo lub RemiZOffAlex i innych ...
Martin Prikryl
wykonanie skryptu wraz z ssh #! / usr / bin / expect set pass [lindex $ argv 1] set host [lindex $ argv 0] spawn ssh -t root @ $ host sh /tmp/anyscript.sh expect "* assword:" wyślij „$ pass \ n”; interakcji ”
Shivam Mehrotra
-3

Aby podłączyć zdalną maszynę za pomocą skryptów powłoki, użyj poniższego polecenia:

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

gdzie IPADDRESS, USERNAMEa PASSWORDto wartości wejściowe, które muszą dostarczyć w skrypcie, albo jeśli chcemy zapewnić w użyciu wykonawczego „read” polecenie.

shyam
źródło
5
Co ta odpowiedź pokazuje obok istniejących odpowiedzi? + Nigdy nie sugeruj nikomu korzystania StrictHostKeyChecking=nobez wyjaśnienia konsekwencji.
Martin Prikryl,
-5
sudo ssh username@server_ip_address -p port_number

naciśnij klawisz enter, a następnie wprowadź hasło systemowe, a następnie na koniec hasło serwera

Manoj Rana
źródło