問題情境:檔案不見了,但沒人承認
共用目錄裡的檔案被刪除,是維運上很常見、也很難事後追查的事件。檔案系統本身不會記錄「誰刪的」,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 crontab | systemd 服務、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 過濾條件決定「看得到誰」,調查初期寧可放寬。
- 規則上線後一定要實測,並同步處理日誌保留與遠端備份。