惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 三生石上(FineUI控件)
Hugging Face - Blog
Hugging Face - Blog
M
MIT News - Artificial intelligence
T
Tailwind CSS Blog
Webroot Blog
Webroot Blog
S
Secure Thoughts
N
News and Events Feed by Topic
月光博客
月光博客
TaoSecurity Blog
TaoSecurity Blog
Microsoft Azure Blog
Microsoft Azure Blog
B
Blog RSS Feed
N
News | PayPal Newsroom
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
小众软件
小众软件
Recent Commits to openclaw:main
Recent Commits to openclaw:main
P
Privacy & Cybersecurity Law Blog
GbyAI
GbyAI
K
Kaspersky official blog
WordPress大学
WordPress大学
P
Proofpoint News Feed
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
博客园 - 叶小钗
W
WeLiveSecurity
Jina AI
Jina AI
The Cloudflare Blog
Project Zero
Project Zero
Simon Willison's Weblog
Simon Willison's Weblog
V
Vulnerabilities – Threatpost
L
LangChain Blog
Forbes - Security
Forbes - Security
PCI Perspectives
PCI Perspectives
Engineering at Meta
Engineering at Meta
Google DeepMind News
Google DeepMind News
Recorded Future
Recorded Future
博客园 - 【当耐特】
H
Heimdal Security Blog
A
About on SuperTechFans
Cisco Talos Blog
Cisco Talos Blog
T
Threat Research - Cisco Blogs
云风的 BLOG
云风的 BLOG
Spread Privacy
Spread Privacy
L
LINUX DO - 最新话题
L
Lohrmann on Cybersecurity
Last Week in AI
Last Week in AI
Google DeepMind News
Google DeepMind News
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
I
Intezer
Martin Fowler
Martin Fowler
S
Securelist
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint

博客园 - 仙守

docker容器大小使用限制 docker容器的磁盘使用进行限额 sentry私有化部署: 在8c16g上降低资源使用 私有化部署sentry: 获取dsn 私有化部署sentry:卷备份及恢复 docker 保存所有镜像 私有化部署sentry:镜像构建 docker拉取代理脚本 vscode密钥从windows连接远程linux 基于docker构建es集群 在es中进行update+upsert milvus遍历查询全部数据 简单剖析qwen-agent回答是怎么获取tool的 一个中转代码,底层调用openai,上层模拟openai 一个小工具识别哪个docker占用gpu NLP之预训练语言模型BERT NLP之预训练语言模型GPT NLP之引言 [推荐系统]粗排之FSCD
用audit审计去记录谁用了docker
仙守 · 2026-02-10 · via 博客园 - 仙守

Linux auditd 记录完整 Docker 命令

Created: 2/10/2026 13:40
Updated: 2/10/2026 15:52
Exported: 2/10/2026 15:55

Prompt:

linux上的审计系统audit 能记录一个用户执行的完整命令么,比如我赋予一个普通用户sudo docker的能力,我想知道他执行的完整sudo docker run 或者什么的,或者说,能监控所有用户执行docker和docker-compose这两个命令的使用情况,因为有些用户加入了docker组,不是用sudo执行的

Response:

是的,Linux 的 auditd 系统可以记录用户执行的完整命令(包括参数),而且可以同时覆盖两种情况:

  1. 用 sudo docker ... 执行的(特权提升)
  2. 直接用 docker 或 docker-compose 执行的(因为加入了 docker 组,有效 uid = 0)

最推荐且最干净的方式是监控 execve 系统调用,并针对 docker 相关可执行文件做过滤。

推荐的规则写法(2025–2026 年主流做法)

把下面这些规则加到 /etc/audit/rules.d/ 下的某个 .rules 文件(例如 docker-audit.rules),然后重启 auditd 或用 auditctl -R 加载。

# 监控所有 execve 系统调用,但只记录真正执行 docker 或 docker-compose 的
# ───────────────────────────────────────────────────────────────

# 方式1:直接针对路径(最精准,推荐)
-a always,exit -F arch=b64 -S execve -F exe=/usr/bin/docker -k docker-exec
-a always,exit -F arch=b64 -S execve -F exe=/usr/bin/docker-compose -k docker-exec
-a always,exit -F arch=b64 -S execve -F exe=/usr/local/bin/docker-compose -k docker-exec   # 有的人装在这个路径

# 如果你的系统还有这些 symlink / 别名,也建议加
-a always,exit -F arch=b64 -S execve -F exe=/usr/bin/docker.io -k docker-exec
-a always,exit -F arch=b64 -S execve -F exe=/snap/bin/docker -k docker-exec   # snap 安装的情况

# 方式2:针对所有以 docker 开头的命令(比较广,但噪音多)
-a always,exit -F arch=b64 -S execve -F path=/usr/bin/docker -k docker-exec
-a always,exit -F arch=b64 -S execve -F dir=/usr/bin -F path_1=/docker -k docker-exec   # 不常用

# 如果你还想同时监控 sudo docker 的情况(其实方式1已经包含了)
-a always,exit -F arch=b64 -S execve -F exe=/usr/bin/sudo -F a0=docker -k sudo-docker

32 位系统(现在很少见)再补上 arch=b32 的对应规则。

实际操作步骤

  1. 确认 docker 和 docker-compose 的真实路径
which docker
which docker-compose
readlink -f $(which docker)

通常是 /usr/bin/docker 和 /usr/bin/docker-compose 或 /usr/local/bin/docker-compose。

  1. 创建规则文件(推荐方式)
cat > /etc/audit/rules.d/99-docker-exec.rules << 'EOF'
-a always,exit -F arch=b64 -S execve -F exe=/usr/bin/docker -k docker-exec
-a always,exit -F arch=b64 -S execve -F exe=/usr/bin/docker-compose -k docker-exec
# 如有需要再加 sudo docker 的显式规则
-a always,exit -F arch=b64 -S execve -F exe=/usr/bin/sudo -F a0=docker -k sudo-docker
EOF
  1. 加载规则
auditctl -R /etc/audit/rules.d/99-docker-exec.rules
# 或直接重启服务(比较保险)
systemctl restart auditd
  1. 查看记录(最常用两种方式)
# 看最近的 docker 相关记录
ausearch -k docker-exec -ts recent | aureport -x --summary
ausearch -k docker-exec --format text | less

# 看某个用户的全部 docker 操作(假设 uid=1001)
ausearch -k docker-exec -ua 1001

# 看完整的命令行(最重要的一行是 EXECVE)
ausearch -k docker-exec -i    # -i 会把 hex 转成可读字符串

# 例子输出大概长这样:
type=EXECVE msg=audit(...): argc=5 a0="docker" a1="run" a2="-d" a3="--name" a4="nginx" a5="nginx:latest"
type=SYSCALL msg=audit(...): exe="/usr/bin/docker" ... auid=1001 uid=0 ... key="docker-exec"

一些实用小技巧

需求 推荐规则写法 说明
只看真正跑容器的命令 -F exe=/usr/bin/docker -F a1=run 只记录 docker run
监控所有 docker 子命令 只用 -F exe=/usr/bin/docker 会包含 run, ps, exec, logs...
也想看 docker-compose 同时加 docker-compose 的 exe 规则 同上
特别关注特权容器 -F exe=/usr/bin/docker -F a1=run -F a2~="--privileged" 模糊匹配参数(audit 支持 ~)
减少噪音 加 -F auid>=1000 -F auid!=unset 排除系统用户(auid=-1)

注意事项

  • auditd 日志默认写在 /var/log/audit/audit.log,很容易长大,建议配置 max_log_file 和 max_log_file_action = rotate。
  • 如果服务器上有很多 docker 使用,-S execve 不加过滤会产生海量日志。
  • 目前(2026 年)主流做法仍然是监控 execve + exe= 或 path=,监控 /var/run/docker.sock 的效果远不如直接监控客户端命令来得完整。
  • 如果你用的是 rootless docker,规则要相应改成监控用户自己的 docker 可执行文件。

这样设置后,无论是 sudo docker run ... 还是普通用户直接 docker run ...、docker-compose up -d,完整命令(含所有参数)都会被记录在 audit 日志里,且带有原始登录用户(auid)。

Prompt:

你把上面的谈话总结下,完整输出audit的安装,规则,什么的,然后python脚本,还有最后的这个监控shell脚本,全部完整输出一遍

Response:

以下是我們整個對話的完整總結,重點是關於 Linux auditd 監控 docker / docker-compose 相關命令的完整方案。

我會按照邏輯順序重新整理一次,並提供目前最穩定的版本(基於對話後期的結論):

  1. auditd 安裝與基本設定
  2. 推薦的 audit 規則(監控 docker 相關 execve)
  3. Python 解析腳本(audit-show.py)
  4. 持續監控 shell 腳本(使用 while + recent,避免重複與格式問題)

1. auditd 安裝與啟動(Ubuntu/Debian 為例)

# 安裝 auditd
sudo apt update
sudo apt install -y auditd audispd-plugins

# 啟動並設定開機啟動
sudo systemctl enable auditd
sudo systemctl start auditd

# 檢查狀態
sudo systemctl status auditd
auditctl -s

2. 推薦的 audit 規則(監控 docker 與 docker-compose)

建立規則檔案,例如:

sudo nano /etc/audit/rules.d/99-docker-exec.rules

內容(64位系統為主):

# 監控 docker 客戶端執行
-a always,exit -F arch=b64 -S execve -F exe=/usr/bin/docker -k docker-exec

# 如果有 docker-compose(常見路徑)
-a always,exit -F arch=b64 -S execve -F exe=/usr/bin/docker-compose -k docker-exec
-a always,exit -F arch=b64 -S execve -F exe=/usr/local/bin/docker-compose -k docker-exec

# 可選:明確監控 sudo docker 的情況(通常不需要,因為上面已包含)
# -a always,exit -F arch=b64 -S execve -F exe=/usr/bin/sudo -F a0=docker -k sudo-docker

# 可選:過濾掉系統用戶(減少噪音)
# -a always,exit -F arch=b64 -S execve -F exe=/usr/bin/docker -F auid>=1000 -F auid!=unset -k docker-exec

載入規則:

sudo augenrules --load
# 或直接
sudo auditctl -R /etc/audit/rules.d/99-docker-exec.rules

# 確認規則已載入
sudo auditctl -l | grep docker-exec

3. Python 解析腳本(audit-show.py)

這個版本已加入 auid / uid 的 fallback 邏輯(當 auid 被錯誤設為 root 時用 uid)

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
解析 ausearch -k docker-exec -i 的輸出
輸出格式:時間|用戶|命令|工作目录|執行文件
當 auid 異常為 root 時,fallback 使用 uid
"""

import re
import sys
from datetime import datetime

def parse_audit_block(block):
    result = {
        'time': None,
        'auid': None,
        'uid': None,
        'command': None,
        'cwd': None,
        'exe': None,
    }

    lines = block.strip().splitlines()

    for line in lines:
        line = line.strip()
        if not line:
            continue

        # 時間
        if 'msg=audit(' in line and result['time'] is None:
            m = re.search(r'msg=audit\((\d{2}/\d{2}/\d{4} \d{2}:\d{2}:\d{2}\.\d{3}:\d+)\)', line)
            if m:
                timestr = m.group(1).split(':', 1)[0]
                try:
                    dt = datetime.strptime(timestr, '%m/%d/%Y %H:%M:%S.%f')
                    result['time'] = dt.strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
                except ValueError:
                    result['time'] = timestr

        # auid
        if 'auid=' in line:
            m = re.search(r'auid=(\S+)', line)
            if m:
                result['auid'] = m.group(1)

        # uid
        if 'uid=' in line and result['uid'] is None:
            m = re.search(r'uid=(\S+)', line)
            if m:
                result['uid'] = m.group(1)

        # cwd
        if line.startswith('type=CWD'):
            m = re.search(r'cwd="([^"]+)"', line)
            if m:
                result['cwd'] = m.group(1)

        # exe
        if 'exe=' in line:
            m = re.search(r'exe="([^"]+)"', line)
            if m:
                result['exe'] = m.group(1)

        # 命令 (EXECVE)
        if line.startswith('type=EXECVE'):
            parts = []
            m_argc = re.search(r'argc=(\d+)', line)
            if m_argc:
                argc = int(m_argc.group(1))
                for i in range(argc):
                    m_arg = re.search(rf'a{i}=("[^"]*"|\S+)', line)
                    if m_arg:
                        arg = m_arg.group(1)
                        if arg.startswith('"') and arg.endswith('"'):
                            arg = arg[1:-1]
                        parts.append(arg)
            if parts:
                result['command'] = ' '.join(parts)

    return result

def get_user(auid, uid):
    bad_auid = {'root', '0', '-1', 'unset', '4294967295'}
    if auid and auid not in bad_auid:
        return auid
    if uid and uid not in {'unset', '4294967295'}:
        return uid
    return auid or uid or '未知'

def main():
    if len(sys.argv) > 1 and sys.argv[1] != '-':
        with open(sys.argv[1], 'r', encoding='utf-8') as f:
            text = f.read()
    else:
        text = sys.stdin.read()

    if not text.strip():
        return

    blocks = [b.strip() for b in re.split(r'-{4,}', text) if b.strip()]

    print("時間|用戶|命令|工作目录|執行文件")

    for block in blocks:
        info = parse_audit_block(block)
        if not info['time'] or not info['command']:
            continue

        time_str = info['time']
        user = get_user(info['auid'], info['uid'])
        cmd = info['command'].replace('|', '\\|')
        cwd = (info['cwd'] or '(未記錄)').replace('|', '\\|')
        exe = (info['exe'] or '(未知)').replace('|', '\\|')

        print(f"{time_str}|{user}|{cmd}|{cwd}|{exe}")

if __name__ == '__main__':
    main()

使用方式:

ausearch -k docker-exec -i -ts today | python3 audit-show.py

4. 持續監控 shell 腳本(最終推薦版本,使用 --start recent)

#!/usr/bin/env bash
# 名稱建議:docker-audit-monitor.sh
# 放在 /usr/local/bin/ 或你喜歡的位置

PARSED_LOG="/var/log/docker-audit-parsed.log"
ERROR_LOG="/var/log/docker-audit-error.log"
PYTHON_SCRIPT="/data/ubuntu/audit-show.py"          # ← 請改成你實際的 python 腳本完整路徑

# 確保目錄與檔案存在
mkdir -p "$(dirname "$PARSED_LOG")" "$(dirname "$ERROR_LOG")"
touch "$PARSED_LOG" "$ERROR_LOG"
chmod 644 "$PARSED_LOG" "$ERROR_LOG"

echo "開始持續監控 docker 命令執行記錄..."
echo "輸出檔案:$PARSED_LOG"
echo "錯誤檔案:$ERROR_LOG"
echo "使用 ausearch --start recent,每 5 秒檢查一次"
echo "建議使用 screen 或 tmux 背景執行"

while true; do
    TMP_RAW="/tmp/docker-audit-raw-$$.txt"

    # 使用 recent 只抓最近的事件,避免重複舊記錄
    ausearch --start recent -k docker-exec -i > "$TMP_RAW" 2>>"$ERROR_LOG"

    if [[ -s "$TMP_RAW" ]]; then
        cat "$TMP_RAW" | python3 "$PYTHON_SCRIPT" >> "$PARSED_LOG" 2>>"$ERROR_LOG"

        # 可選:去重(如果還是偶爾重複)
         sort -u "$PARSED_LOG" -o "$PARSED_LOG"

    fi

    rm -f "$TMP_RAW"
    sleep 5   # 可調整為 10 或 15 秒,視需求
done

執行方式(推薦使用 screen 或 tmux):

chmod +x /data/ubuntu/docker-audit-monitor.sh

# 使用 screen 背景執行
screen -S docker-audit
# 在 screen 裡執行:
/data/ubuntu/docker-audit-monitor.sh

# 之後按 Ctrl+A D 離開 screen
# 回來看:screen -r docker-audit

查看即時結果:

tail -f /var/log/docker-audit-parsed.log

小結與注意事項

  • audit 規則已包含直接執行 docker 的情況(加入 docker 組的用戶),會正確記錄原始 auid(登入身分)。
  • 如果 auid 異常顯示為 root,python 腳本會 fallback 使用 uid。
  • 監控腳本使用 --start recent 避免了時間格式與重複輸出的問題。
  • 如果 log 非常多,可考慮把 sleep 改長一點,或改成每分鐘 cron 執行一次。
  • 記得定期檢查 /var/log/audit/audit.log 大小,並設定 logrotate。

如果未來你發現還有重複、延遲或格式問題,再提供最新 log 片段,我可以繼續幫你微調。

解釋 auditd 日誌輪替監控 Kubernetes 命令總結更簡潔


Powered by Grok Exporter