ByteScope

521

HTTP 521 Web Server Is Down 怎麼修

5xx 伺服器錯誤非標準Cloudflare

Cloudflare 自己的代碼、不是 IETF 的,指的是整個 5xx 範圍裡最窄的一種失敗:你的來源機主動拒絕了 Cloudflare 的 TCP 連線,所以沒有東西慢、也沒有東西送錯地方——是有東西說了不。

為什麼會看到 521,以及該怎麼處理

同樣三個數字,你站在請求的哪一邊,它就是不同的問題。直接讀你自己那一塊。

用 curl 重現 521

對著出錯的那個網址跑一次。它只印狀態碼、不印錯誤頁,所以你看到的是伺服器真正說了什麼,而不是瀏覽器畫出來的東西。

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` 會讓 curl 連到你指定的位址,同時照樣送出原本的主機名稱和 SNI,所以這重現的就是 Cloudflare 撥號到你來源機時做的事,只是把邊緣節點從路徑上拿掉——把範例位址換成你真正的來源機位址。`--connect-timeout 5` 讓拒絕發生得很快,而且同樣有用的是,它把「拒絕」和「安靜地丟掉」分開了。結果有三種,而每一種是不同的 bug。`curl: (7) Failed to connect to example.com port 443: Connection refused` 就是重現成功:來源機拒絕你的方式,跟它拒絕 Cloudflare 的方式一模一樣,而答案在來源機上——沒有東西在監聽、綁錯位址、錯的連接埠,或者一道設成 reject 的防火牆。卡住、然後在五秒的連線逾時結束,那根本不是 521;被丟掉的 SYN 是 Cloudflare 報成 522 的東西,所以同一道防火牆上的 DROP 規則和 REJECT 規則會產生兩個不同的錯誤號碼。而如果它正常回應,代表來源機接受來自你的連線、卻不接受來自 Cloudflare 的,那就直直指向來源位址過濾、不是服務本身——拿來源機的防火牆去對 Cloudflare 公布的 IP 範圍。之後再把 `--resolve` 拿掉跑一次,看邊緣節點的答案、讀 `cf-ray` 標頭,那就是維運方查得到的 id。

521 實際上在講什麼

521 不在 RFC 9110 裡。IETF 登記的 5xx 代碼到 511 為止,而 520 到 526 這一段是 Cloudflare 自己的擴充,只有 Cloudflare 的文件在定義,而且只會出現在經過它代理的流量上——一筆灰雲(未代理)的 DNS 記錄不可能回出這個代碼。Cloudflare 的定義非常精確:錯誤 521 發生在來源網頁伺服器拒絕來自 Cloudflare 的連線時。「拒絕」這兩個字就是這個數字的全部價值。拒絕是一種回答——一個 TCP RST,或一個 ICMP unreachable——這代表封包有到來源機的網路,而那裡有東西回絕了它;光這一步就排掉了旁邊三個代碼。它不是 522,Cloudflare 把 522 定義成逾時:Cloudflare 送出 SYN 之後 19 秒內沒有 SYN+ACK,或者連線建立之後 90 秒內請求沒有被確認。它不是 523,Cloudflare 把 523 定義成完全聯絡不上來源機,典型原因是中間某台網路裝置沒有到來源機位址的路由。它也不是 520,那是來源機回了一個空的、未知的或非預期的東西。Cloudflare 為 521 列了兩個原因——來源網頁伺服器的應用程式離線,以及 Cloudflare 的請求被擋掉——而解法就從這兩個推出來:確認來源機有在回應、翻它的錯誤紀錄找應用程式當機或事故、確認 Cloudflare 的 IP 位址既沒被擋也沒被限流、在來源機的防火牆或其他安全軟體裡放行 Cloudflare 所有的 IP 範圍,還有確認來源機真的綁在、也監聽著你的 SSL/TLS 模式所要求的那個連接埠——Flexible 是 80,Full 和 Full (Strict) 是 443。最後那一項就是大家卡最久的那個情況,因為 Cloudflare 只代理一組固定的連接埠:HTTP 是 80、8080、8880、2052、2082、2086、2095,HTTPS 是 443、2053、2083、2087、2096、8443。監聽在這之外任何地方的來源機,不管它多健康,代理都碰不到。

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 則是 Cloudflare 把同一類縮到單一原因——而這就是 520 到 526 這一段存在的理由:一個籠統的 502 會讓你去查四件事,而一個 521 直接告訴你來源機拒絕了連線,把你送到監聽狀態和防火牆前面。
524相較之下 524 反而讓人安心,因為它證明了連線是成功的:Cloudflare 連上了來源機,然後等了 125 秒都沒等到 HTTP 回應。所以 524 把 521 提出的每一個問題都排除掉了——有東西在監聽、連接埠是對的、防火牆有放 Cloudflare 進來——並且把整個調查搬進應用程式裡。
原因片語
Web Server Is Down
類別
5xx 伺服器錯誤
定義出處
Cloudflare
標準
非標準

站上可以搭配的工具

這些全都在你的瀏覽器裡跑,不會上傳任何東西。

相關狀態碼

查 521 的時候,通常也會順手看一下這幾個。

常見問題

怎麼知道這個狀態碼是哪一台伺服器回的?

去讀回應標頭,不要讀那個網頁。curl -sS -o /dev/null -D - https://example.com/path 會只印標頭、不印內容,而 serverviacf-ray 三個加起來,就能指出是哪一層回答的。有 cf-ray 的值代表這個回應是 Cloudflare 處理的,那個值也是他們客服會跟你要的編號。想把邊緣節點整個排除掉,就加上 --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 可能會刷兩次卡。對一台已經在失敗的伺服器丟出重試風暴,是短暫事故變成長時間事故最常見的那條路。

我可以讓自己的伺服器改回別的狀態碼嗎?

可以,唯一要守的規則是那個代碼必須是真的。所有會自動讀你回應的東西——搜尋引擎、監控、快取、用戶端的重試邏輯——都只看那個數字,從來不看那一頁寫了什麼。用 200 回一頁錯誤訊息,會把故障從你自己的警報裡藏起來;用 200 回一頁不存在的內容,會讓錯誤被當成內容收進索引;而對一個只是格式不對的請求回 500,會把值班的人送去堆疊裡錯的那一半。

521 還是卡住嗎?看完整的狀態碼對照表,或是回到上面,讀為你這一端寫的那一塊。