OpenVPN หา ca.crt ไม่เจอแม้โปรไฟล์จะโหลดขึ้น
พาธของโปรไฟล์ไม่ใช่ฐานของไฟล์ข้างใน ดูว่าทำไม --config แบบเต็มยังล้มเหลวที่ ca.crt และการเริ่มทำงานตัดสินคำตอบอย่างไร
บริการเริ่มทำงาน อ่านโปรไฟล์ได้โดยไม่มีข้อผิดพลาด แล้วก็ตายในบรรทัดที่ดูเหมือนไม่เกี่ยวข้อง: มันเปิด ca.crt ไม่ได้ ไม่มีอะไรเปลี่ยนในใบรับรอง และพาธของโปรไฟล์ในไฟล์ unit เป็นแบบเต็ม รูปแบบผสมนั้นเองคือเบาะแส พาธที่คุณส่งไประบุไฟล์หนึ่งไฟล์ แต่ชื่อที่อยู่ข้างในไฟล์นั้นถูกแก้ไขที่อื่นทั้งหมด ดังนั้นการเริ่มทำงานที่ดูเหมือนระบุครบถ้วนอาจยังอ่านคีย์ของมันจากไดเรกทอรีที่ไม่มีใครตั้งใจ
ความล้มเหลวมีสาเหตุไม่กี่อย่าง และควรแยกตามลำดับ: ไดเรกทอรีฐานที่โปรเซสมีอยู่จริง บริบทการเริ่มทำงานของบริการ และสิทธิ์หรือ sandbox รอบไฟล์เมื่อพาธถูกต้องแล้ว แต่ละอย่างทิ้งร่องรอยต่างกัน — ใน unit ในโปรเซส และบนระบบไฟล์
พาธของโปรไฟล์ไม่ใช่ไดเรกทอรีฐาน
ลองนึกถึงโปรเซสที่เริ่มใน /tmp และได้รับ /etc/vpn/prod/tenant-a.ovpn ภายในโปรไฟล์นั้น บรรทัด ca ca.crt ระบุพาธแบบสัมพัทธ์ ไม่มีอะไรในอาร์กิวเมนต์ที่ค้นพบโปรไฟล์เขียนชื่อนั้นใหม่ โปรเซสจึงค้นหา /tmp/ca.crt และรายงานว่าไฟล์หาย
สิ่งที่น่าสับสนคือลำดับของข้อผิดพลาด OpenVPN แยกวิเคราะห์คอนฟิกก่อนและเปิดไฟล์ที่อ้างถึงเมื่อไปถึง ดังนั้นการพิมพ์ผิดในโปรไฟล์จะถูกรายงานก่อนที่จะแตะคีย์ใด ๆ ขณะที่ใบรับรองที่หายจะปรากฏก็ต่อเมื่อการแยกวิเคราะห์ไปถึงตรงนั้น โปรไฟล์ที่โหลดได้จึงเป็นหลักฐานว่าวากยสัมพันธ์ถูกต้อง ไม่ใช่หลักฐานว่าพบไฟล์ที่มันระบุชื่อ
คู่มือแยกอะไร: --config กับ --cd
คู่มือ OpenVPN 2.6 อธิบายสองตัวเลือกที่ต่างกัน ตัวหนึ่งโหลดไฟล์คอนฟิก อีกตัวเปลี่ยนไดเรกทอรีของโปรเซสก่อนที่จะอ่านคอนฟิก คีย์ สคริปต์ และไฟล์อื่น ๆ และต้องการไดเรกทอรีแบบเต็มโดยไม่มีการอ้างถึงไดเรกทอรีปัจจุบัน
openvpn --cd /etc/vpn/prod --config tenant-a.ovpn
การเรียกนั้นเป็นรูปแบบ ไม่ใช่คำสั่งให้เริ่มโปรไฟล์ของคนอื่น สิ่งที่ได้คือความแน่นอน: ฐานของทุกชื่อแบบสัมพัทธ์ในห่วงโซ่ระบุไว้ในคำสั่งแทนที่จะสืบทอดจากเชลล์หรือตัวจัดการใด ๆ ที่เริ่มโปรเซส ทางเลือกอื่นก็ใช้ได้เท่ากันและมักดีกว่าสำหรับบริการ: ปล่อยไดเรกทอรีทำงานไว้แล้วทำให้ทุกไฟล์ที่อ้างถึงเป็นแบบเต็มภายในโปรไฟล์
ไม่ว่าจะเลือกทางไหน ให้ตรวจทั้งห่วงโซ่ไม่ใช่ความล้มเหลวแรก โปรไฟล์อาจดึงไฟล์คอนฟิกอีกไฟล์เข้ามา และชื่อแบบสัมพัทธ์ของไฟล์ที่ถูกรวมจะถูกแก้เทียบกับไดเรกทอรีโปรเซสเดียวกัน ไม่ใช่ไดเรกทอรีของไฟล์ที่รวมมันไว้ พาธของบันทึก ไฟล์ตรวจสอบสิทธิ์ และสคริปต์ช่วยเหลือก็ใช้กฎเดียวกัน
บริการเริ่มที่อื่น
เชลล์แบบโต้ตอบในไดเรกทอรีโปรไฟล์ไม่ได้พิสูจน์อะไรเกี่ยวกับ unit ที่แพ็กเกจแล้ว ตัวจัดการกำหนดไดเรกทอรีทำงานของตัวเอง และสคริปต์ห่ออาจเปลี่ยนอีกครั้งก่อนไบนารีจะทำงาน unit ที่ล้มเหลวคือการเริ่มทำงานเดียวที่คุ้มค่าจะคิดถึง
systemctl show -p WorkingDirectory -p ExecStart --value openvpn@tenant-a
ls -l /proc/$(pgrep -n openvpn)/cwd
คำสั่งที่สองแสดงไดเรกทอรีที่โปรเซสที่ยังทำงานอยู่ถืออยู่จริง และนั่นน่าเชื่อถือกว่าไฟล์ unit เมื่อมีตัวห่อเข้ามาเกี่ยวข้อง ถ้าทั้งสองไม่ตรงกัน คำตอบคือตัวห่อและ unit เป็นร่องรอยที่ทำให้เข้าใจผิด
หลังการค้นหา: สิทธิ์ chroot และ sandbox
ไดเรกทอรีฐานที่ถูกต้องยังให้ข้อความเดิมได้ เพราะการแก้พาธและการเข้าถึงเป็นคนละขั้นตอน โปรเซสต้องการสิทธิ์เรียกใช้บนทุกไดเรกทอรีแม่และสิทธิ์อ่านบนไฟล์ และ unit ของบริการที่ซ่อนส่วนหนึ่งของระบบไฟล์ก็เปลี่ยนสิ่งที่โปรเซสมองเห็นได้เลย
สามแบบที่พบบ่อยให้ข้อผิดพลาดเดียวกัน ไฟล์อ่านได้เฉพาะ root ขณะที่บริการลดสิทธิ์ก่อนเปิดมัน unit ตั้งค่า มุมมองระบบไฟล์แบบป้องกันที่ไม่รวมไดเรกทอรีโปรไฟล์ เดมอนทำงานด้วย chroot พาธที่มีอยู่บนโฮสต์จึงไม่มีอยู่ภายในมุมมองนั้น
วินิจฉัยด้วยเจ้าของไฟล์และตัวตนของโปรเซส ไม่ใช่ด้วยการผ่อนสิทธิ์ การทำให้คีย์ส่วนตัวอ่านได้โดยทุกคนเพื่อกลบข้อผิดพลาดนี้คือการแลกความล้มเหลวที่ดังด้วยความล้มเหลวที่เงียบ และคีย์คือส่วนของไดเรกทอรีที่คุณอยากเปิดเผยน้อยที่สุด
พิสูจน์การแก้ไขด้วยการเริ่มทำงานของคุณเอง
รีสตาร์ท unit จริงจากไดเรกทอรีที่ไม่เกี่ยวข้องกับโปรไฟล์และดูบรรทัดเริ่มทำงานเดิม จากนั้นยืนยันว่าโปรเซสถือไดเรกทอรีที่ตั้งใจไว้ขณะทำงาน และใบรับรองที่โหลดคืออันที่คุณคาดหวัง
systemctl restart openvpn@tenant-a
systemctl status openvpn@tenant-a --no-pager
journalctl -u openvpn@tenant-a -n 20 --no-pager
เมื่อการโหลดพาธสำเร็จ การตรวจสอบสิทธิ์และการกำหนดเส้นทางยังเป็นขั้นตอนแยกที่มีความล้มเหลวของตัวเอง และการเชื่อมต่อที่ขึ้นมาแต่ไม่ผ่านทราฟฟิกคือการสอบสวนอีกเรื่อง การแก้ไขตรงนี้เกี่ยวกับไดเรกทอรีที่ไฟล์มาจากเท่านั้น และควรเห็นได้ในการเรียก ไม่ใช่ให้คนที่รันด้วยมือครั้งสุดท้ายจำไว้
ถ้าโปรไฟล์ถูกติดตั้งโดยตัวจัดการคอนฟิก ให้วางไดเรกทอรีฐานหรือชื่อไฟล์แบบเต็มไว้ที่นั่นด้วย การแก้ด้วยมือบนโฮสต์เดียวคือเวอร์ชันของปัญหานี้ที่กลับมาหลังการสร้างใหม่ครั้งถัดไป