Grok-Problem mit mehreren IPs in NginX Logstash

Grok-Problem mit mehreren IPs in NginX Logstash

ich habe ein Problem mit der Protokollierung von meinen Webservern, die eine ELB- und dann eine Varnish-Schicht vor der Nginx-Schicht haben.

Varnish ist ordnungsgemäß für X-Forwarded-For eingerichtet und die Protokolle werden normal mit der korrekten „client.ip“ protokolliert.

Es werden jedoch Nginx-Protokolle mit einer ganzen Liste von IPs in der Anforderung gesendet. Das Standardverhalten von Grok scheint die Client-IP an die letzte Stelle der Liste zu setzen, d. h. an die Elb- und Varnish-Server, was mein Client.ip-Feld für Nginx-Protokolle durcheinanderbringt. Die richtige Client-IP sollte die erste (oder zumindest die ersten paar) in der Liste sein.

hier ist ein Beispiel:

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"

das Problem besteht darin, dass ich Grok nicht so anpassen konnte, dass es mit einem solchen Ergebnis umgehen kann. Der Heroku-Gok-Debugger scheint für diese Abfrage und mein Grok nicht zu funktionieren – aber in Logstash funktionieren sie, d. h. Grok-Fehler werden nicht markiert.

ich habe versucht, die spezifischen Teile zu debuggen, habe aber keine Möglichkeit gefunden, das zu tun, was ich mit IP/IPORHOST brauche, wo es eine durch Kommas getrennte Liste von IP-Adressen gibt. Ich muss angeben können, welche IP verwendet werden soll. Das heißt, die erste in der Liste sollte die Client-IP sein, nicht die letzte.

mein Nginx-Grok ist:

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}

irgendwelche Ideen, wie man dieses Protokoll mit Grok abdecken kann?

Antwort1

Ich bin nicht sicher, ob dieses Problem immer noch besteht. Wenn ja, erfahren Sie hier, was für Sie funktionieren könnte.

Bei diesem Protokollformat gilt Folgendes:

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

Das von Ihnen angegebene Grok-Muster berücksichtigt die Hinzufügung der "$host" "$http_x_forwarded_for"Portion nicht.

Ich bin nicht sicher, warum Ihr Grok nicht fehlschlägt, aber es sollte.

Dieses Muster funktioniert in jedem Fall mit dem obigen Protokollformat:

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

Und Ergebnisse in den folgenden Bereichen

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    

Beachten Sie, dass Ihnen im Vergleich zu vorher einige neue Felder zur Verfügung stehen.

Der erste ("x_forward_for" => 1.144.97.102, 1.144.97.102, 1.144.97.102, 127.0.0.1, 172.31.26.59) ist der Inhalt des letzten Satzes von Anführungszeichen oder $http_x_forwarded_foraus dem Protokollformat.
Der zweite ("xff_clientip" => 1.144.97.102) istNurdie erste IP in dieser Liste, die der tatsächlichen Quell-IP der Anfrage entsprechen sollte.

Wenn es nach mir ginge, würde ich das x_forwarded_forFeld auch durch einen mutateFilter laufen lassen, um es in ein Array aufzuteilen:

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

Antwort2

Für den letzten Teil würde die Lösung von Anton Roslov nur die Protokollzeilen "ip1, ip2" und "single-ip" abgleichen, nicht aber "ip1, ip2, ip3".
IMHO so etwas wie

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

sollte funktionieren. Nur zur Kontrolle ...

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

oder

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

sollte das Muster Ihrer Wahl sein. Getestet in grokdebug.herokuapp.com.

verwandte Informationen