ฉันจะโอน Multihop SCP ได้อย่างไร


85

ฉันต้องการคัดลอกไฟล์จากเครื่อง A ไปยังเซิร์ฟเวอร์ C แต่มีสิทธิ์เข้าถึงเซิร์ฟเวอร์ C ผ่านเซิร์ฟเวอร์ B เท่านั้น

แทนที่จะถ่ายโอนไปยังเซิร์ฟเวอร์ B เป็นครั้งแรกให้ลงชื่อเข้าใช้แล้วโอนไปยังเซิร์ฟเวอร์ C คุณสามารถถ่ายโอนไฟล์โดยตรงกับ SCP หรือโปรแกรมที่คล้ายกันได้หรือไม่

(โหมดคนเดินเท้า Emacs มีคุณสมบัตินี้สำหรับการแก้ไขไฟล์จากระยะไกล)

คำตอบ:


48

คุณสามารถเพิ่ม-oตัวเลือกในการแทนscp.ssh/config

scp -o ProxyCommand="ssh $jump_host nc $host 22" $local_path $host:$destination_path

$jump_host คือ "เซิร์ฟเวอร์ B" ของคุณในกรณีนี้


นี่สิวิธีที่ฉันชอบในการทำเช่นนี้ Messing up .ssh / config สำหรับ multihopping ไม่ใช่ทางออกที่ดีที่สุดหากคุณเข้าถึงโฮสต์เดียวกันทั้งจากเกตเวย์และโดยตรง
GabrieleV

สิ่งนี้จะเป็นอย่างไรกับชื่อผู้ใช้และพอร์ตที่แตกต่างกัน / ที่กำหนดเอง
ปาโบล

ฉันลองทำสิ่งนี้และต้องป้อนรหัสผ่าน ฉันจะแก้ไขสิ่งนี้ได้อย่างไร ขอบคุณ
hqt

44

สมมติว่า OpenSSH ให้เพิ่มการกำหนดค่า SSH ของคุณใน. ssh / config

Host distant
ProxyCommand ssh near nc distant 22

สิ่งนี้จะทำให้ SSH สามารถเชื่อมต่อ "โดยตรง" กับเครื่องที่ชื่อไกลได้โดยการมอบฉันทะผ่านเครื่องที่ตั้งชื่อใกล้ จากนั้นสามารถใช้แอปพลิเคชันเช่น scp และ sftp ไปยังเครื่องที่อยู่ห่างไกล

เพื่อให้สามารถใช้งานได้คุณต้องใช้ 'nc' หรือที่เรียกว่า netcat ติดตั้งบนเครื่องที่มีชื่อใกล้เคียง แต่ระบบสมัยใหม่จำนวนมากจะมีอยู่แล้ว

โซลูชัน tar ของ towo นั้นมีประสิทธิภาพมากกว่าสำหรับปัญหาที่เกิดขึ้นครั้งเดียวโดยสมมติว่าคุณได้จดจำไวยากรณ์และกฎการใช้งานของ tar


นี่คือวิธีการเดียวกันที่ผมใช้ ... ในตัวอย่างนี้ 'ไกล' จะเซิร์ฟเวอร์ C และ 'ใกล้' จะเซิร์ฟเวอร์ B สำหรับการชี้แจง ...
เจเรมี Bouse

เครื่องจักรที่ทันสมัยจำนวนมากไม่มี 'nc': โดยปกติจะใช้ได้เฉพาะกับเครื่อง Linux และตามคำขอเท่านั้น (ไม่ใช่ส่วนหนึ่งของการติดตั้งมาตรฐาน)
พ.ค.

1
ssh มีตัวเลือก -W ในขณะนี้ทำสิ่งนี้โดยอัตโนมัติโดยไม่ต้อง 'nc' แต่ฉันสงสัยว่าทำไมไม่มี scp -W
kubanczyk

3
ในกรณีที่ฉันไม่ใช่คนเดียวที่ไม่เห็นได้ชัด: หากชื่อผู้ใช้บนnearแตกต่างจากชื่อผู้ใช้บนdistantผู้ใช้ใกล้จะเข้ามาProxyCommand ssh nearuser@near...และผู้ใช้ที่อยู่ห่างไกลจะแยกเป็นUser distantuserบรรทัด
Mu Mind

เพียงแค่พิมพ์ความหวังหลาย ๆ ssh และกด Google ฉันรู้สึกโชคดี
chandank

19

ด้วยเวอร์ชันล่าสุดของ ssh บนเซิร์ฟเวอร์ near (B) machine ต่อไปนี้จะทำงานโดยไม่ต้อง netcat:

Host distant
    ProxyCommand ssh near -W distant:22

อย่างไรก็ตามจะต้องมี AllowTcpForwarding เป็น yes (ค่าเริ่มต้น) บนเครื่อง near (B)

แก้ไข: ต้องใช้ OpenSSH 5.4+ บน B


ใช้งานได้เหมือนมีเสน่ห์ :)
gongzhitaao

1
และอย่างน้อยที่สุดของ OpenSSH 7.4p1 จะมีคำสั่ง "ProxyJump" ซึ่งมีเพียงรายการเดียวที่แสดงรายการ user @ host: port ที่คั่นด้วยเครื่องหมายจุลภาค ดี!
hmijail

ProxyJump ดี แต่ไม่ได้ใช้ User และ IdentityFile จากไฟล์ปรับแต่ง ProxyCommand -W ทำสิ่งนี้และทำงานกับ scp
rickfoosusa

18

คุณสามารถ ssh ไปยังเซิร์ฟเวอร์ B โดยใช้สิ่งที่ชอบ

ssh -L 5022:<server C IP>:22 <user_serverB>@<server B IP>

จากนั้นคุณสามารถ ssh ไปยังเซิร์ฟเวอร์ C โดยใช้

ssh -p 5022 <user_serverC>@localhost 

SCP ในทำนองเดียวกันจะทำงานโดยใช้

scp -P 5022 foo.txt <user_serverc>@localhost:

อย่าลืมใช้ตัวพิมพ์ที่ถูกต้องของ p ด้วย scp และ ssh


5

เป็นไปได้และค่อนข้างง่ายแม้ว่าคุณจะต้องใช้ใบรับรองสำหรับการตรวจสอบสิทธิ์ (โดยทั่วไปในสภาพแวดล้อม AWS)

คำสั่งด้านล่างจะคัดลอกไฟล์จากremotePathบนโดยตรงลงในเครื่องของคุณที่server2 localPathภายในคำขอ SCP server1ตั้งพร็อกซีผ่าน

scp -i user2-cert.pem -o ProxyCommand="ssh -i user1-cert.pem -W %h:%p user1@server1" user2@server2:/<remotePath> <localpath>

วิธีอื่น ๆ ก็ใช้งานได้เช่นกัน (อัปโหลดไฟล์):

scp -i user2-cert.pem -o ProxyCommand="ssh -i user1-cert.pem -W %h:%p user1@server1" <localpath> user2@server2:/<remotePath>

หากคุณใช้การรับรองความถูกต้องของรหัสผ่านแทนลองด้วย

scp -o ProxyCommand="ssh -W %h:%p user1@server1" user2@server2:/<remotePath> <localpath>

หากคุณใช้ข้อมูลรับรองผู้ใช้เดียวกันในเซิร์ฟเวอร์ทั้งสอง:

scp -o ProxyCommand="ssh -W %h:%p commonuser@server1" commonuser@server2:/<remotePath> <localpath>

3

หากคุณต้องการที่จะชั่วร้ายจริงๆคุณสามารถเชน SSH และ tar บางอย่างเช่นtar c mydir | ssh server "ssh otherserver | tar x"แต่สิ่งนี้สามารถทำงานในทุกปัญหา

วิธีที่ง่ายกว่าคือการตั้งค่าอุโมงค์ SSH ด้วยวิธีการในตัวของ SSH ดู-Dสวิตช์ใน manpage และส่งต่อพอร์ตไปยังพอร์ต ssh ของเซิร์ฟเวอร์อื่น


2

คุณสามารถทำสิ่งนี้ได้ในทางกลับกันและอาจจะง่ายกว่า

สมมติว่าคุณเปิดเซสชัน ssh ด้วยเครื่องที่คุณต้องการส่งไฟล์ไป พีซีเครื่องนี้ที่ไกลที่สุดเราจะเรียกว่า hop2 นี้ โฮสต์ "proxy" ของคุณจะเป็น hop1 พีซีที่เป็นแหล่งกำเนิดไฟล์เราจะเรียกแหล่งกำเนิดนั้น

origin:~/asdf.txt  --> hop1 --> hop2:~/asdf.txt

คุณสามารถสร้างอุโมงค์ทำให้มีพอร์ตในตัวเครื่องบนพีซีระยะไกล เราจึงกำหนดพอร์ตที่จะเปิดบนพีซีระยะไกลซึ่งจะเป็นการเปลี่ยนเส้นทางไปยังพอร์ตที่คุณดึงมากับคุณเมื่อคุณสร้างอุโมงค์

ใน hop2:

ssh -R 5555:127.0.0.1:22 <hop1_user>@<hop1_IP>
#this has the effect of building a tunnel from hop2 to hop1, making hop2's port 22 available on hop1 as port 5555

ขณะนี้ในเซสชันอุโมงค์ที่เปิดคุณสามารถทำเช่นเดียวกันจาก hop1 ถึง file_origin

ใน hop1:

ssh -R 6666:127.0.0.1:5555 <origin_user>@<origin_IP>
#this has the effect of building a tunnel from hop1 to origin while also pulling the active tunnel with it, making hop1's port 5555 (hop2's port 22) available on origin as port 6666.

ตอนนี้คุณถูกส่งจาก hop2 ไปยัง hop1 ไปยังต้นทาง ตอนนี้ทั้งพอร์ต 5555 และ 6666 เปิดพร้อมกันแล้วซึ่งถูกเปลี่ยนเส้นทางไปที่พอร์ตของ hop2 22 ภายในเซสชันนี้ทั้งสองต่อไปนี้เป็นเส้นทาง scp ที่ถูกต้องไปยัง hop2:

บนกำเนิด:

scp -P 6666 ~/asdf.txt <hop2_user>@<127.0.0.1>:~/asdf.txt

ด้วยวิธีนี้คุณสามารถมีจำนวนฮ็อปที่กำหนดเองได้และมันง่ายกว่าที่จะทำงานร่วมกันในแง่ของการผูกมัดกันมากกว่าสองฮ็อพ


1

ลองปรับใช้ตัวอย่างต่อไปนี้ openssh config สำหรับการตั้งค่าที่สามารถใช้กับโฮสต์หลายเครื่องได้:

Host uat-*
     ProxyCommand ssh bastion-uat nc %h %p

สิ่งนี้จะสันนิษฐานชุดของเซิร์ฟเวอร์ที่ขึ้นต้นด้วย "uat-" ที่สามารถเข้าถึงได้ผ่านทาง jumpbox / เกตเวย์เซิร์ฟเวอร์ "bastion-uat" เท่านั้น คุณอาจต้องการเพิ่มForwardAgent yesถ้าคุณใช้รหัสเพื่อเข้าสู่ระบบ


อย่าใช้ForwardAgent yesเพื่อสิ่งนี้ การส่งต่อตัวแทนไม่จำเป็นในกรณีนี้เนื่องจากไม่มีไคลเอ็นต์ ssh ที่จะทำงานบนป้อมปราการและการส่งต่อตัวแทนเมื่อไม่จำเป็นต้องลดความปลอดภัยลง และฉันคิดว่าsshคำสั่งของคุณหายไป หากsshคุณไม่ต้องการใช้เวอร์ชันล่าสุดncคุณสามารถพิมพ์ssh -W %h:%p bastion-uatแทนได้
kasperd

@kasperd แก้ไขเพื่อรวม ssh Re ForwardAgent; ไคลเอ็นต์ ssh จะทำงานเพื่อรันคำสั่ง nc เอง บางทีคุณกำลังอ้างถึงเชลล์?
Benjamin Goodacre

1

นี่ไม่ใช่ SCP (ที่ OP ร้องขอ) แต่ฉันพบว่ามันง่ายมากที่จะใช้rsyncเพื่อคัดลอกจากโลคัลไปยังรีโมตผ่าน hop เดียวด้วย:

rsync -v -e 'ssh -A -t user@jumpserver ssh -A -t user@destinationserver' /path/to/sourcefile :/path/to/destination

ที่มา: http://mjbright.blogspot.com/2012/09/using-rsync-over-multi-hop-ssh.html

ฉันได้ลองใช้คำแนะนำ -o ProxyPass แล้วและไม่ต้องการเปลี่ยนการตั้งค่าสำหรับความต้องการที่เปลี่ยนแปลงของฉัน ในฐานะผู้เขียนในลิงค์ด้านบนสถานะไฟล์ปลายทางที่อยู่ก่อนหน้าโคลอน (:) เป็นสิ่งสำคัญที่จะระบุเส้นทางที่ระบุอยู่บนเซิร์ฟเวอร์ปลายทาง นอกจากนี้การใช้ rsync คุณมีตัวเลือกเปรียบเทียบวันที่ซิงค์โฟลเดอร์ ฯลฯ ฉันหวังว่าสิ่งนี้จะช่วยให้ใครบางคน!


-2

scp -o 'ProxyJump jumpboxname' somefilename.txt finaldestinationhost: / tmp /


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