等保/审计要求Log-Format必须包含客户端真实IP、请求时间、HTTP方法、完整URI(含query)、状态码、响应体大小、Referer、User-Agent、请求耗时、上游服务地址;需用$realip_remote_addr或$http_x_forwarded_for替代$remote_addr,用$request_time和$upstream_response_time区分耗时,用$request_uri保留query,禁用$bytes_sent,严格脱敏敏感参数并分离审计日志。

Log-Format 中必须包含哪些字段才能满足等保/审计要求
等保2.1和金融行业安全审计规范明确要求日志至少记录:客户端真实IP、请求时间、HTTP方法、完整URI(含query)、状态码、响应体大小、Referer、User-Agent、请求耗时、上游服务地址(若反代)。Nginx默认log_format缺省不包含真实IP(仅$remote_addr,易被伪造),也无耗时细分(如upstream响应时间)。
实操建议:
- 用
$http_x_forwarded_for或$realip_remote_addr(需启用ngx_http_realip_module)替代$remote_addr,并确认前端LB已透传XFF头 - 添加
$request_time(接受到首字节至发送完响应的总耗时)和$upstream_response_time(后端返回首字节耗时),二者差值可判断Nginx自身处理瓶颈 - URI必须用
$request_uri而非$uri,后者会丢弃query string,审计时无法追溯参数类攻击(如SQLi、路径遍历) - 强制记录
$status和$body_bytes_sent,禁止使用$bytes_sent(含响应头字节数,不符合“实际传输内容”定义)
如何防止日志中泄露敏感信息(如Token、密码、身份证号)
Nginx原生不支持正则脱敏,直接在log_format里写sub_filter无效。错误做法是让应用层过滤后再打日志——这会导致Nginx无法记录原始请求,失去审计溯源价值。
正确方案分两层:
- 前置清洗:用
map指令对$request_uri和$args做静态替换,例如抹掉token=、password=后所有内容:map $args $safe_args { ~^(.*)(token|password|id_card)=([^&]*)(.*)$ "$1$2=[REDACTED]$4"; default $args; }注意map不支持多级嵌套,复杂规则需拆成多个map块 - 避免记录:禁用
$request_body(需lua-resty-core或OpenResty),因Nginx默认不缓存请求体,开启client_body_buffer_size会显著增加内存开销且仍可能漏记二进制数据 - 权限控制:确保日志文件属主为
root:adm,权限设为640,防止Web进程越权读取
高并发下Log-Format配置引发的性能抖动怎么定位
当启用了$upstream_http_*(如$upstream_http_x_request_id)或$sent_http_*变量时,Nginx需在响应头收齐后才写日志,导致worker进程阻塞。现象是QPS突降、nginx -t正常但ab -n 10000 -c 1000测试时出现大量502/504。
排查与优化:
- 用
strace -p $(pgrep nginx) -e trace=write观察worker是否长时间卡在write()系统调用 - 将
$upstream_http_*变量全部替换为$upstream_addr(后端地址)和$upstream_status(后端状态码),二者在连接建立后即可获取,不依赖响应头 - 启用
buffer=16k和flush=5s参数:access_log /var/log/nginx/audit.log audit buffer=16k flush=5s;
避免每请求刷盘,但需接受最多5秒日志延迟 - 审计日志务必分离:不要复用
main格式,单独定义audit格式并写入独立文件,防止业务日志抖动污染审计流
Log-Format 时间戳字段为什么总是比系统时间慢8小时
这是时区未显式声明导致的典型问题。$time_local和$time_iso8601均依赖Nginx启动时读取的TZ环境变量,而非系统/etc/timezone。容器化部署时,基础镜像常设为UTC,但审计要求必须用本地时区(如CST)。
解决方式唯一且必须:
- 在启动Nginx前设置环境变量:
TZ=Asia/Shanghai(Docker用-e TZ=Asia/Shanghai,systemd用Environment="TZ=Asia/Shanghai") - 绝对不要用
set $tz "CST";这类伪变量,Nginx不解析时区字符串 - 验证方法:
nginx -s reload && date -d "$(tail -1 /var/log/nginx/audit.log | awk '{print $4" "$5}')" +'%z'输出应为+0800
审计日志的时间一致性是刚性要求,时区错位会导致SIEM平台无法关联分析,这个点一旦出错,后续所有日志治理都失去意义。











