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

แยกความสามารถที่หายไปออกจากอุปกรณ์ที่ซ่อนอยู่

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

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

รู้ว่าคุณกำลังดูชุดความสามารถใด

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

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

ให้ความสามารถในยูนิต ไม่ใช่ในตัวห่อ

ส่วนบริการขั้นต่ำสำหรับอุโมงค์ที่ต้องสร้างอุปกรณ์และติดตั้งเส้นทางมีลักษณะเช่นนี้

[Unit]
Description=OpenVPN client, office profile
After=network-online.target

[Service]
Type=notify
User=openvpn
Group=openvpn
NoNewPrivileges=yes
AmbientCapabilities=CAP_NET_ADMIN
CapabilityBoundingSet=CAP_NET_ADMIN
ExecStart=/usr/sbin/openvpn --config /etc/openvpn/office.conf

AmbientCapabilities ใส่สิทธิ์ลงในชุดสภาพแวดล้อมก่อนที่กระบวนการจะเริ่ม และ CapabilityBoundingSet ป้องกันไม่ให้กระบวนการถือสิ่งใดนอกเหนือจากรายการนั้น NoNewPrivileges=yes ปิดกั้นการได้มาซึ่งสิทธิ์ผ่าน setuid หรือความสามารถระดับไฟล์ ในขณะที่ความสามารถที่ยูนิตให้อย่างชัดเจนยังคงมีผล เพิ่ม CAP_NET_BIND_SERVICE เฉพาะเมื่อบริการต้องผูกพอร์ตต่ำ และอย่าเพิ่ม CAP_SYS_ADMIN เพียงเพราะกระทู้ในฟอรัมทำเช่นนั้น

ถ้ายูนิตห่อไบนารีด้วย sudo ให้เอาตัวห่อออก systemd ใช้ User= อยู่แล้ว และชั้นพิเศษนั้นคือสาเหตุที่เป็นไปได้มากที่สุดที่ชุดสภาพแวดล้อมว่างเปล่า

ตรวจสอบกับกระบวนการที่ทำงานอยู่ ไม่ใช่ไฟล์ยูนิต

อ่านสิ่งที่ตัวจัดการนำไปใช้จริง แล้วอ่านกระบวนการที่มันสร้างขึ้น

unit=openvpn-client@office
systemctl show -p User -p AmbientCapabilities "$unit"
systemctl show -p MainPID --value "$unit" | xargs -r getpcaps
grep -E '^Cap(Eff|Amb)' /proc/$(systemctl show -p MainPID --value "$unit")/status

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

ควรปล่อยสิทธิ์หลังเริ่มทำงาน

OpenVPN สามารถเริ่มด้วยสิทธิ์แล้วลดลงไปยังบัญชีไร้สิทธิ์ผ่านตัวเลือก user และ group ของตัวเอง โดย persist-key และ persist-tun ทำให้อุโมงค์ยังใช้งานได้หลังจากนั้น การจัดแบบนี้ทำให้ช่วงเวลาที่กระบวนการถือสิทธิ์แคบลง และมักเหมาะสมกว่าการเริ่มแดมอนทั้งหมดแบบไร้สิทธิ์ด้วยความสามารถถาวร

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

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