上一篇 下一篇 分享链接 返回 返回顶部

Rocky Linux香港服务器如何搭建系统日志全链路审计与异常告警?

发布人:Minchunlin 发布时间:2026-10-05 08:11 阅读量:3

在 Rocky Linux 香港服务器上搭建系统日志全链路审计,重点不是单独安装某一个日志组件,而是让“事件产生、采集、持久化、分类存储、审计检索、异常检测、告警通知、结果验证”形成连续链路。常见系统事件包括 SSH 登录失败、sudo 提权、账号与权限文件变化、计划任务变化、服务配置修改、磁盘空间不足以及应用服务异常。

推荐按以下顺序实施:先确认 Rocky Linux、systemd、SELinux、磁盘和时间状态,再启用持久化 journald;随后配置 auditd 记录关键安全操作,用 rsyslog 统一承接系统告警和自定义事件,最后通过 systemd timer 周期性检测异常并发送邮件或 Webhook 告警。每一步都要先校验配置,再重载服务,避免因错误配置直接中断日志采集。

一、目标环境与审计链路

1. 适用环境

以下示例以 Rocky Linux 9.x、x86_64、systemd 作为 init 系统为例,适合具备 root 或 sudo 权限的香港服务器。

项目示例要求或建议
操作系统Rocky Linux 9.x
架构x86_64
初始化系统systemd
日志组件systemd-journald、rsyslog、auditd
告警脚本依赖Bash、curl、jq、ausearch、journalctl
日志保留journald 约 30 天,auditd 按磁盘容量轮转
告警周期5 分钟检查一次
告警对象SSH 暴力尝试、关键配置变更、计划任务变化、审计日志异常、日志分区高占用
上线目标服务器重启后日志仍可查询,关键操作可定位到时间、用户和事件类型

日志链路可以理解为:

一、目标环境与审计链路配图

SSH、sudo、系统服务、计划任务、应用
        ↓
journald / auditd / 应用日志文件
        ↓
持久化日志目录、/var/log/audit、rsyslog
        ↓
logrotate 或 auditd 自身轮转
        ↓
ausearch、journalctl、告警检测脚本
        ↓
本地日志、邮件或 HTTPS Webhook

需要明确边界:本机日志可以完成本地审计和异常检测,但拥有 root 权限的人员理论上可以修改或删除本机日志。如果需要满足更严格的取证要求,还应将关键日志转发到独立的日志存储端,并使用加密传输。下面的步骤先完成单台 Rocky Linux 服务器上的可执行部署。

2. 首次检查

先不要直接修改配置,保存基础状态和配置备份:

sudo -i

STAMP=$(date +%F-%H%M%S)
install -d -m 0700 "/root/audit-backup/${STAMP}"

cp -a /etc/audit "/root/audit-backup/${STAMP}/"
cp -a /etc/rsyslog.conf "/root/audit-backup/${STAMP}/" 2>/dev/null || true
cp -a /etc/rsyslog.d "/root/audit-backup/${STAMP}/" 2>/dev/null || true
cp -a /etc/systemd/journald.conf "/root/audit-backup/${STAMP}/" 2>/dev/null || true
cp -a /etc/systemd/journald.conf.d "/root/audit-backup/${STAMP}/" 2>/dev/null || true

cat /etc/rocky-release
uname -m
getenforce
systemctl is-system-running
df -hT / /var /var/log
timedatectl

重点查看以下结果:

  • cat /etc/rocky-release 应确认系统确实为 Rocky Linux。
  • uname -m 为 x86_64 时,后续审计规则优先使用 arch=b64。
  • SELinux 建议保持 Enforcing,不要为了绕过权限问题直接关闭。
  • /var/log 所在文件系统应保留足够空间。审计日志增长较快时,建议至少预留数 GB。
  • timedatectl 的时间和时区必须正确,否则不同日志中的时间无法对应。

如果服务器时间异常,先检查时间同步服务:

timedatectl status
systemctl status chronyd --no-pager
chronyc tracking

时间同步策略应按照现有运维规范处理,不建议在生产环境中未经确认直接修改时区或停止时间服务。

二、安装依赖并启用基础服务

安装日志采集、审计和告警脚本依赖:

dnf install -y audit rsyslog curl jq logrotate

确认关键命令已经存在:

command -v journalctl
command -v ausearch
command -v auditctl
command -v rsyslogd
command -v curl
command -v jq

启用 rsyslog。rsyslog 重启期间可能出现很短的日志转发间隔,因此应先完成配置检查再重启:

systemctl enable --now rsyslog
systemctl status rsyslog --no-pager

auditd 的启动方式在 Rocky Linux 上建议使用系统服务脚本:

systemctl enable auditd
service auditd start
service auditd status

如果 auditd 已经处于运行状态,不需要重复启动。先查看当前状态:

auditctl -s
auditctl -l

auditctl -s 中的 enabled=1 表示审计正在运行,enabled=2 表示审计规则已经锁定,通常需要重启服务器才能改变规则。初次部署不要主动加入 -e 2,先验证规则和告警链路,避免后续修改必须安排重启。

三、启用 journald 持久化存储

默认情况下,journald 可能只保存在内存或临时目录中,服务器重启后部分日志会消失。创建持久化目录和配置文件:

install -d -m 2755 -o root -g systemd-journal /var/log/journal
install -d -m 0755 /etc/systemd/journald.conf.d

cat > /etc/systemd/journald.conf.d/10-persistent-audit.conf <<'EOF'
[Journal]
Storage=persistent
SystemMaxUse=2G
RuntimeMaxUse=512M
MaxRetentionSec=30day
Compress=yes
ForwardToSyslog=yes
EOF

这里的 2G 和 30day 是参考值,不是所有服务器都适用。日志量较大时,应根据磁盘容量和审计保留要求调整。SystemMaxUse 只限制 journald 使用的空间,不包含 /var/log/audit 和应用独立日志文件。

重载 journald:

systemctl restart systemd-journald
journalctl --flush
systemctl status systemd-journald --no-pager

验证持久化是否生效:

journalctl --disk-usage
ls -ld /var/log/journal
journalctl -b -n 20 --no-pager

正常情况下,journalctl --disk-usage 会显示 journald 已使用的磁盘空间,/var/log/journal 目录存在且权限为类似 drwxr-sr-x。如果重启后仍然查不到上一次启动记录,优先检查该目录权限、SELinux 审计记录和磁盘是否只读。

四、配置 auditd 记录关键安全操作

1. 设计审计范围

不建议对整台服务器的所有文件和所有系统调用进行无差别审计,这会造成日志量快速增长,甚至影响 I/O。优先记录以下内容:

  • 用户、组和密码文件变化;
  • sudo 与 PAM 配置变化;
  • SSH 配置变化;
  • systemd 服务配置变化;
  • cron 计划任务变化;
  • rsyslog 配置变化;
  • 普通用户执行的命令;
  • 普通用户通过 sudo 获得 root 权限后的命令。

先查看现有规则,避免与已经部署的合规规则重复:

auditctl -l
ls -la /etc/audit/rules.d/

如果已有相同 -k 名称或相同系统调用规则,应合并规则,不要机械追加多份相同配置。

2. 写入本地规则

创建独立的本地规则文件,便于后续回滚:

cat > /etc/audit/rules.d/40-local-audit.rules <<'EOF'
# 账号、认证和权限配置
-w /etc/passwd -p wa -k identity
-w /etc/group -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/gshadow -p wa -k identity
-w /etc/login.defs -p wa -k identity
-w /etc/security/ -p wa -k auth_config
-w /etc/pam.d/ -p wa -k auth_config

# sudo 和 SSH 配置
-w /etc/sudoers -p wa -k privileged_config
-w /etc/sudoers.d/ -p wa -k privileged_config
-w /etc/ssh/sshd_config -p wa -k ssh_config

# 服务和计划任务配置
-w /etc/systemd/system/ -p wa -k service_config
-w /etc/cron.d/ -p wa -k scheduled_task
-w /etc/crontab -p wa -k scheduled_task
-w /etc/rsyslog.conf -p wa -k logging_config
-w /etc/rsyslog.d/ -p wa -k logging_config

# 普通用户执行的命令
-a always,exit -F arch=b64 -S execve -F auid>=1000 -F auid!=unset -k user_commands

# 普通用户通过 sudo 或其他方式执行的 root 命令
-a always,exit -F arch=b64 -S execve -F euid=0 -F auid>=1000 -F auid!=unset -k privileged_commands
EOF

这些规则会带来额外日志量,尤其是 execve 规则。应用服务器、编译服务器或高频任务服务器可能产生较多审计事件。如果部署后发现 /var/log/audit 增长过快,可以先保留关键文件监控,再缩小命令审计范围。

如果服务器确实需要记录 32 位兼容程序的系统调用,应在确认内核架构和程序运行情况后补充 arch=b32 规则。不要在不了解业务负载的情况下直接复制大量 b32 规则。

3. 检查并加载规则

先检查规则语法:

augenrules --check

没有明显错误后加载:

augenrules --load

确认关键规则已经进入内核:

auditctl -l | grep -E 'identity|auth_config|privileged_config|ssh_config|service_config|scheduled_task|logging_config|user_commands|privileged_commands'
auditctl -s

验证某个关键文件的审计查询:

ausearch -k ssh_config -i --start today
ausearch -k privileged_config -i --start today
ausearch -k privileged_commands -i --start today

结果含义如下:

  • 能看到 type=CONFIG_CHANGE、type=SYSCALL 或文件变更记录,说明对应规则已经生效。
  • No matches 只表示查询时间范围内没有匹配事件,不一定代表规则失效。
  • auditctl -l 中没有规则,通常是文件语法错误、规则文件路径错误、规则被其他文件覆盖,或 auditd 已经锁定。
  • 加载时提示某个路径不存在,应检查规则中的目录是否在当前 Rocky Linux 安装中存在。

4. 设置 auditd 日志轮转

auditd 日志由自身配置管理,不应只依赖 logrotate。先备份配置:

cp -a /etc/audit/auditd.conf "/root/audit-backup/${STAMP}/auditd.conf"
grep -E '^(max_log_file|max_log_file_action|num_logs|space_left|space_left_action|admin_space_left|admin_space_left_action|disk_full_action|disk_error_action)' /etc/audit/auditd.conf

可以根据磁盘容量检查并调整以下参数:

max_log_file = 100
num_logs = 10
max_log_file_action = ROTATE
space_left_action = SYSLOG
admin_space_left_action = SUSPEND
disk_full_action = SUSPEND
disk_error_action = SUSPEND

这里的 100 通常表示单个审计文件达到约 100 MB 后轮转,num_logs=10 表示保留若干个轮转文件。具体值需要结合日志量估算。SUSPEND 会在磁盘空间不足时暂停审计写入,能够避免继续消耗磁盘,但也意味着审计链路会出现缺口。调整前要确认业务对“继续运行”和“保证审计完整”的优先级。

修改后不要直接覆盖整个配置文件,完成语法检查和维护窗口验证。auditd 的配置变更可能需要通过服务脚本重载或重启,执行前应确认当前连接方式和业务影响。

五、接入 rsyslog 与应用日志

1. 检查 Rocky Linux 默认日志分类

Rocky Linux 通常已经将部分日志写入以下文件:

ls -lh /var/log/messages /var/log/secure /var/log/maillog /var/log/cron 2>/dev/null
grep -R -nE 'authpriv|/var/log/secure|/var/log/messages' /etc/rsyslog.conf /etc/rsyslog.d/ 2>/dev/null

常见用途如下:

日志位置主要内容
/var/log/messages一般系统服务和内核相关消息
/var/log/secureSSH、sudo、认证和权限相关消息
/var/log/croncron 任务执行情况
/var/log/audit/audit.logauditd 记录的系统调用、权限和配置事件
journalctl -u 服务名systemd 服务的标准输出、错误输出和服务状态

不要为了“统一格式”把 auditd 日志强行再次转发给 rsyslog,这可能造成重复记录或循环写入。auditd 日志优先使用 ausearch、aureport 查询。

2. 保存告警脚本自身的日志

创建 rsyslog 规则,将告警脚本通过 logger 写入独立文件:

cat > /etc/rsyslog.d/30-audit-alert.conf <<'EOF'
template(name="AuditAlertLine" type="string"
         string="%timegenerated:::date-rfc3339% %hostname% %syslogtag%%msg%\n")

if ($programname == "audit-alert") then {
    action(
        type="omfile"
        file="/var/log/audit-alert.log"
        template="AuditAlertLine"
        fileCreateMode="0640"
        dirCreateMode="0750"
    )
}
EOF

检查 rsyslog 配置:

rsyslogd -N1

只有看到配置检查通过后,才重启 rsyslog:

五、接入 rsyslog 与应用日志配图

systemctl restart rsyslog
logger -t audit-alert -p authpriv.notice "audit alert pipeline test"
tail -n 5 /var/log/audit-alert.log

为告警文件设置轮转:

cat > /etc/logrotate.d/audit-alert <<'EOF'
/var/log/audit-alert.log {
    weekly
    rotate 8
    missingok
    notifempty
    compress
    delaycompress
    create 0640 root root
}
EOF

logrotate -d /etc/logrotate.conf

logrotate -d 只进行调试检查,不会实际轮转文件。不要在生产环境中直接使用 logrotate -f,除非已经确认磁盘、权限和业务读取行为不会受到影响。

3. 接入 systemd 服务和应用日志

对于使用 systemd 管理的应用,优先保留标准输出和错误输出:

journalctl -u nginx -S today --no-pager
journalctl -u your-app.service -S today --no-pager

如果服务日志量较大,可以查看时间范围和优先级:

journalctl -u your-app.service --since "30 minutes ago" -p warning..alert --no-pager

如果应用写入独立文件,例如 Nginx 的访问日志和错误日志,应确认文件存在、权限正确并由 logrotate 管理:

ls -lh /var/log/nginx/
grep -R -nE 'access_log|error_log' /etc/nginx/ 2>/dev/null

修改 Nginx 日志路径时,先备份配置并执行:

nginx -t
systemctl reload nginx

reload 通常不会中断已有连接,但如果 nginx -t 失败,不要执行 reload。应用日志和审计日志应分别管理,避免通过修改应用配置造成系统日志链路异常。

六、部署异常检测与告警

1. 告警规则说明

下面的检测脚本每 5 分钟检查一次,默认使用以下参考阈值:

  • 5 分钟内 SSH 失败次数达到 8 次,触发告警;
  • /var/log 使用率达到 80%,触发告警;
  • 最近审计窗口内出现账号、sudo、服务、计划任务或日志配置变化,触发告警;
  • 告警内容写入本地 journald 和 /var/log/audit-alert.log;
  • 配置邮件地址后通过 mailx 发送邮件;
  • 配置 Webhook 地址后通过 curl 发送 JSON。

阈值应根据服务器的登录来源、发布频率和自动化任务调整。办公跳板机、公开 SSH 服务和无人值守应用服务器不应使用完全相同的阈值。

创建配置文件:

cat > /etc/sysconfig/audit-alert <<'EOF'
SSH_FAIL_THRESHOLD=8
DISK_THRESHOLD=80

# 配置邮件接收地址时填写,例如 ops@example.com
ALERT_TO=""

# 接收端必须支持 POST JSON,留空表示不发送 Webhook
WEBHOOK_URL=""
EOF

chown root:root /etc/sysconfig/audit-alert
chmod 0600 /etc/sysconfig/audit-alert

如果 Webhook URL 中包含令牌,必须保持 0600 权限,避免普通用户读取通知凭据。

2. 创建检测脚本

cat > /usr/local/sbin/audit-alert.sh <<'EOF'
#!/usr/bin/env bash

set -u
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

CONFIG="/etc/sysconfig/audit-alert"
STATE_DIR="/var/lib/audit-alert"
STATE_FILE="${STATE_DIR}/last-alert"
HOSTNAME_VALUE="$(hostname -f 2>/dev/null || hostname)"

if [[ -r "$CONFIG" ]]; then
    # 配置文件由 root 管理,权限应保持为 0600
    source "$CONFIG"
fi

SSH_FAIL_THRESHOLD="${SSH_FAIL_THRESHOLD:-8}"
DISK_THRESHOLD="${DISK_THRESHOLD:-80}"
FORCE_TEST="${FORCE_TEST:-0}"

install -d -m 0700 "$STATE_DIR"

alerts=()

fail_count="$(
    journalctl -u sshd --since "5 minutes ago" --no-pager -o cat 2>/dev/null |
    grep -Eic 'Failed password|Invalid user|authentication failure' || true
)"

if [[ "$fail_count" =~ ^[0-9]+$ ]] && (( fail_count >= SSH_FAIL_THRESHOLD )); then
    alerts+=("过去5分钟检测到 ${fail_count} 次 SSH 认证失败,阈值为 ${SSH_FAIL_THRESHOLD}")
fi

disk_used="$(
    df -P /var/log 2>/dev/null |
    awk 'NR==2 {gsub("%","",$5); print $5}'
)"

if [[ "$disk_used" =~ ^[0-9]+$ ]] && (( disk_used >= DISK_THRESHOLD )); then
    alerts+=("/var/log 所在文件系统使用率为 ${disk_used}%,阈值为 ${DISK_THRESHOLD}%")
fi

if ausearch -ts recent -k identity -i >/dev/null 2>&1; then
    alerts+=("最近审计窗口检测到账号或身份配置变化,请检查 ausearch -k identity -i")
fi

if ausearch -ts recent -k privileged_config -i >/dev/null 2>&1; then
    alerts+=("最近审计窗口检测到 sudo 权限配置变化,请检查 ausearch -k privileged_config -i")
fi

if ausearch -ts recent -k service_config -i >/dev/null 2>&1; then
    alerts+=("最近审计窗口检测到 systemd 服务配置变化,请检查 ausearch -k service_config -i")
fi

if ausearch -ts recent -k scheduled_task -i >/dev/null 2>&1; then
    alerts+=("最近审计窗口检测到计划任务变化,请检查 ausearch -k scheduled_task -i")
fi

if [[ "$FORCE_TEST" == "1" ]]; then
    alerts+=("人工测试告警:检测脚本和通知链路正在验证")
fi

if (( ${#alerts[@]} == 0 )); then
    exit 0
fi

ALERT_TEXT=$(
    printf '主机:%s\n' "$HOSTNAME_VALUE"
    printf '时间:%s\n' "$(date --iso-8601=seconds)"
    printf '%s\n' "${alerts[@]}"
)

signature="$(printf '%s' "$ALERT_TEXT" | sha256sum | awk '{print $1}')"
now="$(date +%s)"
old_signature=""
old_time="0"

if [[ -r "$STATE_FILE" ]]; then
    read -r old_signature old_time < "$STATE_FILE" || true
fi

if [[ "$old_time" =~ ^[0-9]+$ ]] &&
   (( now - old_time < 1800 )) &&
   [[ "$old_signature" == "$signature" ]]; then
    exit 0
fi

printf '%s %s\n' "$signature" "$now" > "$STATE_FILE"
chmod 0600 "$STATE_FILE"

logger -p authpriv.warning -t audit-alert -- "$ALERT_TEXT"

if [[ -n "${ALERT_TO:-}" ]] && command -v mailx >/dev/null 2>&1; then
    printf '%s\n' "$ALERT_TEXT" |
        mailx -s "[Rocky Linux审计告警] ${HOSTNAME_VALUE}" "$ALERT_TO" ||
        logger -p authpriv.err -t audit-alert -- "邮件发送失败"
fi

if [[ -n "${WEBHOOK_URL:-}" ]] &&
   command -v curl >/dev/null 2>&1 &&
   command -v jq >/dev/null 2>&1; then

    payload="$(
        jq -n \
          --arg host "$HOSTNAME_VALUE" \
          --arg text "$ALERT_TEXT" \
          '{host: $host, text: $text}'
    )"

    if ! curl -fsS --max-time 8 \
        -H 'Content-Type: application/json' \
        --data "$payload" \
        "$WEBHOOK_URL" >/dev/null; then
        logger -p authpriv.err -t audit-alert -- "Webhook发送失败"
    fi
fi

printf '%s\n' "$ALERT_TEXT"
EOF

chown root:root /usr/local/sbin/audit-alert.sh
chmod 0750 /usr/local/sbin/audit-alert.sh
restorecon -v /usr/local/sbin/audit-alert.sh /etc/sysconfig/audit-alert 2>/dev/null || true

bash -n /usr/local/sbin/audit-alert.sh

脚本只读取日志和审计索引,不会修改 SSH、账号或防火墙配置。邮件功能依赖已经配置好的本地 mailx 和邮件中继;如果没有邮件中继,可以只使用 Webhook 或查看本地告警文件。

3. 使用 systemd timer 定时执行

创建一次性服务:

cat > /etc/systemd/system/audit-alert.service <<'EOF'
[Unit]
Description=Rocky Linux audit anomaly detection
After=network-online.target auditd.service rsyslog.service
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/audit-alert.sh
User=root
NoNewPrivileges=true
PrivateTmp=true
EOF

创建定时器:

cat > /etc/systemd/system/audit-alert.timer <<'EOF'
[Unit]
Description=Run Rocky Linux audit anomaly detection every 5 minutes

[Timer]
OnBootSec=2min
OnUnitActiveSec=5min
AccuracySec=30s
Persistent=true

[Install]
WantedBy=timers.target
EOF

加载并启动:

systemctl daemon-reload
systemctl enable --now audit-alert.timer

systemctl status audit-alert.timer --no-pager
systemctl list-timers --all | grep audit-alert

七、结果验证

1. 验证基础日志链路

logger -t audit-chain -p authpriv.notice "system log chain verification"
journalctl -t audit-chain -n 5 --no-pager

如果需要验证 rsyslog:

logger -t audit-alert -p authpriv.notice "rsyslog alert file verification"
tail -n 10 /var/log/audit-alert.log

正常结果是:日志首先能在 journald 中查询,rsyslog 规则生效后也能在独立文件中看到对应记录。

2. 验证 auditd 规则

在维护窗口内,可以对已纳入监控的 rsyslog 配置目录创建一个空测试文件,再立即删除。该操作只影响测试文件,不要对正在使用的配置文件执行覆盖:

install -o root -g root -m 0644 /dev/null /etc/rsyslog.d/audit-test.conf
rm -f /etc/rsyslog.d/audit-test.conf

ausearch -k logging_config -i --start recent

如果能够看到创建和删除相关事件,说明文件监控规则生效。测试文件必须为空,且不能执行 systemctl restart rsyslog,避免误将测试文件当成有效配置加载。

验证命令审计:

id
sudo -n true 2>/dev/null || true
ausearch -k user_commands -i --start recent
ausearch -k privileged_commands -i --start recent

如果当前用户没有 sudo 权限,sudo -n true 可能返回失败,这是权限检查结果,不代表审计异常。重点查看是否生成了相应的执行记录。

3. 验证告警脚本

使用人工测试模式,不需要制造真实的 SSH 失败登录:

FORCE_TEST=1 /usr/local/sbin/audit-alert.sh

查看执行结果:

journalctl -t audit-alert -n 20 --no-pager
tail -n 20 /var/log/audit-alert.log
systemctl start audit-alert.service
journalctl -u audit-alert.service -n 20 --no-pager

验证定时器下一次执行时间:

systemctl list-timers audit-alert.timer --all

如果配置了 Webhook,应在接收端确认主机名、时间和测试文本。如果通知端没有收到消息,但本地日志存在,优先检查 DNS、出站连接、Webhook 路径、TLS 证书和接收端 JSON 字段要求。一般不需要为出站告警开放新的入站端口。

八、按优先级排查常见故障配图

八、按优先级排查常见故障

优先级检查项目命令结果含义与处理
1磁盘和时间df -hT /var/log; timedatectl磁盘满会导致日志写入失败,时间错误会造成事件顺序混乱。先释放或扩容日志空间,再检查时间同步
2服务状态systemctl status systemd-journald rsyslog auditd服务未运行时先查看对应日志,不要直接反复重启
3journald 持久化journalctl --disk-usage; ls -ld /var/log/journal目录不存在或权限错误时,重建目录并检查 SELinux;重启后没有历史日志通常与此有关
4rsyslog 配置rsyslogd -N1出现语法错误时不要重启 rsyslog,修正配置后再次检查
5auditd 规则augenrules --check; auditctl -l规则未加载时检查文件名、路径、重复规则和 enabled=2 锁定状态
6告警脚本bash -n /usr/local/sbin/audit-alert.sh; FORCE_TEST=1 ...语法错误、依赖缺失或配置文件权限错误会导致脚本直接退出
7定时器systemctl status audit-alert.timer; systemctl list-timers定时器未启用、时间未到或服务执行失败时,查看 journalctl -u audit-alert.service
8SELinuxausearch -m avc -ts recent -i存在 AVC 拒绝时,先定位具体路径和进程,不要直接关闭 SELinux
9告警通道curl -v --max-time 8 "$WEBHOOK_URL"本地有告警而远端无消息,通常是 DNS、出站策略、证书或接收端格式问题

常见故障处理如下。

1. journald 没有历史日志

执行:

journalctl --list-boots
journalctl --verify
ls -ldZ /var/log/journal
df -h /var/log

如果 /var/log/journal 不存在,重新创建并执行:

install -d -m 2755 -o root -g systemd-journal /var/log/journal
systemctl restart systemd-journald
journalctl --flush

如果 SELinux 上下文异常,执行:

restorecon -Rv /var/log/journal

2. auditd 规则加载失败

先查看详细错误:

augenrules --check
journalctl -u auditd -b --no-pager
auditctl -s

如果状态为 enabled=2,说明规则被锁定。此时不要尝试强行删除内核规则,应在确认备份和维护窗口后重启服务器,再重新加载经过修正的规则。

如果是某个路径不存在,检查规则文件中的路径:

while read -r line; do
    case "$line" in
        -w\ *) path=$(awk '{print $2}' <<< "$line"); [[ -e "$path" ]] || echo "不存在:$path" ;;
    esac
done < /etc/audit/rules.d/40-local-audit.rules

3. rsyslog 无法启动

先不要删除现有配置,执行:

rsyslogd -N1
journalctl -u rsyslog -b --no-pager

如果错误来自新增规则,可以临时将新增文件改名停用:

mv /etc/rsyslog.d/30-audit-alert.conf \
   /etc/rsyslog.d/30-audit-alert.conf.disabled

rsyslogd -N1
systemctl restart rsyslog

确认基础日志恢复后,再修正语法并恢复文件名。该回滚只影响新增的告警文件输出,不会删除 /var/log/messages 或 /var/log/secure。

4. 检测脚本没有告警

依次执行:

bash -n /usr/local/sbin/audit-alert.sh
ls -l /etc/sysconfig/audit-alert /usr/local/sbin/audit-alert.sh
command -v ausearch journalctl curl jq
FORCE_TEST=1 /usr/local/sbin/audit-alert.sh
journalctl -t audit-alert -n 30 --no-pager

如果人工测试也没有输出,检查:

  • 脚本是否为 root 所有且可执行;
  • /etc/sysconfig/audit-alert 是否存在语法错误;
  • jq 和 curl 是否安装;
  • /var/lib/audit-alert 是否可写;
  • SELinux 是否拒绝脚本或日志文件操作。

如果人工测试正常,而真实异常没有触发,应检查阈值和日志来源。例如,SSH 服务单元可能不是 sshd.service,可以先查看:

systemctl list-units --type=service | grep -E 'ssh|sshd'
journalctl -u sshd --since "30 minutes ago" --no-pager

5. 日志增长过快

检查各类日志占用:

journalctl --disk-usage
du -sh /var/log/audit /var/log/* 2>/dev/null | sort -h | tail -n 20
ausearch -k user_commands --start today | wc -l
ausearch -k privileged_commands --start today | wc -l

如果主要增长来自 execve 规则,应优先缩小命令审计范围,而不是直接删除所有审计规则。例如,可以暂时停用本地规则文件并重新加载:

mv /etc/audit/rules.d/40-local-audit.rules \
   /etc/audit/rules.d/40-local-audit.rules.disabled

augenrules --load
auditctl -l

这会停用本次新增文件中的规则,影响范围包括账号、服务、计划任务和命令审计。操作前必须确认已经保存备份,并在重新设计规则后恢复。不要移动发行版自带或其他合规系统维护的规则文件。

九、回滚方法

1. 回滚告警系统

停止定时器并保留配置,避免误删现场:

systemctl disable --now audit-alert.timer
systemctl daemon-reload

如果只需要停止通知而保留检测,将 /etc/sysconfig/audit-alert 中的 ALERT_TO 和 WEBHOOK_URL 置空即可。告警记录仍会写入本地日志。

2. 回滚 rsyslog 新增配置

mv /etc/rsyslog.d/30-audit-alert.conf \
   /etc/rsyslog.d/30-audit-alert.conf.disabled

rsyslogd -N1 && systemctl restart rsyslog

该操作只停止独立告警文件的输出,不会删除历史 /var/log/audit-alert.log。

3. 回滚 journald 持久化配置

mv /etc/systemd/journald.conf.d/10-persistent-audit.conf \
   /etc/systemd/journald.conf.d/10-persistent-audit.conf.disabled

systemctl restart systemd-journald

不要直接删除 /var/log/journal,因为这会破坏已经保存的历史日志。若必须清理,应先按照保留策略归档,再使用 journalctl --vacuum-time 或 journalctl --vacuum-size 进行受控清理。

4. 回滚 auditd 本地规则

仅移动本次创建的规则文件:

mv /etc/audit/rules.d/40-local-audit.rules \
   /etc/audit/rules.d/40-local-audit.rules.disabled

augenrules --load
auditctl -l

如果 auditd 已经处于锁定状态,不能在线回滚,需要使用已经验证过的备份配置安排重启。回滚后必须重新验证 auditctl -l,确认既有审计规则没有被误删。

上线与验收检查清单

上线前逐项确认:

  • [ ] 系统版本、架构、时区和时间同步状态正确。
  • [ ] /var/log 有足够可用空间,日志分区不会与业务临时文件争用。
  • [ ] /var/log/journal 已创建,journalctl --disk-usage 能显示持久化占用。
  • [ ] rsyslogd -N1 检查通过,rsyslog 服务正常运行。
  • [ ] auditctl -s 显示审计启用,auditctl -l 能看到本地规则。
  • [ ] ausearch -k identity、ausearch -k privileged_commands 可以查询事件。
  • [ ] auditd 已配置轮转和磁盘不足处理策略。
  • [ ] /var/log/audit-alert.log 能接收测试消息。
  • [ ] audit-alert.timer 已启用,且下一次执行时间正常。
  • [ ] FORCE_TEST=1 测试能够写入本地日志,并在配置时发送邮件或 Webhook。
  • [ ] 已验证 SSH、账号配置、sudo、systemd 和计划任务等关键事件的查询方式。
  • [ ] 已保存 /etc/audit、rsyslog、journald 和告警脚本的回滚备份。
  • [ ] 已记录告警阈值、日志保留周期和异常后的责任处理人。
  • [ ] 如需防止本机日志被篡改,已规划独立日志存储和加密转发链路。
目录结构
全文