日志审计这件事,说起来简单,真正落地时却有不少坑。尤其是在 CentOS 上跑 Golang 应用,既要保证业务日志的完整性,又要满足安全合规对系统调用的审计要求,还得让日志能集中分析、快速检索。下面这套方案,融合了应用层、系统层和传输层的常见实践,希望能帮你少走弯路。

一、总体思路与分层
整个方案可以拆成四个层面来理解:
- 应用层审计:在 Golang 代码里用结构化日志(比如 logrus、zap)输出统一字段——时间戳、用户/请求ID、操作、结果、来源IP等。目的很明确:方便后续检索和聚合分析。
- 系统层审计:借助 auditd 记录关键系统调用和文件访问,比如登录行为、权限变更、敏感文件读写。这是安全合规和取证的基础。
- 日志传输与集中:通过 rsyslog 或 journald 把应用日志和系统日志统一送到 ELK / Graylog 等平台,做检索、告警和可视化。
- 运行与轮转:用 systemd 托管进程,用 logrotate 做日志切割归档,避免单个文件撑爆磁盘或丢失历史数据。
二、应用层 Golang 日志规范与示例
应用层的日志输出,强烈建议用 JSON 格式。字段统一设计为:ts、level、msg、user_id、action、ip、method、path、status、duration_ms、trace_id。注意:绝对不要记录明文密码或密钥,这是安全红线。
成熟库方面,logrus 和 zap 都是不错的选择,再配合 lumberjack 做按大小/时间切割和压缩,就可以长期留存并满足合规归档要求。下面是一个最小可用示例(logrus + JSON + lumberjack):
package main
import (
"github.com/sirupsen/logrus"
"gopkg.in/natefinch/lumberjack.v2"
"os"
)
func main() {
log := logrus.New()
log.SetFormatter(&logrus.JSONFormatter{})
log.SetLevel(logrus.InfoLevel)
log.SetOutput(&lumberjack.Logger{
Filename: "/var/log/myapp/app.log",
MaxSize: 100, // MB
MaxBackups: 30,
MaxAge: 90, // days
Compress: true,
})
log.WithFields(logrus.Fields{
"user_id": "u1001",
"action": "login",
"ip": "192.168.1.10",
"method": "POST",
"path": "/api/v1/login",
"status": 200,
}).Info("user login")
}
运行方式建议用 systemd 托管,日志同时落盘并输出到 journald。这样本地查 tail 很方便,集中平台也能通过 journald 或者直接读取文件来采集。
三、系统层 Linux 审计 auditd 配置
系统层审计的主角是 auditd。安装和启动非常简单:
sudo yum -y install audit audit-libs
sudo systemctl enable --now auditd
几个常用命令需要熟悉:
sudo auditctl -l:查看当前规则sudo autrace -r /path/to/your/app:按进程跟踪sudo ausearch -i -p:检索特定进程的事件sudo aureport -l:生成登录报告- 日志路径:
/var/log/audit/audit.log
规则配置要按需精简,既要覆盖关键路径,又不能过度。下面是一个典型的规则示例,监控应用二进制执行、日志目录和数据目录:
sudo tee /etc/audit/rules.d/99-golang-audit.rules >/dev/null <<'EOF'
-a always,exit -F path=/usr/local/bin/myapp -F perm=x -k myapp_exec
-a always,exit -F dir=/var/log/myapp/ -F perm=rwa -k myapp_log
-a always,exit -F path=/etc/myapp/ -F perm=rwa -k myapp_conf
-w /var/lib/myapp/ -p wa -k myapp_data
EOF
sudo augenrules --load
sudo systemctl restart auditd
需要区分的是:auditd 聚焦系统调用和文件访问,适合安全合规审计;而 syslog / rsyslog / journald 更适合常规业务日志的收集和转发,两者互补。
四、日志收集传输与集中分析
根据团队规模和基础设施,有两种主流方案:
方案 A(轻量):journald + rsyslog + 文件。应用由 systemd 托管,日志写入 journald,然后通过 rsyslog 按服务名或路径采集到 /var/log/myapp/,再用 logrotate 切割归档。适合小规模或初期阶段。
方案 B(集中):Filebeat → Logstash → Elasticsearch → Kibana。Filebeat 采集 /var/log/myapp/ 和 /var/log/audit/audit.log,Logstash 解析 JSON 并提取关键字段,ES 索引存储,Kibana 构建审计仪表盘和告警。这是生产环境的标配。
下面是一个 Logstash 解析 JSON 应用日志的快速示例:
input {
file {
path => "/var/log/myapp/app.log"
start_position => "beginning"
sincedb_path => "/var/lib/logstash/sincedb_myapp"
codec => json
}
}
filter {
date {
match => [ "ts", "ISO8601" ]
target => "@timestamp"
}
}
output {
elasticsearch {
hosts => ["http://es:9200"]
index => "myapp-audit-%{+YYYY.MM.dd}"
}
}
检索和告警方面,在 Kibana 里建立索引模式 myapp-audit-*,然后按 user_id、action、ip、status、trace_id 构建可视化图表和阈值告警。比如登录失败超过5次,触发告警。
五、运行维护与合规要点
日志审计上线只是第一步,日常维护才是大头。这里列几个容易忽略的点:
- 日志轮转与保留:务必给应用日志和审计日志配置 logrotate,示例保留90天、压缩归档。否则日志文件膨胀会撑爆磁盘,导致审计数据丢失。
- 访问控制与完整性:关键日志文件权限建议设为 640,属主 root:adm,仅授权人员可读取。必要时启用 SELinux 或 AppArmor 限制访问。对含敏感信息的日志,考虑传输加密和落盘加密,并建立最小化保留与脱敏策略。
- 监控与告警:对 ERROR / 5xx、登录失败、权限变更、敏感文件访问等异常事件设定阈值告警。结合
journalctl -f、tail -f与集中平台,实现近实时处置。别等到问题爆发了才去翻日志,那叫“事后复盘”,不是审计。