ทำความรู้จัก Landlock วิธีจำกัดสิทธิ์โปรแกรมแบบไม่ต้องง้อ Root
ถ้าคุณกำลังฝึกเขียนโปรแกรมบน Linux คุณอาจเคยได้ยินเรื่องการทำ Sandbox (การกักบริเวณโปรแกรมไม่ให้เข้าถึงไฟล์อื่นในเครื่อง) ซึ่งปกติเรามักต้องใช้เครื่องมือซับซ้อนอย่าง Docker หรือต้องขอสิทธิ์ Root (สิทธิ์ผู้ดูแลระบบสูงสุด) แต่ Landlock คือเทคโนโลยีใน Kernel (หัวใจหลักของระบบปฏิบัติการ) ที่ปล่อยให้โปรแกรมของเรา "ล็อกตัวเอง" ได้โดยไม่ต้องใช้สิทธิ์พิเศษใดๆ เลย
ลองนึกภาพว่าคุณเขียนโปรแกรมขึ้นมาหนึ่งตัว แล้วคุณอยากมั่นใจว่ามันจะอ่านได้แค่โฟลเดอร์ที่เรากำหนดเท่านั้น ไม่ว่าจะมีใครแอบแก้โค้ดหรือพยายามเจาะระบบเข้ามา โปรแกรมของคุณก็จะไม่มีทางไปแตะต้องไฟล์อื่นในเครื่องได้เลย นี่คือความปลอดภัยอีกระดับที่โปรแกรมเมอร์ยุคใหม่ควรทำเป็น เพราะมันช่วยป้องกันความเสียหายในกรณีที่ซอฟต์แวร์ของเราโดนแฮก
Landlock ถูกรวมเข้ากับ Linux Kernel มาตั้งแต่ปี 2021 แล้ว แต่หลายคนยังไม่รู้ว่ามันใช้งานง่ายแค่ไหน เราจะมาสร้างโปรแกรมที่สั่งให้ระบบปฏิบัติการจำกัดสิทธิ์ตัวเองกัน โดยไม่ต้องผ่านการตั้งค่าที่ยุ่งยากหรือต้องติดตั้งซอฟต์แวร์เสริมเพิ่มแต่อย่างใด
เตรียมความพร้อมและตรวจสอบระบบก่อนเริ่ม
ก่อนจะเริ่มเขียนโค้ด เราต้องเช็กก่อนว่าคอมพิวเตอร์ของเราพร้อมใช้ Landlock หรือไม่ เนื่องจากมันเป็นฟีเจอร์ของ Kernel คุณต้องใช้ Linux Kernel เวอร์ชัน 5.13 ขึ้นไป และต้องมีการเปิดใช้งานตัวเลือกความปลอดภัยนี้ไว้ในระบบ ซึ่งโดยปกติแล้ว Ubuntu หรือ Fedora เวอร์ชันใหม่ๆ จะเปิดมาให้เลยอยู่แล้ว
วิธีเช็กง่ายที่สุดคือการใช้คำสั่งใน Terminal (หน้าจอพิมพ์คำสั่ง) เพื่อดูว่าระบบมองเห็น Landlock หรือไม่ ถ้าคำสั่งที่คุณรันออกมามีคำว่า landlock โผล่ขึ้นมา แสดงว่าคุณพร้อมลุยแล้ว แต่ถ้าไม่เจอ คุณอาจต้องไปแก้ค่าใน Bootloader (โปรแกรมเริ่มระบบ) ของเครื่อง ซึ่งเป็นจุดที่มือใหม่หลายคนมักพลาดเพราะลืมตรวจสอบขั้นตอนนี้ก่อนเริ่มเขียนโค้ด
หากคุณรันคำสั่งแล้วไม่พบ Landlock อย่าเพิ่งตกใจ ให้ลองตรวจสอบไฟล์หัวข้อ (Header files) ในเครื่องด้วยว่ามีไฟล์ linux/landlock.h อยู่หรือไม่ ถ้าทุกอย่างครบถ้วน เราก็สามารถเขียนโปรแกรมที่จำกัดสิทธิ์ตัวเองได้ทันทีโดยไม่ต้องใช้สิทธิ์ Sudo (คำสั่งขอสิทธิ์ผู้ดูแล) เลยแม้แต่นิดเดียว
# ตรวจสอบว่าระบบรองรับ Landlock หรือไม่
grep landlock /sys/kernel/security/lsm
# ตรวจสอบว่ามีไฟล์หัวข้อสำหรับการเขียนโปรแกรมหรือไม่
ls /usr/include/linux/landlock.h
คำสั่งแรกคือการค้นหาในระบบว่ามีโมดูลความปลอดภัยชื่อ landlock ทำงานอยู่ไหม ส่วนคำสั่งที่สองคือการเช็กว่าคอมพิวเตอร์ของคุณมีชุดคำสั่ง (Library) สำหรับเรียกใช้งาน Landlock หรือยัง ถ้าผลลัพธ์แสดงรายชื่อโมดูลที่มีคำว่า landlock อยู่ในบรรทัดแรก แสดงว่าระบบพร้อมทำงาน ส่วนคำสั่ง ls ควรจะแสดงชื่อไฟล์ขึ้นมา หากไม่เจอไฟล์แสดงว่าต้องติดตั้ง Kernel Headers (ไฟล์พื้นฐานสำหรับพัฒนาโปรแกรมในระดับระบบ) เพิ่มเติมครับ
เข้าใจหลักการทำงานผ่าน 3 คำสั่งระบบ
ในการใช้งาน Landlock เราไม่ต้องใช้ Library อื่นเลย เราจะคุยกับ Kernel โดยตรงผ่าน Syscall (คำสั่งเรียกใช้งานฟังก์ชันของระบบปฏิบัติการ) ทั้งหมด 3 ตัว คือ landlock_create_ruleset, landlock_add_rule และ landlock_restrict_self ซึ่งทำหน้าที่ต่างกันอย่างชัดเจนในการสร้างและบังคับใช้กฎ
ขั้นตอนแรกคือการสร้าง Ruleset (ชุดกฎความปลอดภัย) เพื่อบอก Kernel ว่าเราจะคุมอะไรบ้าง ต่อมาคือการเพิ่มกฎว่าอนุญาตให้เข้าถึงโฟลเดอร์ไหนได้บ้าง สุดท้ายคือการประกาศใช้กฎนั้นกับตัวเอง ซึ่งจุดที่มือใหม่มักสับสนคือค่า handled_access_fs เพราะหลายคนคิดว่ามันคือการ "อนุญาต" แต่จริงๆ แล้วมันคือการ "บอกว่าเราจะควบคุมอะไร" ถ้าเราใส่ค่าการอ่านลงไป ระบบจะบล็อกการอ่านทั้งหมดทันทีจนกว่าเราจะเพิ่มข้อยกเว้น
จำไว้ว่า Landlock มีไว้เพื่อ "ลด" สิทธิ์เท่านั้น ไม่สามารถเพิ่มสิทธิ์ที่ไม่มีอยู่เดิมได้ นี่คือเหตุผลที่มันปลอดภัยมาก เพราะต่อให้โปรแกรมของเราทำผิดพลาด มันก็ไม่มีทางได้รับสิทธิ์เกินกว่าที่มันเคยมีมาก่อน การทำความเข้าใจส่วนนี้จะช่วยให้คุณออกแบบโปรแกรมที่ปลอดภัยได้ตั้งแต่วันแรกที่เริ่มเขียน
สร้างโปรแกรมจำกัดสิทธิ์ตัวเอง
มาลองเขียนโค้ดกันจริงๆ เลยดีกว่า โปรแกรมนี้จะทำหน้าที่เปิดไฟล์ใน /etc ได้ แต่ถ้าพยายามไปอ่านไฟล์ใน /tmp มันจะถูกปฏิเสธทันที เราจะใช้ฟังก์ชัน prctl เพื่อตั้งค่า PR_SET_NO_NEW_PRIVS ก่อนเสมอ เพราะเป็นเงื่อนไขบังคับที่ทำให้ระบบมั่นใจว่าโปรแกรมจะไม่ไปแอบยกระดับสิทธิ์ตัวเองผ่านช่องทางอื่น
สังเกตว่าเราใช้ O_PATH ในการเปิดโฟลเดอร์ เพื่อให้เราได้ File Descriptor (ตัวระบุไฟล์) มาใช้งานโดยไม่ต้องมีสิทธิ์อ่านไฟล์ในโฟลเดอร์นั้นจริงๆ นี่เป็นเทคนิคที่ฉลาดมาก เพราะช่วยให้เรากำหนดกฎได้โดยไม่ละเมิดความปลอดภัยเสียเอง หลังจากตั้งกฎเสร็จแล้ว เราก็สั่ง restrict_self เพื่อล็อกตัวเองไว้ตลอดกาลจนกว่าโปรแกรมจะจบการทำงาน
ถ้าคุณลืมใส่ prctl โปรแกรมจะแจ้งเตือนว่า Operation not permitted (ไม่มีสิทธิ์ทำรายการ) ทันที เพราะ Kernel จะไม่ยอมให้คุณจำกัดสิทธิ์ตัวเองถ้าคุณยังมีโอกาสไปเพิ่มสิทธิ์ผ่านโปรแกรมอื่นได้ นี่คือกลไกป้องกันการ "แหกคุก" ที่ออกแบบมาเพื่อความปลอดภัยสูงสุดครับ
// ใช้คำสั่ง syscall เพื่อคุยกับ Kernel โดยตรง
// ใน main ให้เรียก create_ruleset และ restrict_self
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
perror("prctl"); // แจ้งเตือนหากตั้งค่าความปลอดภัยไม่ผ่าน
return 1;
}
// restrict_self จะทำให้กฎมีผลกับโปรแกรมทันทีและถาวร
if (restrict_self(ruleset_fd)) {
perror("landlock_restrict_self");
return 1;
}
ส่วนของโค้ดนี้คือหัวใจสำคัญ prctl เป็นการบอกระบบว่าโปรแกรมนี้จะไม่ขอสิทธิ์เพิ่มขึ้นอีก ส่วน restrict_self คือการรัดเข็มขัดความปลอดภัยให้แน่นขึ้น ผลลัพธ์ที่ได้คือเมื่อรันโปรแกรมแล้ว ระบบจะยอมให้อ่านไฟล์ใน /etc/hostname ได้ปกติ แต่ถ้าลองอ่าน /tmp/secret.txt จะขึ้นข้อความว่า Permission denied (ถูกปฏิเสธสิทธิ์) ทันทีครับ
กฎของ Landlock ที่ต้องระวัง
สิ่งที่คนเริ่มใช้ Landlock มักจะพลาดคือ "กฎมันรวมกันไม่ได้" สมมติคุณสร้างกฎแรกอนุญาตโฟลเดอร์ A แล้วสร้างกฎสองอนุญาตโฟลเดอร์ B ผลลัพธ์จะไม่ใช่การอนุญาตทั้ง A และ B แต่จะเป็นการ "ตัด" สิทธิ์ที่เหลือทิ้งไปเรื่อยๆ จนสุดท้ายคุณอาจจะเข้าถึงอะไรไม่ได้เลย
เปรียบเทียบง่ายๆ เหมือนการตัดกระดาษ ถ้าคุณตัดส่วนที่ไม่ต้องการทิ้งไปแล้ว คุณไม่สามารถเอาส่วนที่ตัดไปแล้วกลับมาแปะใหม่ได้ Landlock ทำงานในลักษณะเดียวกัน คือมันมีแต่จะทำให้พื้นที่การทำงานแคบลงเรื่อยๆ ดังนั้นถ้าคุณต้องการให้โปรแกรมเข้าถึงได้หลายที่ คุณต้องใส่ทุกเส้นทางไว้ในกฎชุดเดียวตั้งแต่เริ่มสร้าง
อีกเรื่องที่สำคัญคือ "การสืบทอด" ถ้าโปรแกรมของคุณสั่งรันโปรแกรมลูก (Child process) โปรแกรมลูกเหล่านั้นจะติดกฎความปลอดภัยนี้ไปด้วยโดยอัตโนมัติ ซึ่งเป็นเรื่องดีในแง่ความปลอดภัย แต่ถ้าคุณลืมวางแผนไว้ก่อน อาจทำให้โปรแกรมลูกทำงานไม่ได้เพราะเข้าถึงไฟล์ที่จำเป็นไม่ได้ครับ
สรุป: เอาไปประยุกต์ใช้ในงานจริง
การเข้าใจ Landlock ช่วยให้คุณก้าวข้ามความเป็นโปรแกรมเมอร์มือใหม่ที่เขียนโค้ดแค่ให้รันได้ ไปสู่การเป็นคนเขียนโค้ดที่คำนึงถึง Security (ความปลอดภัย) เป็นหลัก คุณสามารถนำไปใช้ในโปรเจกต์อย่างเช่นโปรแกรมจัดการไฟล์ หรือเครื่องมือที่ต้องรันสคริปต์จากผู้ใช้คนอื่น เพื่อป้องกันไม่ให้โปรแกรมเหล่านั้นเข้าถึงไฟล์สำคัญในเครื่องคุณ
ลองเริ่มจากโปรเจกต์เล็กๆ ของคุณเอง เช่น เขียนโปรแกรมอ่านไฟล์คอนฟิก (ไฟล์ตั้งค่า) แล้วลองจำกัดสิทธิ์ให้มันอ่านได้เฉพาะไฟล์ในโฟลเดอร์นั้นเท่านั้น การฝึกทำแบบนี้จะทำให้คุณเข้าใจการทำงานของ Kernel และความปลอดภัยในระดับลึก ซึ่งเป็นทักษะที่บริษัทซอฟต์แวร์ระดับโลกมองหาในตัวโปรแกรมเมอร์
จำไว้ว่าความปลอดภัยไม่ใช่เรื่องไกลตัว แม้จะเป็นเพียงโปรแกรมเมอร์จูเนียร์ การเขียนโค้ดที่ปลอดภัยตั้งแต่บรรทัดแรกคือจุดเริ่มต้นของการเป็นมืออาชีพครับ เริ่มต้นฝึกใช้ Landlock วันนี้ แล้วคุณจะเห็นภาพชัดขึ้นว่าระบบปฏิบัติการปกป้องเราอย่างไร และเราจะช่วยระบบปกป้องข้อมูลของเราได้อย่างไรบ้าง
ที่มา: How to Sandbox a Linux Process with Landlock, No Root Required — freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More