こんにちは!クラウドやコンテナのネットワークと日々向き合っているSREエンジニアです。
AWSでWebサービスを運用していると、避けては通れないのがロードバランサー(ALB: Application Load Balancer)のアクセスログ調査ですよね。「なんだか最近サイトが重い気がする」「時々アクセスに失敗するユーザーがいる」といった相談を受けてログを開いたとき、見慣れない数字にギョッとした経験はありませんか?
HTTPステータスコードといえば、200 OK(成功)や 404 Not Found(ページが見つからない)、あるいは 500 Internal Server Error(サーバー側でエラー発生)といったあたりがおなじみです。
しかし、ログを眺めていると、たまに 460 や 463 という、一般的なWebの教科書には載っていない謎の3桁の数字が出現することがあります。「えっ、400番台なのに460?RFCの標準仕様にあったっけ……?」と戸惑ってしまう初学者の方も多いはずです。
実はこれら、AWSのALBが独自に定義している特殊なエラーコードなのです。
今回は、インフラやネットワークにこれから詳しくなりたいエンジニアの皆さんに向けて、この 460 と 463 の正体を、身の回りの例え話を交えながら一歩ずつ丁寧に紐解いていきますね!
—
そもそもALBはお店でいう「受付コンシェルジュ」
本題に入る前に、ALBの立ち位置を簡単におさらいしておきましょう。
[ ユーザー (スマホ/PC) ]
│ (注文)
▼
[ ALB (受付コンシェルジュ) ]
│ (厨房へパス)
▼
[ バックエンド (Webサーバー/コンテナ) ]
私たちが運営するWebサイトを「レストラン」に例えてみます。
- お客さん(スマホやPCなどのクライアント)がやってきます。
- お店の入り口には ALBという優秀な受付コンシェルジュ が立っています。
- コンシェルジュはお客さんの注文(リクエスト)を受け取り、奥の厨房にある複数の調理場(WebサーバーやECSなどのコンテナ)へ均等に振り分けます。
通常の 400 番台は「お客さんの注文方法が間違っているよ」、500 番台は「厨房でフライパンが燃えて料理が出せないよ」という合図です。
では、ALBコンシェルジュが返す 460 や 463 は、一体どんな状況なのでしょうか?
—
460エラーの正体:「待ちきれずに帰っちゃったお客さん」
まずは 460 エラーから見ていきましょう。
現実世界で例えると?
あなたがファミレスでお腹を空かせて、店員さん(ALB)に「カレーライスひとつ!」と注文したとします。
店員さんは「かしこまりました!」と厨房へ伝票を回しました。
しかし、厨房が激混みで10分待っても、20分待っても料理が出てきません。
しびれを切らしたあなたは、「もういい!別の店に行く!」と怒って席を立ち、お店を出て行ってしまいました。
その直後、厨房から「お待たせしました、カレーできましたよ!」と料理が届きます。困り果てた店員さんは、誰もいないテーブルを見てこう呟きます。
「えっ……料理を運ぼうとしたのに、お客さんもう帰っちゃったの……?」
これが、まさに 460 エラーの正体 です!
ネットワークの世界で起きていること
ITの言葉で整理すると、次のような現象が起きています。
1. クライアント(ブラウザやアプリ)がALBにHTTPリクエストを送る。
2. ALBはそのリクエストを裏側のターゲット(EC2やFargateなど)に転送する。
3. ターゲットがデータベースの処理などで時間を食い、なかなかレスポンスを返さない。
4. ターゲットが返事をする前に、クライアント側が待ち時間の上限(タイムアウト)に達し、TCP接続を切断(RST や FIN パケットを送信)してしまう。
5. ALBは行き場を失った通信を検知し、「クライアントが途中で接続を切っちゃいました」という記録として 460 を残す。
※このとき、すでにお客さん(クライアント)は接続を切って帰ってしまっているため、実際に画面に「460」という数字が表示されるわけではありません。ALBのアクセスログの中にだけ、ひっそりと記録されます。
原因と対策
460 の根本原因は、ほとんどの場合 「バックエンド(厨房)の処理が遅すぎること」 です。
- チェックポイント1:クライアントのタイムアウト設定
モバイルアプリなどのHTTPクライアント側で、タイムアウトが極端に短く設定されていませんか?(例:3秒など)
- チェックポイント2:バックエンドのレスポンス速度
データベースの重いクエリや、外部APIの呼び出しで時間がかかっていませんか?
対策:ALBとバックエンドのタイムアウト設計を見直そう
ALBには「アイドルタイムアウト(デフォルトは60秒)」という設定があります。システムを設計する際は、タイムアウト値の力関係を意識することが大切です。
【理想的なタイムアウト時間の力関係】
クライアントのタイムアウト時間 > ALBのタイムアウト時間 > バックエンドのタイムアウト時間
もし「バックエンドは正常に処理を終えるのに460が出る」という場合は、クライアント側で待てる時間を少し伸ばしてあげるか、そもそもバックエンドの処理速度を改善(キャッシュの導入やDBのインデックス最適化など)してあげましょう。
—
463エラーの正体:「転送シールでギチギチになった封筒」
続いては、さらに珍しい 463 エラーです。
公式ドキュメントには「X-Forwarded-For リクエストヘッダーで受信したIPアドレスが30個を超えています」と書かれています。これだけ聞くと難しそうですよね。
現実世界で例えると?
今度は 郵便配達 に例えてみましょう。
あなたが誰かに手紙(HTTPリクエスト)を送ります。手紙の封筒の裏には、どこを経由してきたかを証明する「経由スタンプ(X-Forwarded-For ヘッダー)」が押されるルールになっています。
[ あなた ]
↓(スタンプポン!)
[ 郵便局A ]
↓(スタンプポン!)
[ 郵便局B ]
↓(スタンプポン!)
[ 配達所C ] …
普通なら、途中で経由する郵便局は数箇所程度なので、スタンプも2〜3個で済みますよね。
ところが、悪意のあるイタズラか、何かのトラブルによって、経由スタンプが30個以上もベタベタと貼り付けられ、封筒の余白が完全に埋め尽くされてしまった手紙 がALBの元に届きました。
ALBは手紙を見て頭を抱えます。
「うわっ、スタンプが30個を超えていてルール違反です!これ以上はどこから届いたのか確認しきれないので、受け取り拒否(受取拒絶)します!」
これが 463 エラーの正体 です。
ネットワークの世界で起きていること
Webの世界では、プロキシサーバーやCDN(CloudflareやCloudFrontなど)を経由するたびに、送信元のIPアドレスが X-Forwarded-For というヘッダーの後ろにカンマ区切りで追記されていきます。
X-Forwarded-For: 203.0.113.195, 70.41.3.18, 150.172.238.178
AWSのALBには、「X-Forwarded-For に含まれるIPアドレスの数が30個を超えていたら、リクエストを拒否して 463 を返す」 という安全上のハードリミット(仕様)があります。
なぜそんなことが起きるの?
通常のアクセスで、中継地点(プロキシ)を30回もバトンタッチして届く通信なんて、まずあり得ません。
そのため、463 が発生するケースのほとんどは以下の2点です。
1. 攻撃者による不正なリクエスト
セキュリティの仕組みをすり抜けようとして、攻撃者が意図的に超大量の偽IPアドレスをヘッダーに詰め込んでいる。
2. ネットワーク機器のルーティングループ(無限ループ)
社内ネットワークなどの設定不備で、プロキシサーバー同士が「あなたにお願い」「いや、あなたにお願い」とリクエストをお手玉し合ってしまい、経由地が雪だるま式に増えてしまった。
対策:ログをチェックして怪しいアクセスを遮断する
463 を見かけたら、まずはALBのアクセスログを確認し、どんなIPアドレスが詰め込まれているかを確認しましょう。
もし特定の攻撃元からのアクセスであれば、AWS WAF を使ってその通信をALBの手前で弾く(ブロックする)設定を入れるのが一番安全なアプローチになります。
—
現場で役立つ!Amazon Athenaを使ったエラー調査術
「理屈は分かったけれど、実際にうちのシステムで 460 や 463 が出ているか調べるにはどうしたらいいの?」と思いますよね。
ALBのアクセスログをS3に保存している場合、Amazon Athena を使うとSQL感覚で超簡単にログを検索できます。調査の第一歩として使えるクエリサンプルを用意しました!
1. 直近で 460 エラーを起こした通信を調べるクエリ
どのURLに対して、クライアントが待ちきれずに切断してしまったのかを特定します。
-- 460エラーを起こしたリクエストを新しい順に100件抽出
SELECT
time,
client_ip,
target_ip,
request_processing_time, -- ALBがリクエストを受け取るのにかかった時間
target_processing_time, -- バックエンドが処理にかかっていた時間(ここが長いはず!)
response_processing_time,
elb_status_code, -- ALBが返したコード (460)
target_status_code, -- バックエンドの返答コード (切断されたので '-' になることが多い)
request_url
FROM
alb_logs_table -- ※ご自身のAthenaテーブル名を指定してください
WHERE
elb_status_code = '460'
AND parse_datetime(time, 'yyyy-MM-dd''T''HH:mm:ss.SSSSSS''Z''') >= current_timestamp - interval '1' day
ORDER BY
time DESC
LIMIT 100;
target_processing_time(ターゲット処理時間)が異様に長くなっているURLが見つかれば、そこが「激重ボトルネック」になっている証拠です。
2. 463 エラーを出している怪しい通信を調べるクエリ
異常に長いヘッダーを送りつけてきている犯人(IPアドレス)を探し出します。
-- 463エラーを出しているクライアントIPとリクエスト内容を集計
SELECT
client_ip,
request_verb, -- GET, POST などのメソッド
request_url,
user_agent, -- どんなブラウザ・ツールから送られているか
COUNT(*) AS error_count
FROM
alb_logs_table
WHERE
elb_status_code = '463'
AND parse_datetime(time, 'yyyy-MM-dd''T''HH:mm:ss.SSSSSS''Z''') >= current_timestamp - interval '7' day
GROUP BY
client_ip, request_verb, request_url, user_agent
ORDER BY
error_count DESC;
特定のIPアドレスから大量に届いているなら、WAFのIP制限リストに追加するなどの即時対応が打てますね。
—
まとめ:謎のエラーも「誰が困っているか」を考えれば怖くない!
最後に、今回学んだ 460 と 463 のポイントをギュッと整理しておきましょう。
460エラー- 状況: お客さんが「もう待てない!」と途中で帰ってしまった状態。
- 本質: クライアント側のタイムアウトに対し、バックエンドの処理が追いついていない。
- アクション: バックエンドの性能チューニングや、タイムアウト設計の見直しを行おう!
463エラー- 状況: 経由スタンプ(
X-Forwarded-For)が30個を超えて、封筒がパンクした状態。 - 本質: 攻撃者による不正リクエスト、または社内プロキシの無限ループ事故。
- アクション: Athenaでログを調査し、WAFでの遮断や社内ネットワークの経路を見直そう!
ネットワークやインフラのエラーコードは、一見すると無機質な暗号のように思えます。
ですが、「パケット(手紙)が今どこにいて、誰が処理を諦めてしまったのか」を順を追ってイメージしていくと、パズルを解くように原因が見えてきますよ。
トラブルシューティングは、ネットワークの仕組みを深く知る一番のチャンスです。
ログの中に不思議なステータスコードを見つけたら、怖がらずに一歩踏み込んで調べてみてくださいね!
コメント