تحميل غير محدود وراء Cloudflare

انتقلنا بخادمنا من مزود VPS إلى آخر وقمت بترقية المثيل عبر launcher rebuild إلى أحدث إصدار أيضًا، من 3.5.0.beta3 إلى 3.5.0.beta4.

كان المثيل يعمل دائمًا بشكل جيد خلف Cloudflare، ولكن الآن محاولة الوصول إليه تؤدي إلى رسوم متحركة تحميل لا نهائية بنقاط.

لدي إدخال في ملف المضيفين على نظامي المحلي لتجاوز Cloudflare، نظرًا لأن مزود خدمة الإنترنت الخاص بي (Deutsche Telekom AG) لديه سياسات اتصال سيئة بحيث يكون الوصول ضعيفًا جدًا عبر Cloudflare في بعض الأحيان. لذلك في البداية لم ألاحظ المشكلة، حيث أن الوصول بدون Cloudflare يعمل بشكل جيد. لذلك قمت بترقية المثيل، وبالتالي لست متأكدًا الآن مما إذا كان تغيير مزود VPS أو ترقية Discourse هو التغيير ذي الصلة. لقد تأكدت عبر VPN وشبكة الهاتف المحمول، من أن المشكلة حقًا هي Cloudflare نفسها الآن، وليس الاتصال السيئ لمزود خدمة الإنترنت الخاص بي، ويواجه المستخدمون الآخرون نفس المشكلة أيضًا. يمتلك كل من VPS القديم والجديد IPv6، والنظام بأكمله هو نفسه تمامًا، وتم نقله كملف صورة خام.

لا توجد أي رسائل خطأ، لا في المتصفح (وحدة التحكم)، ولا بواسطة وكيل النظام المضيف، ولا بواسطة Nginx داخل الحاوية، ولا بواسطة Rails أو في أي مكان آخر. يتم تحميل المستندات HTML والعديد من البرامج النصية بشكل جيد، ومقارنتها بتلك التي تم تقديمها عند تجاوز Cloudflare تظهر أن كل شيء (لقد تحققت) متطابق. تبدو رؤوس الاستجابة أيضًا متشابهة في الغالب، بخلاف بعض الرؤوس الخاصة بـ Cloudflare، بالطبع. آخر الأشياء التي أراها يتم تحميلها هو المحلل المصغر:

بالطبع، مسح ذاكرة التخزين المؤقت للمتصفح، واستخدام نوافذ خاصة وما إلى ذلك لم يغير شيئًا. كما أن مسح/تعطيل ذاكرة التخزين المؤقت لـ Cloudflare لا يساعد، لذا فإن ذاكرة التخزين المؤقت ليست المشكلة. لقد قمت بتعطيل ذاكرة التخزين المؤقت لـ CF مؤقتًا بالكامل لجميع المنتديات.

تجدر الإشارة إلى أن المنتدى يعمل على مسار فرعي خلف وكيل Apache على المضيف، باتباع هذه التعليمات: Serve Discourse from a subfolder (path prefix) instead of a subdomain
في السابق، أنشأنا مجرد رابط رمزي ln -s . forum بدلاً من الروابط الرمزية uploads/backups وأعدنا كتابة التعليمات مرتين، والتي عملت بشكل جيد لسنوات (وأيضًا الآن بدون Cloudflare)، ولكن كجزء من جهود تصحيح الأخطاء الخاصة بي، انتقلت إلى هذه التعليمات للتأكد من أن الوكيل الداخلي يطبق جميع القواعد كما هو مقصود. رأس الثقة هو CF-Connecting-IP، على الرغم من أنني قمت بتمكين cloudflare.template.yml أيضًا، حتى لو كان ذلك يضاعف الأمور إلى حد ما. وحاولت أيضًا التغيير ذهابًا وإيابًا لأجزاء مختلفة من هذه القوالب وتعليمات أعلاه، أيضًا في محاولة للتحقق مما إذا كانت رؤوس IP للوكيل تحدث أي فرق، حيث أن عدم وجود CF-Connecting-IP هو شيء واحد عند تجاوز Cloudflare.

في هذه المرحلة، لقد نفدت أفكاري تمامًا، وليس لدي أي أثر للمشكلة التي قد تنشأ منها، ولا يوجد أي سجل/إخراج متعلق في أي مكان. عبر Cloudflare، يتعطل Discourse في رسوم متحركة تحميل دون أي أثر إضافي.

آمل أن يكون لدى شخص ما فكرة عن كيفية تصحيح هذا، أو ما إذا كان هناك تغيير بين 3.5.0.beta3 و 3.5.0.beta4 قد يكون ذا صلة. أعتقد أن الرجوع إلى إصدار سابق يمثل مشكلة؟

هذا هو المثيل: https://dietpi.com/forum/
تعديل: لقد قمت بتعطيل Cloudflare في الوقت الحالي. ولكن هناك CNAME لا يزال يمر عبر Cloudflare، لذا يمكن مقارنة هذين: 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/
Resolving www.dietpi.com (www.dietpi.com)... 104.21.12.65, 172.67.193.183, 2606:4700:3035::6815:c41, ...
Connecting to www.dietpi.com (www.dietpi.com)|104.21.12.65|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]
Saving to: â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

كان عليّ اقتطاعه لأنه يتجاوز بكثير الحد الأقصى للأحرف للمنشور. عادة ما يستمر المستند على هذا النحو:

      <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، لكنني قمت بتعطيلها بالفعل في محاولة لحل المشكلات. جربت نفس الشيء مع إعدادات البروتوكول، لكن ذلك لم يغير شيئًا أيضًا:

بالمناسبة، لا يوجد رأس استجابة 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>

ويمكنني تكرار هذه البايتات الـ 73728 نفسها بنسبة 100% عند الوصول إلى https://www.dietpi.com/forum/ باستخدام curl دون طباعتها على الفور إلى وحدة التحكم. هذا غريب جدًا :face_with_monocle:.


لذلك:

  • جميع العملاء يعلقون عند تحميل أي مستند HTML من مثيل Discourse الخاص بنا.
  • يعلق كل عميل عند نفس البايت بالضبط عند تحميل نفس الصفحة.
  • يعلق العملاء المختلفون في نقاط مختلفة، ولكن عند نفس البايت بالضبط عند التكرار بنفس العميل.
  • يعلق كل صفحة في نقطة مختلفة في المستند وبحجم تنزيل مختلف.
  • الأداة نفسها 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 أو رؤوس (مثل اتصال keep alive) وهذا يصبح مشكلة فقط عندما يكون المستند أكبر من X (أشك في 64 كيلوبايت).

نعم، يقوم wget دائمًا بتنزيل المستند بأكمله، ويقوم curl بذلك عند الطباعة مباشرة إلى وحدة التحكم، ولكن لا يتم إغلاق الاتصال. يحدث الشيء نفسه مع المستندات الأصغر بكثير، مثل ما اختبرته لمستند بحجم 14 ألفًا حول موضوع يحتوي على منشورين فقط. ولكن حتى المستندات الأصغر عادةً لا يتم تنزيلها بالكامل بواسطة curl عند التوجيه أو التخزين في ملف، ولا في المتصفح.

تعرض كلتا الأداتين دائمًا HTTP/2، ولدي في Cloudflare تمكين طلبات المصدر HTTP/2. ولكن يجدر الاختبار باستخدام إصدارات HTTP أخرى بشكل صريح. بالأمس قمت بتعطيل جميع إعدادات البروتوكول في Cloudflare كما هو موضح في لقطة الشاشة أعلاه، ولم يساعد ذلك. لكنني سأحاول مرة أخرى. يمكنني أيضًا تمكين سجلات الوصول على الخادم لرؤية الطلب الوارد فعليًا من Cloudflare.

لقد جربت جميع مجموعات إصدارات HTTP (1.1-3) و TLS (1.2-1.3) المدعومة، ولكن ذلك لم يحدث فرقًا. لقد قمت أيضًا بتعطيل دعم HTTP3، وطلبات الأصل HTTP2، واستئناف اتصال 0-RTT هذا مرة أخرى. لا فرق، curl يستمر في التعليق عند 73,728 بايت بالضبط من https://www.dietpi.com/forum/.

فيما يتعلق بنظرية أحجام المستندات الكبيرة جدًا، فإن https://www.dietpi.com/dietpi-software.html تحتوي على 199,475 بايت ويتم تحميلها بشكل مثالي. يجب أن أذكر أن الخادم (نفس خادم الويب) يستضيف موقعًا ثابتًا، ونسخة MkDocs، و Wordpress، و Matomo، وكلها تعمل بشكل مثالي. يوجد أيضًا مثيل Grafana حيث يعمل خادم الويب الأمامي كوكيل عبر مقبس UNIX.

لكنني أتفق على أنه يبدو أنه يتعلق بالمخازن المؤقتة أو أحجام الأجزاء أو شيء من هذا القبيل. إنه غريب فقط أن حجم التنزيل حتى التعليق يتغير كثيرًا بين العملاء والصفحات، بينما يظل كما هو تمامًا على الرغم من تغيير إصدارات البروتوكول، وأنه لا يتم إغلاق الاتصال حتى بعد تنزيل المستند بالكامل. كما لو أن إشارة التوقف مفقودة، على الرغم من أنني أفتقر إلى الرؤى حول HTTP في هذه المرحلة. لذلك فكرت في رأس content-length، ولكن من الواضح أن هذا ليس إلزاميًا.

يعمل خادم الويب أيضًا كوكيل لحاوية Discourse عبر مقبس UNIX. يمكنني تمكين مستمع TCP لجعل مثيل Discourse متاحًا إضافيًا بدون الوكيل (مع ترك Nginx داخل الحاوية، بالطبع).

هل يمكنك تجربة KeepAlive Off في Apache؟

أعتقد أن هذا سيستبعد على الأقل خادم الويب، لذا سيكون ذلك جديرًا بالمحاولة.

إعجاب واحد (1)

لم يتغير شيء. وأيضًا من وثائق Apache:

بالإضافة إلى ذلك، لا يمكن استخدام اتصال Keep-Alive مع عميل HTTP/1.0 إلا عندما يكون طول المحتوى معروفًا مسبقًا.

وبالتالي، نظرًا لعدم وجود content-length، فمن المنطقي أنه لا يتم استخدامه على أي حال لهذا الطلب.

نظرًا لأنه يتطلب إعادة بناء، سأقوم بذلك لاحقًا عندما يكون نشاط موقعنا المشترك في حده الأدنى. أم، أنا أفكر فقط في HTTPS … يبدو أنني بحاجة إلى إجراء بعض التعديلات المخصصة على تكوين Nginx الداخلي للحفاظ على عمل مقبس UNIX بالإضافة إلى اتصالات HTTP العادية، مع الاستماع على منفذ إضافي لـ HTTPS مع شهادات TLS من المضيف، ولكن بدون إعادة توجيه/فرض HTTPS. … ومنفذ TCP HTTP عادي إضافي سيكون مثيرًا للاهتمام أيضًا، للعملاء الذين يمكنهم تجاهل HSTS.

هل تستخدم RocketLoader في CloudFlare بالصدفة؟ أعرف أنه يسبب مشاكل مع بعض النصوص الأخرى.
أيضًا، هل قمت بمسح ذاكرة التخزين المؤقت لـ CF؟
هل تستخدم قواعد واردة على CF قد تكون مرتبطة بعنوان IP الخاص بـ VPS القديم الخاص بك ولم يتم تحديثها إلى العنوان الجديد؟

إعجاب واحد (1)

لا يوجد RocketLoader: لاحظ أنه اعتبارًا من الاختبارات المذكورة أعلاه باستخدام curl و wget، والتي لا تفسر أي صيغة، وبالتالي لا تقوم بتحميل أي JavaScript أو أنماط أو أي شيء آخر، فإن المشكلة هي أن تنزيل مستند HTML الخام يتوقف دائمًا.

ذاكرة التخزين المؤقت لـ Cloudflare غير نشطة للمنتدى، ولم يتم تخزين مستندات HTML الخام مؤقتًا على أي حال.

لا توجد قواعد خاصة بـ VPS. بشكل عام لا توجد قواعد للمنتدى، بخلاف تجاوز ذاكرة التخزين المؤقت. تظهر المشكلة في كلتا الحالتين، لذا فإن ذاكرة التخزين المؤقت ليست المشكلة أيضًا.

إعجاب واحد (1)

أثناء الاختبار لتجاوز وكيل Apache2 على مضيف حاوية Discourse، وتعطيل عمليات إعادة توجيه HTTPS القسرية في Cloudflare لاختبار اتصالات HTTP العادية عبر curl أيضًا، وجدت أخيرًا الجاني في Cloudflare:

لست متأكدًا مما تغير مع تبديل خادم VPS الخاص بنا و/أو ترقية Discourse من 3.5.0.beta3 إلى 3.5.0.beta4 و/أو تزامن ذلك في Discourse في نفس الوقت، ولكن يبدو أن شيئًا ما في مستندات HTML أو CSS أو JavaScript الخاصة بـ Discourse يتسبب في تعطل إعادة كتابة Cloudflare لـ HTTPS للروابط المضمنة. يبدو أن طلبات curl الجزئية والمعلقة لم تكن مرتبطة حقًا، أو ربما تكون كذلك. من الغريب أنه في علامة تبويب شبكة المتصفح يمكن للمرء رؤية المحتوى الجزئي لمستند HTML، كما لو أن ميزة إعادة كتابة HTTPS تفعل ذلك أثناء التدفق عبر المستند.

هل لدى شخص آخر مثيل وحساب 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 لإضافة رمز تتبع Matomo الخاص بنا إلى جميع استجابات text/html، مباشرة قبل وسم النهاية </head>. تعطيلها لـ Discourse (أو تجاوز وكيل Apache2) يحل الأمور أيضًا، على الرغم من تفعيل Cloudflare Automatic HTTPS Rewrites. تعطيل أي من الاثنين يحل الأمور. على جميع الصفحات الأخرى، يعمل المزيج بشكل جيد، وكذلك على الصفحات الكبيرة جدًا لدينا، أكبر من صفحات المنتدى الفاشلة. لذا ربما يؤدي المرشحان، أولاً mod_set على وكيلنا ثم عمليات إعادة كتابة عنوان URL المضمنة بواسطة Cloudflare إلى كسر شيء ما، يتعلق بأحجام المستندات أو الأجزاء أو أي شيء آخر.

نقوم بتضمين المتعقب الآن عبر تعديل سمة Discourse، وقمت أيضًا بتعطيل Cloudflare Automatic HTTPS Rewrites. لا يوجد محتوى مختلط على موقعنا بالكامل. وإذا كان هناك، فمن الجيد رؤيته وإصلاحه، بدلاً من أن تقوم Cloudflare بإخفائه إلى الأبد.

أنا متأكد من أن هذا لا يمكن أن ينجح.

لست متأكدًا تمامًا من المشكلة التي تحاول حلها، ولكنك ربما تحتاج إلى تمكين force_https في ملف app.yml الخاص بك.

4 إعجابات

أتخيل أنه من الاسم فقط “Cloudflare Automatic HTTPS Rewrites” يمكن إساءة فهمه. لدى Cloudflare ميزتان:

  • “Always Use HTTPS” يعيد توجيه جميع طلبات HTTP العادية إلى HTTPS، تمامًا مثلما تفعل force_https في Discourse. تم تمكين كليهما سابقًا، وقمت بتعطيل كليهما لاختبار ما إذا كان HTTPS له أي علاقة بالمشكلة أو صفحات Discourse التي يتم تحميلها بلا نهاية وطلبات curl المعلقة. نجح هذا بشكل مثالي، بل وحل المشكلة بأكملها لطلبات HTTPS أيضًا، ولكن فقط لأنني قمت بتعطيل “Cloudflare Automatic HTTPS Rewrites” في نفس الوقت.
  • “Cloudflare Automatic HTTPS Rewrites” يغير مستندات HTML و CSS و JavaScript لاستبدال جميع عناوين URL العادية المضمنة عبر HTTP بنظائر HTTPS، حيث تعتقد Cloudflare أن المضيف يمكن الوصول إليه عبر HTTPS (بناءً على قائمة HSTS المحملة مسبقًا وما شابه ذلك). هذا لتجنب تحذيرات المحتوى المختلط.

فرض HTTPS أو عدم فرضه في Cloudflare، أو في وكيل المضيف، أو في Discourse لا يهم. ما تسبب في المشكلة هو مزيج من مرشح mod_sed في وكيل المضيف والتعديلات العادية المضمنة عبر HTTP بواسطة Cloudflare. لذلك، مرحلتان تم من خلالهما تمرير محتوى المستندات عبر مرشح. لم تكن المشكلة هي أن هناك أي تغيير فعلي في المحتوى (لا يوجد محتوى مختلط في موقعنا، وبالتالي فإن “Cloudflare Automatic HTTPS Rewrites” لا يغير فعليًا نص المستند)، ولكن ربما يتعلق الأمر بالقطع أو المخزن المؤقت أو التوقيت.

إعجاب واحد (1)

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