NLB と ALB のアクセスログは違うんやで、という話

93件のシェア(ちょっぴり話題の記事)

NLB が TLS Termination 対応と同時にアクセスログ出力が可能になったのは記憶にあたらしいかと思います。

このアップデートで、単純に「NLB でもアクセスログが取得できるようになった」と理解していたのですが、取得できる内容はずいぶん違うんやで、ということをきちんと理解しておりませんでした。 というのが、今日の本題になります。

静的なIPアドレスを持つNLBがTLS Terminationに対応してアクセスログも出力可能に!

NLB アクセスログ

はじめに、大前提になりますが NLB のアクセスログが取得できるのは、リスナーが TLS の場合のみです。リスナーが TCP の場合は、アクセスログを設定していも出力されません。案外、見落としがちなポイントなのでアクセスログ設定して安心している方はご注意を。

それでは、まず NLB のアクセスログを見てみましょう。(以下、公式ガイドからサンプルを拝借)

tls 1.0 2018-12-20T02:59:40 net/my-network-loadbalancer/c6e77e28c25b2234 
g3d4b5e8bb8464cd 72.21.218.154:51341 172.100.100.185:443 5 2 98 246 - 
arn:aws:acm:us-east-2:671290407336:certificate/2a108f19-aded-46b0-8493-c63eb1ef4a99 - 
ECDHE-RSA-AES128-SHA tlsv12 - 
my-network-loadbalancer-c6e77e28c25b2234.elb.us-east-2.amazonaws.com

NLB アクセスログのフィールドは下記のとおりです。

フィールド 説明 サンプルログの値
type リスナーの種類 tls
version ログエントリのバージョン 1.0
timestamp TLS 接続の最後に記録されたタイムスタンプ 2018-12-20T02:59:40
elb ロードバランサーのリソース ID net/my-network-loadbalancer/c6e77e28c25b2234
listener TLS リスナーのリソース ID g3d4b5e8bb8464cd
client:port クライアントの IP アドレスとポート 72.21.218.154:51341
listener:port リスナーの IP アドレスとポート 172.100.100.185:443
connection_time 接続が完了するまでの合計時間(ms) 5
tls_handshake_time TLS ハンドシェイクが完了するまでの合計時間(ms) 2
received_bytes ロードバランサーで受信したバイト数 (復号後) 98
sent_bytes クライアントに送信されたバイト数 (復号前) 246
incoming_tls_alert ロードバランサーによって受信された TLS アラートの整数値。存在しない場合 - に設定 -
chosen_cert_arn クライアントに提供された証明書の ARN arn:aws:acm:us-east-2:671290407336:certificate/2a108f19-aded-46b0-8493-c63eb1ef4a99
chosen_cert_serial 将来のために予約されています。常に - に設定 -
tls_cipher クライアントとネゴシエートされた暗号スイート ECDHE-RSA-AES128-SHA
tls_protocol_version クライアントとネゴシエートされた TLS プロトコル tlsv12
tls_named_group 将来のために予約されています。常に - に設定 -
domain_name クライアント hello メッセージの server_name 拡張機能の値 my-network-loadbalancer-c6e77e28c25b2234.elb.us-east-2.amazonaws.com

ざっと見ておわかりいただけるかと思いますが、ALB のような HTTP リクエストや user_agent といったフィールドは NLB のアクセスログでは取得できません。 ALB が L7 のコンテントベースのロードバランサであるのに対し、NLB は L4 機能を提供するロードバランサあることを思い出せば、「そりゃそうだ」と納得がいきますね。

ALB アクセスログとの比較

それでは、次に ALB の HTTPS リスナーのログエントリを見てみましょう。(以下、公式ガイドからサンプルを拝借)

https 2018-07-02T22:23:00.186641Z app/my-loadbalancer/50dc6c495c0c9188 
192.168.131.39:2817 10.0.0.1:80 0.086 0.048 0.037 200 200 0 57 
"GET https://www.example.com:443/ HTTP/1.1" "curl/7.46.0" ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 
arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/my-targets/73e2d6bc24d8a067
"Root=1-58337281-1d84f3d73c47ec4e58577259" "www.example.com" "arn:aws:acm:us-east-2:123456789012:certificate/12345678-1234-1234-1234-123456789012"
1 2018-07-02T22:22:48.364000Z "authenticate,forward" "-" "-"

ALB アクセスログのフィールドと比較表は下記のとおりです。

ALBのフィールド 説明 NLB のフィールド有無
type リクエストまたは接続のタイプ
timestamp クライアントに対してレスポンスを生成した時刻
elb ロードバランサーのリソース ID
client:port リクエストを送信したクライアントの IP アドレスとポート
target:port このリクエストを処理したターゲットの IP アドレスとポート
request_processing_time リクエストを受け取った時点からターゲットに送信するまでの合計経過時間(ms)
target_processing_time ターゲットにリクエストを送信した時点から、そのターゲットが応答ヘッダーの送信を開始した時点までの合計経過時間(ms)
response_processing_time ターゲットから応答ヘッダーを受け取った時点から、クライアントへの応答の送信を開始した時点までの合計経過時間(ms)
elb_status_code ロードバランサーからの応答のステータスコード
target_status_code ターゲットから応答のステータスコード
received_bytes クライアント (リクエスタ) から受け取ったリクエストのサイズ
sent_bytes クライアント (リクエスタ) に返される応答のサイズ
"request" HTTP メソッド + プロトコル://ホスト:ポート/uri + HTTP バージョン
"user_agent" リクエスト元のクライアントを特定する User-Agent
ssl_cipher [HTTPS リスナー] SSL 暗号
(tls_cipher)
ssl_protocol [HTTPS リスナー] SSL プロトコル
(tls_protocol_version)
target_group_arn ターゲットグループの ARN
"trace_id" X-Amzn-Trace-Id ヘッダーのコンテンツ
"domain_name" [HTTPS リスナー] TLS ハンドシェイク中にクライアントから提供される SNI ドメイン
"chosen_cert_arn" [HTTPS リスナー] クライアントに提示される証明書の ARN
matched_rule_priority リクエストに一致したルールの優先度の値
request_creation_time ロードバランサーがクライアントからリクエストを受け取った時刻
"actions_executed" リクエストの処理時に実行されるアクション
"redirect_url" HTTP レスポンスのロケーションヘッダーのリダイレクトターゲットの URL
"error_reason" reason コード

反対に NLB アクセスログのみのフィールドは下記になります。

  • listener:port
  • connection_time
  • tls_handshake_time
  • incoming_tls_alert
  • chosen_cert_serial
  • tls_named_group

ALB ではリクエストを処理したターゲット IP が記録されますが、NLB ではリスナー IP しか記録されません。リスナー IP は、NLB に割り当てられる ENI のプライベート IP アドレスになります。つまり、NLB のアクセスログだけでは最終的にどのノードにリクエストが流れたかを判断できないことになります。

結論

以上のように、NLB と ALB ではアクセスログの内容が異なりますので、従来の ALB アクセスログと同じ内容を期待して設定されている場合は、お気をつけください。

NLB 配下で HTTP リクエストを含めたアクセスログは、Web サーバ上のアクセスログで取得するようにしましょう。また、アクセスログを最終的に S3 で保管したい場合は、Cloudwatch Logs や、Fluentd をあわせて検討されるのが良いかと思います。

さいごに

「NLB のアクセスログ対応」ときいて、すっかり ALB のアクセスログをイメージしておりましたが、よくよく考えると L4、L7 で機能が違うわけですから、その内容も異なって当然ですね。「ELB アクセスログ」という一括りで考えてしまうと、うっかり見落としてしまうポイントかと思いますので、みなさまもお気をつけください!

以上!ひっそり新しい写真に更新した丸毛(@marumo1981)でした!