■ 発生した事象
とあるお客様のAWS環境に AWS WAF を構築。
1ヶ月間 COUNTモード(遮断はせず検知のみを行うモード)にて動作させ、誤検知がないことを確認後にBLOCKモードにて本稼働することになった。
COUNTモードで動作開始させ、1ヶ月後にAWSコンソールより対象WebACLのTraffic Overview を確認し、BLOCKされているリクエストがないことを確認の上、BLOCKモードへ変更し本稼働を開始した。
本稼働後しばらくするとお客様より「アプリへの通信がBLOCKされているようだ」とのご連絡。
通信元・通信先のアプリログを確認したところ、やはり通信が届いていないとのことから調査開始した。
■ 調査
AWSコンソールより対象WebACLのTraffic Overview を確認するも、Blockedされている形跡はなく、全てAllowedとなっている。
ん?BLOCKはされていない?と思いながら、次にALBのメトリクスを確認すると、「ELB 4XXs」がBLOCKモード切り替え前よりも増えている。
「ELB 4XXs」とはなんぞや?「ターゲット 4XXs」ってのもある。
この機会に調べてみることに。
ドキュメントに記載がありました。
https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/load-balancer-cloudwatch-metrics.html
・ELB 4XXs とは
ロードバランサーから送信される HTTP 4XX クライアントエラーコードの数。この数には、ターゲットによって生成される応答コードは含まれません。
・ターゲット 4XXs とは
ターゲットによって生成された HTTP 応答コードの数。これには、ロードバランサーによって生成される応答コードは含まれません。
ELB 4XXs はクライアントからロードバランサーへの通信で何かあった場合に上昇するもの。
ターゲット 4XXs はロードバランサーからターゲット(バックエンドのインスタンス等)への通信で何かあった場合に上昇するもの。
と、認識した。
実際に何が起きているか、ALBログを確認してみる。
以下が、4XXエラーをピックアップしたALBログ。
(あくまでサンプルです。不要な列等は非表示としています。)
注目したのは『elb_status_code』と『target_status_code』。
elb_status_code に4XX系のエラーコードが入力されており、target_status_code には「-」が記載されている。
4XX系のエラーコードは大半が「460」と「408」だった。
コードの内容は以下のページに説明があった。
https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/load-balancer-troubleshooting.html#http-408-issues
・HTTP 408: Request timeout
アイドルタイムアウト期間の期限が切れる前に、クライアントからデータが送信されませんでした。TCP キープアライブを送信しても、このタイムアウトを防ぐことはできません。各アイドルタイムアウト期間が経過する前に、1 バイト以上のデータを送信します。必要に応じて、アイドルタイムアウト期間を長くします。
・HTTP 460
ロードバランサーはクライアントからリクエストを受信したが、クライアントはアイドルタイムアウトが経過する前に、ロードバランサーとの接続を閉じました。
クライアントのタイムアウト期間がロードバランサーのアイドルタイムアウト期間より長いかどうか確認してください。クライアントのタイムアウト期間が経過する前に、ターゲットがクライアントにレスポンスを返すことを確認するか、クライアントがサポートする場合は、クライアントのタイムアウト期間を増やしてロードバランサーのアイドルタイムアウトに合わせます。
「クライアントはアイドルタイムアウトが経過する前に、ロードバランサーとの接続を閉じました」とのこと。
どういった理由で閉じられてしまったのか?
また遮断されているのであれば、なぜWebACLのTraffic OverviewのBLOCK数がカウントアップしていないか?
これ以上の調査は難しく、AWSサポートへ問い合わせしてみた。
結論としては以下の回答を頂いた。
RFC 7230 に準拠していないリクエストが送信される場合、本事象とは異なる要因にて、ALB または WAF にて正常にリクエストが処理されない可能性がある。
リクエストが7230RFCに準拠していない場合は、ALBやWAFで正常にリクエストが処理されない可能性あるとのこと。
また、今回はALB側で処理されなかったので、WAF WebACL画面のTraffic OverviewにBLOCK数がカウントアップされていないことが判明しました。
しかも、WAFをつけることでALBにて7320RFC準拠がチェックされるようで、WAFをつけていないALBは7230RFC準拠されているかのチェックはされないという事でした。
今回、アプリケーション担当者へ確認すると古いアプリのためRFCに準拠していないとのことで、アプリ側でRFC準拠するように対応するということになりました。
■ 身につけた知識
- 遮断情報の確認はAWSコンソールの Traffic Overview のみではなく、ALBのメトリクスやログを確認し遮断されていないかを確認する
- 7230RFCに準拠していないリクエストが送信された場合、ALBやWAFは正常にリクエストを処理しない可能性がある* WAFをALBにつけることで、ALBにて7320RFCがチェックされる(WAFをALBから外すとALBでチェックされなくなる)