ป้อนรหัสผ่าน SSH โดยอัตโนมัติด้วยสคริปต์


194

ฉันต้องสร้างสคริปต์ที่ป้อนรหัสผ่านโดยอัตโนมัติไปยังsshไคลเอนต์OpenSSH

สมมติว่าฉันต้อง SSH เข้ากับรหัสผ่านmyname@somehosta1234b

ฉันได้ลองแล้ว ...

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

... แต่นี่ใช้ไม่ได้

ฉันจะนำฟังก์ชันนี้มาใช้เป็นสคริปต์ได้อย่างไร

คำตอบ:


278

แรกที่คุณจำเป็นต้องติดตั้งsshpass

  • อูบุนตู / Debian: apt-get install sshpass
  • Fedora / CentOS: yum install sshpass
  • โค้ง: pacman -S sshpass

ตัวอย่าง:

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

ตัวอย่างพอร์ตที่กำหนดเอง:

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

หมายเหตุ:

  • sshpassยังสามารถอ่านรหัสผ่านจากไฟล์เมื่อมีการ-fตั้งค่าสถานะ
    • การใช้-fจะป้องกันไม่ให้มองเห็นรหัสผ่านหากดำเนินการpsคำสั่ง
    • ไฟล์ที่เก็บรหัสผ่านควรมีการอนุญาตที่ปลอดภัย

12
สิ่งนี้ดีกว่าการคาดหวัง
ต่อ Mejdal Rasmussen

5
เพิ่งทราบว่าในขณะที่ sshpass บล็อกรหัสผ่านของคุณจากคำสั่งเช่นps -auxปกติคุณไม่ควรเรียกใช้คำสั่งโดยพิมพ์รหัสผ่านของคุณเพราะผู้ใช้รายอื่นในคอมพิวเตอร์เครื่องเดียวกันอาจเห็นรหัสผ่านps -auxได้ หากใช้งานได้จริงคุณต้องใช้การพิสูจน์ตัวตนด้วยรหัสสาธารณะแทนเช่นที่กล่าวไว้ในคำตอบอื่น สิ่งนี้ช่วยให้คุณสามารถแยกข้อมูลการรับรองความถูกต้องออกจากสคริปต์ของคุณเพื่อให้คุณสามารถแบ่งปันสคริปต์ของคุณกับผู้อื่นได้อย่างไร้กังวลและตัดสินใจเปิดใช้งานการเข้ารหัสในโฟลเดอร์ ~ / .ssh ของคุณในภายหลังโดยไม่ต้องเข้ารหัสสคริปต์
Alexander Taylor

2
น่าเสียดายที่นี่ไม่ทำงานสำหรับฉันบนเซิร์ฟเวอร์ที่มีพอร์ต ssh ที่กำหนดเอง ... ทำไม ssh ไม่ให้ตัวเลือกในการใส่รหัสผ่านในบรรทัดคำสั่ง
Andy

2
สำหรับพอร์ตที่กำหนดเองเพื่อทำงานเพิ่ม "-p หมายเลขพอร์ต" ที่ส่วนท้ายของคำสั่ง
Ye Lwin Soe

1
ผมได้เพิ่มคำตอบกับการใช้งานความปลอดภัยมากขึ้น sshpass
เอียน

96

หลังจากมองหาคำตอบของคำถามเป็นเวลาหลายเดือนในที่สุดฉันก็พบทางออกที่ดีกว่า: เขียนสคริปต์ง่าย ๆ

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

นำไปใช้/usr/bin/expแล้วคุณสามารถใช้:

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

ทำ!


2
คำตอบนี้ควรได้รับคะแนนเสียงมากขึ้น imo มันเป็นเสื้อคลุมที่ดี เพิ่งลองการดำเนินการทั่วไปสองสามอย่างเช่น rsyncing ด้วยแฟล็กต่างๆและการดำเนินการคำสั่งรีโมต เพิ่มไปยังกล่องเครื่องมือของสคริปต์ที่มีประโยชน์แล้วขอบคุณ @damn_c!
user2082382

7
อาจจะไม่ได้รับการโหวตเพิ่มขึ้นอีกเพราะคนไม่คาดหวัง
clearlight

7
เหตุผลว่าทำไมถึงเป็น IMO ไม่ได้คำตอบที่ดีมากเป็นเพราะรหัสผ่านจะถูกเขียนในสคริปต์ซึ่งคือไกลโดยวิธีที่ปลอดภัยอย่างน้อย ...
PierreE

8
ทุกคนที่เรียกใช้ ps บนเครื่องจะมองเห็นรหัสผ่านได้
Daniel Persson


71

ใช้การตรวจสอบคีย์สาธารณะ: https://help.ubuntu.com/community/SSH/OpenSSH/Keys

ในโฮสต์ต้นทางให้รันสิ่งนี้เพียงครั้งเดียว:

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

นั่นคือทั้งหมดหลังจากนั้นคุณจะสามารถทำ ssh ได้โดยไม่ต้องใช้รหัสผ่าน


21
ฉันเห็น. แต่ฉันต้องการรหัสผ่าน ssh นี่เป็นเพราะ "ฉัน" อาจมีสคริปต์บนธัมบ์ไดรฟ์และจำเป็นต้องเรียกใช้จากคอมพิวเตอร์เครื่องใดก็ได้ ในขณะที่ไม่ได้ปิดการใช้งานความต้องการรหัสผ่าน
user1467855

3
@ user1467855 ฉันคิดว่าคุณต้องอธิบายความต้องการของคุณให้ดีขึ้น ไม่มีใครแนะนำว่าคุณมีเครือข่ายที่ไม่ปลอดภัย ในวิธีการใช้รหัสสาธารณะผู้ใช้สามารถเข้าสู่ระบบด้วยรหัสผ่านได้ แต่คุณจะคัดลอกคีย์ส่วนตัวไปที่ thumb drive ซึ่งหมายความว่า thumb drive จะเป็นสิ่งเดียวที่สามารถเข้าสู่ระบบได้โดยไม่ต้องใช้รหัสผ่าน
Aaron McDaid

5
น่าเสียดายที่ฉันอยู่ในสถานการณ์ OP เนื่องจาก sysadmin ไม่อนุญาตการพิสูจน์ตัวตนโดยใช้คีย์ rsa / dsa และต้องใช้รหัสผ่าน คุณจะทำอะไร
Karel Bílek

27
ลงเนื่องจากไม่ได้ลองตอบคำถามจริงที่ถาม
คู่ปรับ Shot

2
สิ่งนี้ยังคงพร้อมท์สำหรับการเข้าสู่ระบบครั้งแรกและไม่สามารถใช้ในสคริปต์ได้!
Mehrdad Mirreza

29

คุณสามารถใช้สคริปต์ที่คาดหวัง ฉันยังไม่ได้เขียนสักครู่ แต่ควรมีลักษณะดังนี้ คุณจะต้องมุ่งหน้าสคริปต์ด้วย#!/usr/bin/expect

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

ฉันทำตามที่คุณแนะนำ แต่ได้รับข้อผิดพลาดดังต่อไปนี้:/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

ขอบคุณ Aaron สำหรับการแก้ไขคำตอบของฉันให้ถูกต้อง คุณอาจจำเป็นต้องเรียกใช้คำสั่งด้านล่างเพื่อค้นหาเส้นทางที่ถูกต้องสำหรับการคาดหวัง which expect
Lipongo

1
นอกจากนี้คุณยังสามารถใช้บรรทัด shebang นี้:#!/usr/bin/env expect
glenn jackman

1
ฉันเพิ่มinteractไปยังจุดสิ้นสุดดังนั้นเซสชัน ssh จึงเป็นแบบโต้ตอบจริง ๆ
Karel Bílek

-1 สำหรับความเสี่ยงด้านความปลอดภัยขนาดใหญ่ในการเก็บรหัสผ่านข้อความธรรมดาในสคริปต์
Aaron Digulla

21

ตัวแปร I

sshpass -p PASSWORD ssh USER@SERVER

Variant II

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

-pธงสำหรับการระบุหมายเลขพอร์ต
Kookerus

4
ไม่ sshpass ไม่ใช่ ssh SYNOPSIS sshpass [-ffilename|-dnum|-ppassword|-e] [options] command arguments
RemiZOffAlex

เพื่อที่จะรัน sshpass ใน Linux CentOS คุณต้องyum -y install epel-releaseแล้วyum -y install sshpass
จูเนียร์Mayhé

ในบริบทนี้ของข้อมูลนี้สามารถละเว้น
RemiZOffAlex

ในขณะที่ฉันรู้ว่านี่เป็นโพสต์เก่า แต่ก็น่าสังเกตว่าวิธี Variant II จะปล่อยรหัสผ่านที่กำหนดให้กับเซสชันที่มีช่องโหว่ในประวัติทุบตีทำให้ไม่น่าสนใจอย่างมาก
เคิร์กแลนด์

11

sshpass + autossh

โบนัสที่ดีอย่างหนึ่งของที่กล่าวถึงแล้วsshpassคือคุณสามารถใช้งานได้โดยautosshกำจัดการขาดประสิทธิภาพเชิงโต้ตอบได้มากขึ้น

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

วิธีนี้จะช่วยให้การเชื่อมต่ออัตโนมัติทำได้เช่นถ้า WiFi ของคุณถูกขัดจังหวะด้วยการปิดแล็ปท็อปของคุณ


2
โปรดทราบว่าคุณไม่สามารถเพิ่มตัวเลือก-fให้ autossh ในชุดนี้ได้เพราะwhen used with autossh, ssh will be *unable* to ask for passwords or passphrases. harding.motd.ca/autossh/README.txtยังsuperuser.com/questions/1278583/ …
allenyllee

9

sshpass ด้วยความปลอดภัยที่ดีขึ้น

ฉันสะดุดหัวข้อนี้ในขณะที่มองหาวิธีการ ssh ลงในเซิร์ฟเวอร์ที่จมอยู่กับที่ - ใช้เวลาหนึ่งนาทีในการประมวลผลความพยายามในการเชื่อมต่อ SSH และหมดเวลาก่อนที่ฉันจะสามารถป้อนรหัสผ่าน ในกรณีนี้ฉันต้องการที่จะสามารถจัดหารหัสผ่านของฉันได้ทันทีเมื่อมีข้อความแจ้ง

(และหากยังไม่ชัดเจนอย่างเจ็บปวด: ด้วยเซิร์ฟเวอร์ในสถานะนี้มันสายเกินไปที่จะตั้งค่าการเข้าสู่ระบบกุญแจสาธารณะ)

sshpassช่วยเหลือ. sshpass -pแต่มีวิธีที่ดีกว่าที่จะไปเกี่ยวกับเรื่องนี้มากกว่า

การนำไปใช้ของฉันข้ามไปยังพรอมต์รหัสผ่านแบบโต้ตอบโดยตรง (ไม่เสียเวลาดูว่าสามารถแลกเปลี่ยนกุญแจสาธารณะได้หรือไม่) และไม่เคยเปิดเผยรหัสผ่านเป็นข้อความธรรมดา

#!/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
หมายเหตุตนเอง: สคริปต์อัปเดตที่จะใช้trapเพื่อป้องกันไม่ให้ Ctrl-C จากรั่วSSHPASSตัวแปร
เอียน

1
ฉันพบว่าใช้งานPreferredAuthentications=keyboard-interactiveไม่ได้ แต่แทนที่ด้วยการPreferredAuthentications=passwordทำงาน
Mike Partridge

8

นี่คือวิธีที่ฉันเข้าสู่เซิร์ฟเวอร์ของฉัน

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

#! / bin / ทุบตี

sshpass -p mypassword ssh root @ $ 1

และดังนั้นจึง...

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

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


3
ฉันคิดว่าบทความนี้กำลังประชดประชัน!
Yan Foto

5

ฉันไม่คิดว่าฉันเห็นใครแนะนำสิ่งนี้และ OP เพียงแค่พูดว่า "สคริปต์" ดังนั้น ...

ฉันต้องการแก้ปัญหาเดียวกันและภาษาที่สะดวกสบายที่สุดของฉันคือ Python

ฉันใช้ห้องสมุด paramiko sudoนอกจากนี้ฉันยังต้องออกคำสั่งที่ฉันจะต้องมีสิทธิ์เพิ่มขึ้นโดยใช้ ปรากฎว่า sudo สามารถรับรหัสผ่านของมันผ่าน stdin ผ่านทางธง "-S" ได้! ดูด้านล่าง:

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

หวังว่านี่จะช่วยใครซักคน กรณีการใช้งานของฉันคือการสร้างไดเรกทอรีการส่งและการลบไฟล์และเริ่มโปรแกรมบนเซิร์ฟเวอร์ ~ 300 ครั้ง ดังนั้นระบบอัตโนมัติจึงเป็นสิ่งสำคัญยิ่ง ฉันพยายามsshpass, expectและจากนั้นมาด้วยนี้


2

ฉันได้งานนี้ดังนี้

.ssh / config ได้รับการแก้ไขเพื่อกำจัดใช่ / ไม่ใช่พรอมต์ - ฉันอยู่หลังไฟร์วอลล์ดังนั้นฉันจึงไม่กังวลเกี่ยวกับปุ่ม ssh ปลอมแปลง

host *
     StrictHostKeyChecking no

สร้างไฟล์ตอบกลับสำหรับความคาดหวังเช่น 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

สร้างสคริปต์ทุบตีของคุณและเพียงแค่โทรคาดหวังในไฟล์

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

  expect answer.expect hadoopslave$i

  i=[$i + 1]
  sleep 5

done

รับ 128 hadoop datanodes รีเฟรชด้วย config ใหม่ - สมมติว่าคุณใช้ NFS mount สำหรับไฟล์ hadoop / conf

หวังว่านี่จะช่วยใครซักคน - ฉันเป็น Windows numpty และใช้เวลาประมาณ 5 ชั่วโมงในการหา!


"ฉันอยู่หลังไฟร์วอลล์ดังนั้นฉันจึงไม่กังวลเกี่ยวกับการปลอมแปลงคีย์ ssh" ไฟร์วอลล์ไม่ทำอะไรเลยในกรณีนี้ HostKeyCheck นั้นเพื่อให้คุณสามารถตรวจสอบโฮสต์ในส่วนอื่น ๆ ไม่ใช่โฮสต์โทรจัน นั่นคือการแกล้งทำเป็นว่าคุณต้องการเชื่อมต่อกับ หากคุณเชื่อมต่อกับโฮสต์ที่ไม่รู้จักและทำบางสิ่งที่ละเอียดอ่อนเช่นเขียนไฟล์ที่มีข้อมูลประจำตัวหรือโทเค็นหรือป้อนรหัสผ่านตอนนี้ข้อมูลนั้นจะเป็นความรู้สาธารณะอย่างมีประสิทธิภาพ คุณอยู่หลังไฟร์วอลล์ไม่เกี่ยวข้อง
JCGB

2

หากคุณกำลังทำสิ่งนี้ในระบบ Windows คุณสามารถใช้ Plink (ส่วนหนึ่งของ PuTTY)

plink your_username@yourhost -pw your_password




0

ในตัวอย่างตะโกนฉันจะเขียนทางออกที่ฉันใช้:

สถานการณ์: ฉันต้องการคัดลอกไฟล์จากเซิร์ฟเวอร์โดยใช้ 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"

-2

ใช้สคริปต์นี้ tossh ภายในสคริปต์อาร์กิวเมนต์แรกคือชื่อโฮสต์และที่สองจะเป็นรหัสผ่าน

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

สิ่งนี้แสดงให้เห็นด้านบนของคำตอบที่มีอยู่? โดยเฉพาะผู้ที่ damn_c, Lipongo หรือ RemiZOffAlex และคนอื่น ๆ ...
Martin Prikryl

การดำเนินการกับสคริปต์พร้อมกับ ssh #! / usr / bin / คาดว่า set pass [lindex $ argv 1] set host [lindex $ argv 0] วางไข่ ssh -t root @ $ host sh /tmp/anyscript.sh คาดหวัง "* assword:" ส่ง "$ pass \ n"; การโต้ตอบ "
Shivam Mehrotra

-3

ในการเชื่อมต่อเครื่องระยะไกลผ่านเชลล์สคริปต์ให้ใช้คำสั่งด้านล่าง:

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

ที่IPADDRESS, USERNAMEและPASSWORDมีค่าการป้อนข้อมูลที่จำเป็นต้องให้ในสคริปต์หรือถ้าเราต้องการที่จะให้ในการใช้งานรันไทม์ "อ่าน" คำสั่ง


5
คำตอบนี้แสดงให้เห็นอะไรเหนือคำตอบที่มีอยู่ + ไม่เคยแนะนำให้ใครใช้StrictHostKeyChecking=noโดยไม่ต้องอธิบายผลที่ตามมา
Martin Prikryl

-5
sudo ssh username@server_ip_address -p port_number

กดปุ่ม enter แล้วป้อนรหัสผ่านระบบของคุณจากนั้นในที่สุดก็ป้อนรหัสผ่านเซิร์ฟเวอร์ของคุณ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.