เข้าถึงเว็บอินเทอร์เฟซภายในคอนเทนเนอร์ VPN: เลือกเจ้าของพอร์ต
แอปใช้เนมสเปซของ VPN ร่วมกัน พอร์ตจึงเป็นของคอนเทนเนอร์ VPN ผูกตัวรับฟังให้ถูกต้อง เผยแพร่ที่เจ้าของ และทำให้เส้นทางแคบไว้
ไม่มีอะไรผิดกับแอปและไม่มีอะไรผิดกับอุโมงค์ แต่แดชบอร์ดยังโหลดไม่ขึ้น เมื่อบริการรันด้วย network_mode: service:vpn มันจะใช้เนมสเปซเครือข่ายของคอนเทนเนอร์ VPN ร่วมกัน ซึ่งหมายความว่าตัวรับฟังและพอร์ตที่เผยแพร่เป็นของเนมสเปซนั้น ไม่ใช่ของบริการ ตามมาด้วยการตัดสินใจสามข้อ คือแอปผูกที่ใด คอนเทนเนอร์ใดเผยแพร่พอร์ต และเส้นทางบริหารแคบเพียงใด ทำผิดลำดับแล้วทุกการตั้งค่าเดี่ยวจะดูถูกต้อง แต่การประกอบกันกลับทำงานไม่ได้
ใครเป็นเจ้าของเนมสเปซของพอร์ต
ในเนมสเปซที่ใช้ร่วมกัน การเพิ่มรายการ ports: ให้บริการที่พึ่งพาอาศัยไม่ได้ผลอะไร และมีตัวเลือกเครือข่ายหลายอย่างที่ไม่รองรับสำหรับบริการนั้นโดยการออกแบบ ให้เผยแพร่บนคอนเทนเนอร์ที่เป็นเจ้าของเนมสเปซแทน คอนเทนเนอร์นั้นยังเป็นคอนเทนเนอร์ที่ที่อยู่ปรากฏบนโฮสต์ การแมปจึงอ่านเป็นรายการเดียวไม่ใช่รายการละหนึ่งบริการ
services:
vpn:
image: vpn-client-image
cap_add: [NET_ADMIN]
ports:
- "127.0.0.1:8080:8080"
app:
network_mode: "service:vpn"
สังเกตที่อยู่ทางซ้ายของการแมป การผูกกับ 127.0.0.1 ทำให้พอร์ตที่เผยแพร่คงอยู่บนลูปแบ็กของโฮสต์ ซึ่งโดยปกติคือสิ่งที่อินเทอร์เฟซบริหารต้องการ การผูกกับ 0.0.0.0 เปิดเผยบนทุกอินเทอร์เฟซของโฮสต์ และนั่นเป็นการตัดสินใจด้านความปลอดภัยอีกแบบ ไม่ใช่ความสะดวก
ทำให้แอปฟังในที่ที่เนมสเปซคาดหวัง
ตัวรับฟังที่ผูกกับ 127.0.0.1 ภายในเนมสเปซเข้าถึงได้จากภายในเนมสเปซนั้นเท่านั้น พอร์ตโฮสต์ที่เผยแพร่มาจากภายนอก แอปจึงต้องผูกที่อยู่ที่กว้างกว่าเพื่อให้การแมปทำงาน นี่เป็นการแก้ไขหนึ่งบรรทัดในเซิร์ฟเวอร์ส่วนใหญ่ และเป็นขั้นตอนที่ผู้คนข้ามไปหลังจากคัดลอกคู่มือการเสริมความแข็งแกร่งที่เขียนไว้สำหรับการติดตั้งโดยไม่มีคอนเทนเนอร์
docker compose exec app ss -lntp
docker port vpn
curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8080/
รายการตัวรับฟังภายในแอปบอกความจริงเกี่ยวกับที่อยู่ที่ผูก และ docker port บอกว่าเจ้าของเผยแพร่สิ่งใดจริง ๆ ถ้าตัวแรกแสดง 127.0.0.1 และตัวที่สองแสดงการแมปบนโฮสต์ คุณพบความไม่ตรงกันโดยไม่ต้องแตะการกำหนดค่า VPN
เลือกว่าทางบริหารจะเข้ามาอย่างไร
มีการจัดวางที่สมเหตุสมผลสามแบบ เผยแพร่บนคอนเทนเนอร์ VPN แล้วเข้าถึงจากโฮสต์หรือจากเครือข่ายท้องถิ่น วางพร็อกซีย้อนกลับไว้หน้าเนมสเปซและให้พอร์ตที่เปิดอยู่เพียงพอร์ตเดียวแก่พร็อกซี หรือเก็บแดชบอร์ดให้เข้าถึงได้จากภายในเนมสเปซเท่านั้นผ่านเซสชัน exec หรืออุโมงค์ SSH ซึ่งเป็นการเปิดเผยน้อยที่สุดและสะดวกน้อยที่สุด
แบบใดเหมาะสมขึ้นอยู่กับว่าใครต้องการอินเทอร์เฟซและจากที่ใด ผู้ดูแลคนเดียวบนโฮสต์เดียวกันพอใจกับการผูกกับลูปแบ็ก ทีมที่เข้าถึงผ่าน VPN ต้องมีเส้นทางที่ออกแบบไว้และเจ้าของที่ระบุชื่อ การเลือกตัวเลือกพร็อกซีให้ TLS และบันทึกการเข้าถึง แต่มีค่าใช้จ่ายเป็นองค์ประกอบอีกหนึ่งอย่างที่ต้องดูแลให้ทันสมัย
เปิดพอร์ตบริหารโดยไม่เปิดทุกอย่าง
นโยบายการเข้าถึงภายในหรือการล็อกของไคลเอนต์ VPN อาจทิ้งคำขอบริหารที่เข้ามาแม้ในขณะที่อุโมงค์ขาออกทำงานสมบูรณ์ อนุญาตข้อยกเว้นที่บันทึกไว้หนึ่งข้อสำหรับแหล่งที่มาและพอร์ตที่ตั้งใจ แล้วยืนยันว่าการป้องกันปกติของอุโมงค์ไม่เปลี่ยน การปิดสวิตช์ฉุกเฉินเพื่อให้แดชบอร์ดโหลดได้คือการแลกการควบคุมจริงกับแท็บเบราว์เซอร์
เปิดการพิสูจน์ตัวตนของแอปเองไว้ การอยู่ภายในสแตกที่เชื่อมต่อ VPN ไม่ได้ให้สิทธิ์แก่ผู้ใช้ภายในทุกคนหรือทุกอุปกรณ์ที่เข้าถึงโฮสต์ได้ และแผงผู้ดูแลที่ไม่มีการพิสูจน์ตัวตนหลังอุโมงค์ก็ยังเป็นแผงผู้ดูแลที่ไม่มีการพิสูจน์ตัวตน
ตรวจสอบจากอุปกรณ์บริหาร แล้วตรวจสอบอีกครั้งภายหลัง
ทดสอบจากเครื่องที่จะบริหารบริการจริง ไม่ใช่จากโฮสต์ แล้วตรวจสอบเส้นทางอินเทอร์เน็ตที่แอปต้องการแยกต่างหาก ความสำเร็จในการบริหารพิสูจน์ทิศทางเดียวและไม่ได้บอกอะไรเกี่ยวกับขาออก
ทดสอบอีกครั้งหลังจากสร้างสแตกใหม่ เจ้าของเครือข่ายที่ถูกเปลี่ยนจะเปลี่ยนเนมสเปซที่แอปเชื่อมต่อ และ URL ที่เคยทำงานก่อนการอัปเดตอาจไม่ชี้ไปที่ใดเลยหลังจากนั้น จดบันทึกการแมปที่เผยแพร่และที่อยู่ที่ผูกไว้ เพื่อให้การสร้างใหม่ครั้งหน้าเป็นการตรวจสองนาทีไม่ใช่การสอบสวนซ้ำ