OpenVPN iroute กับเส้นทางเคอร์เนล: อันไหนหายไป?
เซิร์ฟเวอร์มีเส้นทางอยู่แล้วแต่ทราฟฟิกยังหยุด การตัดสินใจเรื่องเส้นทางหนึ่งเป็นของเคอร์เนล อีกเรื่องหนึ่งเป็นของเพียร์ เรียนรู้ว่าอันไหนหายไปและต้องตรวจสอบอะไร
แพ็กเก็ตที่ส่งไปยัง 10.77.20.0/24 ต้องผ่านการตัดสินใจสองครั้งแยกกันบนเซิร์ฟเวอร์ OpenVPN: ระบบปฏิบัติการต้องส่งมอบแพ็กเก็ตนั้นให้อินเทอร์เฟซ VPN และ OpenVPN ต้องรู้ว่าไคลเอนต์ที่เชื่อมต่อคนไหนเป็นเจ้าของคำนำหน้านั้น เส้นทางเคอร์เนลที่หายไปจะทำให้แพ็กเก็ตถูกทิ้งก่อนถึงอุโมงค์ ส่วนเส้นทางเพียร์ที่หายไปจะทำให้ถูกทิ้งหลังผ่านอุโมงค์ ความล้มเหลวทั้งสองแบบดูเหมือนกันทุกอย่างเมื่อมองจาก LAN ปลายทาง และการวินิจฉัยว่าเจอแบบไหนต้องใช้หนึ่งคำสั่งในแต่ละฝั่ง
ในเส้นทางข้อมูลแบบผู้ใช้ทั่วไปแบบดั้งเดิม เส้นทางเคอร์เนลจะพาแพ็กเก็ตเข้าสู่โปรเซสอุโมงค์ และ iroute บอกโปรเซสนั้นว่าเพียร์ใดควรได้รับมัน ทั้งสองอย่างทดแทนกันไม่ได้ และการตั้งค่าที่มีเพียงอย่างใดอย่างหนึ่งจะดูสมเหตุสมผลไปจนถึงการ ping ครั้งแรก
การตัดสินใจสองครั้ง ไม่ใช่เส้นทางเดียว
ลองนึกถึงลิงก์แบบไซต์ทูไซต์ที่ 10.77.20.0/24 อยู่หลังไคลเอนต์เพียงเครื่องเดียว เส้นทางเคอร์เนลของเซิร์ฟเวอร์ เช่น ip route add 10.77.20.0/24 dev tun0 จะส่งแพ็กเก็ตที่ตรงกันไปยังอุปกรณ์อุโมงค์ จากนั้น OpenVPN จะตรวจสอบตารางภายในของตนเองซึ่งสร้างจากรายการ iroute ในไดเรกทอรีการตั้งค่าไคลเอนต์ เพื่อตัดสินว่าการเชื่อมต่อของเพียร์ใดจะได้รับแพ็กเก็ตเหล่านั้น ถ้าไม่มีเส้นทางเคอร์เนล แพ็กเก็ตจะไม่ถึงโปรเซสเลย และถ้าไม่มีเส้นทางเพียร์ แพ็กเก็ตจะถึงโปรเซสแต่ไปต่อไม่ได้
การแยกกันเช่นนี้ง่ายที่จะลืม เพราะบรรทัดเส้นทางบรรทัดเดียวในโปรไฟล์ไคลเอนต์อาจดูเหมือนทำงานทั้งสองอย่าง มันไม่ใช่: การพุชเส้นทางบอกไคลเอนต์ว่าต้องส่งอะไรผ่านอุโมงค์ ขณะที่ iroute บอกเซิร์ฟเวอร์ว่าใครเป็นเจ้าของช่วงแอดเดรสที่อยู่หลังไคลเอนต์ ทั้งสองอย่างอยู่ในไฟล์คนละไฟล์ ถูกอ่านโดยคนละฝั่ง และล้มเหลวไปคนละทิศทาง
iroute อยู่ที่ไหนและมันบอกอะไร
รายการนี้อยู่ในไฟล์แยกตามไคลเอนต์ที่ตั้งชื่อตาม common_name ของไคลเอนต์ ภายใต้ client-config-dir ในรูปแบบ iroute 10.77.20.0/24 การที่ชื่อไฟล์ต้องตรงกันไม่ใช่เรื่องผิวเผิน: OpenVPN จะค้นหาตัวตนที่ผ่านการรับรองความถูกต้องแล้วอ่านไฟล์ที่ใช้ชื่อนั้นพอดี ดังนั้นไฟล์ชื่อ site-a จะมีผลกับไคลเอนต์ที่มี common name เป็น site-a เท่านั้น เพิ่ม ccd-exclusive หากไคลเอนต์ที่ไม่มีไฟล์ดังกล่าวควรถูกปฏิเสธทันที ซึ่งเป็นค่าที่เหมาะสมเมื่อไคลเอนต์ทุกตัวเป็นเกตเวย์ของไซต์ เก็บไฟล์หนึ่งไฟล์ต่อเกตเวย์หนึ่งตัว และตั้งชื่อตามชื่อผู้รับรองของใบรับรองที่คุณออกจริง
ทดสอบรายการนี้จากฝั่งเซิร์ฟเวอร์ก่อนจะโทษ LAN ปลายทาง ไฟล์สถานะจะแสดงรายชื่อไคลเอนต์ที่เชื่อมต่อพร้อม common name ของแต่ละตัว และเซิร์ฟเวอร์ที่รันด้วย --verb 4 จะบันทึกการติดตั้ง iroute ขณะที่เพียร์เชื่อมต่อ หากไม่มีอะไรปรากฏตอนเชื่อมต่อ แสดงว่าไฟล์อยู่ผิดไดเรกทอรีหรือระบุตัวตนผิด
กับดัก: ไฟล์อยู่ แต่ตัวตนผิด
รายการ iroute ที่ดูถูกต้องแต่อ้างอิงถึงเพียร์ผิดตัวทำให้เสียเวลามากกว่าไฟล์ที่หายไป เพราะทุกอย่างบนดิสก์ดูเรียบร้อย การเปลี่ยนชื่อใบรับรอง ชื่อ common name ที่ซ้ำกัน และ username-as-common-name ที่เปลี่ยนตัวตนที่มีผลจริง ล้วนทำให้เกิดเรื่องนี้ได้ ตรวจสอบว่าตัวตนใดผ่านการรับรองความถูกต้องของเซิร์ฟเวอร์ แทนที่จะตรวจตัวตนที่คุณคาดไว้: เอาต์พุตของสถานะคือข้อมูลที่เชื่อถือได้ ส่วนชื่อไฟล์เป็นเพียงคีย์สำหรับค้นหา
เส้นทางยังอยู่ได้นานกว่าเจ้าของของมันได้ด้วย เส้นทางแบบสแตติกและรายการ iroute อธิบายคำนำหน้ามากกว่าจะรับประกันความพร้อมใช้งาน ดังนั้นทราฟฟิกอาจยังถูกส่งต่อไปยังเพียร์ที่ขาดการเชื่อมต่ออยู่
ทำให้เส้นทางสมบูรณ์เลยตัวเพียร์ไป
ความเป็นเจ้าของเพียร์เป็นเพียงกลางเส้นทาง ไม่ใช่ปลายทาง ไคลเอนต์ต้องส่งต่อแพ็กเก็ตจากอุโมงค์เข้า LAN ของตน ซึ่งหมายถึงการเปิด IP forwarding บนโฮสต์นั้นและกฎไฟร์วอลล์ที่อนุญาตให้ส่งผ่าน โฮสต์ใน LAN ปลายทางต้องการเส้นทางย้อนกลับสำหรับแอดเดรสอุโมงค์ ไม่ว่าจะเป็นเส้นทางที่ชี้กลับไปยังเกตเวย์หรือการออกแบบ NAT อย่างตั้งใจฝั่งไคลเอนต์ ยืนยันการตั้งค่าการส่งต่อบนไคลเอนต์ด้วย sysctl net.ipv4.ip_forward แทนที่จะสมมติว่าค่าดีฟอลต์ของดิสทริบิวชันใช้ได้
หากไคลเอนต์ VPN อื่นต้องเข้าถึงซับเน็ตนั้น การจัดวางก็ซับซ้อนขึ้นอีก: เซิร์ฟเวอร์ต้องมี client-to-client และไคลเอนต์เหล่านั้นต้องกำหนดเส้นทางคำนำหน้านั้นผ่านอุโมงค์ ไม่มีส่วนใดในนี้ที่รับประกันได้จากตารางเส้นทางของเซิร์ฟเวอร์เอง
ตรวจสอบปลายทางหนึ่งจุดจากต้นทางจริง แทนที่จะตรวจจากตัวเซิร์ฟเวอร์เอง การ ping จากโฮสต์ใน LAN ที่ไม่เกี่ยวข้องไปยังโฮสต์ที่อยู่หลังไคลเอนต์จะทดสอบเส้นทางย้อนกลับ กฎการส่งต่อ และความเป็นเจ้าของเพียร์ในการเคลื่อนไหวครั้งเดียว ขณะที่การแฮนด์เชกที่สำเร็จพิสูจน์ได้เพียงตัวตน จากนั้นตัดการเชื่อมต่อเพียร์ที่เป็นเจ้าของและบันทึกว่าเส้นทางทำอะไร เพราะคำตอบนั้นคือโหมดความล้มเหลวของคุณ