ภาพรวมโดยสรุป

  • SSH tunnel เป็นเทคนิคสำหรับเชื่อมต่ออย่างปลอดภัยไปยังบริการที่ไม่สามารถเข้าถึงได้โดยตรงจากภายนอก หรือเปิดเผยบริการภายในออกสู่ภายนอกเป็นการชั่วคราว
  • SSH port forwarding แบ่งหลัก ๆ ได้เป็น local forwarding, remote forwarding, dynamic local forwarding, dynamic remote forwarding
  • -L ให้ SSH client ฝั่งโลคัลเป็นผู้เปิดพอร์ต และ -R ให้ SSH server ฝั่งรีโมตเป็นผู้เปิดพอร์ต
  • หากใช้ Bastion Host จะเชื่อมต่อได้ไม่เพียงแค่ตัว SSH server เอง แต่ยังรวมถึงบริการบนเครือข่ายส่วนตัวอื่น ๆ ที่เซิร์ฟเวอร์นั้นเข้าถึงได้ด้วย
  • Dynamic forwarding จะไม่ตรึงปลายทางไว้ล่วงหน้า แต่สร้าง SOCKS proxy เพื่อให้เข้าถึงหลายโฮสต์และหลายพอร์ตได้
  • หากต้องการเปิดเผย remote forwarding ออกสู่เครือข่ายภายนอก ควรตรวจสอบการตั้งค่า GatewayPorts ของ SSH server

บทนำ

จุดประสงค์ของ SSH tunnel

  • SSH ไม่ได้มีไว้แค่รันคำสั่งระยะไกลเท่านั้น แต่ยังมีความสามารถแบบ tunnel สำหรับส่งต่อทราฟฟิกเครือข่ายแบบเข้ารหัสอีกด้วย

  • โดยไม่ต้องใช้ VPN แยกต่างหากหรือโปรแกรม proxy เฉพาะทาง ก็สามารถเข้าถึงเครือข่ายส่วนตัวและเผยแพร่บริการได้ด้วยคำสั่ง SSH มาตรฐานเพียงอย่างเดียว

  • ตัวอย่างการใช้งานที่พบบ่อยมีดังนี้

    • เข้าถึงบริการภายใน VPC โดยอ้อมผ่าน public server
    • เปิดพอร์ตโลคัลของ remote development server ผ่านเบราว์เซอร์บนเครื่องผู้ใช้
    • เปิดเผยบริการในบ้านหรือในเครือข่ายส่วนตัวออกสู่ภายนอกชั่วคราว
    • เชื่อมพอร์ตดีบักของเบราว์เซอร์ฝั่งโลคัลเข้ากับ remote development agent
  • เวลาทำความเข้าใจ SSH tunnel ควรแยกสองประเด็นนี้ออกจากกัน

    • อุปกรณ์ใดเป็นผู้เปิดพอร์ตใหม่และรอฟังการเชื่อมต่อ
    • ทราฟฟิกที่ผ่าน tunnel ไปแล้ว จะเชื่อมต่อถึงปลายทางจากมุมมองของอุปกรณ์ใด

เนื้อหา

Local forwarding เชื่อมบริการฝั่งรีโมตมาไว้บนเครื่องโลคัล

  • Local port forwarding คือวิธีเชื่อมต่อเซิร์ฟเวอร์ระยะไกล หรือบริการที่เซิร์ฟเวอร์ระยะไกลเข้าถึงได้ เข้ากับพอร์ตโลคัลบนเครื่องผู้ใช้
  • โครงสร้างคำสั่งพื้นฐานมีดังนี้
ssh -L [local_addr:]local_port:remote_addr:remote_port [user@]sshd_addr  
  • SSH client จะรอรับการเชื่อมต่อที่ local_port บนเครื่องผู้ใช้

  • ทราฟฟิกที่เข้ามายังพอร์ตนั้นจะถูกส่งผ่าน SSH tunnel ไปยัง remote_addr:remote_port

  • การเชื่อมต่อไปยังปลายทางสุดท้ายจะเกิดขึ้นจากมุมมองของเครือข่ายที่ SSH server ตั้งอยู่

  • กรณีใช้งานหลักมีดังนี้

    • เชื่อมต่อ MySQL, PostgreSQL, Redis ระยะไกล
    • เข้าถึงเว็บแอปพลิเคชันที่เปิดให้ใช้งานเฉพาะในเครือข่ายส่วนตัว
    • เข้าถึงพอร์ตของคอนเทนเนอร์ที่ไม่ได้เปิดบน external interface ของเซิร์ฟเวอร์

Bastion Host ทำหน้าที่เป็นตัวกลางในการเข้าถึงเครือข่ายส่วนตัว

  • remote_addr กับ sshd_addr ซึ่งเป็นปลายทางของการเชื่อมต่อ SSH ไม่จำเป็นต้องเป็นเครื่องเดียวกัน

  • หาก SSH server เข้าถึงบริการภายในอื่น ๆ ได้ ก็สามารถใช้เซิร์ฟเวอร์นั้นเป็นจุดส่งต่อทราฟฟิกได้

  • เซิร์ฟเวอร์ตัวกลางลักษณะนี้เรียกว่า Bastion Host หรือ Jump Host

  • โครงสร้างการเชื่อมต่อทั่วไปมีดังนี้

    • จากเครื่องผู้ใช้ SSH เข้า public Bastion Host
    • Bastion Host ส่งต่อทราฟฟิกไปยังบริการภายใน VPC ที่มันเข้าถึงได้
  • ด้วยวิธีนี้จึงเข้าถึงฐานข้อมูล, search cluster, internal API และบริการอื่น ๆ ที่ไม่ได้เปิดเผยสู่ภายนอกได้

Remote forwarding เปิดเผยบริการฝั่งโลคัลไปยังฝั่งรีโมต

  • Remote port forwarding คือวิธีเชื่อมบริการบนเครื่องผู้ใช้หรือในเครือข่ายภายใน เข้ากับพอร์ตบน external SSH server
  • โครงสร้างคำสั่งพื้นฐานมีดังนี้
ssh -R [remote_addr:]remote_port:local_addr:local_port [user@]gateway_addr  
  • Remote SSH server จะเปิด remote_port และรอรับการเชื่อมต่อ

  • ทราฟฟิกที่เข้ามายังพอร์ตนั้นจะถูกส่งผ่าน SSH tunnel ไปยัง local_addr:local_port ฝั่ง SSH client

  • กรณีใช้งานหลักมีดังนี้

    • เปิดเผย development server ที่รันอยู่บนโน้ตบุ๊กเพื่อใช้สาธิตจากภายนอก
    • ทำให้เข้าถึงบริการ homelab ผ่านอินเทอร์เน็ตได้
    • ให้พอร์ตดีบักของเบราว์เซอร์ฝั่งโลคัลใช้งานได้ในสภาพแวดล้อมพัฒนาระยะไกล

การเปิดเผยสู่ภายนอกต้องมีการตั้งค่า GatewayPorts

  • ในการตั้งค่าเริ่มต้น พอร์ตของ remote forwarding อาจ bind ได้แค่กับ localhost ของ SSH server เท่านั้น
  • ในกรณีนี้ บริการนั้นจะเข้าถึงได้จากภายใน remote server แต่จะเข้าถึงจากภายนอกไม่ได้
  • หากต้องการให้เชื่อมต่อผ่าน public IP ของ remote server ได้ ควรตรวจสอบการตั้งค่าต่อไปนี้ใน sshd_config
GatewayPorts yes  
  • การตั้งค่านี้อาจทำให้พอร์ตถูกเปิดบน external interface ได้ จึงควรใช้ firewall และ access control ร่วมกัน
  • หากเปิดบริการพัฒนาออกสู่อินเทอร์เน็ตสาธารณะโดยตรง ความเสี่ยงจากการเข้าถึงโดยไม่ได้รับอนุญาตหรือการโจมตีอาจเพิ่มขึ้น

เครื่องโลคัลสามารถเป็น Jump Host ของเครือข่ายส่วนตัวได้

  • ปลายทางของ remote forwarding ไม่ได้จำกัดอยู่แค่เครื่องที่รัน SSH client เท่านั้น

  • หากเครื่องผู้ใช้เข้าถึงเซิร์ฟเวอร์อื่นในเครือข่ายบ้านได้ ก็สามารถเปิดเผยพอร์ตของเซิร์ฟเวอร์ภายในนั้นผ่าน remote SSH server ได้เช่นกัน

  • ในกรณีนี้ เครื่องผู้ใช้จะกลายเป็นอุปกรณ์ตัวกลางที่เชื่อมสองเครือข่ายต่อไปนี้เข้าด้วยกัน

    • เครือข่ายภายในบ้าน หรือเครือข่ายพัฒนาส่วนตัว
    • public SSH gateway server
  • วิธีนี้ช่วยให้เข้าถึงบริการของ home server หรือ internal development server ที่ไม่ได้เชื่อมต่ออินเทอร์เน็ตโดยตรงได้จากภายนอก

Dynamic local forwarding สร้าง SOCKS proxy ฝั่งโลคัล

  • Local forwarding แบบทั่วไปจะตรึงพอร์ตโลคัลหนึ่งพอร์ตไว้กับปลายทางหนึ่งแห่ง
  • Dynamic local forwarding จะสร้าง SOCKS proxy บน SSH client
  • โครงสร้างคำสั่งพื้นฐานมีดังนี้
ssh -D [local_addr:]local_port [user@]sshd_addr  
  • SOCKS proxy จะทำงานที่พอร์ตที่กำหนดบนเครื่องผู้ใช้

  • แอปพลิเคชันที่รองรับ SOCKS สามารถระบุที่อยู่และพอร์ตปลายทางต่างกันได้ในแต่ละครั้งที่เชื่อมต่อ

  • การเชื่อมต่อไปยังปลายทางจริงจะเกิดขึ้นจากมุมมองของเครือข่ายฝั่ง remote SSH server

  • จุดต่างจาก local forwarding แบบตรึงปลายทางคือ สามารถใช้การเชื่อมต่อ SSH เดียวเพื่อเข้าถึงหลายบริการในเครือข่ายส่วนตัวฝั่งรีโมตได้

  • กรณีใช้งานหลักมีดังนี้

    • เรียกใช้ internal API หลายตัวผ่าน Bastion Host
    • สำรวจเว็บแอปพลิเคชันภายในเครือข่ายส่วนตัว
    • เข้าถึง VPC endpoint หลายจุดผ่าน EC2 instance เดียว

Dynamic remote forwarding สร้าง SOCKS proxy ฝั่งรีโมต

  • หากละปลายทางแบบคงที่ในตัวเลือก -R ก็จะสามารถสร้าง SOCKS proxy บน remote SSH server ได้
  • โครงสร้างคำสั่งพื้นฐานมีดังนี้
ssh -R [bind_address:]port [user@]gateway_addr  
  • Remote gateway server จะรอรับการเชื่อมต่อ SOCKS ที่พอร์ตที่กำหนด
  • คำขอที่เข้ามาทาง proxy จะถูกส่งผ่าน SSH tunnel กลับมายังฝั่ง client
  • ปลายทางสุดท้ายจะถูกเชื่อมต่อจากมุมมองของเครือข่ายที่ SSH client ตั้งอยู่
  • ด้วยวิธีนี้ remote server จะเข้าถึงเครือข่ายบ้านหรือเครือข่ายส่วนตัวทั้งหมดที่เครื่องผู้ใช้เข้าถึงได้
  • Dynamic remote forwarding ต้องใช้ OpenSSH 7.6 ขึ้นไปบนฝั่ง client
  • หากต้องการเปิดเผย remote SOCKS proxy ออกสู่ external interface ก็ต้องใช้การตั้งค่า GatewayPorts เช่นเดียวกับ remote forwarding ทั่วไป

ตัวเลือกสำหรับรันเบื้องหลังจะคงไว้เฉพาะ tunnel

  • หากต้องการคงไว้เฉพาะ port forwarding โดยไม่รันคำสั่งใดหลังเชื่อมต่อ SSH ให้ใช้ตัวเลือก -N
  • หากต้องการส่ง tunnel ไปทำงานเบื้องหลัง สามารถใช้ตัวเลือก -f ร่วมกันได้
  • ตัวอย่างตามประเภทมีดังนี้
ssh -f -N -L ...  
ssh -f -N -R ...  
ssh -f -N -D ...  
  • ในงานอัตโนมัติหรือสภาพแวดล้อมที่ต้องรันยาวนาน ควรเตรียมแนวทางสำหรับการปิด tunnel, การเชื่อมต่อใหม่, และการตรวจจับความผิดปกติแยกไว้ด้วย

แยกประเภทคำสั่งได้จากตำแหน่งที่เปิดพอร์ต

  • ssh -L ให้ local SSH client เป็นผู้เปิดพอร์ตใหม่
  • ssh -R ให้ remote SSH server เป็นผู้เปิดพอร์ตใหม่
  • ssh -D สร้าง SOCKS proxy บน local SSH client
  • ssh -R ที่ละปลายทางไว้จะสร้าง SOCKS proxy บน remote SSH server
  • กฎพื้นฐานสำหรับจดจำคำสั่งมีดังนี้
-L = local:remote  
-R = remote:local  
  • ที่อยู่และพอร์ตทางซ้ายของเครื่องหมายโคลอนคือจุด listen ที่ถูกเปิดขึ้นใหม่
  • local อาจหมายถึงตัว SSH client เอง หรือเครื่องภายในที่ client เข้าถึงได้
  • remote อาจหมายถึงตัว SSH server เอง หรือเครื่องภายในอื่นที่ server เข้าถึงได้

บทสรุป

เลือกใช้ SSH tunnel ตามทิศทางการเข้าถึง

  • หากต้องการใช้บริการฝั่งรีโมตบนเครื่องของตนเอง ให้ใช้ local forwarding -L

  • หากต้องการเปิดเผยเครื่องของตนเองหรือบริการภายในไปยังฝั่ง remote server ให้ใช้ remote forwarding -R

  • หากต้องการเข้าถึงหลายปลายทางในเครือข่ายระยะไกลแบบยืดหยุ่น ให้ใช้ dynamic local forwarding -D

  • หากต้องการให้ remote gateway เข้าถึงทั้งเครือข่ายฝั่ง client ได้อย่างยืดหยุ่น ให้ใช้ dynamic remote forwarding -R แบบไม่ระบุปลายทาง

  • เมื่อต้องออกแบบ SSH tunnel ควรตรวจสอบสิ่งต่อไปนี้ก่อนเป็นอันดับแรก

    • ตำแหน่งที่ต้องเปิดพอร์ตใหม่
    • อุปกรณ์ที่สามารถเข้าถึงปลายทางสุดท้ายได้
    • การตั้งค่า GatewayPorts, firewall, และสิทธิ์เข้าถึง SSH
    • ความเสี่ยงด้านความปลอดภัยที่อาจเกิดจากการเปิดเผยสู่ภายนอก
  • เกณฑ์สำคัญที่สุดในการตัดสินใจคือ ต้องการให้บริการมองเห็นจากฝั่งไหน และอุปกรณ์ใดที่สามารถเข้าถึงปลายทางจริงได้

ยังไม่มีความคิดเห็น

ยังไม่มีความคิดเห็น