ByteScope

521

HTTP 521 Web Server Is Down の直し方

5xx サーバーエラー非標準Cloudflare

IETF ではなく Cloudflare 独自のコードで、5xx の中でいちばん狭い失敗を表します。オリジンが Cloudflare の TCP 接続を能動的に拒否した——遅かったのでも、経路を間違えたのでもなく、何かが「駄目だ」と言ったのです。

521 が出ている理由と、やるべきこと

同じ 3 桁でも、リクエストのどちら側にいるかで別々の問題になります。自分に当てはまるブロックを読んでください。

curl で 521 を再現する

失敗した URL に対してそのまま実行してください。エラーページを表示せずにステータスだけを出すので、ブラウザが描画したものではなくサーバーが言ったことが見えます。

curl
curl -sS -o /dev/null --connect-timeout 5 -w '\n%{http_code} connect=%{time_connect}s\n' --resolve example.com:443:203.0.113.10 https://example.com/

`--resolve` は、元のホスト名と SNI を送りつつ指定したアドレスへ curl を接続させるので、エッジを経路から外したうえで、Cloudflare がオリジンにダイヤルするときの動作を再現できます。例のアドレスは自分の本物のオリジンアドレスに置き換えてください。`--connect-timeout 5` は拒否を素早く済ませ、同じくらい有用なことに、無言のドロップと区別してくれます。結果は 3 通りあり、それぞれ別のバグです。`curl: (7) Failed to connect to example.com port 443: Connection refused` が再現です。オリジンは Cloudflare を拒んだのとまったく同じようにあなたを拒んでいて、答えはオリジン側にあります——listener が無い、bind するアドレスが違う、ポートが違う、あるいはファイアウォールが reject に設定されている。5 秒の接続タイムアウトで終わる無反応はそもそも 521 ではありません。落とされた SYN を Cloudflare は 522 として報告するので、同じファイアウォールの DROP ルールと REJECT ルールは 2 つの違うエラー番号を生みます。そして普通に応答が返るなら、オリジンはあなたからの接続は受け付けて Cloudflare からのそれは受け付けていないということで、サービスではなく送信元アドレスのフィルタリングをまっすぐ指しています。Cloudflare の公開 IP レンジと、オリジンのファイアウォールを突き合わせてください。そのあと `--resolve` 無しで同じリクエストを実行してエッジの答えを見て、`cf-ray` ヘッダーを読みます。運用側が引ける ID です。

521 が実際に意味していること

521 は RFC 9110 にありません。IETF に登録された 5xx は 511 で止まっていて、520 から 526 の帯は Cloudflare 独自の拡張です。文書化しているのは Cloudflare だけですし、生成されるのは Cloudflare を経由してプロキシされたトラフィックだけなので、グレークラウドの DNS レコードがこれを返すことはありません。Cloudflare の定義は正確です。エラー 521 は、オリジンのウェブサーバーが Cloudflare からの接続を拒否したときに発生する。この「拒否」という語が、この番号の価値のすべてです。拒否は一つの答えです——TCP の RST か ICMP の unreachable か。つまりパケットはオリジンのネットワークまで到達していて、そこにある何かがそれを断ったということで、これだけで隣接する 3 つのコードが一度に除外されます。522 ではありません。Cloudflare はそちらをタイムアウトと定義していて、SYN から 19 秒以内に SYN+ACK が無い、あるいは接続確立後 90 秒以内にリクエストへの応答が無い場合です。523 でもありません。そちらは Cloudflare がオリジンにまったく到達できない場合で、たいていは間のネットワーク機器がオリジンのアドレスへの経路を持っていないからです。520 でもありません。そちらはオリジンが空・不明・予期しない何かで答えた場合です。Cloudflare は 521 の原因として 2 つ——オフラインになったオリジンのウェブサーバーアプリケーションと、ブロックされた Cloudflare のリクエスト——を挙げていて、対処はそこから素直に導かれます。オリジンが応答することを確認する。アプリケーションのクラッシュや障害についてオリジンのエラーログを確認する。Cloudflare の IP アドレスがブロックもレート制限もされていないことを確認する。オリジンのファイアウォールやその他のセキュリティソフトウェアで Cloudflare の全 IP レンジを許可する。そしてオリジンが、SSL/TLS モードの要求するポート——Flexible なら 80 番、Full と Full (Strict) なら 443 番——で実際に bind して listen していることを確認する。最後の項目がいちばん時間を吸う場合を拾います。Cloudflare がプロキシするポートは決まっているからです。HTTP は 80・8080・8880・2052・2082・2086・2095、HTTPS は 443・2053・2083・2087・2096・8443。それ以外で listen しているオリジンは、どれほど健全でもプロキシからは到達できません。

521 と間違えられやすいコード

紛らわしいコード見分け方
522どちらも Cloudflare がオリジンへの使える接続を得られなかったという意味で、違いはオリジンが答えたかどうかです。521 は拒否——答えの一種なので即座に返ります。522 はタイムアウトで、Cloudflare の定義は正確です。自分の SYN から 19 秒以内に SYN+ACK が無い、または接続確立後 90 秒以内にリクエストへの応答が無い。同じファイアウォールのルールが、REJECT か DROP かによってどちらかを生みます。
523523 は Cloudflare がオリジンにまったく到達できない場合で、ドキュメントはその原因を、間のネットワーク機器がオリジンのアドレスへの経路を持っていないことに帰しています。実例として挙げられているのは AWS のルートテーブルで、広すぎる `172.0.0.0/8` のエントリが Cloudflare 自身の `172.64.0.0/13` レンジを飲み込み、戻りのトラフィックをどこか私設の場所へ送ってしまうというものです。つまり 521 はパケットが届いたうえで拒まれた、523 はそもそも届かなかった、です。
520520 はオリジンが、Cloudflare には使えない何か——空・不明・予期しないもの、そして Cloudflare の 128 KB の上限を超える応答ヘッダーも含みます。これは過剰な Cookie が思ったより頻繁に到達する境界です——で答えた場合です。接続としては 521 の反対側の端で、520 ではハンドシェイクもリクエストも応答も起きていて、間違っていたのは応答の中身だけです。
502502 は、内側のサーバーからの不正な応答に対してどのプロキシも返せる IETF のコードで、拒否もリセットも解釈不能な返答もまとめて覆います。521 は同じ分類を原因 1 つまで絞り込んだ Cloudflare 版で、520 から 526 の帯が存在する理由もそこにあります。汎用の 502 では 4 つのことを調べる羽目になりますが、521 は「オリジンが接続を拒否した」と告げて、listener とファイアウォールへまっすぐ送ってくれます。
524比べれば 524 のほうが安心できるコードです。接続が成功したことを証明しているからです。Cloudflare はオリジンに接続し、そのあと 125 秒間、来ない HTTP 応答を待ちました。つまり 524 は 521 が投げかける問い——listener は上がっているか、ポートは合っているか、ファイアウォールは Cloudflare を通しているか——を全部否定して、調査をまるごとアプリケーションの中へ移します。
理由句
Web Server Is Down
クラス
5xx サーバーエラー
定義
Cloudflare
標準
非標準

このサイトのツール

どれもブラウザ内で完結します。アップロードは発生しません。

関連するステータスコード

521 を調べているとき、ついでに読むことになりがちなコードです。

よくある質問

このステータスコードを出したのがどのサーバーかを知るには?

ページではなく応答ヘッダーを読んでください。curl -sS -o /dev/null -D - https://example.com/path が本文なしでヘッダーだけを出し、serverviacf-ray の 3 つで、答えたのがどの層かが分かります。cf-ray の値があれば応答を扱ったのは Cloudflare で、その値はサポートが聞いてくる ID です。エッジを完全に外して確かめたいなら、--resolve example.com:443:203.0.113.10 を付けて同じリクエストを投げ直します。元のホスト名と SNI を送りつつ、指定したオリジンのアドレスへ接続するので、答えが変われば、エッジとオリジンの言い分が食い違っているということです。

数字のあとの理由句(Not Found など)に意味はありますか?

ありません。分岐条件にしてはいけません。RFC 9112 はクライアントに理由句を無視するよう求めていますし、サーバーは自由に変えられますし、HTTP/2 と HTTP/3 にはそもそも理由句が存在しません。HTTP/1.1 では 404 Not Found として届くものが、HTTP/2 では素の 404 として届きます。このサイトが登録済みの理由句を載せているのは、それが検索される語であり HTTP/1.1 のログに出る文字列だからで、何かのソフトウェアがそれに依存しているからではありません。

このコードで失敗したリクエストは再試行すべきですか?

5xx と 429 は再試行してよく、4xx はしないでください。次に投げても中身は同じだからです。応答に Retry-After が付いていればそれに従ってください。RFC 9110 がまさにこのために定義していて、値は秒数でも日時でも構いません。付いていなければ、ジッター付きの指数バックオフと明確な上限を使い、しかも冪等なメソッドに限ってください。再試行された POST はカードに二重で課金しかねません。すでに失敗しているサーバーへの再試行の嵐は、短い障害を長い障害に変える典型的な経路です。

自分のサーバーが返すステータスコードは変えられますか?

変えられます。守るべき規則は 1 つだけ、そのコードが本当であること。応答を自動で読むもの——検索エンジン、監視、キャッシュ、クライアント側の再試行ロジック——はすべて数字だけで判断し、ページの中身は一切見ません。エラーページを 200 で返せば自分の監視から障害が隠れますし、無いページを 200 で返せばエラーが本文として索引されますし、単に不正なリクエストに 500 を返せば、当番の人をスタックの間違った半分へ送り込むことになります。

521 でまだ詰まっているなら、ステータスコード一覧をすべて見る。あるいは上に戻って、自分の立ち位置に向けて書かれたブロックを読んでください。