แพ็กเก็ตสามารถตามเส้นทาง OpenVPN และยังถูกจับโดยนโยบาย IPsec ได้ และการผสมผสานนี้ดูเหมือนบั๊กการกำหนดเส้นทางจากทุกมุมยกเว้นมุมที่ถูกต้อง Linux จะแก้เส้นทางแล้วจึงปรึกษาฐานข้อมูลนโยบายความปลอดภัยแยกต่างหาก เส้นทางปลายทางที่เฉพาะเจาะจงกว่าจึงไม่แทนที่นโยบาย XFRM ที่ตรงกัน อาการที่เห็นได้คือทราฟฟิกที่ออกจากโฮสต์และไม่เคยไปถึง ขณะที่อุโมงค์ทั้งสองรายงานว่าตนเองแข็งแรง มีสามทางเลือกที่แก้ปัญหานี้ และจะเลือกอันไหนขึ้นอยู่กับว่าเส้นทางใดในสองเส้นทางควรพาคำนำหน้านั้น

สองการตัดสินใจ ไม่ใช่หนึ่ง

การเลือกเส้นทางตอบคำถามแคบ ๆ ว่าโฮปถัดไปและที่อยู่ต้นทางใดควรพาแพ็กเก็ตนี้ ฐานข้อมูลนโยบายความปลอดภัยตอบอีกคำถามหนึ่งว่าแพ็กเก็ตนี้ต้องมีการป้องกัน IPsec หรือไม่ และภายใต้ตัวเลือกใด ทั้งสองทำงานกับแพ็กเก็ตเดียวกัน และการทำให้อย่างแรกสำเร็จไม่ได้บอกอะไรเกี่ยวกับอย่างที่สอง ด้วยเหตุนี้การเปลี่ยนเมตริกหรือเพิ่มเส้นทางแบบคงที่จึงอาจปล่อยให้อาการไม่เปลี่ยนแปลง

ตัวเลือก IPsec ที่กว้างเกินไปคือสาเหตุปกติ นโยบายที่ปกป้อง 172.16.0.0/12 ยังครอบคลุม 172.20.8.0/24 ซึ่งผู้ดูแลอาจตั้งใจจะเข้าถึงผ่านอุโมงค์ OpenVPN แทน เจตนามีอยู่เฉพาะในตารางเส้นทาง และฐานข้อมูลนโยบายไม่เคยรับรู้เรื่องนี้

มองสิ่งนี้เป็นความขัดแย้งระหว่างเส้นทางป้องกันสองเส้นที่กำหนดค่าไว้ ไม่ใช่การแข่งขันระหว่างเมตริกสองค่า การแก้ไขเป็นขององค์ประกอบที่ถูกกำหนดค่าด้วยขอบเขตผิด

อ่านเส้นทางที่เคอร์เนลเลือกจริง

เริ่มจากการค้นหาที่เคอร์เนลทำ รวมถึงที่อยู่ต้นทางและกฎนโยบายใด ๆ ที่อาจเบี่ยงเส้นทางไปยังตารางอื่น เส้นทางในตารางหลักอาจไม่ถูกพิจารณาเลยหากกฎก่อนหน้าเลือกตารางอื่น และการจับคู่คำนำหน้าที่ยาวที่สุดใช้ได้เฉพาะภายในตารางที่กฎเลือก

ip rule show
ip route show table all
ip route get 172.20.8.20 from 10.44.7.15

คำสั่งสุดท้ายคือสิ่งสำคัญ เพราะพิมพ์เส้นทางที่เลือกพร้อมที่อยู่ต้นทางที่เคอร์เนลจะใช้ เปรียบเทียบผลลัพธ์นั้นกับตัวเลือกที่นโยบาย IPsec ตรงกัน เมื่อเส้นทางชี้ไปที่อินเทอร์เฟซ OpenVPN และนโยบายยังตรงกับคู่เดิม แสดงว่าคุณจำลองความขัดแย้งได้โดยไม่ต้องเดา

เก็บดัมป์ให้ปลอดที่อยู่ที่ไม่เกี่ยวข้องก่อนถึงตั๋ว ตารางเส้นทางจากโฮสต์โปรดักชันมีโครงสร้างเครือข่ายภายใน และมีเพียงบรรทัดที่ตอบคำถามเท่านั้นที่ควรค่าแก่การวาง

อ่านนโยบายที่ใช้บังคับด้วย

รายการนโยบายแสดงทิศทาง ตัวเลือก และเทมเพลตที่ตัดสินว่าเกิดอะไรขึ้นกับแพ็กเก็ตที่ตรงกัน อ่านทิศทางขาออกก่อน แล้วจึงอ่านฝั่งขาเข้าสำหรับทราฟฟิกขากลับ เพราะข้อยกเว้นทางเดียวทำให้เกิดการเชื่อมต่อที่เริ่มแล้วไม่เคยเสร็จสิ้น

ip -s xfrm policy
swanctl --list-sas

เปรียบเทียบตัวเลือกในรายการกับคำนำหน้าที่การเชื่อมต่อเจรจาไว้ การปิดการติดตั้งเส้นทางของ strongSwan ไม่ได้ลบนโยบายเหล่านั้น และการเปลี่ยนเมตริกไม่ได้เปลี่ยนว่าคู่โรคต้นทางและปลายทางใดที่นโยบายปกป้อง การแก้ไขปลอมสองอย่างนี้ควรถูกตัดออกตั้งแต่ต้น เพราะเป็นสิ่งแรกที่ผู้คนลอง

หากรายการไม่มีนโยบายสำหรับคำนำหน้าที่คุณคาดไว้ ปัญหาอยู่ที่อื่นและตารางเส้นทางน่าจะบอกความจริง หากมีนโยบายที่กว้างกว่าซึ่งครอบคลุมคำนำหน้านั้น แสดงว่าคุณพบการดักจับแล้ว

สามทางเลือกเมื่อทั้งสองเส้นทางชอบด้วยกฎหมาย

การจำกัดตัวเลือก IPsec ให้แคบลงเป็นทางเลือกที่สะอาดที่สุดเมื่อคำนำหน้าที่กว้างเป็นความสะดวกไม่ใช่ข้อกำหนด การลดตัวเลือกทราฟฟิกระยะไกลให้เหลือเฉพาะซับเน็ตที่อยู่หลัง IPsec จริง ๆ จะลบความขัดแย้งสำหรับทุกโฮสต์ในครั้งเดียว และแลกมาด้วยการเจรจาคีย์ใหม่ ไม่ใช่องค์ประกอบใหม่

ข้อยกเว้นแบบ passthrough คือทางเลือกแบบศัลยกรรมเมื่อตัวเลือกที่กว้างต้องคงอยู่ strongSwan รองรับการเชื่อมต่อแยกที่ child ใช้โหมด pass ซึ่งบอกเคอร์เนลว่าทราฟฟิกที่ตรงกันต้องไม่ถูกประมวลผลโดย IPsec ที่อยู่ระยะไกลแบบ loopback กันการเชื่อมต่อนั้นไม่ให้ถูกเลือกสำหรับเพียร์ขาเข้า และตัวเลือกต้องอธิบายคู่ที่ได้รับอนุญาตจริง ไม่ใช่ทุกอย่าง

connections {
    openvpn-exception {
        remote_addrs = 127.0.0.1
        children {
            openvpn-exception {
                local_ts = 10.44.7.0/24
                remote_ts = 172.20.8.0/24
                mode = pass
                start_action = trap
            }
        }
    }
}

ตัวอย่างการกำหนดค่า strongSwan อธิบายประเภทนโยบายนี้และธรรมเนียมเพียร์แบบ loopback ทางเลือกที่สามคือ การออกแบบอิงเส้นทางด้วยอินเทอร์เฟซ XFRM ซึ่งผูกนโยบายกับทราฟฟิกที่กำหนดเส้นทางผ่านอินเทอร์เฟซที่ตั้งชื่อ แทนที่จะผูกกับตัวเลือกส่วนกลาง เป็นการย้ายระบบไม่ใช่การปรับแต่ง และทราฟฟิกยังต้องเป็นไปตามตัวเลือกที่เจรจาไว้

OptionUse it whenCost
Narrow the selectorThe broad prefix was convenienceA rekey and a policy review
Passthrough childThe broad selector must stayOne exception per intended pair
XFRM interfacePolicy should follow routingA design migration

พิสูจน์ข้อยกเว้นโดยไม่ทำให้ส่วนที่เหลืออ่อนแอ

หลังจากโหลดการเปลี่ยนแปลงแล้ว ให้ทดสอบข้อยกเว้นและปลายทางปกติที่ต้องยังได้รับการปกป้อง ตรวจทั้งสองทิศทาง จากนั้นปล่อยอุโมงค์ OpenVPN ลงและยืนยันว่าเกิดอะไรกับทราฟฟิกที่ถูกยกเว้น ข้อยกเว้นที่ส่งคำนำหน้านั้นแบบเปิดเผยอย่างเงียบ ๆ เมื่ออุโมงค์ล่มคือการตัดสินใจเชิงนโยบายที่คุณควรทำอย่างตั้งใจ ไม่ใช่ค้นพบระหว่างเหตุการณ์

บันทึกว่าคำนำหน้าใดใช้เส้นทางใดและเพราะเหตุใด มิฉะนั้นวิศวกรคนถัดไปที่เห็นตัวเลือกกว้างจะเปิดการสอบสวนเดิมอีกครั้ง และคำตอบจะอยู่ในข้อความ commit ที่ไม่มีใครอ่าน

บทความที่เกี่ยวข้อง