การเผยแพร่พอร์ต Docker กับ VPN: คำตอบไปที่ใด
คอนเทนเนอร์ที่เผยแพร่ตอบกลับจากที่อยู่ของตัวเองก่อนการแปลง NAT ย้อนกลับ สองดีไซน์สามารถคงคำตอบนั้นไว้บนเส้นทางสาธารณะได้ ด้วยต้นทุนที่ต่างกัน
โฮสต์ยังคงตอบ SSH หลังจาก VPN แบบอุโมงค์เต็มรูปแบบขึ้นมา ขณะที่บริการที่เผยแพร่ผ่าน Docker บนเครื่องเดียวกันกลับเงียบลง ตัวรับฟังไม่มีปัญหา: คอนเทนเนอร์ทำงานอยู่ การแมปพอร์ตมีอยู่ และแพ็กเก็ตมาถึง คอนเทนเนอร์แข็งแรงและคำขอไปถึงมันจริง สิ่งที่ต่างคือคำตอบเริ่มจากที่ใดเมื่อ Linux เลือกเส้นทาง และความต่างนั้นกำหนดว่าต้องใช้ดีไซน์ใดในสองแบบด้านล่าง
ติดตามทูเพิลผ่าน NAT ปลายทาง
ใช้โฮสต์ที่ 192.0.2.10 ซึ่งเผยแพร่ TCP 2222 ไปยังคอนเทนเนอร์ที่ 172.30.240.5:22. คำขอจาก 198.51.100.25 ถูกแปลงก่อนไปถึงคอนเทนเนอร์ และคอนเทนเนอร์ตอบกลับในนามของตัวเอง
WAN request: 198.51.100.25 -> 192.0.2.10:2222
after DNAT: 198.51.100.25 -> 172.30.240.5:22
container reply: 172.30.240.5:22 -> 198.51.100.25
ในการตัดสินเส้นทางของโฮสต์ คำตอบยังคงพาที่อยู่ต้นทางของคอนเทนเนอร์ การแปลงย้อนกลับจะคืนทูเพิลที่เผยแพร่ในภายหลัง และนั่นคือเหตุผลที่แพ็กเก็ตดูผิดในจังหวะที่เลือกเส้นทางพอดี
ทำไมกฎที่จำกัดเฉพาะโฮสต์จึงพลาดมัน
กฎที่เลือกตาราง WAN เฉพาะแพ็กเก็ตจาก 192.0.2.10 ครอบคลุมดีมอนของโฮสต์เองและพลาดคำตอบที่ส่งต่อนี้ไปทั้งหมด ที่อยู่ต้นทางบนคำตอบคือ 172.30.240.5 ไม่ใช่โฮสต์
การแก้เกินเหตุคือการส่งทุกอย่างจากคอนเทนเนอร์ผ่าน WAN ซึ่งยังยกเว้นการเชื่อมต่อขาออกที่ไม่เกี่ยวข้องของคอนเทนเนอร์ออกจาก VPN ด้วย นั่นเป็นนโยบายที่ต่างจากที่ขอ และมักทำให้ใครบางคนประหลาดใจในภายหลัง
การจับคู่หลัง DNAT เป็นฮุกอีกแบบ
เอกสาร ไฟร์วอลล์ ของ Docker ระบุว่า การกรองผู้ใช้ทั่วไปเห็นปลายทางหลัง DNAT ดังนั้นการจับคู่พอร์ตที่เผยแพร่ 2222 ในกฎปกติจึงไม่เหมือนกับการจับคู่พอร์ต 22 ของคอนเทนเนอร์ หากทูเพิลดั้งเดิมสำคัญ ให้ใช้กลไกปลายทางดั้งเดิมที่รองรับแทนการเดาว่าพอร์ตใดมองเห็นได้
ความสับสนเรื่องฮุกนี้สร้างกฎที่ดูถูกต้องแต่ไม่เคยตรงกัน ตรวจสอบตัวนับบนกฎเองก่อนเขียนนโยบายใหม่ กฎที่ไม่มีการตรงกันเลยบอกคุณว่ามันถูกประเมินในที่ที่แพ็กเก็ตไปไม่ถึง
ดีไซน์ A: พาเอาคำตัดสินไปเป็นสถานะการเชื่อมต่อ
มาร์กของการเชื่อมต่อสามารถพาคำตัดสินขาเข้าไปข้ามการแปลงได้ แต่ต้องถูกคืนกลับไปยังแพ็กเก็ตก่อนการค้นหาเส้นทางที่สำคัญ ขั้นตอนคือ
- จองฟิลด์มาร์กและลำดับความสำคัญของกฎที่ไม่ชนกับ Docker, VPN หรือเจ้าของนโยบายอื่น
- ระบุเฉพาะการเชื่อมต่อ WAN ใหม่ที่ต้องการ ณ จุดก่อน DNAT ที่มีการติดตามการเชื่อมต่ออยู่
- บันทึกคำตัดสินลงบนมาร์กของการเชื่อมต่อ โดยไม่บังคับให้คำขอดั้งเดิมเองเข้าไปในตาราง WAN
- ในทิศทางคำตอบ ให้คืนเฉพาะบิตมาร์กของคุณเองลงบนแพ็กเก็ตก่อนการกำหนดเส้นทาง
- เลือกตาราง WAN ที่สมบูรณ์ให้เร็วพอที่กฎ VPN จะชนะก่อนไม่ได้
ตารางนั้นต้องมีเส้นทางที่เชื่อมต่อจริงและเกตเวย์ และต้องมีพฤติกรรมที่กำหนดไว้เมื่อไม่มีเส้นทาง การตกไปในอุโมงค์อย่างเงียบ ๆ เป็นผลลัพธ์ที่แย่ที่สุด เพราะการกำหนดค่ายังดูเหมือนทำงานได้ ให้ล้มเหลวแบบปิดและบันทึกแทน
ดีไซน์ B: ยุติที่โฮสต์
ฟรอนต์เอนด์ฝั่งโฮสต์ที่กำหนดค่าไว้อย่างตั้งใจ เช่นพร็อกซี TCP หรือพร็อกซีแบบย้อนกลับหน้าคอนเทนเนอร์ จะคงคำตอบให้เกิดจากที่อยู่ของโฮสต์ จากนั้นกฎที่เขียนสำหรับโฮสต์จะทำงานตามที่คาด และคอนเทนเนอร์ยังอยู่ในเครือข่ายส่วนตัวของตน
ราคาคือชิ้นส่วนที่เคลื่อนไหวอีกชิ้นที่มีการกำหนดค่า การจัดการที่อยู่ต้นทาง และการควบคุมการเข้าถึงของตัวเอง โดยปกติแล้วเป็นขอบเขตที่รองรับซึ่งง่ายกว่า และมักเป็นคำตอบที่ถูกเมื่อนโยบายการกำหนดเส้นทางจะถูกดูแลโดยคนเพียงคนเดียวที่อาจจากไป
ตรวจสอบการเปลี่ยนแปลง ไม่ใช่เจตนา
เปิดการเชื่อมต่อที่ได้รับอนุญาตใหม่จากฝั่งสาธารณะ และยืนยันว่าคำตอบออกทางอินเทอร์เฟซที่ต้องการ จากนั้นตรวจสอบว่าคำขอที่ไม่เกี่ยวข้องซึ่งคอนเทนเนอร์เริ่มต้นยังคงตาม VPN
อย่าล้างตารางการเชื่อมต่อของเครื่องเพื่อทดสอบกฎเดียว: รายการที่มีอยู่คงการแมปเดิมไว้ และการล้างจะทำให้ทุกอย่างอื่นบนโฮสต์เสียหาย การเผยแพร่พอร์ตกำหนดการเข้าถึง มันไม่ได้กำหนดเส้นทางของคำตอบ จดดีไซน์ที่เลือกไว้พร้อมชื่อตาราง เพื่อให้คนถัดไปไม่ต้องค้นพบมันใหม่ระหว่างเหตุการณ์