การย้อนกลับของ SSH tunneling ทำงานอย่างไร


350

ตามที่ฉันเข้าใจสิ่งนี้ไฟร์วอล (สมมติว่าการตั้งค่าเริ่มต้น) ปฏิเสธทราฟฟิกที่เข้ามาทั้งหมดซึ่งไม่มีทราฟฟิกขาออกที่สอดคล้องกันมาก่อน

ขึ้นอยู่กับการย้อนกลับการเชื่อมต่อ sshและSSH Tunneling Made Easy , การย้อนกลับ SSH tunneling สามารถใช้เพื่อหลีกเลี่ยงข้อ จำกัด ไฟร์วอลล์ที่น่ารำคาญ

ฉันต้องการรันคำสั่งเชลล์บนเครื่องระยะไกล เครื่องระยะไกลมีไฟร์วอลล์ของตัวเองและอยู่หลังไฟร์วอลล์เพิ่มเติม (เราเตอร์) มีที่อยู่ IP เช่น 192.168.1.126 (หรือบางอย่างที่คล้ายกัน) ฉันไม่ได้อยู่หลังไฟร์วอลล์และฉันรู้ที่อยู่ IP ของเครื่องระยะไกลที่เห็นจากอินเทอร์เน็ต (ไม่ใช่ที่อยู่ 192.168.1.126) นอกจากนี้ฉันสามารถขอให้บางคนทำงานssh (something)เป็นรูทบนเครื่องระยะไกลได้ก่อน

มีใครอธิบายได้บ้างทีละขั้นตอนการทำ SSH ทันเนลย้อนกลับไปรอบ ๆ ไฟร์วอลล์ได้อย่างไร (ไฟร์วอลล์ของเครื่องโลคอลและรีโมทและไฟร์วอลล์เพิ่มเติมระหว่างพวกเขา)

บทบาทของสวิทช์ (คืออะไร-R, -f, -L, -N)?


คำตอบ:


402

ฉันชอบอธิบายเรื่องนี้ผ่านการสร้างภาพ :-)

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

คิดว่าอุโมงค์ของคุณเป็นหลอดภายในหลอด คุณยังคงมีการเชื่อมต่อ SSH ขนาดใหญ่ แต่ตัวเลือก -L หรือ -R ช่วยให้คุณสามารถตั้งค่าหลอดที่เล็กกว่าภายใน

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

(คุณยังไม่ได้พูด แต่ฉันจะสมมติว่าเครื่อง "ระยะไกล" ที่คุณพูดถึงซึ่งอยู่หลังไฟร์วอลล์สามารถเข้าถึงอินเทอร์เน็ตโดยใช้ Network Address Translation (NAT) นี่เป็นสิ่งสำคัญ โปรดแก้ไขข้อสมมติฐานนี้หากเป็นเท็จ)

เมื่อคุณสร้างอุโมงค์คุณระบุที่อยู่และพอร์ตที่จะรับและที่อยู่และพอร์ตที่จะส่งมอบ -Lตัวเลือกบอกอุโมงค์ที่จะตอบในด้านท้องถิ่นของอุโมงค์ (เจ้าภาพที่ทำงานลูกค้าของคุณ) -Rตัวเลือกบอกอุโมงค์ที่จะตอบในด้านระยะไกล (เซิร์ฟเวอร์ SSH)

ทิศทางอุโมงค์ ssh

ดังนั้น ... เพื่อให้สามารถใช้ SSH จากอินเทอร์เน็ตไปยังเครื่องที่อยู่หลังไฟร์วอลล์คุณต้องมีเครื่องที่ต้องสงสัยเพื่อเปิดการเชื่อมต่อ SSH ไปยังโลกภายนอกและรวมถึง-Rอุโมงค์ที่มี "รายการ" ชี้อยู่ด้าน "ระยะไกล" ของ การเชื่อมต่อของเขา

จากสองรุ่นที่แสดงด้านบนคุณต้องการรุ่นทางด้านขวา

จากโฮสต์ไฟร์วอลล์:

ssh -f -N -T -R22222:localhost:22 yourpublichost.example.com

สิ่งนี้บอกลูกค้าของคุณในการสร้างอุโมงค์ที่มี-Rจุดเข้า emote สิ่งใดก็ตามที่เชื่อมต่อกับพอร์ต 22222 ที่ปลายสุดของอุโมงค์จริง ๆ แล้วจะถึง "localhost พอร์ต 22" โดยที่ "localhost" มาจากมุมมองของจุดออกของอุโมงค์ (เช่นไคลเอนต์ ssh ของคุณ)

ตัวเลือกอื่น ๆ :

  • -f บอก ssh ให้แบ็คกราวน์หลังจากที่มันรับรองความถูกต้องแล้วดังนั้นคุณไม่ต้องนั่งทำงานอะไรบนเซิร์ฟเวอร์ระยะไกลเพื่อให้อุโมงค์ยังมีชีวิตอยู่
  • -Nบอกว่าคุณต้องการการเชื่อมต่อ SSH แต่คุณไม่ต้องการเรียกใช้คำสั่งระยะไกลใด ๆ หากสิ่งที่คุณกำลังสร้างคืออุโมงค์ดังนั้นการรวมตัวเลือกนี้จะช่วยประหยัดทรัพยากร
  • -T ปิดใช้งานการจัดสรรแบบหลอกซึ่งเหมาะเพราะคุณไม่ได้พยายามสร้างเชลล์แบบโต้ตอบ

จะมีการท้าทายด้วยรหัสผ่านหากคุณไม่ได้ตั้งค่าคีย์ DSA หรือ RSA สำหรับการลงชื่อเข้าใช้แบบไม่มีรหัสผ่าน

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

ตอนนี้จากเชลล์บนyourpublichostให้สร้างการเชื่อมต่อกับโฮสต์ไฟร์วอลล์ผ่านช่องสัญญาณ:

ssh -p 22222 username@localhost

คุณจะได้รับรหัสโฮสต์ที่ท้าทายเนื่องจากคุณอาจไม่เคยเจอโฮสต์นี้มาก่อน จากนั้นคุณจะได้รับรหัสผ่านที่ท้าทายสำหรับusernameบัญชี (เว้นแต่คุณได้ตั้งค่าคีย์สำหรับการเข้าสู่ระบบแบบไม่ใช้รหัสผ่าน)

หากคุณกำลังจะเข้าถึงโฮสต์นี้เป็นประจำคุณสามารถทำให้การเข้าถึงง่ายขึ้นโดยการเพิ่มสองสามบรรทัดใน~/.ssh/configไฟล์ของคุณ:

host remotehostname
    User remoteusername
    Hostname localhost
    Port 22222

ปรับremotehostnameและremoteusernameให้เหมาะสม remoteusernameฟิลด์จะต้องตรงกับชื่อผู้ใช้ของคุณบนเซิร์ฟเวอร์ระยะไกล แต่remotehostnameสามารถเป็นชื่อโฮสต์ใด ๆ ที่เหมาะสมกับคุณมันไม่ได้มีเพื่อให้ตรงกับสิ่งที่ resolvable

(ในการเปิดเผยปลายทางย้อนกลับของIP ที่ไม่ใช่ localhostโปรดดูที่โพสต์นี้ )


2
ssh -D เกี่ยวกับอะไร โปรดอธิบายโดยใช้วิธีการเดียวกัน
BigSack

6
SOCKS ผู้รับมอบฉันทะไม่เหมือนกับอุโมงค์ หากคุณมีคำถามเกี่ยวกับวิธีการใช้พวกเขาโปรดขอได้
ghoti

12
ฉันมีเวลายากมากที่จะทำตามคำอธิบายนี้เนื่องจากมีการใช้งานข้อกำหนดอย่างหลวม ๆ : เซิร์ฟเวอร์, ลูกค้า, เครื่องท้องถิ่น, เครื่องระยะไกล, โฮสต์, yourpublichost, localhost, remotehostname ด้วยเงื่อนไขที่หลวมและไม่ได้กำหนดอาจสันนิษฐานได้ว่ามีใครบางคนต้องการคอมพิวเตอร์มากถึง 8 เครื่องในการตั้งค่านี้ ฉันพูดเรื่องนี้เพราะในด้านอื่น ๆ ดูเหมือนว่าคำอธิบายที่ดีมาก กรุณาลดและกำหนดเงื่อนไข
Rucent88

4
@ Rucent88 ฉันไม่แน่ใจว่าจะสามารถลดอะไรได้บ้าง ไคลเอนต์สร้างการเชื่อมต่อกับเซิร์ฟเวอร์ นั่นเป็นคำศัพท์ทั่วไปทั่วโลกของเครือข่าย เครื่องจักรในท้องถิ่นและระยะไกลดูจะปรากฏชัดในตัวเอง หากคุณสับสนเกี่ยวกับ SSH หรือคำศัพท์ยูนิกซ์ทั่วไปหลังจากอ่านเอกสารฉันแน่ใจว่าคุณจะไม่มีปัญหาในการหาคนที่นี่ยินดีตอบคำถามใด ๆ ที่คุณอาจมี
ghoti

9
@ghoti มันทำให้เกิดความสับสนแน่นอนเพราะเครื่องจักรในท้องถิ่นและระยะไกลมีความเกี่ยวข้อง เมื่อฉันนั่งที่ทำงานที่บ้านคอมพิวเตอร์ของฉันเป็นรีโมทเมื่อฉันนั่งที่บ้านคอมพิวเตอร์ที่ทำงานอยู่ไกล เซิร์ฟเวอร์และไคลเอนต์ยังสับสนเมื่อพูดถึงช่องสัญญาณ ตัวอย่างเช่นถ้าฉันเชื่อมต่อกับบ้านจากการทำงานกับ ssh -R ฉันเชื่อมต่อกับงานจากคอมพิวเตอร์ที่บ้านโดยเชื่อมต่อ localhost ดังนั้นจากมุมมองซ็อกเก็ตเซิร์ฟเวอร์คือคอมพิวเตอร์ที่บ้าน แต่มีเหตุผลฉันเชื่อมต่อกับคอมพิวเตอร์ที่ทำงานของฉัน มันสับสน
Calmarius

357

ฉันวาดภาพร่างบางส่วน

เครื่องที่คำสั่งอุโมงค์ SSH พิมพ์เรียกว่า»โฮสต์«ของคุณ

ssh tunnel เริ่มต้นจากโลคัล


ssh tunnel เริ่มต้นจากระยะไกล

บทนำ

  1. ท้องถิ่น: -L Specifies that the given port on the local (client) host is to be forwarded to the given host and port on the remote side.

    ssh -L sourcePort:forwardToHost:onPort connectToHostหมายถึง: เชื่อมต่อกับ ssh ไปยังconnectToHostและส่งต่อความพยายามในการเชื่อมต่อทั้งหมดไปยังโลคัล sourcePortไปยังพอร์ตonPortบนเครื่องที่เรียกว่าforwardToHostซึ่งสามารถเข้าถึงได้จากconnectToHostเครื่อง

  2. ระยะไกล: -R Specifies that the given port on the remote (server) host is to be forwarded to the given host and port on the local side.

    ssh -R sourcePort:forwardToHost:onPort connectToHostหมายถึง: เชื่อมต่อกับ ssh ไปยังconnectToHostและส่งต่อความพยายามในการเชื่อมต่อทั้งหมดไปยังรีโมท sourcePortไปยังพอร์ตonPortบนเครื่องที่เรียกว่าforwardToHostซึ่งสามารถเข้าถึงได้จากเครื่องท้องถิ่นของคุณ

ตัวเลือกเพิ่มเติม

  • -f บอก ssh ให้แบ็คกราวน์หลังจากที่มันรับรองความถูกต้องแล้วดังนั้นคุณไม่ต้องนั่งทำงานอะไรบนเซิร์ฟเวอร์ระยะไกลเพื่อให้อุโมงค์ยังมีชีวิตอยู่
  • -Nบอกว่าคุณต้องการการเชื่อมต่อ SSH แต่คุณไม่ต้องการเรียกใช้คำสั่งระยะไกลใด ๆ หากสิ่งที่คุณกำลังสร้างคืออุโมงค์ดังนั้นการรวมตัวเลือกนี้จะช่วยประหยัดทรัพยากร
  • -T ปิดใช้งานการจัดสรรแบบหลอกซึ่งเหมาะเพราะคุณไม่ได้พยายามสร้างเชลล์แบบโต้ตอบ

ตัวอย่างของคุณ

ภาพที่สามแสดงถึงอุโมงค์นี้ แต่คอมพิวเตอร์สีฟ้าที่เรียกว่า»โฮสต์ของคุณ«แสดงคอมพิวเตอร์ที่มีคนเริ่มอุโมงค์ ssh ในกรณีนี้เครื่องไฟร์วอลล์

ดังนั้นขอให้บางคนเริ่มการเชื่อมต่อช่องสัญญาณ ssh กับเครื่องของคุณ โดยทั่วไปแล้วคำสั่งควรมีลักษณะดังนี้

ssh -R 12345:localhost:22 YOURIP

ตอนนี้อุโมงค์เปิดแล้ว ตอนนี้คุณสามารถเชื่อมต่อผ่าน ssh ไปยังเครื่องไฟร์วอลล์ผ่านอุโมงค์ด้วยคำสั่ง

ssh -p 12345 localhost

ซึ่งจะเชื่อมต่อกับตัวคุณเองlocalhost(เครื่องของคุณ) บนพอร์ต12345แต่พอร์ต12345จะถูกส่งต่อผ่านช่องสัญญาณไปยังพอร์ต 22 ของโลคอลโฮสต์ของคอมพิวเตอร์ไฟร์วอลล์ (เช่นคอมพิวเตอร์ไฟร์วอลล์เอง)


9
คำตอบที่ดี! จะใช้สิ่งนี้ในงานนำเสนอ
อิสยาห์เทอร์เนอร์

4
ขอขอบคุณ. ไม่เป็นไร หากคุณต้องการภาพเวกเตอร์ (svg หรือ pdf) เขียนข้อความถึงฉัน
erik

1
@erik คุณวาดภาพเหล่านี้ได้อย่างไร
Pacerier

31
โอ้มนุษย์ฉันหวังว่าหน้าคนจะมีคำอธิบายเช่นนี้! ขอบคุณ!
ลูคัสพอตเตอร์สกี้

30
คุณรู้อะไรไหม ? ฉันไม่ต้องอ่านคำอธิบายข้อความด้วยซ้ำ การทำงานที่ดี !
deppfx

21

ssh tunneling ทำงานโดยใช้การเชื่อมต่อ ssh ที่สร้างไว้แล้วสำหรับการส่งทราฟฟิกเพิ่มเติม

เมื่อคุณเชื่อมต่อกับเซิร์ฟเวอร์ระยะไกลคุณมักจะมี 1 ช่องสัญญาณสำหรับการโต้ตอบผู้ใช้ปกติ (หรือ 3 ช่องสัญญาณหากคุณพิจารณาแยก STDIN / STDOUT / STDERR) ตลอดเวลากระบวนการโลคัลหรือระยะไกลสามารถเปิดช่องทางเพิ่มเติมในการเชื่อมต่อที่มีอยู่ แชนเนลเหล่านี้จะส่ง / รับสัญญาณทราฟฟิก เมื่อส่งหรือรับการรับส่งข้อมูลกระบวนการ ssh จะบอกว่า "การรับส่งข้อมูลนี้ใช้สำหรับช่อง foobar"

มันใช้งานได้ดีเช่นนี้:

  1. คุณบอกให้ ssh เริ่มฟังพอร์ต XXXX และการรับส่งข้อมูลใด ๆ ที่ควรได้รับคือช่องสัญญาณจากนั้นตั้งค่าเป็น YYYY บนพอร์ต ZZZZ
  2. ssh โลคัลเริ่มฟังบนพอร์ต XXXX (โดยทั่วไปเปิด127.0.0.1แต่สามารถเปลี่ยนแปลงได้)
  3. แอปพลิเคชั่นบางตัวเปิดการเชื่อมต่อกับพอร์ต XXXX บนเครื่องท้องถิ่น
  4. ssh ท้องถิ่นเปิดช่องทางไปยัง ssh ระยะไกลและพูดว่า "การรับส่งข้อมูลใด ๆ ในช่องนี้ไปที่ YYYY: ZZZZ
  5. ssh ระยะไกลเชื่อมต่อกับ YYYY: ZZZZ และส่งกลับ "ตกลงช่องเปิด"
  6. ตอนนี้ทราฟฟิกใด ๆ ที่ส่งไปตามการเชื่อมต่อกับพอร์ต XXXX บนเครื่องโลคัลจะถูกพร็อกซีโดย ssh ถึง YYYY: ZZZZ

กระบวนการนี้เหมือนกันทั้งในการขุดอุโมงค์ไปข้างหน้าและย้อนกลับ (เพียงแค่สลับคำว่า 'local' และ 'remote' ในขั้นตอนข้างต้น) ทั้งสองข้างสามารถเริ่มอุโมงค์ได้ มันไม่จำเป็นต้องเป็นตอนที่คุณเริ่ม ssh ครั้งแรก คุณสามารถเปิดอุโมงค์ได้ในขณะที่ ssh กำลังทำงานอยู่ (ดูESCAPE CHARACTERSเฉพาะ~C)

สำหรับบทบาทของ-R, -f, -Lและ-N, คุณจริงๆก็ควรปรึกษาหน้าคนก็ช่วยให้คุณมีคำอธิบายที่ดีที่สุด แต่ฉันจะพูดถึงและ-R บอก ssh ระยะไกลให้ฟังการเชื่อมต่อและบอกว่า ssh ท้องถิ่นควรเชื่อมต่อกับปลายทางที่แท้จริง บอกให้ ssh โลคัลฟังการเชื่อมต่อและ ssh ระยะไกลควรเชื่อมต่อกับปลายทางที่แท้จริง-L
-R-L

หมายเหตุนี่เป็นคำอธิบายที่หยาบคายมาก แต่ควรให้ข้อมูลมากพอที่จะรับรู้ว่าเกิดอะไรขึ้น


16

นี่คือคำอธิบายในคู่มือ SSH โดยเฉพาะความแตกต่างระหว่าง-L(ท้องถิ่น) และ-R(ระยะไกล)


-L

-L [bind_address:]port:host:hostport

ระบุว่าพอร์ตที่กำหนดในท้องถิ่น (ลูกค้า) โฮสต์ที่จะส่งต่อไปยังโฮสต์ที่กำหนดและพอร์ตที่ด้านระยะไกล

สิ่งนี้ทำงานได้โดยการจัดสรรซ็อกเก็ตเพื่อฟังพอร์ตในด้านโลคัลหรือเลือกผูกกับ bind_address ที่ระบุ

เมื่อใดก็ตามที่มีการเชื่อมต่อกับพอร์ตนี้การเชื่อมต่อจะถูกส่งต่อไปทั่วช่องทางที่ปลอดภัยและมีการเชื่อมต่อไปยังhostพอร์ตhostportจากเครื่องระยะไกล

ตัวอย่างต่อไปนี้ปรับแต่งเซสชัน IRC จากเครื่องไคลเอนต์127.0.0.1( localhost) โดยใช้พอร์ต 1234 ไปยังเซิร์ฟเวอร์ระยะไกลserver.example.com:

$ ssh -f -L 1234:localhost:6667 server.example.com sleep 10

หมายเหตุ: -fตัวเลือกพื้นหลัง ssh และคำสั่งระยะไกลsleep 10มีการระบุเพื่อให้เวลาในการเริ่มบริการที่จะต้องมีการ tunnelled

ตัวอย่าง:

ssh `-N` -L 22000:localhost:11000 remote.server.com
  • -N หลังจากที่คุณเชื่อมต่อเพิ่งแขวนที่นั่น (คุณจะไม่ได้รับพรอมต์เชลล์)

    อย่าดำเนินการคำสั่งระยะไกล

  • -L 22000การเชื่อมต่อจะเกิดขึ้นที่พอร์ต 22000 ของเครื่องL ocal ส่วนตัวของคุณ

  • localhost:11000- remote.server.comจะตรวจสอบให้แน่ใจว่าปลายอีกด้านของอุโมงค์คือlocalhostพอร์ต11000

ssh -N -L 22000: 192.168.1.2: 11000 remote.server.com

ที่มา: คู่มือพร้อมภาพประกอบ, กวดวิชา, วิธีการในการขุดอุโมงค์


-R

-R [bind_address:]port:host:hostport

ระบุว่าพอร์ตที่กำหนดในระยะไกล (เซิร์ฟเวอร์) เจ้าภาพจะได้รับการส่งต่อไปยังโฮสต์ที่กำหนดและพอร์ตในด้านท้องถิ่น

นี้ทำงานโดยการจัดสรรซ็อกเก็ตที่จะฟังportในด้านระยะไกลและเมื่อใดก็ตามที่มีการเชื่อมต่อกับพอร์ตนี้การเชื่อมต่อจะถูกส่งต่อไปทั่วช่องทางที่ปลอดภัยและมีการเชื่อมต่อไปยังhostพอร์ตhostportจากเครื่องท้องถิ่น

ตัวอย่าง:

ssh -N -R 22000:localhost:11000 remote.server.com
  • -N หลังจากที่คุณเชื่อมต่อเพิ่งแขวนที่นั่น (คุณจะไม่ได้รับพรอมต์เชลล์)

    อย่าดำเนินการคำสั่งระยะไกล

  • -R22000 การเชื่อมต่อจะเกิดขึ้นที่พอร์ต 22000 ของคอมพิวเตอร์R Emote (ในกรณีนี้ remote.server.com)

  • localhost:11000คอมพิวเตอร์ส่วนบุคคลของคุณจะตรวจสอบให้แน่ใจว่าปลายอีกด้านของอุโมงค์คือlocalhostพอร์ต11000

ssh -N -R 22000: localhost: 11000 remote.server.com

ที่มา: คู่มือพร้อมภาพประกอบ, กวดวิชา, วิธีการในการขุดอุโมงค์


6
หูและปากทำให้ชัดเจนว่าใครกำลังพูดอยู่และกำลังฟังใคร!
Thufir

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