บทนำ: ทำไมการ Hardening เคอร์เนลจึงสำคัญที่สุดในสายความปลอดภัย Linux
ถ้าเปรียบระบบ Linux ของคุณเป็นอาคาร ไฟร์วอลล์ก็คือรั้วรอบนอก, IDS คือกล้องวงจรปิด แต่ เคอร์เนล (Kernel) คือรากฐานของตัวอาคารเลย ไม่ว่าจะมีกำแพงสูงหรือระบบเตือนภัยดีแค่ไหน ถ้ารากฐานเปราะก็จบเหมือนกัน
พูดง่ายๆ ก็คือ เคอร์เนลเป็นซอฟต์แวร์ที่นั่งอยู่ระหว่างฮาร์ดแวร์กับแอปพลิเคชัน ทำหน้าที่จัดการทุกอย่างในระบบ ไม่ว่าจะเป็นหน่วยความจำ, CPU, ระบบไฟล์ หรือเครือข่าย ถ้าผู้โจมตี exploit ช่องโหว่ระดับเคอร์เนลได้ ก็เท่ากับยึดระบบทั้งหมดได้ทันที ไม่ต้องง้อ root password เลยด้วยซ้ำ
ในปี 2026 เคอร์เนล Linux เวอร์ชัน 6.12 LTS และ 6.13 ได้เพิ่มฟีเจอร์ความปลอดภัยใหม่หลายอย่าง เช่น syscall ตระกูล xattrat() สำหรับจัดการ extended attributes ได้ปลอดภัยขึ้น, sysctl fs.dentry-negative ใหม่ และกำลังจะมี Attack Vector Controls (AVC) ใน kernel 6.17 พร้อมด้วย sysctl kernel.stack_erasing ตัวใหม่
แต่สิ่งที่หลายคนมองข้ามก็คือ เคอร์เนลที่ออกมาจากโรงงาน (default config) นั้น ไม่ได้ถูกตั้งค่ามาเพื่อความปลอดภัยสูงสุด เลย มันเน้นเรื่อง compatibility กับ performance เป็นหลัก ดังนั้นหน้าที่ของ sysadmin อย่างเราก็คือปรับแต่งพารามิเตอร์เหล่านี้ให้เหมาะกับ production environment ที่เราดูแลอยู่
บทความนี้จะพาคุณผ่านทุกแง่มุมของ Linux Kernel Hardening ด้วย sysctl ตั้งแต่พื้นฐานไปจนถึงระดับ advanced รวมถึง Seccomp, eBPF hardening, Kernel Lockdown และการตรวจสอบอัตโนมัติด้วย kernel-hardening-checker — ทั้งหมดนี้พร้อมตัวอย่างคอนฟิกที่ใช้ได้จริงใน production ครับ
ทำความเข้าใจ sysctl: แผงควบคุมเคอร์เนล Linux
sysctl คืออะไร
sysctl คือ interface ที่ช่วยให้เราดูและแก้ไขพารามิเตอร์ของเคอร์เนลขณะที่ระบบกำลังทำงานอยู่ (runtime) โดยไม่ต้อง recompile หรือ reboot เลย ลองนึกภาพว่ามันเป็น "แผงควบคุม" ของเคอร์เนลที่เปิดให้เราเข้าถึงการตั้งค่าต่างๆ ตั้งแต่พฤติกรรมของเครือข่ายไปจนถึงการจัดการหน่วยความจำ
พารามิเตอร์เหล่านี้ถูกเก็บไว้ใน /proc/sys/ filesystem และแก้ไขได้สองวิธีหลักๆ:
- ชั่วคราว (Runtime) — ใช้คำสั่ง
sysctl -w parameter=valueจะหายไปเมื่อ reboot - ถาวร (Persistent) — เขียนลงในไฟล์ config ใน
/etc/sysctl.d/เพื่อให้ load ทุกครั้งที่บูต
โครงสร้างไฟล์คอนฟิก
ผมแนะนำให้ใช้ drop-in directory (/etc/sysctl.d/) แทนการแก้ไฟล์ /etc/sysctl.conf โดยตรง เพราะแยกหมวดหมู่ได้ง่ายกว่า จัดการ version control ได้สะดวก และไม่ต้องกังวลว่าไฟล์จะถูกเขียนทับตอน update ระบบ:
# โครงสร้างที่แนะนำ
/etc/sysctl.d/
├── 10-network-hardening.conf # พารามิเตอร์เครือข่าย
├── 20-kernel-protection.conf # การป้องกันเคอร์เนล
├── 30-filesystem-security.conf # ความปลอดภัยระบบไฟล์
└── 40-memory-hardening.conf # การ hardening หน่วยความจำ
ไฟล์จะถูก load ตามลำดับ lexicographic (ตัวเลข-ตัวอักษร) ดังนั้นไฟล์ที่มีเลขมากกว่าจะ override ค่าจากไฟล์ก่อนหน้า ถ้ามีค่าไหนที่ต้องการให้มี priority สูงสุด ก็ใช้ prefix 99- ได้เลย
Hardening เครือข่ายด้วย sysctl: ปิดช่องทางโจมตีตั้งแต่ระดับ TCP/IP Stack
มาเริ่มกันที่ส่วนที่สำคัญที่สุดก่อนเลยนะครับ — network hardening เพราะเครือข่ายเป็นประตูหน้าที่ผู้โจมตีมักจะลองเข้ามาก่อนเสมอ
ป้องกัน IP Spoofing ด้วย Reverse Path Filtering
Reverse Path Filtering (RPF) ตรวจสอบว่า packet ที่เข้ามานั้นมาจาก route ที่ถูกต้องหรือเปล่า ถ้า source IP ของ packet ไม่ตรงกับ routing table ที่ควรจะเป็น ก็ถูก drop ทันที:
# /etc/sysctl.d/10-network-hardening.conf
# === Reverse Path Filtering (ป้องกัน IP Spoofing) ===
# 1 = strict mode (แนะนำสำหรับ single-homed server)
# 2 = loose mode (สำหรับ multi-homed server หรือ asymmetric routing)
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
ป้องกัน SYN Flood Attack
SYN flood เป็นหนึ่งใน DDoS attack ที่เจอบ่อยมาก ผู้โจมตีจะยิง SYN packet จำนวนมหาศาลเพื่อเปิด half-open connections จนทรัพยากรของเซิร์ฟเวอร์หมด TCP SYN cookies ช่วยให้เซิร์ฟเวอร์ไม่ต้องเก็บ state ของ half-open connections ไว้ ซึ่งช่วยได้เยอะมากตอนโดน flood:
# === SYN Flood Protection ===
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 5
ปิด ICMP Redirect และ Source Routing
ICMP redirect สามารถถูกใช้ในการโจมตีแบบ Man-in-the-Middle (MitM) เพื่อเปลี่ยนเส้นทาง routing ของ packet ได้ ส่วน source routing อนุญาตให้ผู้ส่ง packet กำหนดเส้นทางเอง ซึ่งเปิดช่องให้ bypass firewall rules ได้สบาย:
# === ปิด ICMP Redirect (ป้องกัน MitM Routing Attack) ===
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
# === ปิด Source Routing (ป้องกัน Firewall Bypass) ===
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0
Logging และ Broadcast Protection
# === Log Martian Packets (packet ที่มี source IP ผิดปกติ) ===
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1
# === ป้องกัน Smurf Attack (ICMP broadcast) ===
net.ipv4.icmp_echo_ignore_broadcasts = 1
# === ป้องกัน Bogus ICMP Responses ===
net.ipv4.icmp_ignore_bogus_error_responses = 1
# === ปิด TCP Timestamps (ป้องกันการรั่วไหลของ system time) ===
net.ipv4.tcp_timestamps = 0
ปิด IPv6 Router Advertisement (ถ้าไม่ใช้)
ถ้าเซิร์ฟเวอร์ของคุณไม่ได้ใช้ IPv6 หรือกำหนด IPv6 address แบบ static อยู่แล้ว การปิด Router Advertisement จะช่วยป้องกันการโจมตีแบบ IPv6 RA flood ได้:
# === ปิด IPv6 Router Advertisement ===
net.ipv6.conf.all.accept_ra = 0
net.ipv6.conf.default.accept_ra = 0
# ถ้าไม่ใช้ IPv6 เลย สามารถปิดได้ทั้งหมด
# net.ipv6.conf.all.disable_ipv6 = 1
# net.ipv6.conf.default.disable_ipv6 = 1
Kernel Self-Protection: ปกป้องเคอร์เนลจากการถูกสำรวจและโจมตี
ซ่อนข้อมูลสำคัญของเคอร์เนล
ข้อมูลของเคอร์เนลอย่าง kernel pointer addresses, ข้อความ dmesg และ profiling data ล้วนเป็น "ขุมทรัพย์" สำหรับผู้โจมตี เพราะมันช่วยให้วางแผนการโจมตีได้แม่นยำขึ้น จากประสบการณ์ที่ผมเคยทำ pentest มา การเข้าถึง kernel pointer address เป็นสิ่งแรกๆ ที่มองหาเสมอ เพราะฉะนั้นเราต้องปิดช่องทางเหล่านี้:
# /etc/sysctl.d/20-kernel-protection.conf
# === ซ่อน Kernel Pointer Addresses ===
# 0 = ไม่จำกัด, 1 = ซ่อนจาก unprivileged users, 2 = ซ่อนจากทุกคน (แม้แต่ root)
kernel.kptr_restrict = 2
# === จำกัดการเข้าถึง dmesg ===
# ป้องกันผู้โจมตีจากการอ่าน kernel log ซึ่งอาจเปิดเผยข้อมูลเกี่ยวกับฮาร์ดแวร์และ driver
kernel.dmesg_restrict = 1
# === ปิด Kernel Profiling สำหรับ Unprivileged Users ===
kernel.perf_event_paranoid = 3
# === จำกัดการใช้ ptrace ===
# 0 = ทุกคนใช้ได้, 1 = parent process เท่านั้น
# 2 = เฉพาะ admin (CAP_SYS_PTRACE), 3 = ปิดทั้งหมด
kernel.yama.ptrace_scope = 2
ASLR (Address Space Layout Randomization)
ASLR สุ่มตำแหน่งของโปรแกรมในหน่วยความจำ ทำให้ผู้โจมตีไม่สามารถคาดเดาตำแหน่งของ function หรือ data ที่ต้องการ exploit ได้ ตัวนี้ควรเปิดเป็น 2 เสมอ ไม่มีเหตุผลอะไรที่ต้องปิดบน production server เลย:
# === เปิด ASLR เต็มรูปแบบ ===
# 0 = ปิด, 1 = สุ่มเฉพาะ shared libraries, 2 = สุ่มทั้ง stack, heap, mmap
kernel.randomize_va_space = 2
ปิดการ Load Kernel Module โดยไม่จำเป็น
ถ้าเซิร์ฟเวอร์ของคุณไม่ต้องการ load kernel module ใหม่หลังจากบูตเสร็จ (เช่น เครื่องที่มี hardware คงที่) การปิด module loading จะป้องกันไม่ให้ผู้โจมตี load malicious kernel module ได้:
# === ปิดการ Load Kernel Module (ใช้ด้วยความระมัดระวัง!) ===
# เปิดใช้เฉพาะหลังจากที่มั่นใจว่า module ทั้งหมดถูก load แล้ว
kernel.modules_disabled = 1
คำเตือนสำคัญ: เมื่อตั้งค่านี้เป็น 1 แล้ว จะ ไม่สามารถเปลี่ยนกลับเป็น 0 ได้โดยไม่ reboot นอกจากนี้ยังทำให้ plug USB device ใหม่หรือเพิ่ม hardware ไม่ได้ด้วย ใช้เฉพาะบนเซิร์ฟเวอร์ที่มี hardware คงที่จริงๆ เท่านั้นนะครับ
ป้องกัน Core Dump
# === ปิด Core Dump สำหรับ SUID Programs ===
# ป้องกันไม่ให้โปรแกรม SUID สร้าง core dump ที่อาจมีข้อมูลสำคัญ
fs.suid_dumpable = 0
Filesystem Protections: ปิดช่องโหว่ระดับระบบไฟล์
ป้องกัน TOCTOU Attacks
TOCTOU (Time-of-Check-to-Time-of-Use) เป็นช่องโหว่ประเภท race condition ที่ผู้โจมตีเปลี่ยน symlink หรือ hardlink ระหว่างที่โปรแกรมกำลังตรวจสอบกับตอนใช้งานจริง ฟังดูซับซ้อน แต่จริงๆ แล้วเป็นช่องโหว่ที่พบได้บ่อยพอสมควร โชคดีที่เคอร์เนลมีพารามิเตอร์ป้องกันเรื่องนี้โดยเฉพาะ:
# /etc/sysctl.d/30-filesystem-security.conf
# === ป้องกัน Symlink Attack (TOCTOU) ===
# Symlink จะ follow ได้เฉพาะเมื่อ owner ตรงกับ follower
# หรืออยู่นอก world-writable sticky directory
fs.protected_symlinks = 1
# === ป้องกัน Hardlink Attack ===
# ป้องกันไม่ให้สร้าง hardlink ไปยังไฟล์ที่ไม่มีสิทธิ์ read/write
fs.protected_hardlinks = 1
# === ป้องกัน FIFO Attack ===
# 0 = ไม่จำกัด, 1 = จำกัดใน sticky dir, 2 = จำกัดใน group-writable ด้วย
fs.protected_fifos = 2
# === ป้องกัน Regular File Attack ===
fs.protected_regular = 2
eBPF Hardening: ปิดช่องทาง Exploit ผ่าน BPF Subsystem
ทำไม eBPF ถึงเป็นพื้นผิวโจมตี
eBPF (extended Berkeley Packet Filter) เป็นเทคโนโลยีที่ทรงพลังมากใน Linux สมัยใหม่ ใช้สำหรับ networking, observability, security monitoring และอื่นๆ อีกมากมาย แต่ความทรงพลังนี้ก็เป็นดาบสองคมเหมือนกัน เพราะ eBPF สามารถ run โค้ดภายในเคอร์เนลได้โดยตรง ทำให้มันกลายเป็น attack surface ที่ใหญ่พอสมควร
การโจมตี eBPF ที่พบบ่อยก็มีอย่างเช่น heap spraying ผ่าน JIT compiler, side-channel attacks ที่ใช้ BPF maps และ privilege escalation ผ่าน BPF verifier bugs
# /etc/sysctl.d/20-kernel-protection.conf (เพิ่มเติม)
# === ปิด Unprivileged BPF ===
# ป้องกันไม่ให้ user ทั่วไปใช้ BPF syscall
# ต้องมี CAP_BPF (kernel >= 5.8) หรือ CAP_SYS_ADMIN
kernel.unprivileged_bpf_disabled = 1
# === Harden BPF JIT Compiler ===
# 1 = harden สำหรับ unprivileged users
# 2 = harden สำหรับทุกคน (แนะนำ)
# ใช้ constant blinding เพื่อป้องกัน JIT spray attacks
net.core.bpf_jit_harden = 2
หมายเหตุ: ถ้าคุณใช้เครื่องมือ observability อย่าง Cilium, Falco หรือ bpftrace ในระบบ ไม่ต้องกังวลนะครับ ค่า kernel.unprivileged_bpf_disabled = 1 จะไม่กระทบการทำงานของพวกมัน เพราะเครื่องมือเหล่านี้ run ด้วย root privilege อยู่แล้ว เฉพาะ unprivileged users เท่านั้นที่ถูกบล็อก
Seccomp: กรอง System Calls เพื่อลด Attack Surface
Seccomp คืออะไร
Seccomp (Secure Computing Mode) เป็นกลไกของเคอร์เนลที่จำกัดว่า process หนึ่งๆ จะเรียกใช้ system call อะไรได้บ้าง มี 2 โหมดหลัก:
- Strict Mode — อนุญาตเฉพาะ 4 syscalls คือ
read,write,_exitและsigreturn - Filter Mode (Seccomp-BPF) — ใช้ BPF program กำหนด policy ว่าจะอนุญาต, ปฏิเสธ หรือ log syscall ไหน ยืดหยุ่นกว่ามาก
ตัวอย่างการใช้ Seccomp-BPF กับ Container
Docker และ Kubernetes มี default Seccomp profile ในตัวอยู่แล้ว แต่เป็น allowlist ที่ค่อนข้างกว้าง สำหรับ production ผมแนะนำให้สร้าง custom profile ที่อนุญาตเฉพาะ syscalls ที่แอปต้องการจริงๆ จะปลอดภัยกว่าเยอะ:
# ตัวอย่าง Seccomp profile สำหรับ web server (JSON)
# บันทึกเป็น /etc/docker/seccomp/webserver.json
{
"defaultAction": "SCMP_ACT_ERRNO",
"defaultErrnoRet": 1,
"architectures": ["SCMP_ARCH_X86_64"],
"syscalls": [
{
"names": [
"accept4", "bind", "clone", "close", "connect",
"epoll_create1", "epoll_ctl", "epoll_wait",
"exit_group", "fcntl", "fstat", "futex",
"getpid", "getsockname", "getsockopt",
"listen", "mmap", "mprotect", "munmap",
"openat", "read", "recvfrom", "rt_sigaction",
"rt_sigprocmask", "sendto", "setsockopt",
"socket", "write", "writev"
],
"action": "SCMP_ACT_ALLOW"
}
]
}
# ใช้งานกับ Docker
docker run --security-opt seccomp=/etc/docker/seccomp/webserver.json nginx:latest
สิ่งสำคัญที่ต้องรู้: Seccomp-BPF ใช้ classic BPF (cBPF) ไม่ใช่ eBPF และ ไม่สามารถ dereference pointer ได้ หมายความว่ามันตรวจสอบ file descriptor number ได้ แต่ไม่สามารถอ่านชื่อไฟล์ที่ถูกส่งเป็น argument ได้นะครับ
Kernel Lockdown Mode: ป้องกันการดัดแปลงเคอร์เนลขณะ Runtime
Lockdown คืออะไร
ตั้งแต่ Linux Kernel 5.4 เป็นต้นมา มีฟีเจอร์ Kernel Lockdown ที่เสริมความแข็งแรงของขอบเขตระหว่าง root (UID 0) กับเคอร์เนล พูดอีกแบบคือ แม้แต่ root ก็ไม่สามารถแก้ไขเคอร์เนลที่กำลังทำงานอยู่ได้ มี 2 โหมด:
- Integrity — ป้องกันไม่ให้ userland แก้ไขเคอร์เนลที่กำลังทำงาน เช่น เขียนไปที่
/dev/mem, load unsigned module หรือใช้ kexec - Confidentiality — นอกจากป้องกันการแก้ไขแล้ว ยังป้องกันไม่ให้อ่านข้อมูลลับจากเคอร์เนลด้วย เช่น cryptographic keys หรือ KASLR layout
การเปิดใช้ Lockdown
# เพิ่มใน kernel command line (GRUB)
# แก้ไฟล์ /etc/default/grub
GRUB_CMDLINE_LINUX="lockdown=integrity"
# อัปเดต GRUB
sudo update-grub
# ตรวจสอบสถานะหลัง reboot
cat /sys/kernel/security/lockdown
# ผลลัพธ์: none [integrity] confidentiality
Boot Parameters เสริมความปลอดภัย
นอกจาก lockdown แล้ว ยังมี boot parameters อีกหลายตัวที่ช่วยเสริมความปลอดภัยได้ดีมาก:
# เพิ่มใน GRUB_CMDLINE_LINUX
GRUB_CMDLINE_LINUX="lockdown=integrity slab_nomerge pti=on init_on_alloc=1 init_on_free=1"
# slab_nomerge = ป้องกัน slab merging exploit
# pti=on = เปิด Page Table Isolation (ป้องกัน Meltdown)
# init_on_alloc=1 = เคลียร์หน่วยความจำเมื่อ allocate (ป้องกัน info leak)
# init_on_free=1 = เคลียร์หน่วยความจำเมื่อ free (ป้องกัน use-after-free)
รวมทุกอย่าง: ไฟล์คอนฟิกฉบับ Production-Ready
ทีนี้มาดูไฟล์คอนฟิกที่รวบรวมพารามิเตอร์สำคัญทั้งหมดเข้าด้วยกัน พร้อมใช้งานบน production server ได้เลยครับ (ผมใช้ไฟล์แบบนี้กับเซิร์ฟเวอร์ที่ดูแลอยู่จริงๆ):
# /etc/sysctl.d/99-production-hardening.conf
# Linux Kernel Hardening — Production Server Configuration
# ทดสอบบน Ubuntu 24.04 LTS / RHEL 9.x / Debian 12
# อัปเดต: มีนาคม 2026
# ==========================================
# NETWORK HARDENING
# ==========================================
# SYN Flood Protection
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_synack_retries = 2
# IP Spoofing Protection (Reverse Path Filtering)
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# ปิด ICMP Redirects
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
# ปิด Source Routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0
# Log Martian Packets
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1
# ป้องกัน Smurf Attack & Bogus ICMP
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
# ปิด TCP Timestamps
net.ipv4.tcp_timestamps = 0
# ปิด IPv6 Router Advertisements
net.ipv6.conf.all.accept_ra = 0
net.ipv6.conf.default.accept_ra = 0
# ปิด IP Forwarding (ถ้าไม่ใช่ router/gateway)
net.ipv4.ip_forward = 0
net.ipv6.conf.all.forwarding = 0
# ==========================================
# KERNEL SELF-PROTECTION
# ==========================================
# ซ่อน Kernel Pointers
kernel.kptr_restrict = 2
# จำกัด dmesg
kernel.dmesg_restrict = 1
# ASLR เต็มรูปแบบ
kernel.randomize_va_space = 2
# จำกัด perf_event
kernel.perf_event_paranoid = 3
# จำกัด ptrace (เฉพาะ admin)
kernel.yama.ptrace_scope = 2
# ปิด Unprivileged BPF
kernel.unprivileged_bpf_disabled = 1
# Harden BPF JIT
net.core.bpf_jit_harden = 2
# ปิด SysRq (หรือจำกัดเฉพาะ sync + reboot)
# 0 = ปิดทั้งหมด, 176 = อนุญาตเฉพาะ sync + reboot
kernel.sysrq = 0
# ==========================================
# FILESYSTEM PROTECTIONS
# ==========================================
# ป้องกัน TOCTOU Attacks
fs.protected_symlinks = 1
fs.protected_hardlinks = 1
fs.protected_fifos = 2
fs.protected_regular = 2
# ปิด Core Dump สำหรับ SUID
fs.suid_dumpable = 0
วิธีใช้ไฟล์คอนฟิก
# คัดลอกไฟล์ไปยังตำแหน่งที่ถูกต้อง
sudo cp 99-production-hardening.conf /etc/sysctl.d/
# Apply ค่าทั้งหมดจากไฟล์เฉพาะ
sudo sysctl -p /etc/sysctl.d/99-production-hardening.conf
# หรือ Apply ค่าจากทุกไฟล์ใน /etc/sysctl.d/
sudo sysctl --system
# ตรวจสอบค่าที่ตั้งไว้
sysctl kernel.kptr_restrict
sysctl net.ipv4.tcp_syncookies
sysctl kernel.unprivileged_bpf_disabled
# ดูค่าทั้งหมดที่เกี่ยวข้องกับ security
sudo sysctl -a | grep -E "kptr|dmesg|randomize|ptrace|bpf|syncookies|rp_filter"
ตรวจสอบอัตโนมัติด้วย kernel-hardening-checker
เครื่องมือนี้คืออะไร
kernel-hardening-checker เป็นเครื่องมือ Python โอเพนซอร์สที่ตรวจสอบการตั้งค่า security hardening ของเคอร์เนลแบบอัตโนมัติ มันครอบคลุมทั้ง Kconfig options (compile-time), kernel command line (boot-time) และ sysctl parameters (runtime) รองรับสถาปัตยกรรม X86_64, X86_32, ARM64, ARM และ RISC-V เลยครับ
พูดตรงๆ ว่า ถ้าคุณจะ hardening เคอร์เนลจริงจัง เครื่องมือนี้เป็นสิ่งที่ขาดไม่ได้
การติดตั้งและใช้งาน
# Clone repository
git clone https://github.com/a13xp0p0v/kernel-hardening-checker.git
cd kernel-hardening-checker
# ตรวจสอบเคอร์เนลที่กำลังรันอยู่แบบอัตโนมัติ (ต้องใช้ sudo)
sudo ./bin/kernel-hardening-checker -a
# ตรวจสอบเฉพาะ sysctl
sudo sysctl -a > /tmp/current-sysctl.txt
./bin/kernel-hardening-checker -s /tmp/current-sysctl.txt
# ตรวจสอบ kernel config + command line + sysctl พร้อมกัน
./bin/kernel-hardening-checker \
-c /boot/config-$(uname -r) \
-l /proc/cmdline \
-s /tmp/current-sysctl.txt
# Output เป็น JSON สำหรับ integration กับ CI/CD
sudo ./bin/kernel-hardening-checker -a -m json > hardening-report.json
# แสดงเฉพาะรายการที่ FAIL
sudo ./bin/kernel-hardening-checker -a -m show_fail
การอ่านผลลัพธ์
เครื่องมือจะแสดงผลเป็นตารางที่ระบุ option ที่ตรวจสอบ, ค่าที่แนะนำ (expected), ค่าปัจจุบัน (actual) และผลลัพธ์ (OK หรือ FAIL) ลองดูตัวอย่างนี้ครับ:
# ตัวอย่างผลลัพธ์ (บางส่วน)
[+] Detected version: (6, 12, 0)
[+] Detected architecture: X86_64
option name | type | expected | actual | result
-----------------------------------+------+----------+----------+-------
kernel.kptr_restrict |sysctl| 2 | 2 | OK
kernel.dmesg_restrict |sysctl| 1 | 1 | OK
kernel.unprivileged_bpf_disabled |sysctl| 1 | 0 | FAIL
net.core.bpf_jit_harden |sysctl| 2 | 0 | FAIL
kernel.yama.ptrace_scope |sysctl| 3 | 1 | FAIL
จากตัวอย่างด้านบน เราเห็นว่ามี 2 รายการที่ FAIL ในส่วน BPF hardening และ 1 รายการใน ptrace scope แก้ไม่ยากครับ แค่กลับไปปรับค่าในไฟล์ sysctl config แล้ว apply ใหม่ก็จบ
Automation ด้วย Ansible: Hardening เซิร์ฟเวอร์ทีละร้อยเครื่อง
ทำไมต้อง Automate
ในระดับ enterprise การ hardening เซิร์ฟเวอร์ทีละเครื่องด้วยมือนั้นไม่ practical เลย และเสี่ยงต่อความผิดพลาดมาก Ansible ช่วยให้คุณ apply hardening baseline เดียวกันไปยังเซิร์ฟเวอร์ทุกเครื่องได้อย่างสม่ำเสมอ แถมยังตรวจจับ configuration drift ได้โดยอัตโนมัติอีกด้วย
# playbook: kernel-hardening.yml
---
- name: Apply Linux Kernel Hardening
hosts: production_servers
become: yes
tasks:
- name: Deploy sysctl hardening configuration
ansible.builtin.copy:
src: files/99-production-hardening.conf
dest: /etc/sysctl.d/99-production-hardening.conf
owner: root
group: root
mode: "0644"
notify: reload sysctl
- name: Apply critical sysctl parameters
ansible.posix.sysctl:
name: "{{ item.key }}"
value: "{{ item.value }}"
sysctl_set: yes
state: present
reload: yes
loop:
- { key: "kernel.kptr_restrict", value: "2" }
- { key: "kernel.dmesg_restrict", value: "1" }
- { key: "kernel.randomize_va_space", value: "2" }
- { key: "kernel.unprivileged_bpf_disabled", value: "1" }
- { key: "net.core.bpf_jit_harden", value: "2" }
- { key: "net.ipv4.tcp_syncookies", value: "1" }
- { key: "net.ipv4.conf.all.rp_filter", value: "1" }
- { key: "net.ipv4.conf.all.accept_redirects", value: "0" }
- { key: "net.ipv4.conf.all.send_redirects", value: "0" }
- name: Run kernel-hardening-checker audit
ansible.builtin.shell: |
if [ -d /opt/kernel-hardening-checker ]; then
cd /opt/kernel-hardening-checker
sudo ./bin/kernel-hardening-checker -a -m json
fi
register: audit_result
changed_when: false
ignore_errors: yes
handlers:
- name: reload sysctl
ansible.builtin.command: sysctl --system
ใช้งานร่วมกับ dev-sec.io
ถ้าไม่อยากเขียน playbook เอง โปรเจกต์ dev-sec.io มี Ansible role สำเร็จรูปที่ชื่อ devsec.hardening.os_hardening ซึ่ง align กับ CIS Benchmarks และพร้อมใช้กับ production ได้ทันที:
# ติดตั้ง role
ansible-galaxy install devsec.hardening.os_hardening
# ใช้ใน playbook
- hosts: production_servers
roles:
- devsec.hardening.os_hardening
Compliance: sysctl Hardening กับมาตรฐานความปลอดภัย
การ hardening เคอร์เนลด้วย sysctl ไม่ใช่แค่ best practice แต่ยังเป็นข้อกำหนดของมาตรฐานความปลอดภัยหลายตัวเลย:
- CIS Benchmarks — Section 3 (Network Configuration) กำหนดค่า sysctl สำหรับ network hardening โดยเฉพาะ
- PCI DSS — Requirement 2.2 (Secure Configuration) ครอบคลุมการตั้งค่าพารามิเตอร์ความปลอดภัยของ OS
- NIST 800-53 — SC-7 (Boundary Protection) และ SI-16 (Memory Protection) ตรงกับ sysctl parameters หลายตัว
- ANSSI (หน่วยงานความปลอดภัยไซเบอร์ของฝรั่งเศส) — มี guide เฉพาะสำหรับ Linux kernel hardening
เครื่องมืออย่าง Lynis สามารถ scan ระบบของคุณและสร้างรายงานที่ map กับ compliance framework เหล่านี้ได้ ช่วยให้การ audit ทำได้ง่ายขึ้นมาก ถ้าองค์กรคุณต้อง comply กับมาตรฐานพวกนี้อยู่แล้ว sysctl hardening ก็ถือเป็นสิ่งที่ต้องทำอยู่ดี
ข้อควรระวังและ Troubleshooting
เมื่อ Hardening ทำให้แอปพลิเคชันพัง
ต้องยอมรับตรงๆ ว่าการ hardening บางอย่างอาจทำให้แอปพลิเคชันพังได้ เพราะค่า default ถูกตั้งมาเพื่อ compatibility ก่อน ผมเคยเจอกรณีที่ปิด ip_forward แล้ว Docker container connect ไม่ได้เลย แนวทางที่แนะนำคือ:
- ทดสอบใน staging ก่อนเสมอ — อย่า apply ค่าใหม่บน production โดยตรง ถ้าพังขึ้นมาจะเสียเวลาแก้กว่าจะกลับคืน
- เพิ่มทีละขั้น — เริ่มจากพารามิเตอร์ที่เสี่ยงน้อย (network hardening) แล้วค่อยๆ เพิ่มระดับ
- ใช้ runtime ก่อน — ทดสอบด้วย
sysctl -wก่อน ถ้าไม่มีปัญหาค่อยเขียนลง config ถาวร - ทำ baseline — บันทึกค่า default ไว้ก่อนเปลี่ยน จะได้ rollback ได้ง่ายถ้ามีปัญหา
พารามิเตอร์ที่ต้องระวังเป็นพิเศษ
kernel.modules_disabled = 1— ไม่สามารถ reverse ได้โดยไม่ reboot ให้คิดให้ดีก่อนเปิดnet.ipv4.ip_forward = 0— จะทำให้ Docker networking พัง ถ้าเครื่องรัน Docker ต้องเปิดเป็น 1kernel.sysrq = 0— ปิด SysRq ทั้งหมด ถ้ายังต้องการ emergency reboot ให้ตั้งเป็น 176 แทนnet.ipv4.tcp_timestamps = 0— อาจส่งผลกระทบต่อ TCP performance ในบางกรณี ต้องพิจารณาตาม workload ของคุณ
คำถามที่พบบ่อย (FAQ)
sysctl hardening ต่างจากการตั้งค่าไฟร์วอลล์อย่างไร?
ไฟร์วอลล์ (เช่น nftables หรือ iptables) ทำหน้าที่กรอง packet ก่อนที่จะเข้าถึงระบบ เปรียบเสมือนรั้วรอบนอก ส่วน sysctl hardening ปรับแต่งพฤติกรรมของเคอร์เนลโดยตรง เช่น วิธีจัดการ TCP connections, การป้องกัน IP spoofing ในระดับ kernel และการเข้าถึงข้อมูลภายในเคอร์เนล ที่ดีที่สุดคือใช้ทั้งสองอย่างร่วมกันเพื่อ defense-in-depth ครับ
ตั้งค่า sysctl hardening แล้วต้อง reboot ไหม?
ไม่ต้อง reboot ครับ sysctl parameters apply ได้ทันทีด้วย sudo sysctl -p /etc/sysctl.d/99-production-hardening.conf หรือ sudo sysctl --system ค่าจะมีผลทันที ยกเว้นพารามิเตอร์ที่ต้องตั้งผ่าน kernel command line (boot parameters) อย่าง lockdown mode หรือ pti=on พวกนี้ต้อง reboot
sysctl hardening จะทำให้เซิร์ฟเวอร์ช้าลงไหม?
ส่วนใหญ่ไม่รู้สึกเลยครับ พารามิเตอร์อย่าง kernel.kptr_restrict หรือ fs.protected_symlinks แทบไม่มีผลต่อ performance ส่วน net.core.bpf_jit_harden = 2 อาจมี overhead เล็กน้อยสำหรับ eBPF programs แต่ไม่มีนัยสำคัญกับ workload ทั่วไป ตัวที่อาจมีผลกระทบมากที่สุดคือ pti=on (Page Table Isolation) ซึ่งอาจลด performance ได้ราว 1-5% ขึ้นอยู่กับ workload
ถ้ารัน Docker อยู่ ต้องปรับค่า sysctl อะไรบ้าง?
เซิร์ฟเวอร์ที่รัน Docker ต้องเปิด net.ipv4.ip_forward = 1 เพราะ Docker ใช้ IP forwarding สำหรับ bridge networking ถ้าปิดไป container จะเชื่อมต่อเครือข่ายไม่ได้เลย พารามิเตอร์อื่นๆ ส่วนใหญ่สามารถ hardening ได้ตามปกติ แต่ควรทดสอบกับ workload จริงก่อน apply บน production นะครับ
ควรตรวจสอบค่า sysctl บ่อยแค่ไหน?
แนะนำอย่างน้อยเดือนละครั้ง หรือทุกครั้งที่อัปเดตเคอร์เนล และควร automate ด้วย kernel-hardening-checker หรือ Lynis ผ่าน cron job เพื่อตรวจจับ configuration drift โดยอัตโนมัติ สำหรับองค์กรที่ต้องปฏิบัติตาม compliance framework อย่าง PCI DSS จะมีข้อกำหนดเรื่องหลักฐานการตรวจสอบเป็นระยะอยู่แล้ว ก็ถือว่าได้ประโยชน์สองต่อเลย