ไฟล์ scp ผ่านโฮสต์ระดับกลาง


85

ฉันเข้าถึง 3 เครื่อง A, B และ C การเชื่อมต่อที่เป็นไปได้เท่านั้น (ssh) คือ:

A -> B
B <-> C

ฉันต้องการรับไฟล์จาก A ถึง C ดังนั้นฉันจึงสามารถสแกนไฟล์จาก A ถึง B แล้ว scp จาก B ถึง C อย่างไรก็ตาม B มีพื้นที่ดิสก์ไม่มากดังนั้นจึงไม่ใช่ตัวเลือก มีวิธีการ scp ไฟล์จาก A ถึง C ผ่าน B หรือไม่? หมายเหตุฉันไม่สามารถเข้าถึงรูทบนเครื่องใด ๆ ได้ดังนั้นอย่าคิดว่าฉันสามารถตั้งค่าอุโมงค์ถาวรใด ๆ ได้ แต่แก้ไขฉันถ้าฉันผิด!


6
ฉันรู้ว่านี่ไม่ได้ตอบคำถาม แต่สำหรับผู้ที่ไม่ทราบเกี่ยวกับ rsync หรือไม่รู้วิธีใช้เพื่อข้ามโฮสต์สิ่งนี้อาจเป็นเคล็ดลับที่มีประโยชน์: ใช้ตัวเลือก '-e' ด้วย rsync เช่นนี้:A$ rsync <options> -e 'ssh B ssh' source C:destination
แก้ไขเมื่อ

คำตอบ:


108

ProxyJump

ใหม่ใน OpenSSH 7.3:

A$ scp -oProxyJump=B thefile C:destination

(เบื้องหลังจะใช้ ProxyCommand และssh -W.)

ProxyCommand

อัปเดตเพื่อรวม -W จากคำตอบอื่น ๆ :

A$ scp -oProxyCommand="ssh -W %h:%p B" thefile C:destination

ถ้า A มีไคลเอ็นต์ SSH เก่ามากติดตั้ง (ไม่-Wสนับสนุน) หรือถ้า B ได้รับการกำหนดค่าให้ไม่อนุญาตการส่งต่อ TCP (แต่ยังคงอนุญาตให้ใช้คำสั่งเชลล์) ให้ใช้ทางเลือกอื่น:

A$ scp -oProxyCommand="ssh B socat stdio tcp:%h:%p" thefile C:destination
A$ scp -oProxyCommand="ssh B nc %h %p" thefile C:destination

ท่อ

A$ tar cf - thefile anotherfile | ssh B "ssh C \"cd destination && tar xvf -\""
A$ (echo thefile; echo anotherfile) | cpio -o | ssh B "ssh C \"cd destination && cpio -i\""

สำหรับไฟล์เดียว:

A$ ssh B "ssh C \"cd destination && cat > thefile\"" < thefile

"อุโมงค์" ถึง B

A$ ssh -f -N -L 4567:C:22 B
(continues running in background)

A$ scp -P 4567 thefile localhost:destinationPath

เมื่อคุณทำเสร็จแล้วอย่าลืมที่จะฆ่าเริ่มต้นก่อนหน้านี้sshกระบวนการ (ซึ่งได้ลดลงถึงพื้นหลังเนื่องจากการ-f -N)

  • -fร้องขอ ssh เพื่อไปยังพื้นหลังก่อนการดำเนินการคำสั่ง สิ่งนี้มีประโยชน์ถ้า ssh จะขอรหัสผ่านหรือวลีรหัสผ่าน แต่ผู้ใช้ต้องการมันในพื้นหลัง นี่หมายถึง -n
  • -Nอย่าดำเนินการคำสั่งระยะไกล สิ่งนี้มีประโยชน์สำหรับการส่งต่อพอร์ต

สลับ "อุโมงค์" ไปทาง B ถึง A

ไม่สามารถใช้งานได้เสมอ:

A$ ssh -f -N -R 4567:localhost:22 B
(now you can reach A from B, by using localhost:4567)

B$ scp -P 4567 localhost:thefile C:destination
  • -R ระบุว่าการเชื่อมต่อกับพอร์ต TCP ที่กำหนดหรือซ็อกเก็ต Unix บนโฮสต์ระยะไกล (เซิร์ฟเวอร์) จะถูกส่งต่อไปยังโฮสต์และพอร์ตที่กำหนดหรือซ็อกเก็ต Unix ที่อยู่ด้านโลคัล

ขอบคุณมากสำหรับตัวอย่างเหล่านี้ @grawity คำถามหนึ่ง - เป็นไปได้หรือไม่ที่จะกลับ `tar c thefile anotherfile | ssh B "ssh C \" cd ปลายทาง && tar xv \ "" ´เพื่อคัดลอกดาวน์โหลดจาก C ไปยัง A (อยู่บน A)
dmeu

@dmeu: ใช่มันเป็นไปได้
grawity

วิธี "ฆ่า" กระบวนการ ssh ที่เริ่มต้นก่อนหน้านี้ถ้าบอกว่าฉันใช้ MacOS
Aero Windwalker

หมายเหตุ: ตามปกติถ้าคุณต้องการscp จาก C, แม้ว่า B, ไป A, A$ scp -oProxyJump=B C:destination thefileคุณสามารถทำได้
jvriesem

@Pablo ดีกว่าใช้ -S จากนั้นและ -O ออก หรือ ... อย่างน้อย pkill -f
grawity

24

รุ่นของ scp ตั้งแต่ต้นปี 2011 เป็นต้นไปอาจมีตัวเลือก "-3":

 -3      Copies between two remote hosts are transferred through the local
         host.  Without this option the data is copied directly between
         the two remote hosts.  Note that this option disables the
         progress meter.

หากคุณมีสิ่งนี้คุณสามารถเรียกใช้:

B$ scp -3 A:file C:file

ในกรณีของฉันโฮสต์ A สามารถเข้าถึงได้จาก B เท่านั้น (ซึ่งเป็น VPNed) Host C อยู่บน LAN เดียวกันกับ B. ฉันต้องการรับไฟล์จาก A ถึง C และ scp -3 แก้ปัญหาได้อย่างยอดเยี่ยม
Joe

ฉันมีปัญหากับเรื่องนี้เมื่อโฮสต์ทั้งสองร้องขอรหัสผ่าน ดูเหมือนว่าจะขอทั้งสองอย่างพร้อมกัน (มีรหัสผ่านปรากฏขึ้นสองบรรทัดในบรรทัดเดียวกัน) จากนั้นไม่สามารถยอมรับรหัสผ่านของฉันได้ ในที่สุดฉันก็สามารถทำให้มันทำงานได้โดยการพิมพ์รหัสผ่านซ้ำ ๆ (รหัสผ่านเดียวกันกับทั้งสองโฮสต์) แต่ก็ยากที่จะเข้าใจ
Colin D

8

เกือบทั้งหมดได้รับการพูดไปแล้ว แต่นี่คือเงินล่าสุดของฉัน: ผมใช้ ProxyCommand แตกต่างโดยไม่ต้องมิได้nc socจากOpenSSH Proxies และ Jumphost Cookbookฉันได้สร้างการกำหนดค่าต่อไปนี้:

  1. ดังนั้นเราจึงมีผู้เล่นดังต่อไปนี้:

    • HOME_HOST: เป็นที่ที่เราคัดลอกไฟล์ไปยังโฮสต์เป้าหมาย
    • HOP_HOST: เราคัดลอกผ่านโฮสต์นี้ (บันทึกเป็น HOP_USER)
    • TARGET_HOST: เป็นปลายทางของเรา (รับรองความถูกต้องเป็น TARGET_USER)
  2. ก่อนอื่นฉันเพิ่มกุญแจสาธารณะในพื้นที่ของฉันจากโฮสต์ที่บ้านของฉัน.ssh/id_dsa.pub ไป.ssh/authorized_keysที่ทั้งโฮสต์และโฮสต์เป้าหมาย ใช่คีย์สาธารณะเดียวกันจากโฮสต์ที่บ้านถึงทั้งคู่ โดยปกติแล้วคุณจะคาดหวังว่ามันจะเป็นกุญแจสาธารณะของ HOP ที่คุณต้องเพิ่มไปยังเป้าหมาย

  3. จากนั้นฉันปรับแต่ง.ssh/configเล็กน้อยโดยเพิ่มรายการต่อไปนี้:

    Host TARGET_HOST
       User TARGET_USER
       ProxyCommand ssh -W %h:%p HOP_USER@HOP_HOST
    
  4. scp FILE TARGET_HOST:หลังจากนั้นดำเนินการคัดลอกเป็นง่ายๆเป็น: มันแสดงแบนเนอร์สองเท่าจากทั้ง hop และโหนดเป้าหมาย แต่ใช้งานได้

แน่นอนคุณอาจจะใช้ด้านบนเพื่อ ssh ssh TARGET_HOSTโดยตรงไปยังเป้าหมาย: มันทำงานร่วมกับ SCP และ SSH

ตัวเลือกทั่วไปอื่น ๆ อาจเป็นยูทิลิตีsshuttleซึ่งดูเหมือนจะเป็นชนิดของพร็อกซีแบบโปร่งใส (vpn over ssh) ดังนั้นในกรณีของ A-> B <-> C จะอนุญาตให้เชื่อมต่อกับแต่ละโหนดที่เครือข่ายของ C: A-> B- [CDEFG] มันไม่ต้องการผู้ดูแล แต่มันก็ต้องใช้ Python 2.7 (3.5 ก็โอเค) ซึ่งไม่ได้เป็นอย่างที่เรามี มันคุ้มค่าที่จะลอง


7
ssh -L 4321:hostC:22 youruser@hostB

ในเปลือกอื่น:

scp -P 4321 localfile youruser@127.0.0.1

นี่คือการใช้การส่งต่อพอร์ต ข้อ จำกัด เพียงอย่างเดียวในที่นี้คือต้องกำหนดค่าโฮสต์ B เพื่ออนุญาตให้ส่งต่อพอร์ต มิฉะนั้นจะทำงานได้ดี

ในทางของคำอธิบาย-Lและ-Rช่วยให้คุณสามารถส่งต่อพอร์ต ใน-Lพอร์ตแรกที่กำหนดคือพอร์ต ssh จะเริ่มฟังบนเครื่องต้นทาง (โฮสต์ A) และจะส่งต่อสิ่งใด ๆ ที่ได้รับบนพอร์ตนั้นผ่านการเชื่อมต่อ SSH ของคุณไปยังโฮสต์ B จากนั้นกำหนดเส้นทางไปยังโฮสต์ C บนพอร์ต 22

แก้ไข

ฉันสับสนไวยากรณ์เล็กน้อย มันตั้งค่าไปข้างหน้าบนเครื่อง LOCAL ของคุณ


@astrofrog - หากคำตอบข้อใดข้อหนึ่งของเราตรงกับความต้องการของคุณคุณควรยอมรับหนึ่งในนั้น
Brian Vandenberg

2

คำตอบ ProxyCommand ของ Grawity เหมาะสำหรับฉัน แต่เนื่องจากฉันไม่ค่อยคุ้นเคยกับ SSH จึงต้องทำการทดลอง ฉันคิดว่าฉันจะสะกดคำตอบของ Grawity พร้อมรายละเอียดเพิ่มเติมเพื่อช่วยมือใหม่คนอื่น ๆ ให้ SSH เหมือนตัวฉัน นี่คือคำจำกัดความสำหรับสัญกรณ์ที่ชัดเจนยิ่งขึ้น:

เครื่อง A:เครื่องที่คุณเปิดอยู่

เซิร์ฟเวอร์ B: userB@ip.address.for.B (กระโดดโฮสต์หรือเซิร์ฟเวอร์กลาง)

เซิร์ฟเวอร์ C: userC@ip.address.for.C (เซิร์ฟเวอร์ระยะไกลที่คุณต้องการคัดลอกไป)

ProxyCommnad

    A$ scp -oProxyCommand="ssh -W %h:%p userB@ip.address.for.B" thefile userC@ip.address.for.C:destination

ตัวอย่างคอนกรีต

ดังนั้นสำหรับตัวอย่างที่เป็นรูปธรรมสมมติว่าคุณสามารถเข้าถึงเซิร์ฟเวอร์ที่มี IP 0.0.1.2ด้วยบัญชีผู้ใช้ชื่อbar(เซิร์ฟเวอร์ C) แต่ก่อนอื่นคุณต้องลงชื่อเข้าใช้เซิร์ฟเวอร์ด้วย IP 0.0.1.1ด้วยชื่อบัญชีผู้ใช้foo(เซิร์ฟเวอร์ B) ตอนนี้คุณต้องการคัดลอกไฟล์ที่baz.txtอยู่ในเครื่องปัจจุบันของคุณ (Machine A) ไปยังไดเรกทอรี0.0.1.2ของเซิร์ฟเวอร์ /home/bar/ในการใช้ProxyCommandด้านบนสำหรับตัวอย่างนี้คุณจะใช้งานดังต่อไปนี้:

    A$ scp -oProxyCommand="ssh -W %h:%p foo@0.0.1.1" baz.txt bar@0.0.1.2:/home/bar/

คุณสามารถคัดลอกไฟล์จากเซิร์ฟเวอร์ C ได้อย่างง่ายดายเพียงแค่สลับลำดับของไฟล์และปลายทาง ดังนั้นสำหรับตัวอย่างเช่นถ้าbaz.txtมีอยู่แล้วบนเซิร์ฟเวอร์0.0.1.2ตั้งอยู่ที่/home/bar/แล้วคุณสามารถคัดลอกไปยังเครื่องของคุณโดยใช้:

    A$ scp -oProxyCommand="ssh -W %h:%p foo@0.0.1.1" bar@0.0.1.2:/home/bar/baz.txt /destination/path/on/A

หวังว่านี่จะช่วยให้คนที่ต้องการสิ่งที่สะกดให้พวกเขามากกว่าคนอื่นเล็กน้อย

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