Проблема с несколькими IP-адресами в NginX Logstash
У меня проблема с регистрацией на моих веб-серверах, у которых есть слой elb, а затем слой лака перед слоем nginx.
Лак настроен правильно для 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 для обработки такого результата, отладчик heroku grok, похоже, не работает для этого запроса и для моего grok - но они работают в logstash, т.е. не помечает сбой Грока.
Я попытался отладить определенные части, но я не нашел способа сделать то, что мне нужно, с 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"';
указанный вами шаблон Грока не учитывает добавление "$host" "$http_x_forwarded_for"
часть.
Не уверен, почему ваш грок не терпит неудачу, но он должен.
В любом случае этот шаблон будет работать с форматом журнала выше:
%{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" => ", " }
}
В последней части решение Антона Рослова будет соответствовать только строкам журнала "ip1, ip2" и "single-ip", но не "ip1, ip2, ip3".
ИМХО что-то вроде
(?%{IP:clientip}(?:, [^,]+)*)
должен сделать свое дело. Просто проверка...
... \ "(?:%{DATA:user_agent}|-) \" \ "(?%{IP:clientip}(?:, [^,]+)*)? | - \"
или же
... \ "(?:%{DATA:user_agent}|-) \" \ "(-| (?%{IP:clientip}(?:, [^,]+)*)?) \ "
должен быть вашим выбором. Проверено на grokdebug.herokuapp.com.