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_for
do 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_for
campo por um mutate
filtro 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.