在Nginx中直接用log_format输出合法JSON日志是最轻量可靠的高维反向代理日志方案,需双引号包裹字符串字段、数值不加引号、用$time_iso8601统一时间戳,并通过map安全提取$clientRealIp,再由Filebeat JSON解析采集。

直接在 Nginx 的 log_format 中拼出合法 JSON,并嵌入真实请求上下文字段,是构建高维反向代理日志最轻量、最可靠的方式。它把结构化工作压到日志源头,避免 Logstash 后期用 grok 硬解析带来的性能损耗和字段错位风险。
定义语义清晰的 JSON 日志格式
在 /etc/nginx/nginx.conf 的 http 块内声明:
- 所有字段名必须用双引号包裹,字符串值(如
"$status")也加双引号;数值型变量(如$request_time、$body_bytes_sent)不加引号,防止 Elasticsearch 将其识别为 text 类型 - 时间戳统一用
$time_iso8601,Elasticsearch 可自动映射为date类型,无需额外 date filter - 关键字段建议包含:
@timestamp(标准化时间)、clientip(真实客户端 IP)、upstream_addr(后端服务地址)、upstream_response_time(上游耗时)、proxy_host(反向代理目标)、xff(原始 X-Forwarded-For 全值)
示例:
log_format json_proxy '{"@timestamp":"$time_iso8601",'
'"clientip":"$clientRealIp",'
'"xff":"$http_x_forwarded_for",'
'"proxy_host":"$host",'
'"request_uri":"$request_uri",'
'"method":"$request_method",'
'"status":$status,'
'"bytes_sent":$body_bytes_sent,'
'"request_time":$request_time,'
'"upstream_addr":"$upstream_addr",'
'"upstream_response_time":$upstream_response_time,'
'"upstream_status":$upstream_status,'
'"agent":"$http_user_agent"}';
准确提取真实客户端 IP
反向代理场景下,$remote_addr 是上一跳(如 LB 或 CDN)IP,不是用户真实 IP。需通过 X-Forwarded-For 提取首地址,并做兜底处理:
- 在
http块顶部添加map指令,安全提取第一个非空 IP - 若
X-Forwarded-For为空,则回退到$remote_addr - 该变量后续用于
clientip字段,确保 Kibana 中地理分布、访问频次等分析准确
配置示例:
map $http_x_forwarded_for $clientRealIp {
"" $remote_addr;
~^(?P<firstaddr>[0-9\.]+),?.*$ $firstAddr;
}
</firstaddr>
绑定日志输出并适配 Filebeat
在 server 或 location 块中启用该格式,路径建议独立命名,便于 Filebeat 单独采集:
- 使用
access_log /var/log/nginx/proxy.json json_proxy;,避免与默认 access.log 混合 - 确保日志文件权限可读(如
nginx:nginx 644),Filebeat 能稳定抓取 - Filebeat 配置开启 JSON 解析,关键参数:
json.keys_under_root: true(提升字段至根层级)、json.overwrite_keys: true(防同名覆盖)、json.add_error_key: true(自动标记解析失败事件)
增强维度:补充上游与协议元数据
反向代理日志的价值在于串联请求链路。除基础字段外,可加入以下高维信息:
-
ssl_protocol和ssl_cipher:用于 TLS 版本合规性审计、加密强度分析 -
$scheme与$server_port:区分 HTTP/HTTPS 流量走向 -
$request_length:请求体大小,辅助识别异常上传或重放攻击 -
$sent_http_content_type:响应类型分布,快速定位 API 返回格式异常
这些字段不增加解析负担,却显著提升在 Kibana 中下钻分析、告警策略和安全研判的能力。










