NginX Logstash 中存在多个 IP 的 Grok 问题

NginX Logstash 中存在多个 IP 的 Grok 问题

我在从我的网络服务器进行日志记录时遇到问题,该网络服务器有一个 elb,然后在 nginx 层前面有一个 varnish 层。

varnish 已正确设置 X-Forwarded-For,并且日志可以正常传输,并记录正确的“client.ip”。

但是,nginx 日志会包含请求中的一整套 IP 列表。默认的 grok 行为似乎将客户端 IP 设置为列表中的最后一个,即 elb 和 varnish 服务器,这会弄乱我的 nginx 日志的 client.ip 字段。正确的客户端 IP 应该是列表中的第一个(或至少是前几个)。

以下是一个例子:

172.31.7.219 - - [28/Sep/2015:12:39:56 +1000] "GET /api/filter/14928/content?api_key=apikey&site=website HTTP/1.1" 403 101 "-" "-" "my.website.com" "1.144.97.102, 1.144.97.102, 1.144.97.102, 127.0.0.1, 172.31.26.59"

问题是我无法调整 grok 来处理这样的结果,heroku grok 调试器似乎不适用于这个查询和我的 grok - 但它们在 logstash 中工作,即没有标记 grok 失败。

我试图调试特定的部分,但我还没有找到使用 IP/IPORHOST 来执行我需要的操作的方法,其中有一个以逗号分隔的 IP 地址列表。我需要能够指定它应该使用哪个 IP。即列表中的第一个应该是客户端 ip,而不是最后一个。

我的 nginx grok 是:

NGINXACCESS %{IP:clientip} %{NGUSER:ident} %{NGUSER:auth} \[%{HTTPDATE:timestamp}\] "%{WORD:verb} %{DATA:request} HTTP/%{NUMBER:httpversion}" %{NUMBER:response} (?:%{NUMBER:bytes}|-) (?:"(?:%{URI:referrer}|-)"|%{QS:referrer})(?:;|) %{QS:agent}

有没有关于 grok 的想法来覆盖该日志?

答案1

不确定您是否仍遇到此问题,但如果是的话,以下是适合您的方法。

鉴于此日志格式:

log_format custom '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$host" "$http_x_forwarded_for"';

您指定的 grok 模式没有考虑到 "$host" "$http_x_forwarded_for"部分的添加。

不确定为什么你的 grok 没有失败,但它应该失败。

无论如何,此模式将与上面的日志格式一起使用:

%{IP:clientip} %{NOTSPACE:ident} %{NOTSPACE:auth} \[%{HTTPDATE:timestamp}\] "%{WORD:verb} %{DATA:request} HTTP/%{NUMBER:httpversion}" %{NUMBER:response} (?:%{NUMBER:bytes}|-) (?:"(?:%{URI:referrer}|-)"|%{QS:referrer})(?:;|) %{QS:agent} "%{NOTSPACE:host}" "(?<x_forwarded_for>%{IP:xff_clientip}, .*)"

并在以下字段中产生结果

httpversion      1.1
request          /api/filter/14928/content?api_key=apikey&site=website
timestamp        28/Sep/2015:12:39:56·+1000
auth             -
host             my.website.com
agent            "-"
x_forwarded_for    1.144.97.102,·1.144.97.102,·1.144.97.102,·127.0.0.1,·172.31.26.59
clientip         172.31.7.219
bytes            101
response         403
xff_clientip     1.144.97.102
ident            -
port    
verb             GET
referrer    

请注意,您获得了一些与以前不同的新字段。

第一个(“x_forward_for” => 1.144.97.102, 1.144.97.102, 1.144.97.102, 127.0.0.1, 172.31.26.59)是最后一组引号的内容,或者$http_x_forwarded_for来自日志格式。
第二个(“xff_clientip” => 1.144.97.102)是只是该列表中的第一个 IP,应转换为请求的实际源 IP。

如果是我的话,我还会x_forwarded_for通过过滤mutate器将该字段分解为一个数组:

mutate {
  split  => { "x_forwarded_for" => ", " }
}

答案2

对于最后一部分,Anton Roslov 的解决方案只会匹配“ip1、ip2”和“single-ip”日志行,而不会匹配“ip1、ip2、ip3”。
在我看来,

(?<x_forwarded_for>%{IP:clientip}(?:,[^,]+)*)

应该可以解决问题。只是检查一下...

... \"(?:%{DATA:user_agent} | -)\" \"(?<x_forwarded_for>%{IP:clientip}(?:,[^,]+)*)?| - \"

或者

... \"(?:%{DATA:user_agent} | -)\" \"(-|(?<x_forwarded_for>%{IP:clientip}(?:,[^,]+)*)?)\"

应该是您选择的模式。已在 grokdebug.herokuapp.com 中测试。

相关内容