檔案離奇消失怎麼查?RHEL 8 auditd 刪檔稽核規則設定、驗證與注意事項

問題情境:檔案不見了,但沒人承認

共用目錄裡的檔案被刪除,是維運上很常見、也很難事後追查的事件。檔案系統本身不會記錄「誰刪的」,shell history 可以被清除,也涵蓋不到腳本、排程與服務帳號的行為。

在 RHEL 8 上,要回答這個問題的標準做法是 Linux Audit(auditd):由 kernel 在系統呼叫層級記錄事件,並保留「原始登入者」身分,即使對方用 sudo 或 su 切換過身分也追得到。

但 auditd 無法回溯。規則生效之前發生的刪除不會有任何紀錄,這是「預先佈署」的機制,而不是事後鑑識工具。

適用場景

  • 共用資料目錄、設定檔目錄不定期出現檔案遺失,需要釐清是人為操作還是排程/程式行為
  • 稽核或法遵要求對特定目錄保留異動軌跡
  • 多人共用 sudo 權限的主機,需要還原到個人帳號

環境確認

RHEL 8 預設已安裝並啟用 auditd,多數情況下只需確認狀態:

rpm -q audit
sudo systemctl status auditd

若是最小化安裝或曾被移除,再補裝並啟用:

sudo dnf install audit -y
sudo systemctl enable --now auditd

設定稽核規則

臨時規則(立即生效,重開機後消失)

以監控 /data/important 為例:

sudo auditctl -a always,exit -F arch=b64 \
  -S unlink,unlinkat,rename,renameat,renameat2,rmdir \
  -F dir=/data/important \
  -F 'auid>=1000' -F 'auid!=4294967295' \
  -k important_delete

在命令列上,auid>=1000 一定要加引號。 否則 shell 會把 > 解讀為輸出重導,結果是規則載入失敗,並在目前目錄留下一個名為 =1000 的空檔案。

各參數的作用:

參數作用
-a always,exit在系統呼叫結束時一律產生稽核事件
-F arch=b64比對 64 位元系統呼叫介面
-S unlink,unlinkat,rmdir刪除檔案與目錄
-S rename,renameat,renameat2搬移與改名(mv 移出目錄,效果等同刪除)
-F dir=/data/important遞迴涵蓋該目錄下所有層級
-F 'auid>=1000'只記錄一般使用者帳號(UID 1000 以上)
-F 'auid!=4294967295'排除沒有登入身分的行程,可寫成 auid!=unset
-k important_delete自訂關鍵字,供後續查詢與管理規則使用

永久規則

auditctl 下的規則只存在於本次開機。要永久生效,新增 /etc/audit/rules.d/50-important-delete.rules:

-a always,exit -F arch=b64 -S unlink,unlinkat,rename,renameat,renameat2,rmdir -F dir=/data/important -F auid>=1000 -F auid!=4294967295 -k important_delete
-a always,exit -F arch=b32 -S unlink,unlinkat,rename,renameat,renameat2,rmdir -F dir=/data/important -F auid>=1000 -F auid!=4294967295 -k important_delete

規則檔不經過 shell 解析,所以這裡不需要引號。b32 那一行是為了涵蓋以 32 位元介面發出的系統呼叫,避免留下可繞過的缺口。

載入並確認:

sudo augenrules --load
sudo auditctl -l

augenrules 會依檔名順序合併 rules.d 下的所有 .rules 檔,因此檔名前的數字決定規則順序。

驗證與查詢

以一般使用者登入後建立並刪除測試檔:

touch /data/important/audit-test
rm /data/important/audit-test

# 依 key 查詢,-i 會將 UID 轉成帳號名稱
sudo ausearch -k important_delete -i --start recent

一次刪除會產生一組紀錄,節錄示意如下:

type=PROCTITLE ... : proctitle=rm /data/important/audit-test
type=PATH ...      : item=1 name=/data/important/audit-test nametype=DELETE
type=CWD ...       : cwd=/home/alice
type=SYSCALL ...   : syscall=unlinkat success=yes auid=alice uid=root
                     tty=pts0 ses=12 comm=rm exe=/usr/bin/rm key=important_delete

判讀時看這幾個欄位:

欄位意義
auid原始登入帳號,經過 sudo、su 後仍不變,是追查的主要依據
uid / euid執行當下的身分;auid=alice uid=root 表示 alice 透過 sudo 執行
exe / comm實際執行刪除的程式,可分辨是 rm、rsync 還是某支腳本的直譯器
proctitle完整命令列
tty / ses終端機與登入工作階段,可對照 /var/log/secure 找出來源 IP
name + nametype=DELETE被刪除的路徑

常用的查詢變化:

# 指定時間範圍
sudo ausearch -k important_delete -i --start today
# 只看特定檔案
sudo ausearch -k important_delete -i -f /data/important/report.xlsx

範圍與規則

auid 過濾條件要不要留

若使用 auid>=1000 加上 auid!=unset ,這是 RHEL 官方文件提供的指令範例,雜訊最少,但它會略過幾種很常見的「兇手」:

過濾條件記錄得到記錄不到
auid>=1000 且 auid!=unset一般使用者(含其 sudo 操作、個人 crontab)root 直接登入、root 的 crontab、systemd 服務、容器內行程
僅 auid!=unset以上再加 root 直接登入與 root crontabsystemd 服務、daemon、容器內行程
不過濾 auid所有行程無,但需靠 exe、comm、pid 判斷來源,事件量也最大

實務上,檔案離奇消失的原因經常是清理腳本、logrotate、同步工具或應用程式本身。如果調查目標還不明確,建議先拿掉 auid 過濾,確認事件量可接受後再收斂。

系統呼叫規則與 watch 規則

這個寫法 -w /data/important -p wa -k important_delete,使用時,會有訊息,說這已經過時,改用系統呼叫寫法比較好。

寫法優點代價
-a always,exit -S ...精準鎖定刪除與搬移,可加 auid 等條件語法較長,需自行確認系統呼叫涵蓋範圍
-w ... -p wa語法簡短,寫入與屬性變更一併記錄事件量大,無法只針對刪除;較新的 audit 版本已不建議使用此寫法

只想回答「誰刪的」,系統呼叫規則較合適;若連內容被改寫也要追,再考慮擴大範圍。

監控範圍的界線

本文規則涵蓋的是「檔案從目錄中消失」。檔案被清空或覆寫(例如 > file、truncate)不屬於刪除,不會被記錄。有這類需求時要另外加入 truncate、ftruncate 以及帶寫入旗標的 open/openat,事件量會明顯上升。

實務踩坑與注意事項

1. 用 root 直接登入測試,結果查無資料
root 直接登入時 auid=0,會被 auid>=1000 排除,ausearch 回傳 <no matches>。這是規則如預期運作,不是規則失效。請改用一般帳號登入(之後再 sudo 也可以)進行驗證。

2. 無法用 systemctl 重啟 auditd
RHEL 8 的 auditd 拒絕 systemctl restart 與 stop,這是刻意的設計。調整 auditd.conf 後請用:

sudo service auditd restart

3. 規則被鎖定無法修改
若環境套用過 STIG 或 CIS 強化,規則結尾通常有 -e 2,此時任何新增或刪除都要重開機才生效。可用 sudo auditctl -s 檢查 enabled 是否為 2。自訂規則檔的檔名排序也必須在含 -e 2 的檔案之前。

4. 日誌保留量不足
預設每個檔案 8 MB、保留 5 份,總量約 40 MB。目錄異動頻繁時,證據可能在幾天內就被輪替掉。請依需求調整 /etc/audit/auditd.conf 的 max_log_file 與 num_logs,並確認 /var/log/audit 所在分割區的空間。

5. 有 root 權限的人可以改日誌
稽核紀錄存在本機,能刪檔的 root 同樣能動 audit.log。有法遵需求時,應將事件即時轉送到遠端日誌主機或 SIEM。

6. 網路檔案系統有盲區

  • 本機是 NFS server:用戶端的刪除由 kernel 的 nfsd 處理,不經過系統呼叫,不會有紀錄,需到用戶端主機稽核。
  • 透過 Samba 分享:刪除動作由 smbd 執行,auid 為 unset,會被過濾條件排除;即使不過濾,也只看得到 smbd。建議改用 Samba 的 full_audit 模組。

7. 目錄不存在或掛載時序
-F dir= 指向的路徑在載入規則時必須存在,否則該條規則載入失敗。若 /data 是獨立或網路掛載點,重開機後請再做一次驗證測試,確認規則確實作用在掛載後的檔案系統上。

8. 非 x86_64 架構
aarch64 沒有 unlink、rename、rmdir 這幾個舊式系統呼叫,規則需改為只列 unlinkat,renameat,renameat2。

9. 留意事件遺失
監控範圍大或刪除量高時,用 sudo auditctl -s 觀察 lost 與 backlog。lost 持續增加表示緩衝區不足,需調高 -b 或縮小規則範圍。

規則管理

查看目前生效的規則:

sudo auditctl -l

刪除單一條規則時,參數必須與新增時完全一致,只是把 -a 換成 -d:

sudo auditctl -d always,exit -F arch=b64 \
  -S unlink,unlinkat,rename,renameat,renameat2,rmdir \
  -F dir=/data/important \
  -F 'auid>=1000' -F 'auid!=4294967295' \
  -k important_delete

或者一次移除所有帶有該 key 的規則:

sudo auditctl -D -k important_delete

兩點提醒:

  • -D 不加 -k 會清空全部規則,在正式環境請特別小心。
  • 上述指令只影響執行中的規則。若已寫入 rules.d,要一併刪除該檔案並重新執行 sudo augenrules --load,否則下次開機規則會回來。

小結

  • auditd 必須事先佈署,無法追查規則生效前的刪除。
  • auid 是追查的關鍵欄位,能穿透 sudo 與 su 還原到原始登入者。
  • auid 過濾條件決定「看得到誰」,調查初期寧可放寬。
  • 規則上線後一定要實測,並同步處理日誌保留與遠端備份。