NginX Logstash での複数の IP に関する Grok の問題

NginX Logstash での複数の IP に関する Grok の問題

私の Web サーバーからのログ記録に問題があります。このサーバーには、Nginx レイヤーの前に ELB レイヤーがあり、その後に Varnish レイヤーがあります。

varnish は X-Forwarded-For に対して適切に設定されており、正しい「client.ip」が記録された状態でログが正常に送信されます。

ただし、nginx ログには、リクエスト内の IP のリスト全体が出力されます。デフォルトの grok 動作では、クライアント IP がリストの最後に設定されているようです (つまり、elb サーバーと varnish サーバー)。これにより、nginx ログの client.ip フィールドが台無しになります。正しいクライアント 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 では機能しています (つまり、grok の失敗がタグ付けされていません)。

特定の部分をデバッグしようとしましたが、IP アドレスのコンマ区切りリストがある IP/IPORHOST で必要なことを実行する方法が見つかりませんでした。使用する IP を指定できるようにする必要があります。つまり、リストの最初が client.ip であり、最後ではない必要があります。

私の nginx grok は次のとおりです:

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}

そのログをカバーするための grok に関するアイデアはありますか?

答え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ログ形式から取得されます。2
番目の("xff_clientip" => 1.144.97.102)は、ただそのリストの最初の IP は、リクエストの実際の送信元 IP に変換されるはずです。

私なら、x_forwarded_forフィールドをフィルターにかけてmutate配列に分割します。

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

答え2

最後の部分については、Anton Roslov の解決策では、「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 でテスト済みです。

関連情報