เมื่อสคริปต์ client-connectออกด้วยรหัสที่ไม่ใช่ศูนย์ OpenVPN จะปฏิเสธไคลเอนต์ และผู้ดูแลมักคิดว่าสคริปต์ client-disconnect ที่เกี่ยวข้องจะจัดการทุกอย่างให้เรียบร้อย บ่อยครั้งมันไม่เคยทำงานเลย เพราะการประมวลผล disconnect ขึ้นอยู่กับว่าขั้นตอน connect ทำอะไรสำเร็จไปแล้ว การมองว่าการปฏิเสธและการย้อนกลับเป็นกลไกเดียวกันคือสิ่งที่เปลี่ยนการเข้าสู่ระบบที่ล้มเหลวให้กลายเป็นกฎไฟร์วอลล์ที่รั่วไหลหรือบันทึกที่ไม่มีเจ้าของ สิ่งเหล่านี้เป็นภาระสองอย่างแยกจากกัน และมีเพียงอย่างเดียวที่เป็นอัตโนมัติ อ่านเส้นทางออกของ hook เองก่อนจะโทษเซิร์ฟเวอร์ว่าทิ้งสถานะไว้

การออกด้วยรหัสที่ไม่ใช่ศูนย์ปฏิเสธไคลเอนต์ แต่ไม่ได้ย้อนงานของคุณ

สถานะการออกของ client-connect คือการตัดสินใจรับเข้า เลขศูนย์หมายถึงรับเข้า สิ่งอื่นใดหมายถึงรื้ออินสแตนซ์ก่อนที่มันจะถูกตั้งขึ้นอย่างสมบูรณ์ ไม่มีสิ่งใดในสัญญานั้นตรวจสอบว่าสคริปต์ทำอะไรกับโลกภายนอกไปแล้ว หากสคริปต์เพิ่มกฎ iptables เขียนแถว หรือเพิ่มตัวนับ การเปลี่ยนแปลงเหล่านั้นอยู่รอดจากการปฏิเสธ

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

การปฏิเสธเป็นอัตโนมัติ การล้างข้อมูลไม่ใช่

คู่มือ OpenVPN 2.6 ผูกการประมวลผล client-disconnect ไว้กับการที่การประมวลผล connect ก่อนหน้าสำเร็จ ข้อยกเว้นที่บันทึกไว้ครอบคลุมห่วงโซ่แบบเรียงซ้อน: หากขั้นตอน connect หนึ่งคืนความสำเร็จไปแล้ว ขั้นตอน disconnect ที่เกี่ยวข้องก็ยังทำงานเมื่ออินสแตนซ์ถูกรื้อ แม้ขั้นตอน connect ภายหลังจะล้มเหลว ข้อยกเว้นนั้นแคบและขึ้นอยู่กับจำนวน callback ที่กำหนดค่าไว้ จึงทำให้การทดสอบสคริปต์เชลล์เดียวไม่บอกอะไรคุณเกี่ยวกับห่วงโซ่

ทำแผนที่การกำหนดค่าจริงก่อนออกแบบรอบๆ: สคริปต์ใด ปลั๊กอินใด และทำงานตามลำดับใด ตารางด้านล่างแสดงสิ่งที่การตั้งค่าที่ทำค้างไว้ทิ้งไว้เบื้องหลัง

What the hook did before failingWhat the client seesWhat stays behind
Created a firewall entryA rejection, with no tunnelA rule matching an address nobody owns
Wrote a state rowA rejection, with no tunnelA record of a session that never started
Allocated a tunnel addressA rejection, with no tunnelAn address marked busy until something releases it

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

ชดเชยภายในสคริปต์ที่ล้มเหลว

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

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

ทำให้การชดเชยเป็น idempotent และมีเจ้าของ

การล้างข้อมูลต้องปลอดภัยเมื่อรันสองครั้งและแม่นยำเกี่ยวกับสิ่งที่ลบได้ เหตุการณ์ล่าช้าจากความพยายามก่อนหน้าไม่ควรลบการจัดสรรของเซสชันใหม่กว่าเพียงเพราะทั้งสองใช้ชื่อร่วมกันหรือที่อยู่ tunnels ที่นำกลับมาใช้ใหม่ บันทึก handle หรือ operation id ที่เฉพาะเจาะจงพร้อมทรัพยากร และลบด้วยคีย์นั้นแทนที่จะลบด้วยชื่อ ธุรกรรมฐานข้อมูลช่วยได้เฉพาะกับการเปลี่ยนแปลงของฐานข้อมูลเอง กฎไฟร์วอลล์ที่อยู่นอกขอบเขตนั้นต้องมีขั้นตอนชดเชยที่ชัดเจน

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

ทดสอบสามเส้นทางที่แตกต่างกันจริง

ฝึกสามกรณี: การปฏิเสธก่อนที่จะมีการจัดสรรใดๆ การปฏิเสธหลังการจัดสรรบางส่วน และเซสชันที่รับเข้าตามปกติซึ่งสิ้นสุดในภายหลัง ทั้งสามให้บรรทัดบันทึกและเศษที่เหลือต่างกัน ตรวจสอบสถานะภายนอกหลังแต่ละกรณี ไม่ใช่เพียงข้อความล้มเหลวของไคลเอนต์ เพราะความล้มเหลวของไคลเอนต์คือผลลัพธ์ที่คาดหวังในสองจากสามกรณี

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

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