Cloudflareの背後にある終わらない読み込み

サーバーを別のVPSプロバイダーに移行し、launcher rebuild を使用してインスタンスを 3.5.0.beta3 から 3.5.0.beta4 にアップグレードしました。

インスタンスはCloudflareの後ろで常に正常に動作していましたが、現在アクセスしようとすると、無限の5つのドットのローディングアニメーションが表示されます。

ISP(Deutsche Telekom AG)の接続ポリシーが悪いため、Cloudflare経由でのアクセスが時々非常に遅くなるため、Cloudflareをバイパスするためにローカルシステムにhostsファイルのエントリがあります。そのため、当初は問題に気づきませんでした。Cloudflareなしでのアクセスは問題なく機能していました。その後インスタンスをアップグレードしたため、変更されたVPSとDiscourseのアップグレードのどちらが関連する変更であったかは確信が持てません。VPNとモバイルネットワークで確認したところ、問題はISPの接続不良ではなく、Cloudflare自体にあることが確認されました。他のユーザーも同様の問題に直面しています。旧VPSと新VPSはどちらもIPv6が利用可能で、システム全体は生のイメージファイルとして転送されたため、全く同じです。

ブラウザ(コンソール)、ホストシステムのプロキシ、コンテナ内のNginx、Railsのいずれにもエラーメッセージは表示されません。HTMLドキュメントやいくつかのスクリプトは正常に読み込まれ、Cloudflareをバイパスした場合に提供されるものと比較しても、確認したすべてが同一です。レスポンスヘッダーも、Cloudflare固有のものを除けば、ほとんど同じように見えます。最後に読み込まれるのはミニプロファイラーです。

もちろん、ブラウザのキャッシュをクリアしたり、プライベートウィンドウを使用したりしても何も変わりませんでした。Cloudflareのキャッシュをクリアまたは無効にしても問題は解決しないため、キャッシュが原因ではありません。フォーラム全体でCFキャッシュを一時的に完全に無効にしました。

特筆すべきは、フォーラムがホスト上のApacheプロキシの後ろのサブパスで実行されており、次の指示に従っていることです: Serve Discourse from a subfolder (path prefix) instead of a subdomain
以前は、アップロード/バックアップのシンボリックリンクではなく、単に ln -s . forum のシンボリックリンクを作成し、指示を2回書き直しただけで、長年(Cloudflareなしでも現在も)うまく機能していましたが、デバッグの過程で、内部プロキシがすべてのルールを意図通りに適用していることを確認するために、これらの指示に従いました。信頼されるヘッダーは CF-Connecting-IP ですが、cloudflare.template.yml も有効にしました。これはいくらか重複しますが。また、これらのテンプレートと上記の指示のさまざまな部分を元に戻したり戻したりして、プロキシIPヘッダーが違いを生むかどうかを確認しようとしました。Cloudflareをバイパスする際に CF-Connecting-IP が欠落していることもその一つです。

この時点で、私は完全にアイデアがなくなり、問題の原因を特定する手がかりも、関連するログ/出力もどこにもありません。Cloudflare経由では、Discourseは追加のトレースなしでローディングアニメーションでハングします。

この問題をデバッグする方法、または 3.5.0.beta33.5.0.beta4 の間にこれに関連する可能性のある変更があったかどうか、誰かアイデアがあれば幸いです。ダウングレードは問題があると思いますか?

インスタンスはこちらです: https://dietpi.com/forum/
編集:Cloudflareは現在無効にしました。しかし、まだCloudflareを通過するCNAMEがあります。そのため、この2つを比較できます: https://www.dietpi.com/forum/

興味深い問題ですね。

永遠にハングしているのは、単に https://www.dietpi.com/forum/ です。

$ wget https://www.dietpi.com/forum/
--2025-05-03 10:52:18--  https://www.dietpi.com/forum/
www.dietpi.com (www.dietpi.com) を解決しています... 104.21.12.65, 172.67.193.183, 2606:4700:3035::6815:c41, ...
www.dietpi.com (www.dietpi.com)|104.21.12.65| への接続中:443... 接続しました。
HTTP リクエストを送信しました。応答を待っています... 200 OK
長さ: 不明 [text/html]
保存先: âindex.html.1â

    [<=                            

興味深いのは、https://www.dietpi.com/forum/site.json のような呼び出しは成功することです。

https://www.dietpi.com/forum/t/why-there-are-two-kernals-in-my-raspberry-pi4/23355 は機能せず永遠にハングしますが、
https://www.dietpi.com/forum/t/why-there-are-two-kernals-in-my-raspberry-pi4/23355.json は機能します。

「いいね!」 1

実に興味深い。HTMLドキュメントが完全に読み込まれず、途中でハングしてしまうことに今気づきました。両方のケースで /forum/ を比較しましたが、同一だと思っていました。しかし、おそらくヘッダーに集中しすぎて、下部の本文の一部が欠けているのでしょう。

Cloudflare経由で読み込んだ際の最後の行:

      <discourse-assets-json>
        <div class="hidden" id="data-preloaded" data-preloaded="{&quot;topic_list&quot;:&quot;{&quot;users&quot;...&quot;:false,&quot;allowed_iframes&quot;:&quot;https://dietpi.com/forum/discobot/certificate.svg&quot;

投稿の文字数制限を大幅に超えるため、切り取る必要がありました。通常、ドキュメントは次のように続きます:

      <discourse-assets-json>
        <div class="hidden" id="data-preloaded" data-preloaded="{&quot;topic_list&quot;:&quot;{&quot;users&quot;...&quot;:false,&quot;allowed_iframes&quot;:&quot;https://dietpi.com/forum/discobot/certificate.svg&quot;,&quot;can_permanently_delete...

他のページもまったく同じ場所でハングします。これは何か関係があると思います。

編集:ああ、待ってください、間違ってチェックしていました。他のページは別の場所でハングします。したがって、この特定のHTML要素/属性ではありません。

はい、各ページ/HTMLドキュメントは、ブラウザ経由で再度読み込んだ際に、毎回同じ文字数でハングしますが、異なるページは異なる場所でハングします。そして、それらを curl 経由で読み込んだ場合も、常に同じ場所でハングしますが、それは別の場所であり、wget も同様に常に同じ場所でハングしますが、それはわずかに異なる場所です。非常に奇妙です。

最適化は有効になっていますか?

いいえ、(コンテンツ)最適化はありません。103 Early Hints機能を有効にしていましたが、問題を解決しようとして既に無効にしました。プロトコル設定でも同じことを試しましたが、何も変わりませんでした。

ところで、content-length レスポンスヘッダーはありません。これが問題の原因になる可能性がありますか?Cloudflareをバイパスした場合でも存在しませんが、Cloudflareに何か問題があるのでしょうか?編集:いいえ、動的ページでは通常のようです。WordPressやMatomoのページでも同じですが、それらは問題を引き起こしていません。

curlでいじっているときに別の発見がありました。STDOUTに出力すると、完全なHTMLドキュメントが表示されますが、それでもハングし、最後に次のようになります。

  <p class='powered-by-link'>Powered by <a href="https://www.discourse.org">Discourse</a>, best viewed with JavaScript enabled</p>
</footer>


  </body>

</html>

しかし、-oや単純なリダイレクトで保存しようとしたり、grepにパイプしたりしても、異なる場所でハングします。

            <div class="link-bottom-line">
                <a href='/forum/c/general-discussion/7' class='badge-wrapper bullet'>
                  <span class='badge-category-bg' style='background-color: #F7941D'></span>
                  <span class='badge-category clear-badge'>
                    <span class='category-name'>General Discussion</span>
                  </span>
                </a>

そして、https://www.dietpi.com/forum/にcurlでアクセスしたときに、コンソールに表示するだけでない場合、この全く同じ73728バイトを100%再現できます。これは非常に奇妙です:face_with_monocle:。


したがって:

  • すべてのクライアントは、DiscourseインスタンスからHTMLドキュメントを読み込む際にハングします。
  • 各クライアントは、同じページを読み込む際に、同じバイト数でハングします。
  • 異なるクライアントは異なるポイントでハングしますが、同じクライアントで繰り返すと、同じバイト数でハングします。
  • 各ページは、ドキュメント内の異なるポイントで、異なるダウンロードサイズでハングします。
  • 同じツールcurlは、STDOUTに表示するだけの場合と、ドキュメントをどこかにパイプまたは保存する場合で、異なるポイントでハングします。
  • wgetは、完全なドキュメント(少なくともhttps://www.dietpi.com/forum/)をファイルにダウンロードできますが、それでも最後にハングします。curl https://www.dietpi.com/forum/でコンソールに完全なドキュメントを表示した場合も同様ですが、最後にハングします。

それはバッファリングかもしれませんが、調査中に別のことに気づきました。

wget -O - https://www.dietpi.com/forum/latest

これは以下で終わります。

  </body>
</html>

しかし、接続は決して閉じられません。

理論:HTTPバージョンまたはヘッダー(キープアライブ接続など)の不一致がある設定の問題があり、これはドキュメントがX(64KBと推測)より大きい場合にのみ問題になります。

はい、wget は常にドキュメント全体をダウンロードし、curl はコンソールに直接表示する場合にそうしますが、接続は閉じられません。投稿が2つしかないトピックの14kのような小さいドキュメントでも同じことが起こります。しかし、パイプまたはファイルへの保存時に curl がブラウザでも、小さいものでも通常は完全にダウンロードされません。

どちらのツールも常に HTTP/2 を表示し、Cloudflare では HTTP/2 オリジンリクエストが有効になっています。しかし、他の HTTP バージョンを明示的に使用してテストする価値はあります。昨日、上記のスクリーンショットで見られる Cloudflare のすべてのプロトコル設定を無効にしましたが、効果はありませんでした。しかし、もう一度試してみます。また、サーバーでアクセスログを有効にして、Cloudflare から実際に入ってくるリクエストを確認することもできます。

HTTP(1.1-3)とTLS(1.2-1.3)のすべての組み合わせを試しましたが、違いはありませんでした。HTTP3サポートを無効にし、HTTP2オリジンリクエストでも、この0-RTT接続の再開が再び発生しました。違いはなく、curlhttps://www.dietpi.com/forum/のちょうど73,728バイトでハングし続けます。

ドキュメントサイズが大きすぎるという理論に関して、https://www.dietpi.com/dietpi-software.htmlは199,475バイトで、問題なくロードされます。サーバー(同じWebサーバー)は、静的Webサイト、MkDocsインスタンス、WordPress、Matomoをホストしており、すべて問題なく動作することを言及しておくべきです。また、フロントWebサーバーがUNIXソケット経由でプロキシとして機能するGrafanaインスタンスもあります。

しかし、バッファーやチャンクサイズ、あるいはそれに類するものに関連しているように思われることに同意します。ダウンロード中にハングするサイズがクライアントやページによって大きく異なる一方で、プロトコルバージョンを変更しても全く同じままであり、ドキュメントが完全にダウンロードされた後でも接続が閉じられないというのは奇妙です。停止信号が欠落しているかのようですが、この時点ではHTTPに関する洞察が不足しています。そのため、content-lengthヘッダーについて考えましたが、それは明らかに必須ではありません。

Webサーバーは、UNIXソケット経由でDiscourseコンテナのプロキシとしても機能します。TCPリスナーを有効にして、プロキシなしでDiscourseインスタンスを追加で利用可能にすることができます(もちろん、コンテナ内のNginxはそのままにします)。

ApacheでKeepAlive Offを試していただけますか?

少なくともウェブサーバーを特定できる可能性があるので、試す価値はあると思います。

「いいね!」 1

変更なし。Apacheのドキュメントにも次のようにあります。

さらに、HTTP/1.0クライアントとのKeep-Alive接続は、コンテンツの長さが事前にわかっている場合にのみ使用できます。

したがって、content-length が欠落しているため、このリクエストではいずれにしても使用されないのが理にかなっています。

再構築が必要なので、ウェブサイトの通常の活動が最小限になったら後で行います。うーん、HTTPSについて考えているのですが… UNIXソケットを機能させ、プレーンHTTP接続も機能させながら、ホストからのTLS証明書を使用してHTTPS用の追加ポートでリッスンし、HTTPSリダイレクト/強制なしにするには、内部Nginx構成にカスタム調整を行う必要があるようです。…また、HSTSを無視できるクライアントのために、追加のプレーンHTTP TCPポートも興味深いでしょう。

CloudflareのRocketLoaderを使用していますか?他のスクリプトでも問題が発生することがあります。\nまた、CFのキャッシュをクリアしましたか?\n古いVPSのIPアドレスに紐付けられたまま、新しいIPアドレスに更新されていないCFのインバウンドルールを使用していませんか?

「いいね!」 1

RocketLoaderなし: curlwgetを使用した上記のテストでは、構文を解釈せず、JavaScriptやスタイルなどを一切読み込まないため、生のHTMLドキュメントのダウンロードが常にハングするという問題があります。

Cloudflareのキャッシュはフォーラムではアクティブではなく、生のHTMLドキュメントはそもそもキャッシュされていませんでした。

VPS固有のルールはありません。一般的にフォーラムにはキャッシュをバイパスするためのルール以外はありません。どちらの場合も問題が発生するため、キャッシュも問題ではありません。

「いいね!」 1

Apache2 プロキシを Discourse コンテナホストでバイパスしようとしていたとき、Cloudflare で強制 HTTPS リダイレクトを無効にして curl で通常の HTTP 接続をテストしていたところ、ついに Cloudflare で原因を特定しました。

VPS の切り替えや Discourse 3.5.0.beta3 から 3.5.0.beta4 へのアップグレード、またはそれと同時に Discourse で何かが変更されたのかは定かではありませんが、Discourse の HTML、CSS、または JavaScript ドキュメントの何かが、Cloudflare の埋め込み URL の HTTPS 書き換えを妨げているようです。部分的に中断した curl リクエストは実際には関係なかったのか、あるいは関係しているのかは不明です。ブラウザのネットワークタブで、HTTPS 書き換え機能がドキュメントをストリーミングしながら処理しているかのように、HTML ドキュメントの部分的なコンテンツが表示されるのは奇妙です。

誰かインスタンスと Cloudflare アカウントを持っていて、これをテストできる人はいますか?一般的な問題なのか、それとも私たちの特定のインスタンス/セットアップに関連しているのか?

ちなみに、プロキシのバイパスと HTTP をテストするために、コンテナ内の Nginx 設定を次のように手動で調整すると、完全に機能します。

root@dietpi-discourse:/var/www/discourse# cat /etc/nginx/conf.d/outlets/server/10-http.conf
listen unix:/shared/nginx.http.sock;
set_real_ip_from unix:;
listen 8080;
listen [::]:8080;
listen 8443 ssl;
listen [::]:8443 ssl;
http2 on;

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;

ssl_certificate /shared/fullchain.cer;
ssl_certificate_key /shared/dietpi.com.key;

ssl_session_tickets off;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:1m;

もちろん、HTTPS リダイレクトと HSTS ヘッダーを削除し、追加されたポートを公開することが重要です。

そして、もう一つの発見です。私たちはmod_sedを使用して、すべてのtext/htmlレスポンスの</head>終了タグの直前にMatomoトラッカーコードを追加しています。Cloudflareの自動HTTPSリライトが有効になっているにもかかわらず、Discourseでこれを無効にする(またはApache2プロキシをバイパスする)ことでも問題は解決します。どちらか一方を無効にすると問題が解決します。他のすべてのページでは、この組み合わせは正常に機能しており、失敗しているフォーラムページよりも大きいページでも問題ありません。したがって、おそらく2つのフィルター、最初にプロキシでのmod_set、次にCloudflareによる埋め込みURLリライトが、ドキュメントまたはチャンクのサイズなどに関連して何かを壊している可能性があります。

現在、Discourseのテーマ編集を通じてトラッカーを埋め込み、さらにCloudflareの自動HTTPSリライトを無効にしました。ウェブサイト全体に混合コンテンツはありません。もしあれば、Cloudflareが永遠に隠すのではなく、それを見て修正するのは良いことです。

それは機能しないと確信しています。

どのような問題を解決しようとしているのかよくわかりませんが、おそらく app.ymlforce_https を有効にする必要があるでしょう。

「いいね!」 4

「Cloudflare Automatic HTTPS Rewrites」という名前から誤解される可能性があると想像します。Cloudflareには2つの機能があります。

  • 「Always Use HTTPS」は、Discourseのforce_httpsと同様に、すべての通常のHTTPリクエストをHTTPSにリダイレクトします。どちらも以前は有効になっていましたが、HTTPSが問題や、Discourseの無限ロードページ、ハングするcurlリクエストに関係しているかどうかをテストするために両方を無効にしました。これは完全に機能し、HTTPSリクエストの問題も解決しましたが、それは「Cloudflare Automatic HTTPS Rewrites」を同時に無効にしたためです。
  • 「Cloudflare Automatic HTTPS Rewrites」は、HTML、CSS、JavaScriptドキュメントを変更して、CloudflareがホストがHTTPS経由で到達可能であると判断した(HSTSプリロードリストなどに基づく)すべての埋め込みHTTP URLをHTTPSバリアントに置き換えます。これは、混合コンテンツの警告を回避するためです。

Cloudflare、ホストプロキシ、またはDiscourseでHTTPSを強制するかどうかは関係ありません。問題を引き起こしたのは、ホストプロキシのmod_sedフィルターとCloudflareによる埋め込みHTTP編集の組み合わせでした。つまり、ドキュメントの内容がフィルターを通過する2つの段階がありました。問題は、実際の内容が変更されたことではありません(私たちのサイトには混合コンテンツはありません。「Cloudflare Automatic HTTPS Rewrites」はドキュメント本文を実際には変更しません)、おそらくチャンク、バッファ、またはタイミングに関連していました。

「いいね!」 1

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.