ทราฟฟิก Docker และ VM หลัง OpenVPN: กำหนดเส้นทางหรือเปลี่ยนเลข?
คอนเทนเนอร์และเกสต์บนโฮสต์ที่รันไคลเอนต์ OpenVPN อาจเสียเส้นทางขากลับหรือชนกับคำนำหน้าของอุโมงค์ สามคำถามเลือกวิธีแก้
โฮสต์ท่องเว็บผ่านอุโมงค์ แต่คอนเทนเนอร์ข้าง ๆ กลับเข้าถึงอะไรไม่ได้เลย การเผยแพร่พอร์ตจากคอนเทนเนอร์ที่รันไคลเอนต์ VPN ของตัวเองนั้นแย่กว่า: คำขอมาถึงแต่คำตอบไม่เคยออกไป ทั้งสองอย่างเป็นการตัดสินใจเรื่องเส้นทางบนโฮสต์ และ Docker เป็นเพียงผู้ส่งสาร
คำถามสามข้อตัดสินว่าคุณกำลังเจอกรณีใดจากสองกรณีนี้ และใช้เวลาราวหนึ่งนาที
สองความล้มเหลวที่หน้าตาเหมือนกัน
กรณีแรกคือปัญหาเส้นทางขากลับ พอร์ตที่เผยแพร่ถูกแปลงเข้าไปในคอนเทนเนอร์ คำขอมาถึง และคำตอบถูกส่งตามเส้นทางเริ่มต้นของโฮสต์ ซึ่งไคลเอนต์ OpenVPN ชี้ไปที่ tun0 คำตอบออกจากแอดเดรสที่ปลายทางไกลไม่คาดคิด จึงถูกทิ้ง กรณีที่สองคือการชนกันของคำนำหน้า: บริดจ์เริ่มต้นของ Docker ครอบ 172.17.0.0/16 และอุโมงค์ขององค์กรดันช่วงเดียวกันเข้ามา
อันหนึ่งแก้ด้วยตารางเส้นทาง อีกอันแก้ด้วยการเปลี่ยนเลขบริดจ์ การแก้ก่อนรู้ว่าเป็นกรณีไหนคือวิธีทำให้คอนเทนเนอร์ที่ใช้งานได้พัง
ตัดสินด้วยคำถามสามข้อ
คำถามข้อหนึ่ง: ความล้มเหลวหายไปเมื่อหยุด VPN หรือไม่ ถ้าทุกอย่างทำงานได้เมื่อปิดอุโมงค์ ให้สงสัยเส้นทางขากลับ คำถามข้อสอง: ip route show table all แสดงคำนำหน้าเดียวกันสองครั้งหรือไม่ ครั้งหนึ่งบนบริดจ์และอีกครั้งบน tun0 นั่นคือการชนกัน คำถามข้อสาม: แอดเดรสที่ได้รับผลกระทบเป็นคอนเทนเนอร์ เกสต์ NAT หรือเกสต์ที่ทำบริดจ์
คำถามข้อสามสำคัญเพราะแต่ละแบบมีวิธีแก้ที่ถูกต้องต่างกัน และหากเอาวิธีแก้ของคอนเทนเนอร์ไปใช้กับเกสต์ libvirt ก็เสียเวลาทั้งเย็น
ip route
ip route show table all | grep -E '172\.1[7-9]|10\.8'
docker network inspect bridge --format '{{.IPAM.Config}}'เส้นทางขากลับ: ตารางสำหรับแอดเดรสต้นทางหนึ่งรายการ
เมื่อทราฟฟิกของคอนเทนเนอร์ต้องออกผ่านอินเทอร์เฟซกายภาพ ขณะที่โฮสต์เองใช้อุโมงค์ การกำหนดเส้นทางตามต้นทาง คือการเปลี่ยนแปลงที่เล็กที่สุด เพิ่มกฎที่ตรงกับแอดเดรสของคอนเทนเนอร์แล้วส่งไปยังตารางเฉพาะ ไม่มีอย่างอื่นบนโฮสต์ที่ขยับ
ip rule add from 172.22.0.3 lookup 10
ip route add default via 172.22.0.1 table 10ทุกแพ็กเก็ตที่มีต้นทางเป็นแอดเดรสนั้นจะดูตาราง 10 ก่อน และตาราง 10 ส่งต่อไปยังเกตเวย์ของบริดจ์แทนอุโมงค์
ตรวจสอบด้วย ip route get 1.1.1.1 from 172.22.0.3 คำตอบต้องระบุอินเทอร์เฟซของบริดจ์ ไม่ใช่ tun0 กฎที่เพิ่มแบบนี้จะหายไปเมื่อรีบูต จึงควรใส่ไว้ใน unit หรือฮุกเครือข่ายที่เป็นเจ้าของคอนเทนเนอร์
รูปแบบเดียวกันใช้ได้กับคอนเทนเนอร์ WireGuard ซึ่งเส้นทางคำตอบก็ต้องมีกฎที่ชัดเจนเช่นกัน
การชนกันของคำนำหน้า: เปลี่ยนเลขบริดจ์
ตารางเส้นทางส่งคำนำหน้าหนึ่งรายการไปยังที่เดียว ถ้า VPN ดัน 172.17.0.0/16 เข้ามาขณะที่บริดจ์ของ Docker อยู่ตรงนั้นแล้ว เมตริกที่ต่ำกว่าจะชนะ: Docker ติดตั้งเส้นทางที่เชื่อมต่ออยู่ที่เมตริก 0 และเส้นทางที่ถูกดันเข้ามาจะมาถึงที่ 50 อุโมงค์จึงดูเหมือนพังทั้งที่ Docker ยังทำงานอยู่ หรือกลับกัน ขึ้นกับลำดับการติดตั้ง เปลี่ยนเลขบริดจ์ดีกว่าฝืนสู้กับเมตริก
{
"bip": "10.200.0.1/24",
"default-address-pools": [{"base": "10.201.0.0/16", "size": 24}]
}รีสตาร์ต Docker หลังการเปลี่ยนแปลงและสร้างเครือข่ายที่สร้างด้วยพูลเดิมขึ้นใหม่ การเปลี่ยนเมตริกเพียงย้ายความขัดแย้งไปยังการบูตครั้งถัดไป
VM ต้องการคำตอบอีกแบบ
เกสต์ libvirt บนเครือข่าย NAT เริ่มต้นสืบทอดเส้นทางของโฮสต์ และจะเข้าออกไม่ได้เมื่ออุโมงค์ของโฮสต์ครอบเส้นทางเริ่มต้น การย้ายเกสต์ไปยังบริดจ์หรืออุปกรณ์ macvtap ทำให้เกสต์มีเส้นทางของตัวเองบนเครือข่ายกายภาพ ใน virt-manager ให้เพิ่มฮาร์ดแวร์ เลือก Network ตั้งต้นทางเป็นอุปกรณ์โฮสต์ macvtap คง virtio เป็นโมเดล แล้วปิดใช้งานอินเทอร์เฟซ NAT เดิม
เกสต์ macvtap มักเข้าถึงโฮสต์ของตัวเองไม่ได้ นั่นเป็นพฤติกรรมที่คาดไว้ ไม่ใช่ความผิดพลาด และควรอยู่ในบันทึกที่คุณทิ้งไว้
สำหรับเกสต์ที่ต้องการเพียง LAN ของโฮสต์ ไคลเอนต์ของผู้ให้บริการอาจมีสวิตช์ที่ขาดอยู่: กับ Mullvad mullvad lan set allow จะคืนการเข้าถึงในเครื่องโดยไม่ต้องแตะ libvirt และเมื่อคอนเทนเนอร์ต้องเข้าถึงได้เฉพาะผ่านอุโมงค์ ให้ผูกพอร์ตที่เผยแพร่กับแอดเดรสของอุโมงค์ -p 10.8.0.5:8080:8080 แทนการเผยแพร่บนทุกแอดเดรส