คอนเทนเนอร์ที่ไม่สามารถเข้าถึงสิ่งใดหลัง VPN ขององค์กรมักอยู่ในเนมสเปซเครือข่ายที่ต่างจากอุโมงค์ เส้นทาง เซิร์ฟเวอร์ DNS และเครื่องหมายไฟร์วอลล์ของไคลเอนต์โฮสต์เป็นของสแตกของโฮสต์ ส่วนคอนเทนเนอร์เครือข่ายบริดจ์มีสแตกของตัวเอง ข้อเท็จจริงเดียวนี้อธิบายรายงานส่วนใหญ่ที่มาถึงทีมแพลตฟอร์ม และยังเป็นเหตุผลที่ «VPN เสีย» กับ «Docker เลี่ยง VPN» อาจผิดพร้อมกันได้ การตั้งค่าสองแบบที่ต่างกันมากซ่อนอยู่หลังอาการเดียว ดังนั้นระบุว่าคุณมีแบบไหนก่อนเปลี่ยนการตั้งค่าใด ๆ

ค้นหาว่าเนมสเปซใดเป็นเจ้าของอุโมงค์

บน Docker Desktop สำหรับ macOS หรือ Windows คอนเทนเนอร์ทำงานภายในเครื่องเสมือน Linux ไคลเอนต์ VPN ที่ติดตั้งบนเดสก์ท็อปสร้างอุโมงค์ในระบบปฏิบัติการของเดสก์ท็อป และเครื่องเสมือนไม่เคยเห็นมัน การกำหนดค่าคอนเทนเนอร์ใด ๆ ไม่สามารถแก้ได้ เพราะอินเทอร์เฟซที่คอนเทนเนอร์ต้องการไม่มีอยู่จริงในเนมสเปซเครือข่ายของมัน

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

docker info --format '{{.OperatingSystem}}'
docker run --rm --net=host alpine ip route | head -5
docker run --rm alpine ip route | head -5

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

เครือข่ายโฮสต์คือการทดสอบ ไม่ใช่การออกแบบ

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

docker run --rm --net=host curl -sS -o /dev/null -w '%{http_code}\n' https://api.internal/health

เก็บไว้เป็นเครื่องมือวินิจฉัย เครือข่ายโฮสต์ละทิ้งการเผยแพร่พอร์ตและพื้นที่แยกส่วนใหญ่ที่คุณต้องการจากคอนเทนเนอร์ และบน Docker Desktop «host» หมายถึงเครื่องเสมือน ไม่ใช่เดสก์ท็อป ดังนั้นความสำเร็จหรือล้มเหลวตรงนั้นอาจทำให้เข้าใจผิดหากคุณลืมว่ากำลังติดต่อโฮสต์ใด

อุปกรณ์ tun และสิทธิพิเศษที่มาพร้อมกัน

ไคลเอนต์ VPN ภายในคอนเทนเนอร์ต้องใช้อุปกรณ์อุโมงค์และสิทธิ์ในการกำหนดค่า ทางลัดทั่วไปคือ --privileged ซึ่งให้อุปกรณ์ทุกชิ้นและผ่อนคลายนโยบายความปลอดภัยทั่วทั้งคอนเทนเนอร์ นั่นมากเกินกว่าที่งานนี้ต้องการ และยากที่จะให้เหตุผลในการตรวจสอบ

sudo modprobe tun
docker run --rm -it --device /dev/net/tun --cap-add NET_ADMIN myvpn-client

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

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

NAT ของบริดจ์เปลี่ยนต้นทางที่ VPN เห็น

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

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

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

DNS ตามเดมอน ไม่ใช่ตามอุโมงค์

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

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

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

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

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