บทนี้คือ “ยามรักษาความปลอดภัย” ของเครื่อง RHEL — เราจะดูแล 3 เรื่อง: SELinux (ชั้นรักษาความปลอดภัยพิเศษ), firewall (กำแพงกันคนเข้าผิดประตู) และการ mount NFS (ดึงพื้นที่เก็บข้อมูลจากเครื่องอื่นมาใช้) — โดยเฉพาะ SELinux นั้นเป็นพระเอกของข้อสอบ RHCSA เลย
🌱 บทนี้เขียนเพื่อคนที่ไม่เคยแตะ Linux มาก่อนเลยพอเครื่อง Linux ออกไปอยู่บนเน็ตหรือในองค์กรจริง มันต้องป้องกันตัวเองจากคนที่ไม่หวังดี — RHEL เลยมี “ยาม” หลายชั้นซ้อนกัน บทนี้เราจะรู้จัก 3 ตัวหลัก:
นึกถึง ตึกออฟฟิศที่ปลอดภัยสูง:
• firewalld = รปภ.หน้าประตูตึก คอยเช็คว่าใครเข้าตึกได้ ทางประตูไหน
• SELinux = ระบบคีย์การ์ดในตึก ที่ถึงคุณจะเข้าตึกมาได้แล้ว ก็ยัง “เข้าได้แค่บางห้อง” ตามป้ายชื่อบนการ์ดของคุณเท่านั้น
• NFS = ห้องเก็บของที่อยู่ตึกอื่น แต่เดินทะลุทางเชื่อมเข้าไปใช้ได้เหมือนเป็นห้องในตึกเดียวกัน
ปกติ Linux คุมการเข้าถึงไฟล์ด้วย สิทธิ์ (permission) — เจ้าของ/กลุ่ม/คนอื่น อ่าน-เขียน-รัน ได้ไหม (เรื่องนี้เรียนไปแล้วในบทก่อนๆ) แต่ RHEL เพิ่มชั้นที่ เข้มกว่านั้นอีกชั้น เรียกว่า SELinux (Security-Enhanced Linux)
SELinux จะคุมว่า โปรเซสตัวไหน แตะไฟล์/port/อะไรได้บ้าง — และมันคุมโดย “ดูป้ายกำกับ (context)” ไม่ใช่ดูแค่สิทธิ์ไฟล์ธรรมดา พูดง่ายๆ คือ ต่อให้สิทธิ์ไฟล์อนุญาตแล้ว ถ้าป้าย context ไม่ตรงกัน SELinux ก็ยังบล็อกอยู่ดี
สิทธิ์ไฟล์ธรรมดา = กุญแจห้อง คุณมีกุญแจก็เปิดประตูได้
SELinux = รปภ.อีกคนที่ยืนอยู่หลังประตู ถึงคุณจะมีกุญแจเปิดเข้ามาได้ เขายังขอดู “ป้ายชื่อ/บัตรพนักงาน” ของคุณอีกที ถ้าป้ายไม่ตรงกับห้องนี้ เขาก็ไล่คุณออก — SELinux ดู ป้าย (context) ไม่ใช่กุญแจ
มือใหม่เจอ SELinux บล็อกแล้วชอบ “ปิดมันทิ้งซะเลย” — ในข้อสอบนี่คือคำตอบที่ผิดและจะถูกหักคะแนน โจทย์ต้องการให้คุณ ทำให้บริการทำงานได้ โดยที่ SELinux ยังเปิดอยู่ (Enforcing) วิธีที่ถูกคือ “แก้ context/boolean ให้ถูก” ไม่ใช่ปิด SELinux ทั้งระบบ
SELinux ทำงานได้ 3 โหมด คิดง่ายๆ ว่า “รปภ.จะเอาจริงแค่ไหน”:
| โหมด | พฤติกรรม |
|---|---|
Enforcing | บังคับจริง — บล็อกสิ่งที่ผิดกฎ และเก็บ log ด้วย (โหมดที่ข้อสอบต้องการ) |
Permissive | ปล่อยผ่านแต่จดบันทึก — ไม่บล็อกอะไร แต่ log ทุกครั้งที่ “ควรจะบล็อก” เหมาะกับช่วงหาสาเหตุปัญหา |
Disabled | ปิดสนิท — ไม่ทำงานเลย (อย่าใช้ในข้อสอบ) |
[root@server1 ~]# getenforce Enforcing [root@server1 ~]# sestatus SELinux status: enabled Current mode: enforcing Mode from config file: enforcing
getenforceบอกโหมดปัจจุบันแบบสั้นๆ (Enforcing / Permissive / Disabled)sestatusบอกละเอียดกว่า รวมถึง “โหมดในไฟล์ config” ด้วย — เทียบกับโหมดที่รันอยู่จริง[root@server1 ~]# setenforce 0 # สลับเป็น Permissive [root@server1 ~]# setenforce 1 # สลับกลับเป็น Enforcing
setenforce 00 = ผ่อนคลาย (Permissive) — มักใช้ตอนหาสาเหตุ ว่าปัญหาเกิดจาก SELinux จริงไหมsetenforce 11 = เข้มงวด (Enforcing) — กลับมาบังคับจริง—วิธีนี้ ไม่ถาวร — รีบูตเครื่องแล้วกลับไปใช้ค่าในไฟล์ configถ้าบริการไม่ทำงาน ลองสั่ง setenforce 0 ดู — ถ้าจู่ๆ บริการกลับทำงานได้ แปลว่า ปัญหามาจาก SELinux แน่นอน จากนั้นค่อยสั่ง setenforce 1 กลับ แล้วไปแก้ context/boolean ให้ถูกต้อง (ไม่ใช่ปล่อยให้ Permissive ค้างไว้)
# This file controls the state of SELinux on the system. SELINUX=enforcing # enforcing - SELinux security policy is enforced. # permissive - SELinux prints warnings instead of enforcing. # disabled - No SELinux policy is loaded. SELINUXTYPE=targeted
แก้บรรทัด SELINUX= ให้เป็นค่าที่ต้องการ (enforcing / permissive / disabled) — ค่านี้คือค่าที่เครื่องจะใช้ ทุกครั้งที่บูต
คำสั่ง setenforce เปลี่ยนแค่ชั่วคราว หายหลัง reboot — ถ้าต้องการให้โหมดอยู่ถาวร ต้องแก้ในไฟล์ /etc/selinux/config เสมอ และ การเปลี่ยนระหว่าง enabled กับ disabled ต้อง reboot เครื่องถึงจะมีผลเต็มที่
หัวใจของ SELinux คือ context (ป้ายกำกับ) — ทุกไฟล์และทุกโปรเซสจะมีป้ายติดอยู่ SELinux ตัดสินว่า “แตะได้ไหม” โดยดูว่าป้ายตรงกันหรือเปล่า
context หน้าตาเป็น 4 ส่วนคั่นด้วย : แบบนี้:
system_u : object_r : httpd_sys_content_t : s0 user role TYPE ← ส่วนที่สำคัญที่สุด level
มือใหม่จำแค่ส่วนเดียวพอ คือ type (ตัวที่ลงท้ายด้วย _t) — 90% ของงาน SELinux ในข้อสอบเกี่ยวกับการทำให้ type ตรงกัน เช่น ไฟล์ของเว็บเซิร์ฟเวอร์ต้องเป็น type httpd_sys_content_t
[root@server1 ~]# ls -Z /var/www/html/ unconfined_u:object_r:httpd_sys_content_t:s0 index.html
เติม option -Z (ตัวใหญ่) เข้าไปในคำสั่ง ls จะเห็น context ของแต่ละไฟล์ — สังเกต type httpd_sys_content_t นี่คือป้ายที่เว็บเซิร์ฟเวอร์ (httpd) แตะได้
[root@server1 ~]# ps -eZ | grep httpd system_u:system_r:httpd_t:s0 1234 ? 00:00:00 httpd
โปรเซส httpd รันด้วย type httpd_t — SELinux อนุญาตให้โปรเซส type httpd_t อ่านไฟล์ type httpd_sys_content_t ได้ เพราะป้ายคู่กัน ถ้าไฟล์ป้ายผิด (เช่นเป็น default_t) โปรเซสจะโดนบล็อกทันที
หลายคำสั่งใช้ -Z ตัวใหญ่เพื่อดูข้อมูล SELinux: ls -Z (ไฟล์), ps -Z (โปรเซส), id -Z (ตัวเราเอง) — จำง่ายๆ ว่า “Z = SELinux”
สมมติคุณย้ายไฟล์เว็บไปไว้ที่โฟลเดอร์ใหม่ (เช่น /web) แล้วเว็บเปิดไม่ขึ้น — สาเหตุมักเป็นเพราะไฟล์ในโฟลเดอร์ใหม่นั้น context type ผิด SELinux เลยไม่ให้ httpd อ่าน เราต้องแก้ type ให้ถูก มี 2 วิธี และ วิธีที่ออกสอบคือวิธีที่ถาวร
[root@server1 ~]# chcon -t httpd_sys_content_t -R /web
-tระบุ type ที่ต้องการ (เช่น httpd_sys_content_t)-Rทำซ้ำลงทุกไฟล์/โฟลเดอร์ย่อย (recursive)chcon เปลี่ยน context ได้ก็จริง แต่มัน ไม่ถาวร — พอมีการ “relabel” ระบบ (เช่นสั่ง restorecon หรือบูตด้วย autorelabel) ค่ามันจะ เด้งกลับเป็นค่าเดิม เพราะ chcon ไม่ได้บันทึกกฎไว้ในนโยบายของระบบ ในข้อสอบอย่าใช้ chcon เป็นคำตอบสุดท้าย
วิธีถาวรมี 2 ขั้นตอน — ขั้นแรกบันทึก “กฎ” ว่า path นี้ควรเป็น type อะไร แล้วขั้นที่สอง “ลงสีจริง” ตามกฎ
[root@server1 ~]# semanage fcontext -a -t httpd_sys_content_t "/web(/.*)?" [root@server1 ~]# restorecon -Rv /web Relabeled /web/index.html from unconfined_u:object_r:default_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
semanage fcontext -aเพิ่ม (add) กฎใหม่ลงนโยบายถาวร-t ...type ที่ต้องการ"/web(/.*)?"รูปแบบ path: /web และทุกอย่างที่อยู่ข้างใน — ต้องใส่ในเครื่องหมายคำพูดrestorecon -Rv“ลงสีจริง” ตามกฎที่บันทึกไว้ (-R ทั้งโฟลเดอร์, -v โชว์ว่าเปลี่ยนอะไรบ้าง)เวลาเจอโจทย์ “ทำให้ไฟล์ที่ path นี้มี context ถูกต้องอย่างถาวร” ให้ตอบ:
1️⃣ semanage fcontext -a -t TYPE "/path(/.*)?" (บันทึกกฎ)
2️⃣ restorecon -Rv /path (ลงสีจริง)
ขาด restorecon ไป context จะยังไม่เปลี่ยน เพราะ semanage แค่ “บันทึกกฎ” เฉยๆ
เปิดดู context ของโฟลเดอร์มาตรฐานที่ใช้งานได้อยู่แล้วเป็นต้นแบบ เช่น ls -Z /var/www/html เพื่อดูว่าเว็บใช้ type อะไร แล้วใช้ type เดียวกันกับโฟลเดอร์ใหม่ของเรา
บางทีไฟล์ context ก็ถูกหมดแล้ว แต่บริการยังถูกบล็อก เพราะ SELinux มี “สวิตช์” เปิด/ปิดความสามารถบางอย่างไว้ตั้งแต่ต้น เราเรียกสวิตช์พวกนี้ว่า boolean (มีแค่ on/off)
boolean เหมือน สวิตช์ไฟบนกำแพง — เช่นสวิตช์ “ยอมให้เว็บเซิร์ฟเวอร์เข้าถึงโฟลเดอร์ home ของ user ได้ไหม” ถ้าปิดอยู่ ต่อให้ทุกอย่างถูกหมด มันก็ไม่ยอม จนกว่าคุณจะ “สับสวิตช์” ให้เป็น on
[root@server1 ~]# getsebool -a | grep httpd httpd_enable_homedirs --> off httpd_can_network_connect --> off [root@server1 ~]# setsebool -P httpd_enable_homedirs on [root@server1 ~]# getsebool httpd_enable_homedirs httpd_enable_homedirs --> on
getsebool -aแสดงรายชื่อ boolean ทั้งหมด (มักต่อ | grep ... เพื่อกรองหาตัวที่สนใจ)setsebool -Pเปลี่ยนค่า boolean แบบถาวร (เป็น on หรือ off)ถ้าสั่ง setsebool httpd_enable_homedirs on เฉยๆ ไม่มี -P ค่าจะ หายหลัง reboot! ในข้อสอบโจทย์มักต้องการให้อยู่ถาวร เพราะหลังตรวจเขาจะ reboot เครื่อง — ดังนั้น ติดนิสัยใส่ -P ทุกครั้ง
SELinux ไม่ได้คุมแค่ไฟล์ — มันคุม port ด้วย! เช่นปกติเว็บเซิร์ฟเวอร์รันที่ port 80/443 แต่ถ้าคุณอยากให้ httpd ฟังที่ port 8080 (ไม่มาตรฐาน) SELinux จะบล็อก จนกว่าคุณจะบอกมันว่า “port 8080 ก็เป็น port ของเว็บนะ”
[root@server1 ~]# semanage port -a -t http_port_t -p tcp 8080 [root@server1 ~]# semanage port -l | grep http_port_t http_port_t tcp 8080, 80, 81, 443, 488, 8008, 8009, 8443, 9000
-a -t http_port_tเพิ่ม (add) ให้ port เป็น type ของเว็บ-p tcp 8080โปรโตคอล tcp, หมายเลข port 8080-llist — ดูว่ามี port อะไรอยู่ใน type นี้บ้างเวลามีอะไรไม่ทำงานแล้วสงสัยว่า SELinux เป็นต้นเหตุ — ทุกครั้งที่ SELinux บล็อกอะไร มันจะ จดบันทึก ลงในไฟล์ log ชื่อ AVC (Access Vector Cache) ที่ /var/log/audit/audit.log
[root@server1 ~]# ausearch -m AVC -ts recent type=AVC msg=audit(...): avc: denied { read } for pid=1234 comm="httpd" path="/web/index.html" scontext=...:httpd_t ... [root@server1 ~]# sealert -a /var/log/audit/audit.log SELinux is preventing httpd from read access on the file... ***** Plugin catchall (...) suggests ************
ausearch -m AVCค้นหาเหตุการณ์ที่ SELinux บล็อก (มองหาคำว่า denied)-ts recentเฉพาะช่วงเวลาล่าสุด (time-start recent)sealert -aวิเคราะห์ log แล้ว แนะนำวิธีแก้ ให้เลย (มักบอกคำสั่ง semanage/setsebool ที่ต้องใช้)1) บริการพัง → 2) setenforce 0 ลองดู ถ้าหายแสดงว่าเป็น SELinux → 3) setenforce 1 กลับ → 4) ดู log ด้วย ausearch/sealert → 5) แก้ context หรือ boolean ตามที่ sealert แนะนำ → 6) ทดสอบอีกครั้งโดย SELinux ยังเป็น Enforcing
เรื่องที่สองของบทนี้คือ firewall — ตัวคุมว่าการเชื่อมต่อจากข้างนอกเข้ามาทาง port ไหนได้บ้าง บน RHEL ใช้ตัวจัดการชื่อ firewalld และสั่งงานผ่านคำสั่ง firewall-cmd
public (เน็ตทั่วไป ไม่ค่อยเชื่อใจ) เป็นค่ามาตรฐานที่ใช้บ่อยสุดhttp = port 80, ssh = port 22 — เปิดด้วยชื่อง่ายกว่าจำเลข portfirewall เหมือน กำแพงรอบตึกที่มีหลายประตู ปกติปิดหมด คุณต้อง “เปิดเฉพาะประตูที่จำเป็น” — เปิดประตู “http” ก็เหมือนบอก รปภ.ว่า “อนุญาตให้คนที่มาทางเว็บเข้าได้นะ”
[root@server1 ~]# firewall-cmd --state running [root@server1 ~]# firewall-cmd --list-all public (active) services: ssh dhcpv6-client ports:
--stateเช็คว่า firewalld กำลังทำงานอยู่ไหม--list-allดูกฎทั้งหมดของ zone ปัจจุบัน — มี service/port อะไรเปิดอยู่บ้าง[root@server1 ~]# firewall-cmd --add-service=http --permanent success [root@server1 ~]# firewall-cmd --add-port=8080/tcp --permanent success [root@server1 ~]# firewall-cmd --reload success
--add-service=httpเปิดบริการ http (port 80 อัตโนมัติ)--add-port=8080/tcpเปิด port เฉพาะเจาะจง (เลข/โปรโตคอล) — ใช้กับ port ที่ไม่ใช่บริการมาตรฐาน--permanentเขียนกฎลง “ไฟล์ถาวร” ให้อยู่หลัง reboot--reloadโหลดกฎถาวรเข้ามาใช้ “ตอนนี้เลย” (ไม่งั้นกฎ permanent ยังไม่มีผลจนกว่าจะ reboot)นี่คือกับดักคลาสสิก:
• ถ้าใส่ เฉพาะ --permanent → กฎจะถูกบันทึก แต่ ยังไม่มีผลตอนนี้ ต้อง --reload ก่อน
• ถ้า ไม่ใส่ --permanent → กฎมีผลตอนนี้ก็จริง แต่ หายหลัง reboot
✅ ทางที่ปลอดภัยสุดในห้องสอบ: ใส่ --permanent ทุกบรรทัด แล้วปิดท้ายด้วย firewall-cmd --reload หนึ่งครั้ง
อย่าลืมว่าเป็น “ยาม 2 ชั้น” — ถ้าคุณเปลี่ยนให้เว็บฟังที่ port 8080 ต้อง เปิด port ที่ firewall (ชั้นนอก) และ เพิ่ม port context ที่ SELinux (ชั้นใน) ทั้งสองอย่าง บริการถึงจะเข้าถึงได้จริง
เรื่องสุดท้ายคือการ ยืมพื้นที่จากเครื่องอื่น — NFS (Network File System) คือการเอาโฟลเดอร์ที่ “แชร์” มาจากเซิร์ฟเวอร์อื่น มาเชื่อม (mount) เข้ามาใช้ในเครื่องเรา เหมือนเป็นโฟลเดอร์ปกติ
[root@server1 ~]# mount -t nfs server2:/export /mnt [root@server1 ~]# df -h /mnt Filesystem Size Used Avail Use% Mounted on server2:/export 10G 1G 9G 10% /mnt
-t nfsบอกว่าชนิดเป็น nfsserver2:/exportที่อยู่ฝั่งเซิร์ฟเวอร์: ชื่อเครื่อง:โฟลเดอร์ที่แชร์/mntโฟลเดอร์ในเครื่องเราที่จะเอามาเชื่อมไว้ (mount point)เหมือนเรื่อง persist ทั้งหลายในบทนี้ — ถ้าต้องการให้ mount ค้างอยู่หลังบูต ต้องไปเขียนไว้ในไฟล์ /etc/fstab (เคยเรียนในบท storage) โดยเพิ่มบรรทัดประมาณ server2:/export /mnt nfs defaults 0 0
AutoFS คือผู้ช่วยที่ mount ให้อัตโนมัติเฉพาะตอนที่มีคนเข้าใช้ โฟลเดอร์นั้น และถอดออกเองเมื่อไม่ได้ใช้ — เหมาะกับ home directory ของ user ที่เก็บไว้บนเซิร์ฟเวอร์กลาง
# 1) ไฟล์ master: /etc/auto.master.d/data.autofs /mnt/data /etc/auto.data # 2) ไฟล์ map: /etc/auto.data shared -rw server2:/export/shared [root@server1 ~]# systemctl enable --now autofs
*.autofsไฟล์ใน /etc/auto.master.d/ บอกว่า “โฟลเดอร์แม่ตรงไหน” คู่กับ “ไฟล์ map ตัวไหน”auto.dataไฟล์ map บอกรายละเอียด: ชื่อโฟลเดอร์ย่อย, ตัวเลือก (-rw), และที่อยู่ NFSenable --now autofsเปิดบริการ autofs ให้ทำงานตอนนี้ และ ทุกครั้งที่บูตเอาโฟลเดอร์แม่จากไฟล์ master (/mnt/data) มาต่อกับชื่อย่อยในไฟล์ map (shared) → พอมีคน cd /mnt/data/shared AutoFS ถึงจะ mount ให้อัตโนมัติทันที
chcon ไม่ถาวร เด้งกลับเมื่อ restorecon/relabel — ให้ใช้ semanage fcontext + restorecon แทนsemanage fcontext อย่างเดียวไม่พอ มันแค่ “บันทึกกฎ” ต้อง restorecon -Rv ตามเพื่อ “ลงสีจริง”-P ค่า boolean จะหายหลัง reboot — ติดนิสัยใส่ -P ทุกครั้ง--permanent = หายหลัง reboot; ไม่มี --reload = กฎถาวรยังไม่มีผลตอนนี้ — ต้องมีทั้งคู่| คำสั่ง | ทำอะไร |
|---|---|
getenforce | ดูโหมดปัจจุบัน (Enforcing/Permissive/Disabled) |
sestatus | ดูสถานะ SELinux แบบละเอียด |
setenforce 0 / 1 | สลับโหมดชั่วคราว (0=Permissive, 1=Enforcing) — หายหลัง reboot |
/etc/selinux/config | ตั้งโหมด ถาวร (แก้บรรทัด SELINUX=) |
ls -Z / ps -Z | ดู context ของไฟล์ / โปรเซส |
chcon -t TYPE -R path | เปลี่ยน context ชั่วคราว (หายเมื่อ relabel — อย่าใช้สอบ) |
semanage fcontext -a -t TYPE "path(/.*)?" | บันทึกกฎ context ถาวร |
restorecon -Rv path | ลงสี context จริงตามกฎที่บันทึกไว้ |
getsebool -a | ดูรายชื่อ boolean ทั้งหมด |
setsebool -P NAME on/off | เปลี่ยน boolean ถาวร (อย่าลืม -P) |
semanage port -a -t TYPE -p tcp PORT | เพิ่ม port ให้ SELinux รู้จัก |
ausearch -m AVC -ts recent | ค้นหาเหตุการณ์ที่ SELinux บล็อก |
sealert -a /var/log/audit/audit.log | วิเคราะห์ log และแนะนำวิธีแก้ |
| คำสั่ง | ทำอะไร |
|---|---|
firewall-cmd --state | เช็คว่า firewalld ทำงานอยู่ไหม |
firewall-cmd --list-all | ดูกฎทั้งหมดของ zone ปัจจุบัน |
firewall-cmd --add-service=http --permanent | เปิดบริการ (ถาวร) |
firewall-cmd --add-port=8080/tcp --permanent | เปิด port เฉพาะเจาะจง (ถาวร) |
firewall-cmd --reload | โหลดกฎถาวรเข้ามาใช้ทันที |
| คำสั่ง / ไฟล์ | ทำอะไร |
|---|---|
mount -t nfs server:/export /mnt | mount NFS ด้วยมือ (ชั่วคราว) |
/etc/fstab | เขียนไว้ให้ mount ถาวรหลัง reboot |
/etc/auto.master.d/*.autofs | ไฟล์ master ของ AutoFS (ชี้โฟลเดอร์แม่ + ไฟล์ map) |
ไฟล์ map (เช่น /etc/auto.data) | รายละเอียดโฟลเดอร์ย่อย + ที่อยู่ NFS |
systemctl enable --now autofs | เปิดบริการ autofs ตอนนี้และทุกครั้งที่บูต |
ตั้งโหมด SELinux ได้ทั้งชั่วคราวและถาวร → ดูและ แก้ context ให้ถาวร ด้วย semanage fcontext + restorecon → เปิด/ปิด boolean ด้วย setsebool -P → หาสาเหตุเมื่อ SELinux บล็อก → เปิด service/port ที่ firewall ให้ถาวร → และ mount NFS ทั้งด้วยมือและผ่าน AutoFS ได้ — โดย ไม่ต้อง disable SELinux เลย!