أعدّ بوّابة صفحة الوكيل مع nginx
بنهاية هذا الدرس ستكون البوّابة تعمل أمام موقع خلف nginx: زائر غير مُمرَّر يُرسَل إلى تحقّق، واجتيازه يضبط كوكي، وطلبات لاحقة تمرّ مباشرةً. ستراقب الأمر كلّه أولًا في وضع المعاينة، فلا يُحجَب شيء حتى تؤكّد التوصيل. يُستخدَم هنا nginx؛ ووصفات Traefik وCaddy وAuthelia تتبع الشكل نفسه.
1. شغّل وضع المعاينة
في لوحة التحكّم، افتح الفريق وشغّل وضع المعاينة. وطوال تشغيله، يسجّل مُخوِّل البوّابة قرارات التحدّي مقابل المرور المباشر في صفحة الإحصاءات لكنه لا يحجب أبدًا. ستطفئه في النهاية.
2. فعّل البوّابة على مفتاح موقعك
افتح مفتاح موقعك واذهب إلى صفحة بوّابة الوكيل. شغّل الحالة ← مفعّل، ثم اضبط:
- نوع التحدّي: لعب لعبة (الافتراضي) أو التأكيد بمربّع اختيار. مفتاح موقع يطلب لعبة يعرض لعبة دائمًا، والصفحة تقول ذلك. واختيار لعبة يستلزم لعبة مثبّتة واحدة على الأقلّ ذات أثر قابل لإعادة التشغيل.
- مدّة السماح TTL: كم من الوقت يمرّر حلٌّ واحد زائرًا (افتراضيًّا 30 دقيقة). الأقصر يعني فحوصًا أكثر لكن نافذة أصغر إن سُرِق كوكي.
- وضع الفشل: ما يفعله وكيلك حين لا يستطيع بلوغ مُخوِّل Caputchin. الفشل المغلق (fail closed) يحجب (أأمن لبوّابة تسجيل دخول)؛ والفشل المفتوح (fail open) يمرّر الطلبات (يتفادى التوقّف على موقع عام).
اترك اللغة والسِّمة على طابِق الزائر: عندها يتكلّم التحقّق لغة الزائر، ويتبع تفضيله الفاتح أو الداكن، ويحمل هوية علامة مفتاح الموقع هذا تلقائيًّا. وتحت متقدّم تستطيع إعادة تسمية كوكي البوّابة، ونقل مسار ردّ النداء، وقصر البوّابة على مسارات بعينها؛ وهذا الشرح يستخدم الافتراضيات. انظر خصّص التحدّي.
تعرض الصفحة أيضًا مقتطف nginx جاهزًا للنسخ وإعداداتك مملوءة فيه سلفًا. تستغرق الإعدادات حتى عشر ثوانٍ لتبلغ الحافّة بعد أن تغيّرها.
3. اسمح بالأصل الذي تغلقه ببوّابة
التحقّق لا يعيد التوجيه إلا إلى أصل مسموح، القائمة نفسها للأصول المسموحة التي تستخدمها الأداة. تأكّد أنها تشمل الأصل الذي تغلقه، مثلًا https://auth.example.com. اضبطه في إعداد Cap لمفتاح الموقع إن لم يكن موجودًا سلفًا.
4. صِل المُخوِّل وإعادة التوجيه إلى التحدّي
كتلتا location: طلب فرعي مُخوِّل داخلي، وإعادة توجيه تحدٍّ يقفز إليها الوكيل عند 401. استبدِل YOUR_SITE_KEY بمفتاحك العامّ.
# Gate the protected paths.
location / {
auth_request /_cpt_authz; # 204 = allow, 401 = challenge
error_page 401 = @cpt_challenge;
proxy_intercept_errors on;
error_page 500 502 503 504 = @cpt_unreachable;
# ...proxy_pass to your app...
}
location = /_cpt_authz {
internal;
auth_request off;
proxy_pass https://verify.caputchin.com/v1/gate/authz?site=YOUR_SITE_KEY;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header Cookie $http_cookie; # forward the cpt_gate cookie
proxy_connect_timeout 2s;
proxy_read_timeout 2s;
}
location @cpt_challenge {
return 302 https://verify.caputchin.com/v1/gate/challenge?site=YOUR_SITE_KEY&return=$scheme://$host$request_uri;
}
# This is your fail mode. `return 403` blocks when Caputchin is unreachable
# (fail closed); `return 204` lets the request through (fail open).
location @cpt_unreachable {
return 403;
}المُخوِّل لا يجيب إلا 204 أو 401، فأي شيء آخر، بما فيه انتهاء المهلة، يعني أن Caputchin غير قابل للوصول ووضع الفشل عندك هو من يقرّر. انسخ المقتطف من لوحة التحكّم وهو مطابق سلفًا لوضع الفشل الذي اخترته.
أغلِق مسارات الدخول ببوّابة (HTML البوّابة وPOST تسجيل الدخول). لا تغلق الطلب الفرعي للمُخوِّل، ولا فحوص السلامة، ولا ردّ النداء أدناه.
5. أضِف ردّ النداء الذي يضبط الكوكي
تنتهي صفحة التحقّق بإرسال ذاتي لـ POST صغير إلى /__cpt/callback على أصلك (أو إلى مسار ردّ النداء الذي ضبطته)، مع cpt_gate (التصريح) وto (إلى أين يُرسَل الزائر) في الجسم. واسم الحقل cpt_gate حتى لو أعدت تسمية الكوكي. مُعالِج ضئيل يضبط الكوكي ويعيد التوجيه. العقد الكامل، بما فيه لِمَ تهمّ كل سمة كوكي، في وصفات الوكيل العكسي. الحدّ الأدنى:
app.post("/__cpt/callback", express.urlencoded({ extended: false }), (req, res) => {
const pass = String(req.body.cpt_gate || "");
const to = String(req.body.to || "/");
const target = new URL(to, `https://${req.headers.host}`);
if (target.host !== req.headers.host) return res.status(400).end(); // same-origin only
res.setHeader(
"Set-Cookie",
`cpt_gate=${pass}; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=1800`
);
res.redirect(303, target.pathname + target.search);
});6. راقبها في المعاينة
حمّل الرابط المغلق. لأن المعاينة مشغّلة، تمرّ مباشرةً، لكن صفحة الإحصاءات تسجّل challenge_served (لم يكن لديك كوكي) و، حالما تحلّ ويعمل ردّ النداء، pass_issued. أعِد التحميل ويُفترَض أن ترى passthrough يتسلّق. إن لم تظهر التحدّيات أبدًا، فكتلة المُخوِّل لا تُلمَس؛ وإن ردّ ردّ النداء بـ 400، فافحص أصل to.
7. انطلِق حيًّا
حين تبدو الأرقام صحيحة، أطفئ وضع المعاينة. تفرض البوّابة الآن: الزوّار غير المُمرَّرين يُرسَلون إلى اللعبة، والزوّار الذين حلّوا يتجوّلون حتى ينتهي تصريحهم.
إلى أين بعد ذلك
- وصفات الوكيل العكسي: Traefik، وCaddy، وشرح Authelia الكامل.
- إحصاءات بوّابة صفحة الوكيل: ما الذي يعنيه كل رقم حالما تصير حيًّا.
- نظرة عامة: الفكرة وما الذي لا تفعله البوّابة عمدًا.