Files
tripz-llc/docs/20-tls.md
T
Hamza-AyedandClaude Opus 4.8 d2a34f753c feat: TLS — إغلاق المنافذ المكشوفة + الثقة بالبروكسي + دليل الإصدار
النطاق: tripz-api.intaleqapp.com (قرار المالك) — مملوك وجاهز، ومحايد عن
اسم العلامة الذي لم يُحسم فلا يحتاج تغييراً لاحقاً.

ثغرتان كانتا ستُبطلان TLS من أصله:
- API كان منشوراً على 0.0.0.0:4010 → صار 127.0.0.1. بلا هذا يبقى
  http://IP:4010 مفتوحاً فيتجاوز TLS كلياً وتصير الشهادة زينة
- **Postgres كان مكشوفاً على 0.0.0.0:55432** — القاعدة على الإنترنت مباشرة
  → صار 127.0.0.1. المنفذ غير القياسي إخفاء لا أمان. الوصول من الماك عبر
  نفق SSH (docs/20 §4)

trust proxy = 1: خلف Nginx كان req.ip يصير 127.0.0.1 للجميع فيمتلئ سجل
التدقيق المالي (I7) بعنوان البروكسي بدل السائق — أثرٌ بلا قيمة عند النزاع.
قفزة واحدة فقط: الثقة المفتوحة تسمح للعميل بتزوير X-Forwarded-For.

docs/20: DNS → موقع reverse proxy → شهادة → **إعداد ترقية WebSocket**
(بدونه يسقط التتبّع الحيّ) + مهلة 3600s للنبضات طويلة العمر + فحص تحقّق
أهمّه أن http://IP:4010 يجب أن **يفشل**.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 16:36:14 +03:00

5.3 KiB

20 — TLS: إنهاء الطبقة المشفّرة أمام الـAPI

النطاق المعتمد: tripz-api.intaleqapp.com (قرار المالك 2026-07-17). السبب في اختيار نطاق فرعي على intaleqapp.com: مملوك وجاهز بلا انتظار DNS، ومحايد عن اسم العلامة التجارية الذي لم يُحسم — فلا يحتاج تغييراً لاحقاً.


1. لماذا هذا يسبق كل عمل مدفوعات

الـAPI كان يعمل على http://194.163.173.157:4010. من يلتقط الشبكة (واي-فاي عام) يقرأ توكن أي سائق ويسحب أرباحه. لا OTP ولا HMAC ولا سجل تدقيق يمنع ذلك — كلها تُبنى فوق قناة مكشوفة. TLS هو الأساس، لا طبقة إضافية.

2. ثغرتان أُصلحتا في نفس الشغل (بلا هذا يصير TLS زينة)

كان صار لماذا
4010:4010 أي 0.0.0.0 127.0.0.1:4010 بلا هذا يبقى http://IP:4010 مفتوحاً فيتجاوز TLS كلياً. الشهادة على النطاق لا تُغلق المنفذ.
55432:5432 أي 0.0.0.0 127.0.0.1:55432 Postgres كان على الإنترنت مباشرة. المنفذ غير القياسي إخفاء لا أمان.

بعد هذا لا يصل للـAPI إلا Nginx المحلي، ولا تصل القاعدة إلا من داخل السيرفر.

3. الخطوات على السيرفر

3.1 DNS

سجل A لـtripz-api.intaleqapp.com → 194.163.173.157. تحقّق قبل المتابعة:

dig +short tripz-api.intaleqapp.com    # يجب أن يطبع 194.163.173.157

Let's Encrypt يفشل إن لم ينتشر الـDNS بعد. لا تُصدر الشهادة قبل أن يطبع الأمر العنوان الصحيح.

3.2 موقع Reverse Proxy في CloudPanel

CloudPanel → Add Site → Create Reverse Proxy:

  • Domain: tripz-api.intaleqapp.com
  • Reverse Proxy URL: http://127.0.0.1:4010

3.3 الشهادة

CloudPanel → الموقع → SSL/TLS → Actions → New Let's Encrypt Certificate. CloudPanel يجدّدها تلقائياً.

3.4 دعم WebSocket (إلزامي — بدونه يسقط التتبّع الحيّ)

Socket.IO يحتاج ترقية الاتصال. في Vhost Editor للموقع، تأكّد أن كتلة location / تحوي:

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

# نبضات المواقع والسوكت طويلة العمر — الافتراضي 60s يقطعها
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;

X-Forwarded-For ضروري: بدونه يسجّل التدقيق المالي (docs/17 — I7) عنوان البروكسي لكل سائق، فيصير الأثر بلا قيمة. الباك إند يثق بقفزة واحدة فقط (trust proxy = 1) — الثقة المفتوحة تسمح للعميل بتزوير العنوان.

3.5 النشر

cd /home/tripz-llc && git pull origin main
cd backend && docker compose up -d --build
docker image prune -f

3.6 التحقق

curl -I https://tripz-api.intaleqapp.com/api/health          # 200 عبر TLS
curl -I http://194.163.173.157:4010/api/health               # يجب أن **يفشل** الآن
docker compose exec api printenv | grep -c PLATFORM_SECRET   # 1

الفحص الثاني هو الأهم: نجاحه يعني أن المنفذ ما زال مكشوفاً وأن TLS يُتجاوَز.

4. الوصول للقاعدة بعد الإغلاق

لم تعد 55432 مفتوحة. من الماك:

ssh -L 55432:127.0.0.1:55432 root@194.163.173.157
# ثم اتصل بـ localhost:55432 كالمعتاد

سكربتات التحقق لا تتأثر — تعمل داخل شبكة tripz-net وتنادي http://tripz-api:4010 مباشرة.

5. بعد نجاح TLS — خطوات تابعة

البند التفصيل
فلاتر: BASE_URL --dart-define BASE_URL=https://tripz-api.intaleqapp.com/api
فلاتر: إغلاق النصّ الصريح usesCleartextTraffic=false في AndroidManifest — يمنع أي رجوع صامت لـhttp
تفعيل التوقيع PAYMENTS_REQUIRE_SIGNATURE=true بعد أن يوقّع فلاتر (docs/17 — I6)
HSTS بعد التأكد من استقرار TLS — يمنع الرجوع لـhttp
بقية intaleqapp.com map-saas وnabeh على https أصلاً ✅

6. ما لا يحلّه TLS

  • لا يحمي من تطبيق مُفكَّك: TLS يحمي القناة لا الطرف. الحماية من الطرف هي الاستحقاقات على السيرفر (19-entitlements-licensing).
  • لا يمنع pinning bypass: من يملك الجهاز يرى حركته. لذلك تبقى القاعدة: السيرفر لا يثق بالعميل أبداً.

← ذو صلة: 15-deploy-flow · 14-server-conventions · 17-backend-backlog