ตอนบูต หน่วย socket ที่ผูกที่อยู่ VPN แบบตายตัวอาจล้มเหลวก่อนที่ทันเนลจะกำหนดที่อยู่นั้นให้ และบริการที่อยู่ข้างหลังก็ไม่เคยเริ่มทำงาน สวิตช์สองตัวดูเหมือนการแก้ไขและแก้คนละครึ่งของปัญหานี้ FreeBind ให้ systemd สร้างตัวรับฟังได้ขณะที่ที่อยู่ยังไม่มี ส่วน After= เพียงจัดลำดับงาน จึงเปลี่ยนว่าอะไรเริ่มเมื่อใดโดยไม่ได้ทำให้ที่อยู่มาถึงเร็วขึ้น

สองปัญหาที่ต่างกัน สองสวิตช์ที่ต่างกัน

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

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

FreeBind: ตัวรับฟังมีอยู่ก่อนที่อยู่

FreeBind บอกเคอร์เนลให้อนุญาตการผูกกับที่อยู่ที่ไม่ใช่ที่อยู่ท้องถิ่น systemd จึงสร้าง socket ที่รับฟังตอนบูตและส่งให้แอปพลิเคชันทุกครั้งที่แอปพลิเคชันเริ่ม นี่คือจุดมุ่งหมายของการเปิดใช้งานด้วย socket และเป็นเหตุผลที่ socket อยู่ได้นานกว่าบริการที่อยู่ข้างหลัง

[Socket]
ListenStream=
ListenStream=10.8.0.1:8443
FreeBind=yes

การกำหนดค่าว่างจะล้างรายการรับฟังที่สืบทอดจากหน่วยของผู้ให้บริการก่อนเพิ่มรายการใหม่ ซึ่งป้องกันไม่ให้ตัวรับฟัง wildcard ที่ตกค้างตอบบนทุกอินเทอร์เฟซ แทนที่ที่อยู่และพอร์ตด้วยของคุณเอง และตรวจสอบหน่วยที่มีผลจริง ไม่ใช่แค่ไฟล์ drop-in ใช้ drop-in ภายใต้ชื่อหน่วยแทนการแก้ไฟล์แพ็กเกจในที่ เพราะการอัปเดตแพ็กเกจครั้งถัดไปจะเขียนทับการแก้ไขและไม่เหลือร่องรอยของเจตนา จากนั้นนำไปใช้ผ่านขั้นตอนโหลดใหม่และรีสตาร์ตที่หน่วย socket คาดหวัง

เอกสารอ้างอิง socket ของ systemdอธิบายพฤติกรรม IPv4 และ IPv6 ที่อยู่เบื้องหลังตัวเลือกนี้ และรายละเอียดสำคัญคือมันใช้กับการผูก ไม่ใช่กับการกำหนดเส้นทาง ไม่มีอะไรในนั้นที่กำหนดที่อยู่หรือเริ่ม VPN FreeBind คือสิทธิ์ที่ให้แก่ตัวรับฟัง ไม่ใช่ตัวแทนของอินเทอร์เฟซ

After= และ Wants=: ลำดับไม่ใช่ความพร้อม

ลำดับและข้อกำหนดเป็นแกนที่แยกจากกัน การสับสนทั้งสองทำให้ได้หน่วยที่เริ่มตามลำดับถูกต้องแต่ยังล้มเหลวAfter=vpn-client.serviceหมายความเพียงว่าถ้าทั้งสองงานถูกเริ่ม งานนี้จะรอให้อีกงานเริ่มก่อน มันไม่ดึง VPN เข้ามา และไม่รอให้ VPN เชื่อมต่อเสร็จ

คำสั่งด้านข้อกำหนดอย่างWants=และRequires=ดูแลการเปิดใช้งาน และต่างกันในสิ่งที่เกิดขึ้นเมื่อการพึ่งพาล้มเหลว ตัวหนึ่งดำเนินต่อ อีกตัวหยุด ทั้งสองไม่รู้ว่าทันเนลที่เชื่อมต่อแล้วหมายถึงอะไร โปรเซส VPN อาจทำงานอยู่โดยไม่มีที่อยู่ที่กำหนด หรือมีที่อยู่แล้วแต่ไม่มีเส้นทางไปยังคู่ และทั้งสองสถานะก็ทำให้การพึ่งพาเป็นจริง ถ้าแอปพลิเคชันต้องการให้ที่อยู่มีอยู่จริง ให้จำลองเงื่อนไขนั้นอย่างชัดเจนแทนที่จะถือว่าการเริ่มโปรเซสเป็นหลักฐานของความพร้อม

ตรวจสอบว่าหน่วยประกาศอะไรจริงด้วยsystemctl catและsystemctl show -p After -p Wants -p Requiresdrop-in จากสามไดเรกทอรีที่ต่างกันอาจเพิ่มคำสั่งที่คุณไม่เคยเขียน และ systemd อ่านเฉพาะหน่วยที่มีผลจริง

สิ่งที่ network-online.target ไม่ได้ทำ

หน่วยที่ถูกจัดลำดับหลังnetwork-online.targetจะรอให้ตัวจัดการเครือข่ายประกาศว่าเครือข่ายใช้งานได้ ซึ่งเป็นจุดซิงโครไนซ์ตอนบูต ไม่ใช่เงื่อนไขต่อเนื่อง มันไม่บอกว่าทันเนลหนึ่งๆ ขึ้นอยู่หรือไม่ และจะไม่ทำงานอีกเมื่อ VPN เชื่อมต่อใหม่กลางบ่าย การมองมันเป็นตัวเฝ้าดูการเชื่อมต่อใหม่คือการอ่านเป้าหมายนั้นผิดที่พบบ่อยที่สุด

โครงการ systemd เอกสารความแตกต่างนั้นโดยตรง และผลในทางปฏิบัติคือทุกสิ่งที่ต้องการที่อยู่ของทันเนลต้องมีการพึ่งพาเป็นของตัวเอง หน่วยที่รอ network-online แล้วผูกที่อยู่ของทันเนลจะถูกต้องก็ต่อเมื่อทันเนลขึ้นก่อนโดยบังเอิญ และนั่นคือความบังเอิญ ไม่ใช่การออกแบบ

ทดสอบวงจรชีวิตที่คุณเลือกจริง

ทดสอบการบูตที่สะอาด คำขอหลังที่อยู่ปรากฏ และพฤติกรรมหลัง VPN ล่มแล้วกลับมา สามกรณีนั้นแยกตัวรับฟังที่ทำงานออกจากบริการที่ทำงาน

systemd-analyze verify myapp.socket
systemctl cat myapp.socket
ss -ltn "sport = :8443"

คำสั่งแรกจับข้อผิดพลาดของไฟล์หน่วยก่อนรีบูต คำสั่งที่สองแสดงหน่วยที่รวมแล้ว และคำสั่งที่สามพิสูจน์ว่าตัวรับฟังมีอยู่และอยู่บนที่อยู่ใด ตัวรับฟังบนที่อยู่ wildcard ในจุดที่คุณคาดว่าจะเป็นที่อยู่ของทันเนลคือเศษที่เหลือซึ่ง ListenStream ว่างควรลบออก ทำคำสั่งที่สามซ้ำหลัง VPN เชื่อมต่อใหม่เพื่อดูว่าที่อยู่ย้ายหรือไม่

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

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