🛡️
VPS

SELinux (Security-Enhanced Linux) เป็นชั้นกำลังความปลอดภัยของ Linux ที่ทำงานอยู่เหนือระบบสิทธิ์ประจำตัว (DAC - Discretionary Access Control) ของ Linux ทั่วไป ส่วนใหญ่ผู้ดูแล VPS มักปิด SELinux ทั้งสิ้นเพราะไม่เข้าใจวิธีการทำงาน แต่ถ้าเข้าใจและใช้อย่างถูกต้อง SELinux จะเป็นเครื่องมือป้องกันระดับ Linux ที่ทรงพลัง ช่วยให้ระบบลดความเสี่ยงจากการเข้าถึงที่ไม่ได้รับอนุญาต บทความนี้จะสอนคุณวิธีตั้งค่า SELinux บน CentOS Stream, Rocky Linux, หรือ AlmaLinux อย่างถูกต้อง รวมทั้งวิธีแก้ไขปัญหาเมื่อเกิด Denial ขึ้น และวิธีใช้ audit2allow เพื่อสร้างนโยบายแทนการปิด SELinux ทั้งหมด

สรุปสั้น: SELinux คือชั้นกำลังความปลอดภัยที่ทำงานอยู่เหนือสิทธิ์ Linux ปกติ มีสามโหมด ได้แก่ Enforcing (บังคับใช้ ปลอดภัยที่สุด), Permissive (บันทึกเท่านั้น), และ Disabled (ปิดอย่างสมบูรณ์) เพื่อไม่ให้โปรแกรมหยุดทำงาน ให้ใช้การตรวจสอบ audit log และ audit2allow เพื่อสร้างนโยบายให้สิทธิ์เฉพาะที่จำเป็น ไม่ควรปิด SELinux ทั้งหมด

SELinux คืออะไร และแตกต่างจากสิทธิ์ Linux ปกติอย่างไร

Linux ดั้งเดิมใช้ระบบสิทธิ์แบบ DAC (Discretionary Access Control) ซึ่งอยู่ในชั้นของผู้ใช้ (user) และกลุ่ม (group) เท่านั้น ตัวอย่างเช่น ถ้าไฟล์ /var/www/html/index.php อยู่ในสิทธิ์ของ root แล้ว process Apache ที่รันด้วยผู้ใช้ www-data จะไม่สามารถอ่านไฟล์นี้ได้ อย่างไรก็ตาม ถ้า Apache เกิดการโจมตีและถูก compromise ผู้โจมตีก็จะมีสิทธิ์ทั้งหมดของผู้ใช้ www-data นั้น รวมถึงการเข้าถึงไฟล์ต่างๆ ที่ www-data มีสิทธิ์

SELinux เพิ่มเติมชั้นกำลังที่สองชื่อว่า Mandatory Access Control (MAC) ซึ่งทำงานแยกจากสิทธิ์ DAC ปกติ แทนที่จะจำกัดสิทธิ์บนพื้นฐาน user/group เพียงอย่างเดียว SELinux จะกำหนด "บทบาท" (role) และ "บริบท" (context) ให้กับแต่ละ process และไฟล์ ตัวอย่างเช่น process Apache อาจถูกกำหนด context "httpd_t" แล้วไฟล์เว็บอาจมี context "httpd_sys_content_t" SELinux kernel จะอนุญาตให้ httpd_t อ่านไฟล์ที่เป็น httpd_sys_content_t เท่านั้น แม้ว่า www-data จะมีสิทธิ์อื่นๆ ก็ตาม แม้ว่าจะเกิด vulnerability ใน Apache ผู้โจมตีก็ไม่สามารถเข้าถึงไฟล์อื่นที่ SELinux ห้ามไว้

เคล็ดลับ: การคิดถึง SELinux ว่าเป็น "กำแพงป้องกัน" หรือ "firewall ด้านเซิร์ฟเวอร์" อาจช่วยให้เข้าใจได้ สิทธิ์ DAC ปกติเป็น "บัตรเข้า" (authentication) แต่ SELinux เป็น "ชั้นรักษาความปลอดภัย" (authorization layer) ที่ตรวจสอบรายการหนึ่งครั้งอีกครั้ง

สามโหมดของ SELinux

SELinux มีสามโหมดการทำงานที่สำคัญ

ตรวจสอบสถานะ SELinux ในปัจจุบัน

ก่อนทำการตั้งค่าใดๆ ให้ตรวจสอบสถานะปัจจุบันของ SELinux บน VPS โดยใช้คำสั่ง getenforce

getenforce

คำสั่งนี้จะแสดงผลเป็น Enforcing, Permissive, หรือ Disabled ในบรรทัดเดียว สำหรับข้อมูลรายละเอียดมากขึ้น ให้ใช้คำสั่ง sestatus

sestatus

ผลลัพธ์จะแสดงโหมดปัจจุบัน นโยบาย (policy) ที่ใช้อยู่ รายการไฟล์ context และอื่นๆ สำหรับข้อมูลละเอียดเพิ่มเติม ให้เพิ่ม -v flag

sestatus -v

เปลี่ยนโหมด SELinux

ในการเปลี่ยนโหมด SELinux ชั่วคราว (จนกว่าจะ reboot) ให้ใช้คำสั่ง setenforce

setenforce 0

คำสั่งข้างต้นจะตั้งค่า SELinux เป็นโหมด Permissive (0 = Permissive, 1 = Enforcing) เป็นการเปลี่ยนชั่วคราว เฉพาะจนกว่าจะ reboot ในการเปลี่ยนถาวร ให้แก้ไขไฟล์ /etc/selinux/config ด้วย root access

sudo nano /etc/selinux/config

หาบรรทัด SELINUX= และเปลี่ยนเป็นค่าที่ต้องการ

SELINUX=enforcing

ค่าที่สามารถตั้งได้คือ enforcing, permissive, หรือ disabled ถ้าเปลี่ยนจาก disabled เป็น enforcing หรือ permissive คุณต้องรีบูต VPS เพราะระบบจำเป็นต้องทำการ relabel ไฟล์ทั้งหมด

ข้อควรระวัง: เมื่อเปลี่ยน SELinux โหมดจาก disabled เป็น enforcing หรือ permissive ระบบจะต้องทำการ relabel ไฟล์ทั้งหมด (scanning ทุกไฟล์เพื่อกำหนด context) ซึ่งอาจใช้เวลาหลายชั่วโมงขึ้นอยู่กับขนาดของข้อมูล ระหว่างการ relabel นี้ VPS ของคุณจะทำงานช้าลง และระหว่าง relabel ขณะใช้ enforcing mode อาจทำให้บริการบางตัวขัดข้อง

ทำความเข้าใจ SELinux Contexts

SELinux context มีรูปแบบ user:role:type:level ส่วนที่สำคัญที่สุดสำหรับการปฏิบัติงานทั่วไปคือ type (แบบ/ประเภท) ตัวอย่าง context ทั่วไปสำหรับไฟล์เว็บไซต์

httpd_sys_content_t

Context สำหรับ process Apache

httpd_t

ในการดูว่าไฟล์มี context อะไร ให้ใช้คำสั่ง ls ที่มี flag -Z

ls -Z /var/www/html/index.php

ในการดูว่า process ใดกำลังรันและมี context อะไร ให้ใช้

ps auxZ | grep httpd

ผลลัพธ์จะแสดง context ของแต่ละ process ที่อยู่ในระบบ

คำสั่ง SELinux ที่ใช้บ่อย

chcon - เปลี่ยน context ของไฟล์

ในการเปลี่ยน context ของไฟล์ หรือโฟลเดอร์ ให้ใช้คำสั่ง chcon (change context)

chcon -t httpd_sys_rw_content_t /var/www/html/uploads/

ทั้งนี้ -t หมายถึงเปลี่ยน type เท่านั้น คำสั่งข้างต้นเปลี่ยน context ประเภท (type) ของโฟลเดอร์ uploads เป็น httpd_sys_rw_content_t ซึ่งอนุญาตให้ Apache อ่านและเขียนไฟล์ในโฟลเดอร์นั้นได้

ในการเปลี่ยน context ของโฟลเดอร์และไฟล์ภายในแบบเรียกซ้ำ ให้เพิ่ม -R flag

chcon -Rt httpd_sys_rw_content_t /var/www/html/uploads/

restorecon - คืน context ไปเป็นค่าเริ่มต้น

ถ้าคุณเปลี่ยน context ผิดหรือต้องการคืนไปเป็นค่าตามนโยบาย SELinux ให้ใช้คำสั่ง restorecon

restorecon -v /var/www/html/

คำสั่งนี้จะอ่าน context ที่ควรจะเป็นจากนโยบาย SELinux ปัจจุบัน แล้วปรับไฟล์ให้ตรงกัน -v flag หมายถึง verbose (แสดงรายละเอียดว่าเปลี่ยนไฟล์ไหนบ้าง)

ในการอัปเดต context ของโฟลเดอร์และไฟล์ทั้งหมดแบบเรียกซ้ำ

restorecon -Rv /var/www/html/

semanage - จัดการนโยบายและ context

semanage เป็นเครื่องมือหลักในการจัดการ SELinux policy การใช้งานทั่วไปคือการกำหนด context ของโฟลเดอร์อย่างถาวร ตัวอย่าง

semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/uploads(/.*)?"

คำสั่งข้างต้นบอก SELinux ว่า โฟลเดอร์ /var/www/html/uploads และทุกไฟล์และโฟลเดอร์ภายในนั้นควรมี context เป็น httpd_sys_rw_content_t อย่างถาวร หลังจากตั้งค่าแล้ว ให้รัน restorecon เพื่อให้ SELinux ปรับไฟล์ปัจจุบันให้ตรงกับการตั้งค่านี้

restorecon -Rv /var/www/html/uploads/

บูลีน (Booleans) ของ SELinux

SELinux มีชุดสิทธิ์เล็กๆ ชื่อว่า booleans ซึ่งควบคุมพฤติกรรมเฉพาะของนโยบาย ตัวอย่าง boolean ที่สำคัญ คือ httpd_can_network_connect ซึ่งอนุญาตให้ Apache ทำการเชื่อมต่อเครือข่ายออกไปข้างนอก (outbound network connection) ซึ่งจำเป็นสำหรับแอปพลิเคชันที่ต้องเชื่อมต่อ database, API, หรือบริการภายนอก

ในการดูรายการ booleans ปัจจุบันทั้งหมด

getsebool -a

ในการตั้งค่า boolean เฉพาะตัว ให้ใช้ setsebool

setsebool -P httpd_can_network_connect on

-P flag หมายถึง persistent (ถาวร) ถ้าไม่มี -P การตั้งค่าจะหายไปหลังจาก reboot

สถานการณ์จริง: Apache ไม่สามารถเชื่อมต่อฐานข้อมูล

สมมติว่าคุณตั้ง VPS ใหม่ด้วย Rocky Linux ติดตั้ง Apache และเว็บแอปพลิเคชัน PHP ที่เชื่อมต่อกับ MySQL บนเซิร์ฟเวอร์อื่น ถ้า SELinux ตั้งเป็น Enforcing คุณอาจได้รับข้อผิดพลาด "Connection refused" หรือ timeout เมื่อเว็บแอปพลิเคชันพยายามติดต่อ database แม้ว่า firewall และสิทธิ์ Linux ทั้งหมดถูกต้อง

เพื่อยืนยันว่า SELinux เป็นสาเหตุ ให้เปลี่ยน SELinux เป็น Permissive ชั่วคราวเพื่อบันทึกการละเมิด

sudo setenforce 0

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

ใช้ Audit Log เพื่อค้นหาปัญหา

เมื่อระบบมี SELinux denial ไฟล์ /var/log/audit/audit.log จะบันทึกรายละเอียด ในการดูการละเมิดล่าสุด

tail -30 /var/log/audit/audit.log | grep denied

บรรทัด denial จะมีลักษณะเช่นนี้

type=AVC msg=audit(1625126789.123:456): avc: denied { connect } for pid=1234 comm="apache" saddr=192.168.1.1 sport=12345 daddr=10.0.0.2 dport=3306

บรรทัดนี้บอกว่า Apache (PID 1234) พยายามสร้าง network connection ไปยัง 10.0.0.2:3306 (MySQL) แต่ SELinux ปฏิเสธ เพื่ออ่านได้ง่ายขึ้น ใช้เครื่องมือ ausearch

ausearch -m AVC -ts recent | head -30

-m AVC ค้นหาข้อความประเภท AVC, -ts recent ค้นหาเฉพาะเหตุการณ์เมื่อเร็วๆ นี้

ใช้ audit2allow เพื่อสร้างนโยบาย

แทนที่จะปิด SELinux ทั้งหมด เราสามารถใช้ audit2allow เพื่อให้ SELinux สร้างนโยบายอนุญาต (policy) สำหรับการกระทำที่จำเป็น ก่อนอื่น ติดตั้ง packages ที่จำเป็น

sudo yum install -y audit policycoreutils-python-utils

จากนั้น สร้างโมดูลนโยบาย โดยให้ audit2allow อ่าน audit log และสร้างแนวทางนโยบาย

sudo audit2allow -a -M myapp

-a flag หมายถึง all (อ่านทุกข้อมูล denial ในไฟล์ audit log ที่ยังไม่ได้ประมวลผล), -M flag หมายถึงสร้างโมดูล ชื่อ myapp คำสั่งจะสร้างไฟล์ myapp.pp (policy package) และ myapp.te (type enforcement)

ก่อนโหลด policy ให้ตรวจสอบไฟล์ myapp.te เพื่อดูว่า audit2allow สร้างการอนุญาตอะไร

cat myapp.te

ถ้าข้อมูลดูสมเหตุสมผลและไม่กว้างเกินไป ให้โหลด policy

sudo semodule -i myapp.pp

เมื่อ policy โหลดแล้ว ให้ปรับ SELinux กลับไปเป็น Enforcing mode

sudo setenforce 1

ตอนนี้ลองใช้เว็บแอปพลิเคชันอีกครั้ง มันควรจะทำงานโดยไม่มีข้อผิดพลาด SELinux denial ถ้ายังมี denial อื่นๆ ให้วนซ้ำ audit2allow อีกครั้ง

เคล็ดลับ: ถ้า audit2allow สร้างนโยบายที่กว้างเกินไป (allow ทุกอย่าง) อย่ารีบโหลดเลย ให้ลบ myapp.pp และ myapp.te แล้ว ลองมี setenforce เป็น permissive ต่อ แล้วเปลี่ยนเป็นเพียงการอนุญาต denial ที่เฉพาะเจาะจง

การกำหนดค่า SELinux อย่างปลอดภัย

การกำหนดค่า SELinux อย่างปลอดภัย หมายถึงไม่เพิ่งปิด SELinux ทั้งหมด แต่ใช้ workflow ที่ระมัดระวัง ดังนี้

  1. ตั้ง SELinux เป็น Permissive mode ชั่วคราว เพื่อบันทึก denial แต่ไม่บังคับใช้
  2. รัน application ของคุณและทดสอบคุณลักษณะทั้งหมด ต้องมั่นใจว่าคุณได้ทดสอบทั้ง read, write, network, และการทำงานอื่นๆ ที่ application ทำ
  3. ดูไฟล์ audit log และหา denial ที่เกี่ยวข้อง
  4. ใช้ audit2allow เพื่อสร้าง custom policy สำหรับการอนุญาตที่จำเป็นเท่านั้น
  5. ตรวจสอบไฟล์ .te ที่สร้าง ตรวจสอบว่าอนุญาตเฉพาะการกระทำที่ application ต้องการจริง
  6. โหลด policy module ด้วย semodule -i
  7. ตั้งค่า SELinux กลับไปเป็น Enforcing mode
  8. ทดสอบ application อีกครั้ง ตรวจสอบว่าทุกคุณลักษณะทำงานได้

ด้วยการทำตาม workflow นี้ คุณจะสร้าง SELinux policy ที่ปลอดภัย และ VPS ของคุณจะได้รับความปกป้องที่ SELinux ให้มา โดยไม่ต้องปิด SELinux ทั้งหมด

สรุป

SELinux เป็นเครื่องมือความปลอดภัยระดับ Linux ที่ทรงพลัง แต่บ่อยครั้งที่เข้าใจไม่ถูกต้อง บุคคลส่วนใหญ่มักปิด SELinux ทั้งหมดแทนที่จะเข้าใจและใช้อย่างถูกต้อง ด้วยการแบ่งแยกมันออกเป็นขั้นตอนเล็กๆ และเข้าใจโหมด บริบท audit log และ audit2allow คุณสามารถกำหนดค่า SELinux ที่เหมาะสมสำหรับ VPS ของคุณได้อย่างมั่นใจ และเพิ่มชั้นกำลังความปลอดภัยจริงให้กับระบบของคุณ

คำถามที่พบบ่อย (FAQ)

SELinux ช้าไหม ทำให้เซิร์ฟเวอร์หยุดนิ่งจริงหรือ

SELinux มีผลต่อประสิทธิภาพเพียงเล็กน้อย ปกติ 1-5% ที่ระบบจะ context switch มากขึ้น ถ้า VPS ของคุณขาด CPU performance อย่างรุนแรง อาจมีปัญหาอื่นร้ายแรงกว่า ตามปกติ SELinux ไม่ใช่คอคาคาก

ฉันเพิ่งปิด SELinux เพราะปัญหา ต้องเปิดใหม่ไหม

ถ้า SELinux ปิด (Disabled) คุณสามารถเปิด Permissive ได้ทันที แต่ถ้าต้องการ Enforcing จะต้องรีบูตเพื่อ relabel ไฟล์ กระบวนการนี้อาจใช้เวลาทั้งกลางคืน ถ้าคุณกำลังจะตั้ง VPS ใหม่ให้เปิด Permissive ตั้งแต่ต้น

audit2allow สร้าง policy ที่ allow ทุกอย่าง มันปลอดภัยไหม

audit2allow สร้างการอนุญาตที่เบสสุดตามที่มีการละเมิด หากคุณตั้ง Permissive แล้วทดสอบ application หลายวัน audit2allow ก็จะสร้าง policy ที่ครอบคลุมเพียงพอ แนะนำให้ตรวจสอบไฟล์ .te ก่อนโหลด

ฉันจะลบ SELinux policy ที่ผิดได้ไหม

ได้ ใช้ semodule -l เพื่อดูรายการ module ที่โหลด แล้ว semodule -r myapp เพื่อลบ module myapp ถ้าต้องการ reset ให้ใช้ restorecon -R เพื่อคืน context ไปเป็นค่าเริ่มต้น

เริ่มต้นใช้งาน VPS AsiaGB วันนี้

VPS AsiaGB ใช้ SSD Storage ทุก Plan เลือก Datacenter ไทยหรือสิงคโปร์ได้ พร้อม Root Access เต็มรูปแบบ เริ่มต้น 500 บาท/เดือน (Linux) พร้อมทีมซัพพอร์ตภาษาไทย

ดูแพ็กเกจ VPS