Grok Проблема с несколькими IP-адресами в NginX Logstash

Grok Проблема с несколькими IP-адресами в NginX Logstash

У меня возникла проблема с логированием с моих веб-серверов, на которых перед слоем nginx есть слой elb, а затем слой Varnish.

Varnish правильно настроен для X-Forwarded-For, и журналы проходят нормально с регистрацией правильного «client.ip».

Однако логи nginx поступают с целым списком IP-адресов в запросе. Похоже, что поведение grok по умолчанию устанавливает клиентский IP-адрес на последний в списке, т. е. серверы elb и Varnish, что портит мое поле client.ip для журналов nginx. Правильный клиентский 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 для обработки такого результата. Отладчик Grok Heroku, похоже, не работает для этого запроса, а мой Grok — но они работают в LogStash, т. е. не помечают ошибки Grok.

Я пытался отладить определенные части, но не нашел способа сделать то, что мне нужно, с IP/IPORHOST, где есть список IP-адресов, разделенных запятыми. Мне нужно иметь возможность указать, какой IP-адрес следует использовать. То есть первым в списке должен быть client.ip, а не последним.

Мой взгляд на 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}

есть идеи по поводу того, как охватить это бревно?

решение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

Для последней части решение Антона Рослова будет соответствовать только строкам журнала "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.

Связанный контент