Bali, Indonesia
Insights

Bottleneck Dirty Page Writeback Akibat Serialisasi Event Inotify pada File Integrity Monitoring Skala Besar

Invalid Date
0:00
Maraknya serangan web defacement—terutama injeksi konten judi online yang menyasar portal institusi publik seperti yang dipaparkan dalam penelitian Jurnal Teknologi dan Sistem Informasi Bisnis—mendorong tim operasional memperketat sistem deteksi. Pendekatan reaktif berbasis polling HTTP terjadwal (seperti workflow otomasi n8n yang dibahas dalam jurnal tersebut) kerap dianggap memiliki latency deteksi yang terlalu lebar. Sebagai gantinya, tim keamanan infrastruktur biasanya menggelar File Integrity Monitoring (FIM) berbasis kernel event secara real-time pada layer hosting. Namun, mengaktifkan real-time monitoring pada node shared hosting dengan ribuan virtual host dan jutaan inode menyimpan jebakan performa yang mematikan. Alih-alih mengamankan sistem, implementasi FIM yang naif—terutama yang mengandalkan inotify standar tanpa mempertimbangkan profil I/O Linux page cache—sering kali memicu petaka: server mendadak membeku, load average meroket tanpa kenaikan traffic pengunjung, dan worker web server terjebak dalam status uninterruptible sleep (D).
Subsistem inotify bekerja dengan mendaftarkan watch descriptor pada inode tertentu via syscall inotify_add_watch(). Ketika sebuah direktori dipantau secara rekursif melintasi ratusan ribu struktur folder web tenant (misalnya struktur direktori CMS yang padat seperti WordPress), konsumsi kernel memory meningkat drastis. Setiap watch descriptor membutuhkan alokasi memori internal kernel di slab cache (dentry dan inode cache). Masalah fundamental inotify bukan hanya pada limitasi antrean (max_queued_events), melainkan sifat pemrosesan event di ruang pengguna (userspace). Ketika sebuah file dimodifikasi (IN_CLOSE_WRITE atau IN_MODIFY), daemon FIM menerima notifikasi tersebut. Untuk menentukan apakah modifikasi tersebut merupakan serangan defacement atau sekadar update legal, FIM daemon umumnya melakukan operasi I/O intensif: membaca ulang file, menghitung cryptographic digest (SHA-256), dan menulis riwayat status ke log audit atau local database. Ketika terjadi operasi massal—seperti eksekusi auto-update plugin serentak, rotasi log, atau deployment patch—ribuan event inotify terdistribusi masuk ke queue secara beruntun. Serialisasi pembacaan dan penulisan metadata ini mengubah sistem yang tadinya read-heavy menjadi write-heavy dalam hitungan detik. Di sinilah subsistem memori virtual Linux mulai kehilangan kestabilannya.
Linux mengelola operasi penulisan disk secara asinkron menggunakan page cache. Ketika daemon FIM menulis log audit atau aplikasi web memodifikasi file, data tidak langsung dikirim ke block device fisik (NVMe/SSD), melainkan ditandai sebagai dirty page di RAM. Kernel mendelegasikan tugas flushing dirty page ini ke kernel thread kworker (flusher thread) berdasarkan nilai sysctl berikut:
BASH
# Ambang batas background writeback (kworker mulai bekerja secara asinkron)
vm.dirty_background_ratio = 10

# Ambang batas blocking writeback (userspace process dipaksa berhenti untuk flush)
vm.dirty_ratio = 20
Pada server hosting dengan RAM 128 GB, vm.dirty_background_ratio = 10 berarti flusher thread baru akan aktif saat ada sekitar 12.8 GB dirty page di memori. Jika write I/O yang dihasilkan oleh daemon FIM (yang sedang panik menghitung hash dan menulis state ribuan file) melampaui throughput I/O hardware, dirty pages akan terakumulasi sangat cepat hingga menyentuh vm.dirty_ratio (sekitar 25.6 GB). Saat batas vm.dirty_ratio tercapai, kernel Linux mengaktifkan rem darurat via fungsi internal balance_dirty_pages(). Kernel tidak lagi mengizinkan operasi tulis asinkron. Setiap proses yang memanggil syscall write()—termasuk Nginx yang sedang menulis log akses, PHP-FPM yang menulis session file, atau MySQL yang melakukan buffer flush—akan dipaksa melakukan sinkronisasi data ke disk secara langsung (synchronous writeback).
TEXT
[FIM Burst Write] --> [Dirty Pages Melonjak] --> [Menembus vm.dirty_ratio]
                                                            |
  +---------------------------------------------------------+
  v
[Kernel Memanggil balance_dirty_pages()]
  |
  +--> Nginx Worker: Blocked di write(access.log) --> Status 'D'
  +--> PHP-FPM: Blocked di write(session_id)      --> Status 'D'
  +--> HTTP Queue Penuh --> 504 Gateway Timeout
Akibatnya, thread web server terperangkap dalam D-state (uninterruptible sleep). Dari perspektif monitoring luar, server tampak seolah mati total karena waktu tunggu I/O (iowait) menyerap seluruh siklus penjadwalan CPU, menyebabkan cascading failure di seluruh stack reverse proxy.
Untuk mencegah FIM melumpuhkan sistem hosting multi-tenant, kita perlu memutus kopling antara deteksi event filesystem dan saturasi page cache. Langkah pertama adalah merevisi parameter writeback kernel agar proses pembersihan memory cache dilakukan lebih awal dan lebih halus, tanpa menunggu akumulasi gigabyte yang memicu rem mendadak.
BASH
# Gunakan batasan berbasis byte absolut alih-alih rasio persentase RAM
sysctl -w vm.dirty_background_bytes=67108864    # 64 MB
sysctl -w vm.dirty_bytes=268435456              # 256 MB
sysctl -w vm.dirty_expire_centisecs=1500        # Data kotor berumur max 15 detik
Dengan mematok vm.dirty_background_bytes ke 64 MB dan vm.dirty_bytes ke 256 MB, flusher thread mulai menulis ke disk jauh sebelum antrean I/O menumpuk. Operasi penulisan menjadi lebih stabil (smooth streaming) alih-alih meledak dalam satu lonjakan besar yang membuat I/O controller jenuh. Namun, tuning sysctl hanya mengobati gejala. Solusi arsitektural yang sesungguhnya adalah menghentikan pemrosesan I/O berat di hot-path inotify. Pendekatan FIM modern meninggalkan model inotify rekursif tradisional untuk beralih ke Fanotify atau subsistem eBPF (Extended Berkeley Packet Filter). Dengan eBPF, kita dapat memasang probe pada LSM (Linux Security Modules) hook atau tracepoint VFS (misalnya vfs_write atau security_file_open). Alih-alih menghitung hash file secara inline di mesin produksi, program eBPF cukup mencatat PID, inode number, path, dan comm ke dalam ring buffer (BPF_MAP_TYPE_RINGBUF). Ring buffer ini dibaca oleh daemon userspace tanpa memicu context switch berlebih maupun memory allocation besar di kernel. Selain itu, verifikasi integritas file harus dideferensiasi: hanya file dengan ekstensi executable atau script (.php, .phtml, .so, shell script) yang diinspeksi secara mendalam saat terjadi mutasi. File statis (gambar, stylesheet, video cache) yang sering menjadi sumber false-positive dan badai event inotify harus sepenuhnya diabaikan di level kernel filter. FIM adalah pilar vital untuk menangkal epidemi defacement dan injeksi backdoor script. Namun, membangun mekanisme proteksi tanpa memahami interaksi antarmuka VFS dan subsistem virtual memory Linux hanya akan mengganti satu bencana keamanan dengan bencana ketersediaan layanan.