Problema Grok com vários IPs no NginX Logstash

Problema Grok com vários IPs no NginX Logstash

tenho um problema com o log de meus servidores da web, que tem um elb e uma camada de verniz na frente da camada nginx.

O verniz está configurado corretamente para X-Forwarded-For e os logs chegam normalmente com o 'client.ip' correto sendo registrado.

no entanto, os logs do nginx estão chegando com uma lista completa de IPs na solicitação. o comportamento padrão do grok parece definir o IP do cliente para o último da lista, ou seja. os servidores elb e verniz, o que atrapalha meu campo client.ip para logs nginx. o IP do cliente correto deve ser o primeiro (ou pelo menos os primeiros) da lista.

aqui está um exemplo:

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"

O problema é que não consegui ajustar o grok para lidar com tal resultado, o depurador heroku grok parece não funcionar para esta consulta e meu grok - mas eles estão trabalhando no logstash, ou seja. não marcando falha grok.

Tentei depurar as partes específicas, mas não encontrei uma maneira de fazer o que preciso com IP/IPORHOST, onde há uma lista de endereços IP separados por vírgula. eu preciso ser capaz de especificar qual IP ele deve usar. ou seja. o primeiro da lista deve ser client.ip e não o último.

meu grok nginx é:

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}

alguma idéia sobre grok para cobrir esse registro?

Responder1

Não tenho certeza se você ainda está tendo esse problema, mas se sim, aqui está o que funcionará para você.

Dado este formato de log:

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

o padrão grok que você especificou não leva em consideração a adição da "$host" "$http_x_forwarded_for"porção.

Não sei por que seu grok não está falhando, mas deveria.

De qualquer forma, este padrão funcionará com o formato de log acima:

%{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}, .*)"

E resulta nos seguintes campos

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    

Observe que você tem alguns campos novos do que teria antes.

O primeiro ("x_forward_for" => 1.144.97.102, 1.144.97.102, 1.144.97.102, 127.0.0.1, 172.31.26.59) é o conteúdo do último conjunto de cotações ou $http_x_forwarded_fordo formato de log.
O segundo ("xff_clientip" => 1.144.97.102) éapenaso primeiro IP dessa lista, que deve ser traduzido no IP de origem real da solicitação.

Se fosse eu, também passaria o x_forwarded_forcampo por um mutatefiltro para dividi-lo em um array:

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

Responder2

Para a última parte, a solução de Anton Roslov corresponderia apenas às linhas de log "ip1, ip2" e "single-ip", mas não a "ip1, ip2, ip3".
IMHO algo como

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

deve fazer o truque. Apenas checando...

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

ou

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

deve ser o seu padrão de escolha. Testado em grokdebug.herokuapp.com.

informação relacionada