เคยเจอ Permission Denied ทั้งที่ chmod ถูกต้องไหม
สำหรับผู้ดูแลระบบ Linux โดยเฉพาะสาย Rocky Linux, RHEL, AlmaLinux หรือ CentOS เดิม หลายคนคงเคยเจอเหตุการณ์แบบนี้
ตั้งค่า Apache ถูกแล้ว
กำหนด permission ถูกแล้ว
owner ก็ถูกแล้ว
แต่เว็บยังเปิดไม่ได้ หรือ application ยังเขียนไฟล์ไม่ได้
พอค้นไปค้นมาเจอคำแนะนำยอดนิยมว่า
sudo setenforce 0
หรือหนักกว่านั้นคือแก้ไฟล์ config เพื่อปิด SELinux ถาวร
ปัญหาคือ วิธีนี้อาจทำให้ระบบ “ใช้งานได้” จริง แต่เป็นการลดชั้นความปลอดภัยสำคัญของ Linux Server ลงทันที บทความนี้จะพาเข้าใจ SELinux แบบไม่ปวดหัว พร้อมแนวทางแก้ปัญหาแบบ SysAdmin ใช้งานจริง โดยไม่ต้องปิด SELinux เป็นคำตอบแรก
บทความนี้เหมาะสำหรับผู้เริ่มต้นถึงระดับกลางที่ดูแล Linux Server และต้องการเข้าใจ SELinux ให้ใช้งานได้จริง ไม่ใช่แค่ท่องจำคำสั่ง
เราจะเรียนรู้เรื่องสำคัญต่อไปนี้
-
SELinux คืออะไร และต่างจาก permission ปกติอย่างไร
-
โหมด Enforcing, Permissive, Disabled ต่างกันอย่างไร
-
วิธีตรวจสอบสถานะ SELinux
-
วิธีดู SELinux context ของไฟล์และ process
-
วิธีแก้ปัญหาเว็บหรือ service ถูก SELinux block
-
วิธีใช้
semanage,restorecon,setsebool,ausearch -
แนวทาง Troubleshooting แบบไม่ต้องปิด SELinux ถาวร
ทดสอบแนวทางคำสั่งบน Rocky Linux 9/10 และใช้ได้กับระบบตระกูล RHEL-compatible เป็นหลัก
พื้นฐานที่จำเป็นก่อนเริ่ม
ก่อนทำตามบทความนี้ ควรมีพื้นฐานดังนี้
-
ใช้งาน command line บน Linux ได้
-
มีสิทธิ์
sudo -
ใช้ Rocky Linux, RHEL, AlmaLinux หรือ CentOS Stream
-
เข้าใจ Linux permission เบื้องต้น เช่น
chmod,chown,ls -l -
มี service สำหรับทดลอง เช่น Apache HTTP Server หรือ Nginx
ติดตั้งเครื่องมือที่จำเป็นก่อน
sudo dnf install -y policycoreutils-python-utils setroubleshoot-server audit
คำอธิบาย:
-
policycoreutils-python-utilsมีคำสั่งสำคัญ เช่นsemanage -
setroubleshoot-serverช่วยวิเคราะห์ SELinux denial -
auditใช้บันทึกเหตุการณ์ด้าน security รวมถึง SELinux block
เปิดใช้งาน audit service
sudo systemctl enable --now auditd
ตรวจสอบสถานะ
sudo systemctl status auditd
SELinux คืออะไร
SELinux ย่อมาจาก Security-Enhanced Linux เป็นระบบควบคุมสิทธิ์แบบ Mandatory Access Control หรือ MAC
ถ้าจะอธิบายให้ง่าย Linux permission ปกติ เช่น owner, group, mode 755, 644 เป็นระบบที่เรียกว่า Discretionary Access Control หรือ DAC หมายความว่าเจ้าของไฟล์มีอำนาจกำหนดสิทธิ์ไฟล์ของตัวเองได้
แต่ SELinux ทำงานอีกชั้นหนึ่ง โดยมี policy กลางของระบบคอยตัดสินว่า process ไหนสามารถเข้าถึง file, directory, port หรือ resource อะไรได้บ้าง
ตัวอย่างเช่น
-
Apache process อาจมี domain เป็น
httpd_t -
ไฟล์เว็บปกติควรมี type เป็น
httpd_sys_content_t -
ไดเรกทอรีที่เว็บต้องเขียนไฟล์ได้ อาจต้องใช้ type เป็น
httpd_sys_rw_content_t
ดังนั้น แม้ Linux permission จะอนุญาตแล้ว แต่ถ้า SELinux policy ไม่อนุญาต ระบบก็ยัง block ได้
นี่คือเหตุผลที่บางครั้งเราเจอปัญหา
Permission denied
ทั้งที่ chmod และ chown ดูเหมือนถูกต้องแล้ว
ทำไม SELinux ถึงมีประโยชน์
ให้จินตนาการว่าเว็บเซิร์ฟเวอร์ถูกโจมตีผ่านช่องโหว่ของ web application ถ้าไม่มี SELinux ผู้โจมตีอาจใช้สิทธิ์ของ process นั้นอ่านไฟล์อื่นในระบบ หรือเข้าถึง path ที่ไม่ควรแตะต้องได้ง่ายขึ้น
แต่ถ้าเปิด SELinux ในโหมด Enforcing ต่อให้ process ถูกเจาะได้ การเคลื่อนไหวของ process จะยังถูกจำกัดด้วย policy
พูดง่าย ๆ คือ SELinux ช่วย “กักบริเวณ” service ไม่ให้ทำเกินหน้าที่ของตัวเอง
ตัวอย่างแนวคิด:
-
Apache ควรอ่านไฟล์เว็บ ไม่ควรอ่านไฟล์ส่วนตัวของ user
-
Database ควรเขียนใน directory ของ database ไม่ควรเขียนมั่วทั้งระบบ
-
Service ที่ไม่ได้รับอนุญาต ไม่ควร bind port บางประเภท
-
Container หรือ daemon ควรถูกจำกัดขอบเขตการเข้าถึง resource
ดังนั้น SELinux ไม่ใช่ตัวปัญหา แต่เป็น security guard ที่เข้มงวดมาก ถ้าเราเข้าใจกฎของเขา การดูแลระบบจะปลอดภัยขึ้นมาก
โหมดของ SELinux
SELinux มีโหมดสำคัญที่ผู้ดูแลระบบต้องรู้
1. Enforcing
เป็นโหมดที่ SELinux ทำงานเต็มรูปแบบ ถ้า policy ไม่อนุญาต ระบบจะ block ทันที
ตรวจสอบได้ด้วยคำสั่ง
getenforce
ถ้าผลลัพธ์เป็นแบบนี้ แปลว่า SELinux กำลังบังคับใช้นโยบายจริง
Enforcing
โหมดนี้เหมาะกับ production server
2. Permissive
โหมดนี้ SELinux จะไม่ block การทำงานจริง แต่จะบันทึก log ว่า “ถ้าเป็น Enforcing จะถูก block”
เหมาะสำหรับใช้วิเคราะห์ปัญหาชั่วคราว เช่น เพิ่งติดตั้ง application ใหม่ แล้วต้องการดูว่า SELinux จะ block อะไรบ้าง
เปลี่ยนเป็น Permissive ชั่วคราว
sudo setenforce 0
กลับเป็น Enforcing
sudo setenforce 1
ตรวจสอบอีกครั้ง
getenforce
⚠️ คำสั่ง setenforce มีผลชั่วคราวเท่านั้น เมื่อ reboot ค่าอาจกลับไปตาม config เดิม
3. Disabled
เป็นการปิด SELinux ไม่ให้โหลด policy
ไม่แนะนำให้ใช้ในงาน production เพราะนอกจากระบบจะเสียชั้นป้องกันสำคัญแล้ว ยังอาจทำให้ไฟล์ใหม่ไม่มี label ที่ถูกต้อง เมื่อต้องการเปิด SELinux กลับมาในอนาคต อาจต้อง relabel filesystem ใหม่ ซึ่งใช้เวลานานและเสี่ยงต่อปัญหาระหว่าง boot
ตรวจสอบสถานะ SELinux
ใช้คำสั่งพื้นฐาน
getenforce
ดูรายละเอียดมากขึ้น
sestatus
ตัวอย่างผลลัพธ์
SELinux status: enabled
Loaded policy name: targeted
Current mode: enforcing
Mode from config file: enforcing
จุดที่ควรดูคือ
-
SELinux statusเปิดหรือไม่ -
Loaded policy nameใช้ policy อะไร -
Current modeตอนนี้เป็น Enforcing หรือ Permissive -
Mode from config fileค่า default หลัง reboot คืออะไร
ตั้งค่า SELinux ถาวร
ไฟล์ config หลักคือ
sudo nano /etc/selinux/config
ตัวอย่างค่าที่แนะนำ
SELINUX=enforcing
SELINUXTYPE=targeted
คำอธิบาย:
-
SELINUX=enforcingให้ SELinux ทำงานจริง -
SELINUX=permissiveใช้สำหรับทดสอบหรือ debug -
SELINUX=disabledไม่แนะนำ ยกเว้นมีเหตุผลเฉพาะและเข้าใจผลกระทบ -
SELINUXTYPE=targetedเป็น policy ที่ใช้ทั่วไปในระบบตระกูล RHEL
หลังแก้ไขไฟล์ config ต้อง reboot เพื่อให้มีผลเต็มรูปแบบ
sudo reboot
⚠️ ถ้าเครื่องเคยปิด SELinux มาก่อน แล้วต้องการเปิดกลับมา ควรวางแผน maintenance window เพราะระบบอาจต้อง relabel filesystem
ทำความเข้าใจ SELinux Context
SELinux ใช้ label หรือ context ในการตัดสินสิทธิ์
ดู context ของไฟล์
ls -Z /var/www/html
ดู context ของ directory
ls -Zd /var/www/html
ตัวอย่างผลลัพธ์
system_u:object_r:httpd_sys_content_t:s0 /var/www/html
ส่วนที่ SysAdmin มักต้องสนใจมากที่สุดคือ type
จากตัวอย่างนี้คือ
httpd_sys_content_t
แปลว่าไฟล์หรือ directory นี้เป็น content ที่ Apache/httpd สามารถอ่านได้ตาม policy
ดู context ของ process
ps -eZ | grep httpd
ตัวอย่าง
system_u:system_r:httpd_t:s0 1234 ? 00:00:01 httpd
ในกรณีนี้ process ของ Apache ทำงานใน domain httpd_t
หลักคิดง่าย ๆ คือ
process domain ต้องเข้ากันได้กับ file type ตาม policy ของ SELinux
ตัวอย่างปัญหา: Apache อ่านเว็บจาก /srv/www ไม่ได้
สมมุติเราต้องการเก็บไฟล์เว็บไซต์ไว้ที่
/srv/www/sysadmin
สร้าง directory และไฟล์ทดสอบ
sudo mkdir -p /srv/www/sysadmin
echo "Hello SELinux" | sudo tee /srv/www/sysadmin/index.html
กำหนด owner และ permission ตามปกติ
sudo chown -R apache:apache /srv/www/sysadmin
sudo chmod -R 755 /srv/www/sysadmin
ตรวจ context
ls -Zd /srv/www/sysadmin
ถ้าเห็น type เช่น var_t หรือ default_t Apache อาจยังเข้าไม่ได้ แม้ permission จะถูกต้อง
วิธีแก้ที่ถูกต้องคือบอก SELinux ว่า directory นี้เป็น web content
sudo semanage fcontext -a -t httpd_sys_content_t "/srv/www/sysadmin(/.*)?"
จากนั้น apply context จริงด้วย restorecon
sudo restorecon -Rv /srv/www/sysadmin
ตรวจสอบอีกครั้ง
ls -Zd /srv/www/sysadmin
ควรเห็น type เป็น
httpd_sys_content_t
สรุปคือ
-
semanage fcontextใช้เพิ่มกฎ context แบบถาวร -
restoreconใช้ apply label ให้ไฟล์จริง -
อย่าใช้
chconเป็นทางเลือกหลักใน production เพราะมักไม่ถาวรเท่าsemanage fcontext
กรณีเว็บต้องเขียนไฟล์ เช่น uploads
ถ้า web application ต้องเขียนไฟล์ใน directory เช่น
/var/www/html/uploads
การใช้ httpd_sys_content_t อาจไม่พอ เพราะ type นี้เหมาะกับการอ่าน content เป็นหลัก
ให้ใช้ type ที่อนุญาตการเขียนสำหรับ httpd
sudo mkdir -p /var/www/html/uploads
sudo chown -R apache:apache /var/www/html/uploads
กำหนด SELinux context
sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/uploads(/.*)?"
Apply context
sudo restorecon -Rv /var/www/html/uploads
ตรวจสอบ
ls -Zd /var/www/html/uploads
ควรเห็น
httpd_sys_rw_content_t
⚠️ อย่ากำหนด writable context ให้ทั้ง /var/www/html ถ้าไม่จำเป็น ควรจำกัดเฉพาะ directory ที่ต้องเขียนจริง เช่น uploads, cache, storage
จัดการ SELinux Boolean
SELinux Boolean คือ switch เปิด/ปิดพฤติกรรมบางอย่างของ service โดยไม่ต้องเขียน policy ใหม่
ดู boolean ที่เกี่ยวกับ Apache
getsebool -a | grep httpd
ตัวอย่างที่พบบ่อยคือ ถ้า Apache ต้องเชื่อมต่อ network ออกไปหา backend, API หรือ database บางกรณี อาจต้องเปิด boolean นี้
sudo setsebool -P httpd_can_network_connect on
คำอธิบาย:
-
setseboolใช้เปลี่ยนค่า boolean -
-Pหมายถึง persistent หรือถาวรหลัง reboot -
onคือเปิดใช้งาน
ตรวจสอบค่า
getsebool httpd_can_network_connect
⚠️ เปิดเฉพาะ boolean ที่จำเป็นจริง อย่าเปิดทุกอย่างเพราะต้องการให้ service ทำงานง่ายขึ้น เพราะจะทำให้ขอบเขต security กว้างเกินไป
จัดการ Port ที่ SELinux อนุญาต
บางครั้ง service ทำงานถูกต้อง แต่ย้าย port แล้ว SELinux ไม่อนุญาต เช่น Apache ต้องการใช้ port 8080 หรือ 8888
ตรวจ port ที่ SELinux อนุญาตให้ httpd ใช้
sudo semanage port -l | grep http_port_t
ถ้าต้องการเพิ่ม port 8080 ให้ Apache ใช้
sudo semanage port -a -t http_port_t -p tcp 8080
ถ้า port นั้นมีอยู่แล้วและต้องการแก้ไข type ให้ใช้
sudo semanage port -m -t http_port_t -p tcp 8080
ตรวจสอบอีกครั้ง
sudo semanage port -l | grep http_port_t
จากนั้น restart service
sudo systemctl restart httpd
วิธี Troubleshoot เมื่อสงสัยว่า SELinux block
เมื่อ service ใช้งานไม่ได้ อย่าเพิ่งปิด SELinux ให้ไล่ตรวจตามลำดับนี้
ขั้นที่ 1 ตรวจ Linux permission ปกติก่อน
ls -l /path/to/file
ตรวจ path ทั้งเส้นทาง
namei -l /path/to/file
ถ้า permission ปกติผิด ให้แก้ chmod หรือ chown ก่อน เพราะ SELinux ไม่ได้มาแทนที่ Linux permission แต่ทำงานเป็นชั้นเสริม
ขั้นที่ 2 ตรวจ context
ls -Z /path/to/file
ls -Zd /path/to/directory
ดูว่า type ถูกต้องหรือไม่ เช่น web content ควรเป็น httpd_sys_content_t
ขั้นที่ 3 ดู log ของ SELinux
ค้นหา AVC denial ล่าสุด
sudo ausearch -m AVC,USER_AVC -ts recent
ถ้าต้องการดูเฉพาะ service เช่น httpd
sudo ausearch -m AVC,USER_AVC -c httpd -ts recent
ขั้นที่ 4 ใช้ sealert วิเคราะห์
sudo sealert -a /var/log/audit/audit.log
เครื่องมือนี้มักให้คำแนะนำว่า denial เกิดจากอะไร และควรแก้ด้วย context, boolean หรือ policy
ขั้นที่ 5 ใช้ audit2why เพื่ออ่านเหตุผล
sudo ausearch -m AVC,USER_AVC -ts recent | audit2why
คำสั่งนี้ช่วยแปล denial ให้อ่านง่ายขึ้น
แล้ว audit2allow ใช้ได้ไหม?
ใช้ได้ แต่ควรใช้เป็นทางเลือกท้าย ๆ ไม่ใช่คำสั่งแรก
หลายคนเห็น denial แล้วสั่งประมาณนี้ทันที
sudo ausearch -m AVC -ts recent | audit2allow -M mypolicy
sudo semodule -i mypolicy.pp
แม้วิธีนี้จะทำให้ service ผ่านได้ แต่มีความเสี่ยงคือเราอาจสร้าง policy ที่อนุญาตกว้างเกินไปโดยไม่เข้าใจปัญหาจริง
แนวทางที่ปลอดภัยกว่าคือ
-
ตรวจ Linux permission ก่อน
-
ตรวจ SELinux context
-
แก้ด้วย
semanage fcontextและrestorecon -
ตรวจ boolean ที่เกี่ยวข้อง
-
ตรวจ port type
-
ใช้ custom policy เฉพาะเมื่อจำเป็นจริง
ถ้าต้องใช้ audit2allow ควรอ่านไฟล์ .te ก่อนเสมอ
cat mypolicy.te
ติดตั้ง policy เฉพาะเมื่อเข้าใจว่าอนุญาตอะไร
sudo semodule -i mypolicy.pp
⚠️ ไม่ควร copy-paste policy จากอินเทอร์เน็ตเข้าระบบ production โดยไม่อ่านรายละเอียดก่อน
Checklist ใช้งาน SELinux แบบไม่ปวดหัว
ใช้ checklist นี้ทุกครั้งเมื่อเจอ Permission Denied
[ ] ตรวจ getenforce ว่าอยู่ใน Enforcing หรือไม่
[ ] ตรวจ permission ปกติด้วย ls -l
[ ] ตรวจ path permission ด้วย namei -l
[ ] ตรวจ context ด้วย ls -Z / ls -Zd
[ ] ดู audit log ด้วย ausearch
[ ] วิเคราะห์ด้วย sealert หรือ audit2why
[ ] แก้ label ด้วย semanage fcontext + restorecon
[ ] ตรวจ boolean ด้วย getsebool
[ ] ตรวจ port type ด้วย semanage port -l
[ ] ใช้ audit2allow เป็นทางเลือกสุดท้าย
คำสั่งสรุปที่ควรจำ
ตรวจสถานะ
getenforce
sestatus
เปลี่ยนโหมดชั่วคราว
sudo setenforce 0 # เปลี่ยนเป็น Permissive ชั่วคราว
sudo setenforce 1 # กลับเป็น Enforcing
ดู context
ls -Z /path/to/file
ls -Zd /path/to/directory
ps -eZ | grep service-name
แก้ context แบบถาวร
sudo semanage fcontext -a -t TYPE_T "/path(/.*)?"
sudo restorecon -Rv /path
ดู denial log
sudo ausearch -m AVC,USER_AVC -ts recent
วิเคราะห์ denial
sudo sealert -a /var/log/audit/audit.log
sudo ausearch -m AVC,USER_AVC -ts recent | audit2why
จัดการ boolean
getsebool -a | grep keyword
sudo setsebool -P boolean_name on
จัดการ port
sudo semanage port -l | grep service
sudo semanage port -a -t http_port_t -p tcp 8080
แนะนำ Screenshot สำหรับบทความ
ควรเพิ่มภาพประกอบในบทความตามจุดต่อไปนี้
-
ผลลัพธ์คำสั่ง
sestatus -
ตัวอย่าง
ls -Zก่อนแก้ context -
ตัวอย่าง
semanage fcontextและrestorecon -
ตัวอย่าง
ausearch -m AVC -ts recent -
Diagram สั้น ๆ แสดงความสัมพันธ์ระหว่าง Process Domain → File Type → SELinux Policy
สรุป
SELinux ไม่ใช่ศัตรูของ SysAdmin แต่เป็นระบบรักษาความปลอดภัยอีกชั้นที่ช่วยลดความเสียหายเมื่อ service ถูกโจมตีหรือทำงานผิดพลาด
หัวใจสำคัญคืออย่าแก้ปัญหาด้วยการปิด SELinux ทันที แต่ให้เปลี่ยนวิธีคิดใหม่ว่า เมื่อระบบ block บางอย่าง แปลว่าเราต้องตรวจว่า permission ปกติถูกไหม context ถูกไหม boolean เหมาะสมไหม และ port ได้รับอนุญาตหรือยัง
ถ้าจำ workflow ได้เพียงชุดเดียว ให้จำชุดนี้
ตรวจ permission → ตรวจ context → อ่าน audit log → แก้ label/boolean/port → ใช้ custom policy เมื่อจำเป็น
เมื่อเข้าใจหลักนี้ SELinux จะไม่ใช่เรื่องปวดหัวอีกต่อไป แต่จะกลายเป็นเครื่องมือสำคัญที่ช่วยให้ Linux Server ของเราปลอดภัยและเป็นมืออาชีพมากขึ้น
—
Write by Dr.Arnut Ruttanatirakul
SysAdmin Knowledge
https://www.sysadmin.in.th
June 11, 2026

