- SSH tunneling ใช้ขนส่งทราฟฟิก TCP ผ่าน การเชื่อมต่อ SSH ที่ปลอดภัย เพื่อเปิดเส้นทางที่มีข้อจำกัดอย่างปลอดภัย เช่น การเข้ารหัสโปรโตคอลรุ่นเก่า การเข้าถึงแผงจัดการ หรือการเชื่อมต่อไปยังเซิร์ฟเวอร์ที่อยู่หลัง NAT
- ฝั่งเซิร์ฟเวอร์ต้องเปิด
AllowTcpForwarding yes และหากต้องการเปิดพอร์ตบนอินเทอร์เฟซที่ไม่ใช่ลูปแบ็ก ต้องตั้งค่า GatewayPorts yes และรีสตาร์ตเซิร์ฟเวอร์ SSH
ssh -J, ssh -L, ssh -R, ssh -D มีหน้าที่สำหรับ jump host, local forwarding, remote forwarding และ dynamic forwarding บนพื้นฐาน SOCKS5 ตามลำดับ
- หากต้องการให้ tunnel ทำงานอยู่เบื้องหลัง ให้ใช้
ssh -fN และการตรวจจับการหลุดของการเชื่อมต่อสามารถปรับได้ด้วย การตั้งค่า heartbeat เช่น ClientAliveInterval และ ClientAliveCountMax
- SSH tunneling ไม่รองรับ UDP โดยตรง และอาจมีปัญหาเรื่อง latency และ throughput เมื่อเป็น TCP-over-TCP จึงใกล้เคียงกับเครื่องมือสำหรับเปิดเส้นทาง TCP เฉพาะจุดมากกว่าจะเป็น ตัวแทน VPN
สถานการณ์ที่ใช้ SSH tunneling
- SSH tunneling และ port forwarding ส่งต่อ ทราฟฟิก TCP ผ่านการเชื่อมต่อ SSH จากไคลเอนต์ไปยังเซิร์ฟเวอร์ หรือจากเซิร์ฟเวอร์มายังไคลเอนต์
- สามารถใช้ทั้ง TCP port และ UNIX socket ได้ แต่ตัวอย่างนี้เน้นที่ TCP port
- รูปแบบการใช้งานหลักแบ่งได้เป็นด้านความปลอดภัย การแก้ปัญหา และการเชื่อมต่อ
- ความปลอดภัย
- เข้ารหัสการเชื่อมต่อที่ไม่ปลอดภัย เช่น FTP หรือโปรโตคอลรุ่นเก่า
- เข้าถึงแผงจัดการเว็บผ่าน SSH tunnel ที่อิงการยืนยันตัวตนด้วยกุญแจสาธารณะ
- เปิดเพียงพอร์ต 22 โดยไม่ต้องเปิดพอร์ตเพิ่มอย่าง 80/443
- การแก้ปัญหา
- ข้ามไฟร์วอลล์หรือ content filter
- เลือกเส้นทางเครือข่ายอื่น
- การเชื่อมต่อ
- เข้าถึงเซิร์ฟเวอร์ที่อยู่หลัง NAT
- เข้าสู่เซิร์ฟเวอร์ภายในจากอินเทอร์เน็ตผ่าน jump host
- เปิดเผย local port ออกสู่อินเทอร์เน็ต
การตั้งค่าที่ควรตรวจสอบก่อนทำ port forwarding
- ตัวเลือกในตัวอย่างสามารถนำมาผสมกันตามสภาพแวดล้อมได้
- หากไม่ระบุ
bind_address ค่าเริ่มต้นคือ localhost
- ผู้ใช้ฝั่ง local และ remote ต้องมีสิทธิ์เปิดพอร์ตบนแต่ละเครื่อง
- พอร์ต
0-1024 ต้องใช้ สิทธิ์ root หากไม่มีการตั้งค่าเพิ่มเติม
- พอร์ตอื่นนอกเหนือจากนั้น ผู้ใช้ทั่วไปก็สามารถตั้งค่าได้
- ไคลเอนต์และไฟร์วอลล์เครือข่ายก็ต้องเปิดให้ตรงกับเส้นทาง forwarding ด้วย
- ต้องเปิดใช้ port forwarding บนเซิร์ฟเวอร์ SSH
AllowTcpForwarding yes
- โดยมากมักเปิดใช้งานอยู่แล้ว แต่ควรตรวจสอบการตั้งค่าของเซิร์ฟเวอร์
- หากต้องการ forward พอร์ตไปยังอินเทอร์เฟซที่ไม่ใช่
127.0.0.1 ต้องเปิด GatewayPorts บนเซิร์ฟเวอร์ SSH
GatewayPorts yes
- หลังตั้งค่าแล้วต้องรีสตาร์ตบริการเซิร์ฟเวอร์ SSH
SSH jump host และ tunnel หลายชั้น
ssh -J ใช้เมื่อจะ เชื่อมต่ออย่างโปร่งใส ไปยังโฮสต์ปลายทางผ่านโฮสต์อย่างน้อยหนึ่งตัว
ssh -J user@REMOTE-MACHINE:22 -p 22 user@10.99.99.1
- หากใช้พอร์ตเริ่มต้น
22 สามารถละการระบุพอร์ตได้
- เมื่อใช้ REMOTE-MACHINE เป็น jump host จะเห็นการเชื่อมต่อดังนี้
[user@REMOTE-MACHINE]$ ss | grep -i ssh
tcp ESTAB 0 0 167.135.173.108:ssh 192.160.140.207:45960
tcp ESTAB 0 0 10.99.99.2:49770 10.99.99.1:ssh
- บทบาทของที่อยู่ในตัวอย่างมีดังนี้
167.135.173.108: public IP ของ REMOTE-MACHINE
192.160.140.207: public IP ของ LOCAL-MACHINE
10.99.99.2: internal IP ของ REMOTE-MACHINE
10.99.99.1: internal IP ของ REMOTE-WEBAPP
- หากใช้ jump host หลายตัว ให้คั่นด้วยเครื่องหมายจุลภาค
ssh -J user@REMOTE-MACHINE:22,user@ANOTHER-REMOTE-MACHINE:22 -p 22 user@10.99.99.1
Local port forwarding
- Local port forwarding ใช้ตัวเลือก
ssh -L
- ตัวอย่างแรกส่งต่อ
10.10.10.1:8001 ของ LOCAL-MACHINE ไปยัง localhost:8000 ของ REMOTE-MACHINE
ssh -L 10.10.10.1:8001:localhost:8000 user@REMOTE-MACHINE
- log การเข้าถึงของเว็บเซิร์ฟเวอร์บน REMOTE-MACHINE ที่ bind อยู่กับ
127.0.0.1 เท่านั้น จะมีลักษณะดังนี้
127.0.0.1 - - [30/Dec/2022 18:05:15] "GET / HTTP/1.1" 200
- คำขอนี้เริ่มต้นมาจาก LOCAL-MACHINE
- ตัวอย่างที่สองส่งต่อ local
8001 ไปยัง 10.99.99.1:8000 ผ่าน REMOTE-MACHINE
ssh -L 8001:10.99.99.1:8000 user@REMOTE-MACHINE
- ใน log การเข้าถึงเว็บเซิร์ฟเวอร์ของ REMOTE-WEBAPP จะถูกบันทึกว่าเป็นคำขอที่มาจาก internal IP ของ REMOTE-MACHINE
10.99.99.2 - - [30/Dec/2022 21:28:42] "GET / HTTP/1.1" 200
Remote port forwarding
- Remote port forwarding ใช้ตัวเลือก
ssh -R
- ตัวอย่างนี้ส่งต่อ
8000 ของ REMOTE-MACHINE ไปยัง localhost:8001 หรือ 10.10.10.2:8001 ฝั่ง local
ssh -R 8000:localhost:8001 user@REMOTE-MACHINE
ssh -R 8000:10.10.10.2:8001 user@REMOTE-MACHINE
- ยังสามารถตั้งค่าให้รับฟังบนอินเทอร์เฟซ remote เฉพาะอย่าง
10.99.99.2:8000 ได้เช่นกัน
ssh -R 10.99.99.2:8000:10.10.10.2:8001 user@REMOTE-MACHINE
- หากต้องการรับฟังบนอินเทอร์เฟซที่ไม่ใช่ลูปแบ็ก ต้องเปิดใช้
GatewayPorts yes บนเซิร์ฟเวอร์ SSH
Dynamic port forwarding และ SOCKS5
- เมื่อต้องส่งต่อหลายพอร์ต SSH จะใช้โปรโตคอล SOCKS
- SOCKS เป็นโปรโตคอลพร็อกซีแบบโปร่งใส และ SSH ใช้ SOCKS5 ซึ่งเป็นเวอร์ชันล่าสุด
- พอร์ตเริ่มต้นของเซิร์ฟเวอร์ SOCKS5 คือ
1080 ตามที่กำหนดไว้ใน RFC 1928
- ไคลเอนต์ต้องถูกตั้งค่าให้ใช้ SOCKS proxy ในระดับแอปพลิเคชันหรือระดับ OS
- ตัวอย่าง
ssh -D เปิด SOCKS proxy ที่ 10.10.10.1:5555
ssh -D 10.10.10.1:5555 user@REMOTE-MACHINE
- ฝั่งไคลเอนต์ LOCAL สามารถทดสอบเส้นทางการเชื่อมต่อด้วย
curl
curl -L -x socks5://10.10.10.1:5555 brrl.net/ip
- หากทำงานปกติ จะได้ public IP ของ REMOTE-MACHINE กลับมา
SSH TUN/TAP tunneling
- สามารถสร้าง tunnel แบบสองทิศทางได้ด้วยแฟลก
-w
- ต้องสร้างอินเทอร์เฟซไว้ล่วงหน้า
- มีข้อสังเกตว่าวิธีนี้ยังไม่ได้รับการทดสอบ
-w local_tun[:remote_tun]
การรันเบื้องหลังและการหยุดทำงาน
- หากต้องการรัน tunnel เบื้องหลังด้วยวิธี native ให้ใช้
-fN
-f: รันเบื้องหลัง
-N: ไม่เปิดเชลล์
ssh -fN -L 8001:127.0.0.1:8000 user@REMOTE-MACHINE
- นอกจากนี้ยังสามารถใช้
screen หรือเครื่องมืออื่นได้
- SSH ที่กำลังรันอยู่เบื้องหลังสามารถค้นหาโปรเซสและหยุดด้วย PID ได้
user@pleasejustwork:~$ ps -ef | grep ssh
[...]
user 19255 1 0 11:40 ? 00:00:00 ssh -fN -L 8001:127.0.0.1:8000 user@REMOTE-MACHINE
[...]
kill 19255
การคงการเชื่อมต่อ SSH และการเชื่อมต่อใหม่
- มีหลายวิธีในการคงการเชื่อมต่อ SSH ไว้
- ตัวเลือก heartbeat สำหรับจัดการ timeout สามารถตั้งได้ที่ฝั่งไคลเอนต์ ฝั่งเซิร์ฟเวอร์ หรือทั้งสองฝั่ง
ClientAliveInterval จะส่งคำขอทุก ๆ n วินาทีเพื่อคงการเชื่อมต่อไว้
ClientAliveInterval 15
ClientAliveCountMax คือ จำนวนคำขอ heartbeat ที่จะส่งหลังจากไม่ได้รับการตอบกลับจากอีกฝั่ง ก่อนจะยุติการเชื่อมต่อ
ClientAliveCountMax 3
- ค่า
3 เป็นค่าเริ่มต้น และหากตั้งเป็น 0 จะปิดการยุติการเชื่อมต่อ
- ในตัวอย่างนี้ หากไม่มีการตอบกลับ การเชื่อมต่อจะหลุดภายในประมาณ 45 วินาที
- หลังการเชื่อมต่อหลุด สามารถใช้
autossh, สคริปต์ หรือ cronjob เพื่อเชื่อมต่อใหม่ได้
ข้อจำกัดและข้อควรระวังด้านความปลอดภัย
-
UDP
- SSH อาศัยการส่งข้อมูลที่เชื่อถือได้เพื่อให้ถอดรหัสได้อย่างถูกต้อง
- UDP ไม่มีความเชื่อถือได้ในลักษณะนั้น จึงไม่รองรับและไม่แนะนำให้ใช้กับ SSH tunnel
- มีวิธีที่พูดถึง UDP over SSH tunneling แต่มีข้อสังเกตว่ายังไม่ได้ทดสอบ
-
TCP-over-TCP
- มี overhead ทำให้ throughput ลดลงและ latency เพิ่มขึ้น
- บนการเชื่อมต่อที่มี packet loss หรือ latency สูง อาจเกิด TCP meltdown
- สามารถดู บทความเกี่ยวกับ TCP over TCP เพิ่มเติมได้
- จากการใช้งาน OpenVPN-over-TCP อยู่ช่วงหนึ่ง พบว่า throughput ต่ำกว่า UDP แต่ทำงานได้เสถียร โดยผลลัพธ์ขึ้นอยู่กับการตั้งค่าอย่างมาก
-
ข้อจำกัดเมื่อใช้แทน VPN
- แม้จะใช้ SSH tunneling แบบ VPN ได้ แต่หากต้องการประสิทธิภาพที่ดีกว่า VPN เหมาะสมกว่า
-
ความเสี่ยงด้านความปลอดภัย
- หากไม่จำเป็นต้องใช้ฟีเจอร์นี้ แนะนำให้ปิดใช้งาน
- ผู้โจมตีอาจใช้ SSH tunneling และ port forwarding เพื่อหลบเลี่ยงไฟร์วอลล์และมาตรการความปลอดภัยอื่น ๆ ได้
-
เอกสารอ้างอิง
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
ในปี 2024 แทนที่จะพิมพ์คำสั่ง SSH ยาว ๆ เอง ควรตั้งค่า LocalForward, RemoteForward, ProxyJump ไว้ใน
~/.ssh/configจะดีกว่าช่วยลดเวลาได้มากเมื่อต้องเข้าถึงเซิร์ฟเวอร์ระยะไกลผ่าน
ssh,scp,rsyncโดยต้องผ่านการเชื่อมต่อ SSH ตัวกลางหลายชั้นตัวอย่างเช่น ตั้ง
jump-host-1,jump-host-2,jump-host-3ให้เชื่อมต่อกันด้วยProxyJumpแล้วเข้าtarget-serverด้วย alias ก็พอLocalForward 0.0.0.0:8080 0.0.0.0:80จะส่งต่อพอร์ต 80 ของฝั่งรีโมตมายังพอร์ต 8080 ในเครื่อง local และRemoteForward 0.0.0.0:9022 0.0.0.0:22จะส่งต่อคำขอ SSH ที่เข้ามาที่พอร์ต 9022 ของรีโมตมายังพอร์ต 22 ในเครื่อง localใน
LocalForwardและRemoteForwardฝั่งซ้ายคือเซิร์ฟเวอร์เป้าหมาย ฝั่งขวาคือเครื่อง local และยังมีทิปว่าให้ใช้0.0.0.0แทนlocalhostหรือ127.0.0.1ssh_configการตั้งค่าให้แยกทางอัตโนมัติจะมีประโยชน์มาก: เมื่ออยู่ในบ้านหรือใน VPN ที่โฮสต์เองก็ SSH เข้าแต่ละเครื่องโดยตรง แต่ถ้าอยู่นอกบ้านให้ผ่าน jump hostเช่น ใช้
Match host *.example.org exec "getent ahosts router.example.org | grep -q ^10.0.0.1"เพื่อตรวจจากที่อยู่ของเราเตอร์ก่อนว่าอยู่ที่บ้าน/ใน VPN หรือไม่ แล้วใช้arpตรวจ MAC address ถ้าไม่ตรงกับค่าที่คาดไว้ก็ให้ใช้ProxyJump jump.example.orgลำดับสำคัญมาก ต้องตรวจจับ VPN/เครือข่ายบ้านก่อน จากนั้นค่อยใช้ jump host เมื่ออยู่นอกเครือข่าย
กรณีสร้าง VPS ใช้ชั่วคราวเพื่อใช้ SSH เป็น SOCKS proxy สำหรับเลี่ยงข้อจำกัดตามภูมิภาค หรือช่วยทีมอื่นชั่วคราวโดยต้องเข้าเซิร์ฟเวอร์ที่ปกติไม่เคยเข้าถึง ผมมองว่าตัวเลือกบนบรรทัดคำสั่งเหมาะกว่า
0.0.0.0อาจอันตรายได้มันอาจเปิดพอร์ตบนทุก network interface และโดยเฉพาะถ้าเซิร์ฟเวอร์รีโมตไม่มีไฟร์วอลล์ ก็เท่ากับเปิดบางอย่างให้ทั้งอินเทอร์เน็ตเข้าถึง
ถ้าเป็น tunneling หรือ port forwarding ที่ใช้บ่อย ไฟล์ตั้งค่าก็ดี แต่ถ้าเป็นงานครั้งเดียวหรือไม่บ่อย ผมมองว่าตัวเลือกบนบรรทัดคำสั่งเหมาะกว่า
กำลังมองหาแนวทางคล้าย GitOps ที่เหมาะกับผู้ใช้คนเดียว/หลายเครื่อง โดยไม่ต้องมีเซิร์ฟเวอร์แยกเปิดทิ้งไว้ตลอด และดึงการตั้งค่าจากที่อย่าง GitHub ได้
bash/fishพื้นฐานไว้ เพื่อให้จำ argument ให้น้อยที่สุดถ้าลืมก็ไปดูนิยามฟังก์ชันที่ทำเอกสารไว้
ในสภาพแวดล้อมองค์กรสุดไร้สาระที่ผมทำงานอยู่ SSH tunneling เป็นสิ่งจำเป็น
บางครั้งกว่าจะได้สิทธิ์เข้าถึง เปิดพอร์ต หรือขอยกเว้นไฟร์วอลล์/VPN ต้องติดระบบราชการนานเป็นสัปดาห์
บทความนี้พูดถึง
-Dแต่ยังอธิบายพลังของมันไม่พอถ้ารัน
ssh -D 8888 someserverแล้วตั้ง SOCKS proxy ของเบราว์เซอร์เป็นlocalhost:8888ทราฟฟิกของเบราว์เซอร์ทั้งหมดจะถูก route ผ่านsomeserverFirefox ยังตั้งค่านี้ได้โดยไม่ต้องเปลี่ยนค่า default ของระบบ จึงมีประโยชน์มาก
แต่พอเข้าไปทำงานในบริษัท กลับพบว่าเพราะรายการ IP ที่อนุญาต แม้แต่การเชื่อมต่อ SSH ไปยังเซิร์ฟเวอร์ใด ๆ บนอินเทอร์เน็ตก็ทำไม่ได้ ทรมานมากจนถึงขั้นศึกษาวิธีทำ HTTP tunnel และเอาเซิร์ฟเวอร์ที่ตัวเองควบคุมใส่ไว้ใน allowlist สุดท้ายก็ ย้ายงาน
ข้อจำกัดเหล่านั้นมีเหตุผล และการเลี่ยงอาจถูกมองว่าเป็นการขาดความเชี่ยวชาญและไม่เคารพขั้นตอนกับความปลอดภัยขององค์กร
ถ้าการขอสิทธิ์เข้าถึงต้องใช้เวลาหลายสัปดาห์หรือหลายเดือน ก็ต้องรอแบบนั้น และคุณคงไม่อยากรับผิดชอบที่เปิด backdoor ให้ข้อมูลลับหรือทำให้ความปลอดภัยเสียหาย
การแฮ็ก SSH tunneling ที่เละที่สุดที่เคยทำตอนตี 3 คือการเชื่อมดาต้าเซ็นเตอร์สามแห่งเข้าด้วยกัน
สิ่งอำนวยความสะดวกทั้งสามแห่งอยู่ในเขตเมืองเดียวกันและเชื่อมต่อกับ upstream อินเทอร์เน็ต แต่เพราะนโยบาย routing แปลก ๆ A เชื่อมได้แค่ B และมีเพียง B เท่านั้นที่เชื่อมไป C ได้
สุดท้ายเพื่อย้ายข้อมูลของ A ผ่าน B ไปยัง C ต้องผสม rsync + SSH tunnel + key + ทริก routing เข้าด้วยกัน แก้คำสั่งเหมือนร่ายคาถาอยู่หลายครั้ง แล้วพอเห็นทุกอย่างขยับพร้อมกันทีเดียวก็เหมือนเวทมนตร์
ตอนนี้มองกลับไปก็ชัดเจนมากว่าควรทำอย่างไร แต่สำหรับผมในตอนนั้นที่ยังเป็นมือใหม่ มันเป็นความสำเร็จใหญ่ และยังจำความตื่นเต้นตอนยืนยันว่าซิงก์เสร็จแล้วได้อยู่
~/.ssh/configกับ ProxyJump ก็แทบจะกระโดดผ่านได้กี่ขั้นก็ได้ เช่น A, B, C, D, Eรายละเอียดของภาพประกอบดีมาก
ในเรื่อง networking ผมอยากให้มีเครื่องมือที่ แสดงภาพทราฟฟิก มากขึ้นอีกมาก โดยเฉพาะการเชื่อมต่อในระดับที่ต่ำกว่า
แน่นอนว่านี่เป็นเพียงการแสดงแนวคิดแบบคงที่ และ vendor เครือข่ายส่วนใหญ่ก็มีการแสดงภาพทราฟฟิกในรูปแบบใดรูปแบบหนึ่งอยู่แล้ว แต่ปกติก็มักจบแค่ระดับ metric หรือกราฟรายตัว
ถ้าเซิร์ฟเวอร์ Linux หรืออุปกรณ์ IoT อยู่หลังไฟร์วอลล์และไม่มี IP คงที่ แต่ต้องการเชื่อมต่อผ่าน SSH ก็สามารถใช้ บริการ tunneling อย่าง https://sshreach.me ได้
ใช้ tunneling มาค่อนข้างเยอะหลายปี แต่ไม่รู้จักตัวเลือก
-Jมาก่อนแทนที่จะเสียเวลาตั้งค่า 30 นาทีทุกครั้งที่ต้องใช้ tunnel ทุกไม่กี่เดือน อยากให้มี เครื่องมือภาพ ที่ช่วยประกอบ tunnel ให้
มีคำอธิบายว่า TCP-over-TCP เพิ่มโอเวอร์เฮด ทำให้ throughput ต่ำลงและ latency สูงขึ้น และอาจทำให้เกิด TCP meltdown ได้บนการเชื่อมต่อที่มี packet loss หรือมี latency สูง เช่น เครือข่ายดาวเทียม
แต่ใน SSH tunnel หากไม่ได้ใช้ TAP/TUN จริง ๆ แล้วจะไม่เป็นปัญหา
เพราะ SSH คลาย TCP stream แล้วส่งต่อให้
อย่างไรก็ตาม เมื่อใช้หลายช่องทาง ประสิทธิภาพอาจลดลงได้เพราะ head-of-line blocking
เมื่อราว 15 ปีก่อน เคยเรียนรู้ SSH tunnel เพื่อเลี่ยงไฟร์วอลล์ของเครือข่ายมหาวิทยาลัย และต้องเปลี่ยนพอร์ตพื้นฐานเป็น 443
หลังจากนั้นก็ยังใช้ต่อเนื่องในงานที่หลากหลายกว่าแค่การเลี่ยงไฟร์วอลล์มาก
ถ้าลองใช้
sshuttleการทำ tunneling จะสะดวกขึ้นมากใช้ประมาณ
sshuttle -r user@host 10.0.0.0/8แล้วช่วง10/8จะถูก tunnel ให้อัตโนมัติ และโดยพื้นฐานแล้วทำงานเหมือน VPN บน SSHสงสัยว่า SSH เองมีฟีเจอร์ redirect หรือไม่
เช่น ถ้า A พยายาม SSH ไปที่ B แล้ว B แจ้งให้เชื่อมต่อไปที่ C จากนั้น A เชื่อมต่อโดยตรงกับ C แบบโปร่งใส และ B ไม่อยู่ในเส้นทางข้อมูลหลักอีกต่อไป มีฟีเจอร์แบบนี้ไหม
ไฟร์วอลล์/เราเตอร์ของฉันไม่ส่งต่อ DHCP option 67 ให้ถูกต้อง และส่งที่อยู่ของตัวเองเสมอ จึงต้องตั้งค่า IP เสมือน/กฎให้ทราฟฟิก PXE boot ของพอร์ตนั้นที่ไปยัง IP ของเราเตอร์ถูก route ไปยังเซิร์ฟเวอร์ PXE boot จริง
ถ้าไม่ใช่แบบนั้นก็ใช้ฟีเจอร์ jump ได้:
ssh -J B Cถ้า B ไม่จำเป็นต้องอยู่ในเส้นทางและสามารถเชื่อมต่อ C โดยตรงได้ ก็เชื่อมต่อ C ตรง ๆ ไปเลย; แต่ถ้าทำไม่ได้ อย่างไร B ก็ต้องอยู่เป็น hop อยู่ดี
ถ้าอธิบายปัญหาเพิ่มเติม อาจมีวิธีแก้ที่เหมาะกว่านี้
ถ้าเป็นโฮสต์ที่ค่อนข้าง embedded อาจให้ DNS รับหน้าที่ “routing” ได้ แต่ในกรณีนี้ต้องจัดการ การตรวจสอบลายนิ้วมือ host key เอง