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

แพ็กเก็ตของคอนเทนเนอร์ Windows เข้าสู่โฮสต์ตรงไหน

คอนเทนเนอร์บนเครือข่ายเริ่มต้น nat ได้รับที่อยู่จากเพรฟิกซ์ของบริการ Host Networking Service ซึ่งมักอยู่ภายใน 172.16.0.0/12 และเข้าถึงโฮสต์ผ่านอะแดปเตอร์เสมือน โฮสต์เป็นเจ้าของเส้นทางของเพรฟิกซ์นั้นและแปลทราฟฟิกไปยังอะแดปเตอร์ที่ใช้งานอยู่ ไม่มีเครื่องเสมือนแยกต่างหากอยู่กลางเส้นทางนั้น

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

ไคลเอนต์ VPN เปลี่ยนอะไรในเส้นทางนั้น

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

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

Container modeOutbound pathTypical result behind the VPN
Windows, default natHost routes and translates container trafficContainer prefix follows the tunnel and fails
Windows, transparentContainer sits on the physical linkDepends on the local subnet being allowed
Linux engine on Docker DesktopVM egress proxied by a host processOften keeps working

ทำไมคอนเทนเนอร์ Linux จึงทำงานต่างออกไป

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

ความต่างนี้ยังอธิบายด้วยว่าทำไมสูตรสำเร็จของ Linux จึงยกมาใช้ไม่ได้ คอนเทนเนอร์ Linux ที่ต้องการอุโมงค์ของตัวเองจะได้อุปกรณ์ TUN พร้อมความสามารถ NET_ADMIN คอนเทนเนอร์ Windows ไม่เปิดเผยอินเทอร์เฟซเป็นอุปกรณ์ ดังนั้นรูปแบบนั้นจึงไม่มีสิ่งที่เทียบเท่าในฝั่งนั้น

พิสูจน์เส้นทาง แล้วจึงเลือกการออกแบบ

เก็บหลักฐานจากโฮสต์ ไม่ใช่จากคอนเทนเนอร์ เพราะโฮสต์เป็นผู้ค้นหา:

docker network inspect nat --format "{{range .IPAM.Config}}{{.Subnet}}{{end}}"
route print -4
Get-NetRoute -AddressFamily IPv4 | Where-Object DestinationPrefix -like "172.16.*"

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

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

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

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