ไคลเอนต์บนเซิร์ฟเวอร์ OpenVPN สองเครื่องมองเห็นกันได้หรือไม่?
เซิร์ฟเวอร์ OpenVPN สองเครื่องสร้างพูลไคลเอนต์สองพูล ไม่ใช่เครือข่ายเดียว จัดเส้นทางระหว่างกันด้วยซับเน็ตที่แยกจากกัน เส้นทางสองทิศทาง และขอบเขตความเชื่อถือที่ชัดเจน
การตั้งเซิร์ฟเวอร์ OpenVPN เครื่องที่สองทำให้คุณมีที่ที่สองให้ไคลเอนต์เชื่อมต่อ และไม่มีอะไรมากกว่านั้น มันไม่ได้ใส่ไคลเอนต์เหล่านั้นลงในเครือข่ายของเซิร์ฟเวอร์เครื่องแรก และตัวเลือกที่ชื่อ client-to-client เปลี่ยนเฉพาะการส่งต่อภายในโปรเซสเซิร์ฟเวอร์เดียว พูลทั้งสองกลายเป็นเครือข่ายเดียวเมื่อคุณกำหนดเส้นทางระหว่างกันอย่างตั้งใจ โดยมีเจ้าของสำหรับแต่ละทิศทาง ทุกอย่างด้านล่างสมมติโหมด TUN ในพื้นที่ผู้ใช้โดยปิดการส่งต่อภายในนั้นไว้ เคอร์เนลจึงเป็นผู้ตัดสินใจ
ความเชื่อผิด: บัญชีชุดเดียว เครือข่ายเดียว
การยืนยันตัวตนและความสามารถในการเข้าถึงถูกปนกันเพราะทั้งคู่อาศัยอยู่ในคอนฟิกของเซิร์ฟเวอร์ ผู้ใช้ที่ล็อกอินได้บนเกตเวย์ใดก็ได้ในสองตัวดูจากภายนอกเหมือนผู้ใช้บนระบบเดียวที่มีสองประตู ข้างในเซิร์ฟเวอร์แต่ละเครื่องแจกที่อยู่จากพูลของตัวเองและติดตั้งเส้นทางให้เฉพาะไคลเอนต์ที่ตนรับช่วงอยู่ ดังนั้นไคลเอนต์บนเกตเวย์ A ที่ส่งแพ็กเก็ตไปยังไคลเอนต์บนเกตเวย์ B กำลังขอปลายทางที่เซิร์ฟเวอร์ของตัวเองไม่เคยได้ยิน แพ็กเก็ตนั้นไปตามเส้นทางเริ่มต้นของ A ออกจากอุโมงค์ และไปถึงไฟร์วอลล์ที่ไม่เคยถูกขอให้อนุญาต
การเพิ่มเซิร์ฟเวอร์เครื่องที่สองจึงไม่ได้เพิ่มความซ้ำซ้อน การค้นพบ หรือโดเมนบรอดแคสต์ที่ใช้ร่วมกัน มันเพิ่มเครือข่ายที่มีการกำหนดเส้นทางซึ่งต้องมีแผน และแผนนั้นเริ่มต้นที่การกำหนดที่อยู่
ให้แต่ละเกตเวย์มีพูลและที่อยู่ทรานซิตของตัวเอง
สองช่วงที่ซ้อนทับกับสิ่งอื่นไม่ได้ บวกกับลิงก์ทรานซิตเล็ก ๆ ระหว่างโฮสต์ คือแผนที่อยู่ทั้งหมด เก็บทรานซิตไว้บนเซกเมนต์ส่วนตัวที่คุณควบคุม และจดตัวเลขไว้ก่อนที่เซิร์ฟเวอร์ใดจะแจกเช่า
| Gateway | Client pool | Transit address |
|---|---|---|
| gateway-a | 10.64.10.0/24 | 172.28.44.1/30 |
| gateway-b | 10.64.20.0/24 | 172.28.44.2/30 |
จงต้านทานการล่อใจที่จะให้เซิร์ฟเวอร์ทั้งสองใช้พูลเดียวกันเพื่อให้โปรไฟล์เหมือนกัน เส้นทางของเคอร์เนลไม่สามารถบอกได้ว่าโฮสต์ใดในสองเครื่องถือที่อยู่ใด ๆ ภายในช่วงที่ใช้ร่วมกันในขณะนี้ ดังนั้นตารางเส้นทางจะชี้ไปที่เกตเวย์หนึ่งและไคลเอนต์อาจเชื่อมต่อกับอีกเครื่อง ชื่ออินเทอร์เฟซเป็นธรรมเนียมท้องถิ่น ไม่ใช่สถานะที่ใช้ร่วมกัน ที่นี่โฮสต์ทั้งสองเรียกอุปกรณ์อุโมงค์ว่า tun0 และลิงก์ทรานซิตว่า transit0 ซึ่งไม่เป็นไรเพราะไม่มีแพ็กเก็ตใดพาชื่อเหล่านั้นไป
ติดตั้งเส้นทางทั้งสองฝั่ง
เกตเวย์แต่ละตัวต้องการเส้นทางไปยังพูลของอีกฝั่งผ่านที่อยู่ทรานซิต และต้องเปิดการส่งต่อเพื่อให้ตัวใดตัวหนึ่งทำหน้าที่เป็นฮอปได้ ยืนยันตารางปัจจุบันก่อน แล้วเพิ่มรายการและทำให้คงอยู่ผ่านตัวจัดการเครือข่ายของโฮสต์แทนที่จะเป็นฮุกเชื่อมต่อใหม่
sysctl net.ipv4.ip_forward
ip route add 10.64.20.0/24 via 172.28.44.2 dev transit0
ip route get 10.64.20.37
สะท้อนสิ่งนี้บนโฮสต์อีกเครื่องโดยสลับพูล การเพิ่มเส้นทางเดิมซ้ำ ๆ จากสคริปต์ที่ไม่เกี่ยวข้องคือวิธีที่โฮสต์จะลงเอยด้วยสำเนาหลายชุดและการเปลี่ยนแปลงลึกลับในครั้งถัดไปที่มีคนอ่านตาราง หากลิงก์ทรานซิตเป็นอุโมงค์เอง เส้นทางจะชี้ไปที่โทโพโลยีของอุโมงค์นั้นและฮอปต้องอยู่รอดจากการเชื่อมต่อใหม่ ที่อยู่ทรานซิตที่หายไปสามสิบวินาทีจะพาเส้นทางระหว่างพูลไปด้วย ซึ่งเป็นคุณสมบัติของการออกแบบที่ควรกล่าวถึงมากกว่าจะค้นพบ
ดันเส้นทางของไคลเอนต์โดยไม่แกล้งทำเป็นเจ้าของ
ไคลเอนต์ต้องการเส้นทางไปยังพูลระยะไกล มิฉะนั้นระบบปฏิบัติการของพวกเขาจะส่งแพ็กเก็ตไปยังเกตเวย์เริ่มต้นและอุโมงค์จะไม่เห็นมันเลย คอนฟิกของเซิร์ฟเวอร์เป็นที่ธรรมชาติในการส่งมอบ
push "route 10.64.20.0 255.255.255.0"
ใส่บรรทัดสะท้อนในคอนฟิกของเซิร์ฟเวอร์อีกเครื่อง แล้วเชื่อมต่อไคลเอนต์ทดสอบใหม่และอ่านตารางของมัน ไคลเอนต์ที่ไม่สนใจเส้นทางที่ถูกดันต้องมีคอนฟิกที่ได้รับอนุมัติของตัวเอง และเส้นทางที่ไม่เคยมาถึงก็ไม่ใช่การควบคุมการเข้าถึง อย่าให้ iroute แก่ไคลเอนต์สำหรับพูลทั้งหมดของเกตเวย์อีกฝั่ง คำสั่งนั้นมีไว้สำหรับซับเน็ตที่อยู่หลังไคลเอนต์ที่เชื่อมต่อหนึ่งราย และการใช้มันกลบเส้นทางที่ขาดหายระหว่างเกตเวย์ย่อมสร้าง เซิร์ฟเวอร์ที่เชื่อว่าตนถือที่อยู่ที่เข้าถึงไม่ได้.
พิสูจน์คำขอหนึ่งและปฏิเสธอีกอัน
เลือกการดำเนินการจริง เช่น HTTPS จากไคลเอนต์ที่ 10.64.10.21 ไปยังบริการที่ 10.64.20.37 และอนุญาตเฉพาะสิ่งนั้นบนโฮสต์ทั้งสอง ไฟร์วอลล์แต่ละตัวยอมรับคำขอที่ฝั่งขาเข้าและคำตอบที่ติดตามได้ที่ฝั่งขากลับ นโยบายบริการของปลายทางเองยังต้องยอมรับด้วย
iptables -A FORWARD -i tun0 -o transit0 -s 10.64.10.21 -d 10.64.20.37 -p tcp --dport 443 -j ACCEPT
iptables -A FORWARD -i transit0 -o tun0 -d 10.64.10.21 -s 10.64.20.37 -p tcp --sport 443 -m conntrack --ctstate ESTABLISHED -j ACCEPT
เมื่อมีเส้นทางสองทิศทาง NAT ต้นทางไม่จำเป็นและเป็นอันตรายอย่างยิ่งที่นี่ การแปลที่อยู่ต้นทางซ่อนว่าไคลเอนต์ใดส่งคำขอและทำลายนโยบายที่อิงต้นทางฝั่งปลายทาง ตรวจสอบว่ากฎ masquerade ที่มีอยู่สำหรับการออกอินเทอร์เน็ตไม่ได้จับเส้นทางนี้ด้วย จากนั้นทดสอบการปฏิเสธ บริการที่ควรอยู่เฉพาะในพูล B ต้องยังเข้าถึงไม่ได้จากพูล A และคู่ไคลเอนต์บนเกตเวย์เดียวกันก็ต้องทดสอบด้วย เนื่องจากนโยบายการส่งต่อที่คุณเพิ่งเปลี่ยนใช้กับพวกเขาด้วย
แก้ไขแบบจำลองทางความคิดอีกจุด: ลิงก์ทรานซิตบรรทุกแพ็กเก็ตภายในที่ถอดรหัสแล้ว ดังนั้นมันจึงเป็นขอบเขตความเชื่อถือ ไม่ใช่การรับประกันส่วนตัว หากมันข้ามเครือข่ายที่คุณไม่ได้ควบคุม ให้ปกป้องฮอปนั้นด้วยอุโมงค์เข้ารหัสที่ได้รับอนุมัติและกำหนดเส้นทางผ่านโทโพโลยีจริงของมัน TLS ตั้งแต่ต้นจนจบยังคงยืนยันแอปพลิเคชันด้วยตัวเอง ซึ่งเป็นเหตุผลที่บริการภายในควรใช้ต่อไป