วิธีกำหนดค่าทางลัดสำหรับการเชื่อมต่อ SSH ผ่านอุโมงค์ SSH


22

เซิร์ฟเวอร์ที่ใช้งานจริงของ บริษัท (FOO, BAR ... ) ตั้งอยู่หลังเซิร์ฟเวอร์เกตเวย์สองเครื่อง (A, B) ในการเชื่อมต่อกับเซิร์ฟเวอร์ FOO ฉันต้องเปิดการเชื่อมต่อ ssh กับเซิร์ฟเวอร์ A หรือ B ด้วยชื่อผู้ใช้ของฉัน JOHNDOE จาก A (หรือ B) ฉันสามารถเข้าถึงเซิร์ฟเวอร์ที่ใช้งานจริงใดก็ได้ที่เปิดการเชื่อมต่อ SSH ด้วยชื่อผู้ใช้มาตรฐาน Webby)

ดังนั้นทุกครั้งที่ฉันต้องทำสิ่งที่ชอบ:

ssh johndoe@a
...
ssh webby@foo
...
# now I can work on the server

อย่างที่คุณสามารถจินตนาการได้ว่านี่เป็นเรื่องยุ่งยากเมื่อฉันต้องใช้งานscpหรือถ้าฉันต้องเปิดการเชื่อมต่อที่หลากหลาย

ฉันได้กำหนดค่าคีย์ ssh และฉันใช้. ssh / config สำหรับทางลัด

ฉันสงสัยว่าฉันสามารถสร้างการกำหนดค่า ssh บางอย่างเพื่อพิมพ์ได้ไหม

ssh foo

และให้ SSH เปิด / ส่งต่อการเชื่อมต่อทั้งหมดให้ฉัน มันเป็นไปได้?

แก้ไข

คำตอบของ womble เป็นสิ่งที่ฉันกำลังมองหา แต่ดูเหมือนว่าตอนนี้ฉันไม่สามารถใช้ netcat ได้เพราะไม่ได้ติดตั้งบนเซิร์ฟเวอร์เกตเวย์

weppos:~ weppos$ ssh foo -vv
OpenSSH_5.1p1, OpenSSL 0.9.7l 28 Sep 2006
debug1: Reading configuration data /Users/xyz/.ssh/config
debug1: Applying options for foo
debug1: Reading configuration data /etc/ssh_config
debug2: ssh_connect: needpriv 0
debug1: Executing proxy command: exec ssh a nc -w 3 foo 22
debug1: permanently_drop_suid: 501
debug1: identity file /Users/xyz/.ssh/identity type -1
debug2: key_type_from_name: unknown key type '-----BEGIN'
debug2: key_type_from_name: unknown key type 'Proc-Type:'
debug2: key_type_from_name: unknown key type 'DEK-Info:'
debug2: key_type_from_name: unknown key type '-----END'
debug1: identity file /Users/xyz/.ssh/id_rsa type 1
debug2: key_type_from_name: unknown key type '-----BEGIN'
debug2: key_type_from_name: unknown key type 'Proc-Type:'
debug2: key_type_from_name: unknown key type 'DEK-Info:'
debug2: key_type_from_name: unknown key type '-----END'
debug1: identity file /Users/xyz/.ssh/id_dsa type 2
bash: nc: command not found
ssh_exchange_identification: Connection closed by remote host

คำตอบ:


36

ในฐานะที่เป็นคำตอบของ Kyle ที่เป็นรูปธรรมมากขึ้นสิ่งที่คุณต้องการใส่ใน~/.ssh/configไฟล์ของคุณคือ:

host foo
  User webby
  ProxyCommand ssh a nc -w 3 %h %p

host a
  User johndoe

จากนั้นเมื่อคุณเรียกใช้ "ssh foo" SSH จะพยายาม SSH ไปที่johndoe@aรันnetcat( nc) จากนั้นดำเนินการ SSH เพื่อwebby@fooผ่านอุโมงค์นี้ มายากล!

แน่นอนในการทำเช่นนี้ netcat จะต้องติดตั้งบนเซิร์ฟเวอร์เกตเวย์ แพคเกจนี้สามารถใช้ได้สำหรับทุกการกระจายที่สำคัญและระบบปฏิบัติการ


ยอดเยี่ยม ฉันพยายามคิดออกว่าฉันไม่เคยเจอสถานการณ์ที่แน่นอนมาก่อน ฉันจะเก็บคำตอบไว้ที่นั่นในกรณีที่อาจช่วยคนอื่นด้วยสถานการณ์ที่เฉพาะเจาะจงน้อยลงในอนาคต
Kyle Brandt

ฉันได้อัปเดตคำถามเดิมของฉันแล้วรวมถึงผลลัพธ์ที่ได้จากการเชื่อมต่อของฉัน ดูเหมือนว่าฉันไม่สามารถใช้ netcat ได้ โดยค่าเริ่มต้นควรหรือไม่
Simone Carletti

ไม่เสมอคุณมีอำนาจในการติดตั้งหรือไม่ คุณอาจจะสามารถทำเช่นนี้กับ Telnet เกินไปผมไม่เคยพยายามที่ ...
ไคล์ Brandt

คุณอาจดาวน์โหลด netcat ไปยังโฮมไดเร็กตอรี่ของคุณและคอมไพล์มันได้ จากนั้นคุณสามารถใช้เส้นทางแบบเต็มในคำสั่งพร็อกซีนั่นคือ / home / ชื่อผู้ใช้ / bin / nc
Kyle Brandt

ฉันเพิ่งตรวจสอบการตั้งค่าระบบ ใน Ubuntu netcat ดูเหมือนว่าจะมีให้ใช้งานตามค่าเริ่มต้น แต่น่าเสียดายที่เกตเวย์เซิร์ฟเวอร์ใช้พลังงานจาก OpenSUSE ฉันจะพิจารณาติดตั้ง netcat บนเซิร์ฟเวอร์เกตเวย์ด้วย
Simone Carletti

7

คุณสามารถใช้คำสั่ง ProxyCommand ในไฟล์ ~ / .ssh / config ของคุณตัวอย่างเช่นการใช้ netcat เป็นรีเลย์:

host server2
    ProxyCommand ssh server1 nc server2 22

คุณแค่ใช้ 'ssh server2' ข้อมูล man page สำหรับคำสั่งนี้พบได้ใน 'man ssh_config'


5

ฉันชอบวิธีการอื่นที่รักษาช่องสัญญาณที่พิสูจน์ตัวตนไว้ล่วงหน้าไปยังเซิร์ฟเวอร์เกตเวย์ ใน~/.ssh/config:

Host a
    ControlMaster auto
    ControlPath ~/.ssh/control-master/%r@%h:%p

จากนั้นใน.bashrc:

s () {
        if ( ssh -O check a 2>&1 > /dev/null 2>&1 )
        then
                ssh -t a ssh $1
        else
                if [[ -S ~/.ssh/control-master/insyte@a:22 ]]
                then
                        echo "Deleting stale socket..."
                        rm ~/.ssh/control-master/insyte@a:22
                fi
                echo "Opening master session..."
                if ssh -Nf a
                then
                         ssh -t a ssh $1
                fi
        fi
 }

ดังนั้นเพื่อเชื่อมต่อกับ foo:

s foo

ครั้งแรกที่คุณเชื่อมต่อจะรับรองความถูกต้องของคุณกับ "a" และเปิดอุโมงค์ ssh ที่มีพื้นหลังแบบถาวร การเรียก "s" ที่ตามมาจะเปิดเกือบจะทันทีผ่านอุโมงค์ที่ตรวจสอบล่วงหน้า

ใช้งานได้ดี


2

ฟังก์ชันการทำงานประเภทนี้มีอยู่ใน OpenSSH เวอร์ชันที่ใหม่กว่าและสามารถใช้งานได้

ssh -W server2 server1

server2ปลายทางของคุณอยู่ที่ไหนและserver1เป็นพร็อกซีโฮสต์ของคุณ คุณสามารถทำให้ง่ายขึ้นโดยใช้ProxyCommandตัวเลือกในการกำหนดค่า ssh ของคุณเช่น:

host = *.example.com
user = packs
port = 22
ProxyCommand ssh -W %h:%p server1

ดูเหมือนว่าสิ่งนี้จะใช้งานได้คุณต้องใช้ OpenSSH 5.4+ ทั้งสามแห่ง: เดสก์ท็อปคนกลางปลายทาง (อย่างแรกและสุดท้ายแน่นอน)
Steve Bennett

@SteveBennett: ฉันใช้วิธีนี้มาระยะหนึ่งแล้วมันใช้งานได้ดีมาก ฉันต้องย้อนกลับไปใช้วิธี netcat ในระบบ RHEL5 สองระบบซึ่งน่ารำคาญ
Scott Pack

2

เมื่อnetcatไม่พร้อมใช้งานบนพร็อกซีให้ลองเคล็ดลับนี้:

host foo
  User webby      
  ProxyCommand ssh a 'exec 3<>/dev/tcp/foo/22; cat <&3 & cat >&3;kill $!'

host a
  User johndoe

ssh fooแล้วคุณควรจะสามารถ

นอกจากนี้หากคุณมีเวอร์ชันล่าสุดของ ssh บน a (เช่นด้วย-Wคำสั่งสำหรับการส่งต่ออินพุตและเอาต์พุตมาตรฐาน) คุณอาจสามารถใช้:

host foo
  User webby
  ProxyCommand ssh -W foo:%p a

host a
  User johndoe

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

host */*
  ProxyCommand ssh ${$(dirname %h)/\%%/@} nc ${$(basename %h)#*%%} %p

และจากนั้นก็ssh machine1/machine2ควรให้เปลือกบนmachine2, machine1เจาะผ่าน

ฉันสงสัยว่าใช้sedคำสั่งที่กำหนดเองแทนdirnameและbasenameอาจไม่แก้ปัญหาด้วยชื่อผู้ใช้ที่แตกต่างกันหรือไม่


2

ssh -At johndoe@a ssh webby@fooนี้สามารถทำได้โดยการทำ -Aคำสั่งส่งต่อตัวแทน SSH คุณ (เพื่อให้คุณสามารถหลีกเลี่ยงการรับรองความถูกต้องอีกครั้งในพร็อกซี่) ในขณะที่-tมั่นใจขั้วที่มีอยู่บนพร็อกซี่ ฟังก์ชั่นทุบตีต่อไปนี้อาจมีประโยชน์:

ssh-bounce () {
    local cmd=""
    for i in "$@"; do
        cmd+="ssh -At $i "
    done
    $cmd
}

นี่คือทางออกที่ง่ายที่สุด ตอนนี้มันต้องการอีก 35 upvotes (Btw the -A ไม่ได้ทำอะไรเพื่อฉันเลย)
Steve Bennett

0
weppos:~ weppos$ ssh foo -vv
[..]
bash: nc: command not found

netcat aไม่ได้ติดตั้ง เมื่อคุณเรียกใช้ssh host "command arg", commandจะถูกดำเนินการเกี่ยวกับการhostไม่ได้อยู่ในเครื่องของคุณ


ใช่ฉันรู้. ตรงนี้เป็นสิ่งที่ฉันรายงานในความคิดเห็นต่อคำตอบของ womble :)
Simone Carletti

0

ตั้งแต่ OpenSSH 7.3 (2016-08-01) ProxyJumpตัวเลือกและ-Jการตั้งค่าสถานะบรรทัดคำสั่งที่สอดคล้องกันนั้นมีไว้เพื่ออนุญาตให้มีการเปลี่ยนทิศทางที่ง่ายขึ้นผ่านช่อง SSH หนึ่งครั้งหรือมากกว่าหรือ "jump hosts"

ซึ่งจะลบการพึ่งพาncคำสั่งภายนอกตามที่พบในโซลูชันของ Wombleการแก้ปัญหาของ

ssh -J johndoe@a webby@foo 

จะสร้างการเชื่อมต่อ SSH จากเวิร์กสเตชันของคุณไปยังเซิร์ฟเวอร์เกตเวย์ aในฐานะผู้ใช้ johndoe และสร้างช่องสัญญาณเซสชัน SSH ไปยังโฮสต์ foo สำหรับผู้ใช้ Webby ผ่านทางนั้น

เพื่อลดความซับซ้อนที่สร้างคำจำกัดความโฮสต์สำหรับทั้งใน~/.ssh/configและของคุณคุณสามารถดำเนินการssh foo

Host a
    User johndoe

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