2019年2月27日水曜日

GCE のファイアウォールのログからアクセス元の IP アドレスをカウントする

概要

GCE のファイアウォールはデフォルトでロギングがオフになっています
これをオンにすることでファイアウォールのアクセスログが Stackdriver に保存されます
今回は Stackdriver に保存されたログを API で取得しアクセス元の IP アドレスの数をカウントしてみました

環境

  • Ruby 2.5.1p57
    • google-cloud-logging 1.6.2

ファイアウォールのロギングをオンにする

GCE に適用されているファイアウォールのロギングをオンにしましょう

画像は default-allow-https ですが好きなファイアウォールのロギングをオンにしてください
ちなみに view を押すと Stackdriver に溜まったログをコンソールで確認できます

サービスアカウント作成

今回は Ruby のスクリプトから Stackdriver の API をコールします
すでにサービスアカウント+ API コール用の鍵があればそれを流用して OK です
新規で作成する場合はロールの設定の際に Stackdriver logging にアクセスできるロールを設定しましょう

コード

準備が揃ったらコーディングします
まずはライブラリをインストールしましょう

  • bundle init
  • vim Gemfile
gem "google-cloud-logging"
  • bundle install --path vendor

スクリプトです
全体は以下の通りです
あとで解説しています

require 'google/cloud/logging'

Google::Cloud.configure do |config|
  config.project_id = "project-123456"
  config.keyfile = "./project-123456.json"
end

logging = Google::Cloud::Logging.new
filter = {
  :filter => 'logName:(compute.googleapis.com%2Ffirewall) AND jsonPayload.rule_details.reference:("network:default/firewall:default-allow-https")'
}
entries = logging.entries filter

# puts entries.all.to_a.size
# entries.all.each { |e| puts e.payload.to_json }
ret = entries.all.each_with_object(Hash.new(0)) { |e, acc| acc[e.payload['connection']['src_ip']] += 1 }
puts ret

解説

まずは Google::Cloud.configure で初期化します
プロジェクト ID と作成したサービスアカウントの JSON 鍵ファイルのパスを設定しましょう

ポイントはログを取得する際の logging.entries filter になります
filter を指定することで対象のファイアウォールのログだけを取得しています
Stackdriver にはログを検索するためのクエリがあります
基本はブラウザや gcloud コマンドでフィルタするときと同じ内容でフィルタすることができます
今回であれば 'logName:(compute.googleapis.com%2Ffirewall) AND jsonPayload.rule_details.reference:("network:default/firewall:default-allow-https")' になります
条件は 2 つあり logName でログの名前を絞り込みかつ対象のファイアウォールを rule_details.reference で絞り込んでいます
後者のファイアウォール名を変更すれば別のファイアウォールのログを引っ張ってくることができます

取得したログのエントリは最新から 50 件ずつ取得されるようです
クエリを使えば古いログから取得することもできると思います
nextPageToken がありそれを使って次のログを取得するのですがライブラリを使えば all を呼び出すだけで OK です
エントリ (Google::Cloud::Logging::Entry) の基本的な構図はここが参考になると思います

each で回した際の payload オブジェクトは Google::Protobuf::Struct クラスのオブジェクトです
Stackdriver のログは JSON の文字列か Protocol Buffer になります
GCP 内からのロギングは自動的に Protocol Buffer に変換されて保存されるようです
payload オブジェクトを参照する場合はハッシュで値を取得すれば OK です
ハッシュの中身がわからない場合は to_json で一度中を見てもいいと思います
ちょっと特殊な JSON ですが参照する際は普通の JSON のように参照することができます

実行結果

  • bundle exec ruby app.rb

で実行しましょう
今回は IP のカウンタ結果のハッシュを表示しているだけです

最後に

GCE へのアクセス元 IP を Stackdriver に溜め API で集計してみました
Stackdriver にログを溜めるのと API をコールするのは有料操作ですが容量は 50GB まで API コールは 100 万回まで無料なので検証レベルであれば料金がかかることはないかなと思います
GCE へのアクセスが多い場合は溜まるログの量も大量になるのでその場合は容量に注意が必要です
ロギングする際にルールを決められるのである IP からのログはロギングしないなどの工夫が必要になるかもしれません

参考サイト

0 件のコメント:

コメントを投稿