บริการของคุณทำงานบนเครื่อง อุโมงค์ขึ้นแล้ว แต่เบราว์เซอร์บนโต๊ะของคุณยังคงรอคำตอบ ไม่มีอะไรเสียหายในความหมายปกติ: แอปพลิเคชันกำลังฟังอยู่ ภายในเนมสเปซเครือข่าย และสแตกนั้นมองไม่เห็นจาก LAN ลูปแบ็กของมันเป็นของเนมสเปซ ดังนั้นไคลเอนต์บนเครื่องอื่นจึงไม่มีที่อยู่ใดที่ไปถึงพอร์ตได้ การกระโดดหนึ่งครั้งโดยเจตนา หรือคู่ veth หนึ่งคู่ แก้ปัญหานี้ได้โดยไม่ต้องย้ายส่วนที่เหลือของโฮสต์

ทำไมจึงไม่มีอะไรตอบบนที่อยู่ LAN

เนมสเปซคือสแตกเครือข่ายที่สมบูรณ์: อินเทอร์เฟซ เส้นทาง กฎไฟร์วอลล์ และลูปแบ็กส่วนตัว โปรเซสที่เริ่มผ่าน ip netns exec จะเห็นเฉพาะสแตกนั้นและไม่เห็นอย่างอื่น ดังนั้นที่อยู่ที่ผูกไว้จะถูกแก้ไขภายในเนมสเปซเท่านั้น 127.0.0.1 ของโฮสต์เองเป็นลูปแบ็กที่แตกต่างออกไปโดยสิ้นเชิง

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

เผยแพร่พอร์ตเดียวด้วยการกระโดด socat

socat เชื่อมสองสแตกในพื้นที่ผู้ใช้ ซึ่งเพียงพอเมื่อต้องข้ามพอร์ต TCP เพียงพอร์ตเดียว ฝั่งโฮสต์ฟังบน LAN และสำหรับทุกการเชื่อมต่อที่ยอมรับ จะเริ่ม socat ตัวที่สองภายในเนมสเปซซึ่งเชื่อมต่อไปยังลูปแบ็กของแอป โปรเซสภายในเข้าถึงแอปพลิเคชันเหมือนไคลเอนต์ภายในเครื่องทุกประการ ไม่มีอะไรเปลี่ยนในการกำหนดเส้นทางของเนมสเปซ แอปจึงใช้อุโมงค์เป็นทางออกเดียวต่อไป

socat TCP-LISTEN:9100,reuseaddr,fork EXEC:'ip netns exec vpn socat STDIO tcp-connect:127.0.0.1:9100',nofork

โปรเซสภายนอกต้องมี root หรือความสามารถในการเข้าเนมสเปซ ถ้า VPN หลุด แอปจะสูญเสียเส้นทาง และพอร์ตที่เผยแพร่จะล้มเหลวแบบปิด ซึ่งเป็นพฤติกรรมที่คุณต้องการจากกรงขัง

ใช้คู่ veth เมื่อมีมากกว่าหนึ่งพอร์ตข้าม

คู่ veth คือคำตอบที่ถูกต้องเมื่อต้องข้ามหลายพอร์ตหรือหลายโปรโตคอล หรือเมื่อโฮสต์อื่นต้องเริ่มการเชื่อมต่อ ปลายหนึ่งอยู่บนโฮสต์ อีกปลายย้ายเข้าเนมสเปซ และ /30 เล็กๆ ให้ที่อยู่ที่มั่นคงทั้งสองฝ่าย จากนั้นเส้นทางโฮสต์จะส่งที่อยู่ของเนมสเปซผ่านคู่นั้น

ip link add veth0 type veth peer name veth1
ip link set veth1 netns vpn
ip addr add 10.77.0.1/30 dev veth0
ip link set veth0 up
ip netns exec vpn ip addr add 10.77.0.2/30 dev veth1
ip netns exec vpn ip link set veth1 up

อย่าเพิ่มเส้นทางเริ่มต้นผ่านโฮสต์ เว้นแต่คุณตั้งใจจะทำลายกรงขัง อุโมงค์ควรยังเป็นทางออก ที่อยู่บริการที่เผยแพร่เท่านั้นจึงเข้าถึงได้ผ่านคู่ ให้ไฟล์ตัวแก้ไขชื่อของเนมสเปซเองด้วย เพราะ ip netns exec อ่าน /etc/netns/vpn/resolv.conf และถ้าไม่มี การแก้ไขชื่อภายในกรงขังจะว่างเปล่า

ทดสอบจากเครื่องอื่น ไม่ใช่จากโฮสต์

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

ip netns exec vpn ss -lntp

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

บทความที่เกี่ยวข้อง