> ## Content Index
> Fetch the complete content index at: https://arabroot.io/llms.txt
> Use this file to discover other available public pages before exploring further.

# تشغيل خادمك من إنترنت المنزل: CGNAT وDDNS وCloudflare Tunnel
- URL: https://arabroot.io/articles/تشغيل-خادمك-من-إنترنت-المنزل/
- Published: 2026-09-17T15:20:00.000Z
- Updated: 2026-10-05T13:28:19.000Z
- Description: هل يمكنك تشغيل خدماتك من اتصال الإنترنت في منزلك؟ يشرح هذا الدليل كيف تعرف ما يسمح به اتصالك، ومتى يكفي توجيه المنافذ، ولماذا يكون Cloudflare Tunnel غالباً الحل الأسهل والأكثر أماناً.
- Author: فريق عرب رووت
- Tags: الأدلة التقنية, الشبكات والوصول, هوم لاب, الاستضافة الذاتية, Cloudflare Tunnel

لنفرض أن لديك في المنزل أو المكتب جهازاً صغيراً، حاسوباً قديماً أو Raspberry Pi أو جهاز تخزين شبكي NAS، وتريد أن تشغل عليه خدماتك بدل أن تدفع اشتراكاً شهرياً لسيرفر في السحابة، فالفكرة مغرية لأن مساحة التخزين Storage عندك كبيرة ورخيصة، وبياناتك تحت سقف بيتك حرفياً. ولكن سوف تجد أن اتصال الإنترنت المنزلي مصمم لكي *تطلب* أنت من الإنترنت، وليس لكي يطلب الإنترنت منك، فالزائر الذي يكتب اسم موقعك من الخارج لا يعرف طريقاً إلى جهاز يجلس خلف ال Router في منزلك.

والحل البسيط الذي يخطر على البال هو أن تدخل إلى لوحة ال Router وتفتح منفذاً، ثم تعطي الناس عنوانك العام، ولكن هذا الحل يفشل عند أغلب الناس لثلاثة أسباب: فقد لا يكون لديك عنوان عام Public IP أصلاً لأن مزود الخدمة يضعك خلف CGNAT، وإذا كان لديك عنوان عام فهو غالباً يتغير كل بضعة أيام، وإذا ثبت العنوان وفتحت المنفذ فقد أصبح جهاز في منزلك مكشوفاً للإنترنت كله. لذلك سوف نمر على هذه العقبات بالترتيب، ثم ننتقل إلى الطريق الذي نوصي به في أغلب الحالات، وهو [**Cloudflare Tunnel**](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/?ref=arabroot.io)، حيث يتجاوز هذه العقبات كلها باتصال صادر Outbound يبدؤه جهازك بنفسه.

وسوف نناقش في هذا المقال ما يلي:

- كيف تعرف هل لديك عنوان عام، أم أنك خلف CGNAT.
- العنوان الثابت والعنوان المتغير، وكيف يعطيك DNS الديناميكي Dynamic DNS اسماً ثابتاً لعنوان يتغير.
- توجيه المنافذ Port Forwarding بالطريقة الصحيحة، وما الذي لا يجب أن توجهه أبداً.
- تشغيل Cloudflare Tunnel في Docker بنفق مؤقت للتجربة، ثم بنفق دائم تديره من اللوحة أو من ملف إعداد.
- مقارنة الطرق من ناحية الأمان، ثم التحقق والنسخ الاحتياطي والتحديث وأشهر المشكلات.

وقبل أن تبدأ، لا تستضف من المنزل خدمة حرجة لعمل مؤسستك تحتاج إلى التوافرية High Availability، والسبب أن الكهرباء والإنترنت في المنزل ينقطعان، وسرعة الرفع Upload في أغلب الاشتراكات أقل بكثير من سرعة التنزيل Download، وفي هذه الحالة يناسبك سيرفر افتراضي صغير، وتجد معايير اختياره في دليل [كيف تختار خادماً افتراضياً VPS](https://arabroot.io/articles/%D9%83%D9%8A%D9%81-%D8%AA%D8%AE%D8%AA%D8%A7%D8%B1-%D8%AE%D8%A7%D8%AF%D9%85%D8%A7-%D8%A7%D9%81%D8%AA%D8%B1%D8%A7%D8%B6%D9%8A%D8%A7-vps/). وكثيرون يجمعون بين الاثنين، فتبقى البيانات الكبيرة في المنزل، وتكون نقطة الدخول Entry Point على سيرفر VPS.

## ما تحتاجه قبل أن تبدأ

- جهاز يعمل على مدار الساعة، عليه Linux وDocker، وإذا لم يكن Docker جاهزاً فاتبع دليل [تثبيت Docker على Ubuntu](https://arabroot.io/articles/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-docker-%D8%B9%D9%84%D9%89-ubuntu/). والأفضل أن يتصل بالشبكة بكابل وليس عبر Wi-Fi، وأن يكون موصولاً بمزود طاقة احتياطي UPS إن أمكن.
- صلاحية الدخول إلى لوحة إدارة ال Router، إذا اخترت توجيه المنافذ.
- نطاق Domain تملكه، ولاحظ أن مسار Cloudflare Tunnel يشترط أن تكون [خوادم أسماء النطاق Nameservers لدى Cloudflare](https://developers.cloudflare.com/dns/zone-setups/full-setup/?ref=arabroot.io)، والخطة المجانية تكفي.
- راجع شروط مزود خدمة الإنترنت ISP، فبعض العقود المنزلية تمنع تشغيل السيرفرات، أو تحجب الاتصالات الواردة Inbound على المنافذ 25 و80 و443.

## هل لديك عنوان عام أصلاً؟ اكتشاف CGNAT

عندما نفدت عناوين IPv4، أصبح كثير من مزودي الإنترنت يضعون عدداً من المشتركين خلف عنوان عام واحد، وهذا شائع في شبكات الجوال وفي كثير من اشتراكات الألياف الحديثة، واسم هذه التقنية الترجمة على مستوى المزود **Carrier-Grade NAT** واختصاراً CGNAT. وفي هذه الحالة يحصل ال Router لديك على عنوان خاص Private IP من شبكة المزود وليس على عنوان عام، والنتيجة أنه لا يوجد منفذ تستطيع فتحه، لأن الباب الخارجي عند المزود وليس عندك، فأنت تشبه ساكناً في عمارة يستطيع أن يفتح باب شقته كما يشاء، ولكن باب العمارة مع الحارس.

ولكي تعرف وضعك، قارن بين عنوانين:

1. **عنوان WAN** كما يظهر في صفحة الحالة في ال Router (Status أو Internet).
2. **عنوانك العام** كما يراه الإنترنت، وتعرفه بالأمر التالي من أي جهاز في المنزل:

```bash
curl -4 -s https://api.ipify.org; echo
```

إذا تطابق العنوانان فلديك عنوان عام، وإذا اختلفا فأنت خلف طبقة NAT إضافية. وإذا كان عنوان WAN ضمن النطاق `100.64.0.0/10` (من `100.64.x.x` إلى `100.127.x.x`)، فهو من مساحة العناوين التي خصصتها [RFC 6598](https://www.rfc-editor.org/rfc/rfc6598?ref=arabroot.io) لشبكات CGNAT تحديداً، والفحص التالي يكشف ذلك:

```bash
ip=100.72.13.5
IFS=. read a b c d <<<"$ip"
if [ "$a" -eq 100 ] && [ "$b" -ge 64 ] && [ "$b" -le 127 ]; then echo "$ip is CGNAT (100.64.0.0/10)"; fi
```

```bash
100.72.13.5 is CGNAT (100.64.0.0/10)
```

وهناك مؤشر آخر، وهو أن تشغل الأمر `traceroute -n 1.1.1.1` من جهاز في المنزل، فإذا ظهر بعد ال Router مباشرة عنوان من `100.64.0.0/10` أو من شبكة خاصة Private Network، فهذا يعني أن هناك طبقة NAT عند المزود.

وإذا كنت خلف CGNAT فأمامك ثلاثة خيارات: الأول أن تطلب من المزود عنواناً عاماً، فبعض المزودين يعطيه مجاناً عند الطلب وبعضهم بمقابل. والثاني IPv6 إذا كان مزودك يوفره، حيث يحصل كل جهاز على عنوان عام ولا توجد ترجمة عناوين، ولكن جدار الحماية Firewall في ال Router يمنع الاتصالات الواردة افتراضياً فتحتاج إلى قاعدة تسمح بها لعنوان السيرفر، والزوار الذين ليس لديهم IPv6 لن يصلوا إليه مباشرة. والثالث أن تتجاوز المشكلة كلها بنفق Tunnel صادر، كما سيأتي في قسم Cloudflare Tunnel.

### الوصول إلى جهاز المنزل من العمل خلف CGNAT

وهذه حالة من تجربة شخصية، فاتصال منزلي خلف CGNAT، وشبكة العمل لا تسمح بتثبيت أي برنامج VPN ولا يخرج منها إلا اتصال سطح المكتب البعيد Remote Desktop Protocol واختصاراً RDP، لذلك أصل إلى جهازي في المنزل عبر سيرفر آخر: جهاز المنزل يفتح بنفسه نفق SSH عكسياً Reverse SSH Tunnel إلى سيرفر VPS، ومن العمل أتصل ب RDP بهذا السيرفر فيوصلني النفق إلى جهاز المنزل. والاتجاه هنا هو سر الحل، فالاتصال يخرج من المنزل ولا يدخل إليه، وبالتالي لا يهم أن العنوان غير عام. أما الخطوات كاملة، أي كيف تحصر المنفذ على عنوان العمل وحده وكيف تبقي النفق متصلاً، فقد شرحناها في [شرح الأنفاق Tunnels في الشبكات](https://arabroot.io/articles/%D9%85%D8%A7-%D9%87%D9%88-%D8%A7%D9%84%D9%86%D9%81%D9%82-tunnel-%D9%81%D9%8A-%D8%A7%D9%84%D8%B4%D8%A8%D9%83%D8%A7%D8%AA/#rdp-case).

## هل تحتاج إلى عنوان ثابت؟

حتى لو كان لديك عنوان عام، فهو يتغير غالباً في الاشتراكات المنزلية، إما عند إعادة تشغيل ال Router أو كل بضعة أيام، والعنوان الثابت Static IP خدمة إضافية بمقابل عند أغلب المزودين. فهل تحتاجه فعلاً؟ الجدول التالي يقارن بين الخيارات الثلاثة:

|                         | عنوان ثابت                                                                     | عنوان متغير مع DDNS                        | نفق صادر                            |
| ----------------------- | ------------------------------------------------------------------------------ | ------------------------------------------ | ----------------------------------- |
| التكلفة                 | رسوم شهرية في الغالب                                                           | مجاني                                      | مجاني للاستخدام الأساسي             |
| عند تغير العنوان        | لا يتغير                                                                       | انقطاع لبضع دقائق حتى يتحدث سجل DNS Record | لا أثر له، فالنفق يعيد الاتصال وحده |
| يعمل خلف CGNAT          | نعم، لأن المزود يمنحك عنواناً عاماً فعلياً                                     | لا يعمل                                    | نعم                                 |
| البريد الإلكتروني Email | ممكن مع سجل PTR، مع أن كثيراً من قوائم الحظر Blocklists تحظر العناوين المنزلية | غير عملي                                   | غير مناسب للبريد                    |
| يكشف عنوان منزلك        | نعم                                                                            | نعم                                        | لا يكشفه                            |

## اسم ثابت لعنوان يتغير: DDNS

فكرة DNS الديناميكي Dynamic DNS واختصاراً DDNS بسيطة، وهي برنامج صغير على جهازك يراقب عنوانك العام، ويحدث سجل `A` للنطاق `home.example.com` كلما تغير العنوان. وكثير من أجهزة ال Router فيها عميل DDNS Client مدمج يدعم مزودين محددين، فإذا كان مزودك منهم فهذا أبسط خيار.

أما إذا كان نطاقك لدى Cloudflare، فسوف نستخدم السكربت التالي، وهو يعمل عبر [واجهة Cloudflare البرمجية API لتعديل سجلات DNS](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/edit/?ref=arabroot.io). أنشئ أولاً سجل `A` للاسم يدوياً من اللوحة، ثم أنشئ [توكن API Token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/?ref=arabroot.io) بصلاحية *Zone › DNS › Edit* على هذه المنطقة Zone وحدها، والسبب أن التوكن سوف يبقى في ملف على جهاز منزلي، فإذا تسرب لا يستطيع صاحبه أن يعبث بباقي نطاقاتك. بعد ذلك ثبت الأدوات اللازمة:

```bash
sudo apt install -y curl jq
```

واحفظ الأسرار Secrets في الملف `/etc/cf-ddns.env` بصلاحية `600` حتى لا يقرأه غير root:

```bash
sudo tee /etc/cf-ddns.env >/dev/null <<'EOF'
CF_API_TOKEN=ضع-الرمز-هنا
CF_ZONE_ID=0123456789abcdef0123456789abcdef
CF_RECORD_NAME=home.example.com
EOF
sudo chmod 600 /etc/cf-ddns.env
```

والسكربت `/usr/local/bin/cf-ddns.sh` سوف يكون كما يلي:

```bash
#!/usr/bin/env bash
set -euo pipefail
source /etc/cf-ddns.env
STATE=/var/lib/cf-ddns.last
IP=$(curl -4 -fsS --max-time 10 https://api.ipify.org)
[[ $IP =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]] || { echo "bad IP: $IP" >&2; exit 1; }
[[ -f $STATE && $(cat "$STATE") == "$IP" ]] && exit 0
API=https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records
AUTH=(-H "Authorization: Bearer $CF_API_TOKEN" -H "Content-Type: application/json")
ID=$(curl -fsS "${AUTH[@]}" "$API?type=A&name=$CF_RECORD_NAME" | jq -r '.result[0].id')
[[ -n $ID && $ID != null ]] || { echo "record $CF_RECORD_NAME not found" >&2; exit 1; }
curl -fsS -X PATCH "${AUTH[@]}" "$API/$ID" --data "{\"content\":\"$IP\"}" | jq -e '.success' >/dev/null
echo "$IP" > "$STATE"
logger -t cf-ddns "updated $CF_RECORD_NAME to $IP"
```

في السكربت أعلاه لاحظ التالي:

- يتحقق السكربت من أن ما أعاده الموقع عنوان IPv4 صحيح قبل أن يرسله، حتى لا يكتب في السجل صفحة خطأ أو نصاً فارغاً.
- يحفظ آخر عنوان سجله في ملف حالة، ولا يتصل بالواجهة البرمجية إلا إذا تغير العنوان، وبالتالي لا يستهلك حدود الطلبات Rate Limits وهو يعمل كل خمس دقائق.
- يستخدم الطلب PATCH ليعدل محتوى السجل فقط، ويترك باقي إعداداته كما هي.

الآن اجعله قابلاً للتنفيذ، وجدوله ليعمل كل خمس دقائق، ثم شغله مرة يدوياً:

```bash
sudo chmod 755 /usr/local/bin/cf-ddns.sh
echo '*/5 * * * * root /usr/local/bin/cf-ddns.sh' | sudo tee /etc/cron.d/cf-ddns
sudo /usr/local/bin/cf-ddns.sh && journalctl -t cf-ddns -n 5
```

وإذا كان التوكن غير صالح فسوف ترفضه الواجهة برسالة مثل `curl: (22) ... error: 400`، ويتوقف السكربت دون أن يحفظ الحالة، فيعيد المحاولة في الدورة التالية، ومع توكن صالح يتحدث السجل. واجعل [مدة بقاء السجل TTL](https://developers.cloudflare.com/dns/manage-dns-records/reference/ttl/?ref=arabroot.io) قصيرة، 60 أو 120 ثانية، حتى يسري التغيير بسرعة.

## فتح المنافذ في ال Router بالطريقة الصحيحة

ال Router يرفض كل اتصال وارد لم يطلبه جهاز داخلي، و**توجيه المنافذ Port Forwarding** قاعدة تقول له: أرسل كل ما يصل على المنفذ 443 إلى الجهاز `192.168.1.50` على المنفذ 443\. والشاشات تختلف من جهاز إلى آخر، ولكن الخطوات واحدة:

1. أعط السيرفر عنواناً داخلياً ثابتاً عن طريق حجز DHCP Reservation في ال Router، وليس بتعيينه يدوياً على السيرفر، والسبب أن ال Router يبقى هو المرجع الوحيد للعناوين فلا يعطي عنوان السيرفر لجهاز آخر.
2. في صفحة Port Forwarding أو NAT أو Virtual Server، وجه المنفذ الخارجي `443/tcp` إلى `192.168.1.50:443`، والمنفذ `80/tcp` إلى `192.168.1.50:80`، ولاحظ أن المنفذ 80 لازم [للتحقق عبر HTTP (HTTP Challenge) في Let's Encrypt](https://letsencrypt.org/docs/challenge-types/?ref=arabroot.io). وأضف `51820/udp` إذا كنت سوف تشغل [WireGuard](https://www.wireguard.com/?ref=arabroot.io).
3. شغل على السيرفر Reverse Proxy واحداً يستقبل المنفذين 80 و443 ويوزع الطلبات على الخدمات، مثل [Nginx Proxy Manager](https://arabroot.io/articles/nginx-proxy-manager-%D9%86%D8%B7%D8%A7%D9%82%D8%A7%D8%AA-%D9%88%D8%B4%D9%87%D8%A7%D8%AF%D8%A7%D8%AA-tls/)، ولا توجه منفذاً مستقلاً لكل تطبيق.
4. عطل UPnP في ال Router، لأنها تسمح لأي جهاز داخلي أن يفتح منافذ لنفسه دون علمك.

واختبر الوصول من شبكة أخرى مثل بيانات الهاتف، وليس من شبكة المنزل، والسبب أن كثيراً من أجهزة ال Router لا تدعم الوصول إلى عنوانها العام من داخل الشبكة، وهي الخاصية التي تسمى NAT Loopback أو Hairpin. ومن الخارج نفذ:

```bash
curl -sI https://home.example.com | head -n 1
nc -vz home.example.com 443
```

🛑

كل منفذ توجهه يجعل جهازاً في منزلك هدفاً مباشراً لعمليات المسح الآلي Automated Scanning على الإنترنت، وهذا الجهاز يشارك نفس الشبكة مع حواسيب العائلة وهواتفها. لذلك لا توجه أبداً المنافذ الإدارية، مثل SSH (22) أو لوحات الإدارة أو قواعد البيانات Databases أو SMB، وللوصول الإداري من الخارج استخدم شبكة خاصة افتراضية VPN كما في دليل [شبكة خاصة مع WireGuard وwg-easy](https://arabroot.io/articles/%D8%B4%D8%A8%D9%83%D8%A9-%D8%AE%D8%A7%D8%B5%D8%A9-%D9%85%D8%B9-wireguard-%D9%88-wg-easy/). وإن أمكنك، فضع السيرفر في شبكة منفصلة (VLAN أو منطقة DMZ حقيقية) تمنعه من الوصول إلى بقية أجهزة المنزل.

## الطريق الذي نوصي به: Cloudflare Tunnel

بدل أن تفتح منفذاً في ال Router، سوف تشغل على السيرفر برنامجاً صغيراً اسمه `cloudflared`، وهذا البرنامج يفتح اتصالات **صادرة** مشفرة Encrypted إلى شبكة Cloudflare ويبقيها مفتوحة. وعندما يطلب زائر `app.example.com` يصل طلبه إلى Cloudflare أولاً، فتمرره عبر ذلك الاتصال المفتوح إلى `cloudflared`، وهو بدوره يسلمه إلى ال Container المحلي، أي أن الباب يفتح من الداخل ولا يحتاج أحد إلى طرقه من الخارج. فماذا تكسب عملياً؟

- يعمل النفق خلف CGNAT، ومع العنوان المتغير، ومع المزود الذي يحجب المنفذين 80 و443، ولا يحتاج إلى DDNS.
- لا يبقى في ال Router أي منفذ وارد مفتوح، ولا يظهر عنوان منزلك في سجلات DNS.
- تصدر Cloudflare شهادة TLS Certificate العامة تلقائياً.
- تستطيع أن تضع طبقة تسجيل دخول عبر [Cloudflare Access](https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/self-hosted-public-app/?ref=arabroot.io)، وهي جزء من منصة Zero Trust، أمام أي تطبيق دون أن تعدل فيه شيئاً.

### تجربة سريعة دون حساب

قبل الإعداد الدائم، تأكد أن شبكتك تسمح ل `cloudflared` بالاتصال بالخارج، واستخدم لذلك [نفقاً مؤقتاً Quick Tunnel](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/do-more-with-tunnels/trycloudflare/?ref=arabroot.io) على نطاق عشوائي من `trycloudflare.com`. وملف Compose التالي للتجربة فقط:

```yaml
services:
  whoami:
    image: traefik/whoami:v1.11.0
    restart: unless-stopped

  cloudflared:
    image: cloudflare/cloudflared:2026.9.3
    command: tunnel --no-autoupdate --url http://whoami:80
    depends_on:
      - whoami
```

```bash
docker compose up -d
docker compose logs cloudflared | grep -A1 'quick Tunnel has been created'
```

وخلال ثوان سوف يظهر عنوان مثل `https://considerations-logistics-act-soonest.trycloudflare.com`، وطلبه من الإنترنت يجب أن يعود بالرمز `200`. ولاحظ أن التطبيق تصله ترويسات Headers منها `X-Forwarded-Proto: https` و`Cf-Connecting-Ip`، والأخيرة فيها عنوان الزائر الحقيقي. وقبل ذلك يطبع `cloudflared` جدولاً بنتائج فحوص الاتصال Connectivity Checks، وهو يفيدك في التشخيص Troubleshooting:

```bash
|  UDP Connectivity  region1.v2.argotunnel.com  PASS    QUIC connection successful    |
|  TCP Connectivity  region1.v2.argotunnel.com  PASS    HTTP/2 connection successful  |
|  Cloudflare API    api.cloudflare.com:443     PASS    API is reachable              |
|  SUMMARY: Environment is healthy. cloudflared will use 'quic' as primary protocol.  |
```

وهذا النفق السريع للتجربة فقط، والسبب أن عنوانه يتغير مع كل تشغيل، ولا يوجد ضمان لتوفره، ولا يقبل أكثر من 200 طلب متزامن. أوقفه بالأمر `docker compose down`، وانتقل إلى النفق المسمى Named Tunnel.

### نفق دائم تديره من لوحة Cloudflare

هذه الطريقة تسمى [remotely-managed tunnel](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/get-started/create-remote-tunnel/?ref=arabroot.io)، وهي الأسهل في الصيانة، لأنك تدير القواعد Rules من اللوحة، والسيرفر لا يحتاج إلا إلى توكن واحد. والخطوات في لوحة Cloudflare كما يلي، مع العلم أن أسماء بعض العناصر قد تتغير قليلاً مع تحديثات الواجهة:

1. افتح Networking ثم Tunnels ثم Create a tunnel، وسم النفق (`home-server`).
2. في صفحة التثبيت اختر Docker، وسوف تعرض اللوحة أمراً فيه `--token eyJ...`، فانسخ منه **التوكن فقط**.
3. في تبويب Routes اختر Add route ثم Published application، وأضف لكل خدمة النطاق الفرعي Subdomain `app` والنطاق `example.com`، وفي Service URL اختر النوع `HTTP` والعنوان `whoami:80`. وسوف تنشئ Cloudflare سجل DNS من نوع CNAME تلقائياً.

وعلى السيرفر أنشئ المجلد `/opt/cloudflared`، وضع فيه ملف `.env` بصلاحية `600`:

```bash
sudo mkdir -p /opt/cloudflared
sudo chown $USER: /opt/cloudflared
cd /opt/cloudflared
printf 'TUNNEL_TOKEN=%s\n' 'الصق-الرمز-هنا' > .env
chmod 600 .env
```

ثم أنشئ الملف `/opt/cloudflared/compose.yaml`، وسوف نضع فيه `cloudflared` على شبكة `proxy` التي تعمل عليها تطبيقاتك، وبالتالي يصل إليها بأسماء ال Containers دون نشر أي منفذ:

```yaml
services:
  cloudflared:
    image: cloudflare/cloudflared:2026.9.3
    container_name: cloudflared
    restart: unless-stopped
    command: tunnel --no-autoupdate --metrics 127.0.0.1:2000 run
    environment:
      TUNNEL_TOKEN: ${TUNNEL_TOKEN}
    networks:
      - proxy
    healthcheck:
      test: ["CMD", "cloudflared", "tunnel", "--metrics", "localhost:2000", "ready"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 20s

networks:
  proxy:
    external: true
```

في الإعداد أعلاه لاحظ التالي:

- `--no-autoupdate`: نحدث ال Container بتغيير الوسم Tag، وليس بالتحديث الذاتي Auto-update، حتى تعرف دائماً أي إصدار يعمل عندك.
- `--metrics`: يشغل [سيرفر المقاييس Metrics](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/monitor-tunnels/metrics/?ref=arabroot.io) داخل ال Container، ومنه النقطة `/ready`، وعليها يعتمد فحص الصحة Health Check عبر الأمر `cloudflared tunnel ready`، والسبب أن ال Image ليس فيها Shell ولا `curl`. وبعد اتصال النفق تصبح حالة ال Container `healthy`، وتعيد النقطة `/ready` قيمة مثل `"readyConnections":1`.
- التوكن في ملف `.env` وليس في ملف Compose، حتى لا يصل إلى Git، لأن من يملك التوكن يستطيع أن يشغل نفقك من أي مكان.

```bash
docker network create proxy
docker compose up -d
docker compose ps
docker compose logs --tail 20 cloudflared
```

وعند تشغيل الأوامر ابحث في السجل Log عن العبارة `Registered tunnel connection`، وسوف تجدها عادة أربع مرات، كل مرة اتصال بمركز بيانات Data Center مختلف، وفي لوحة Cloudflare تصبح حالة النفق Healthy.

### هل تحتاج إلى Reverse Proxy خلف النفق؟

تستطيع أن توجه كل اسم في النفق إلى ال Container الخاص به مباشرة (`http://gitea:3000`)، وهذا يكفي غالباً. أما إذا كان لديك Nginx Proxy Manager بقوائم وصول Access Lists وإعدادات جاهزة، فوجه كل الأسماء إلى `http://npm:80` ودعه يوزع الطلبات حسب اسم النطاق، وفي هذه الحالة لا تفعل Force SSL في NPM، والسبب أن الاتصال بين `cloudflared` وNPM يجري عبر HTTP بينما يرى المستخدم HTTPS، أو فعل خيار الثقة بترويسة البروتوكول القادمة من ال Proxy كما في دليل NPM، وإلا فسوف تدخل في حلقة تحويل Redirect Loop لا تنتهي.

### إذا كنت تفضل القواعد في ملف إعداد

إذا كنت تفضل حفظ القواعد في Git بدل اللوحة، فأنشئ [النفق من الطرفية Terminal](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/do-more-with-tunnels/local-management/create-local-tunnel/?ref=arabroot.io) (`cloudflared tunnel login` ثم `cloudflared tunnel create home-server` ثم `cloudflared tunnel route dns home-server app.example.com`)، ثم اكتب [ملف الإعداد](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/do-more-with-tunnels/local-management/configuration-file/?ref=arabroot.io) `config.yml`:

```yaml
tunnel: 6ff42ae2-765d-4adf-8112-31c55c1551ef
credentials-file: /etc/cloudflared/6ff42ae2-765d-4adf-8112-31c55c1551ef.json
ingress:
  - hostname: app.example.com
    service: http://whoami:80
  - hostname: git.example.com
    service: http://gitea:3000
  - service: http_status:404
```

ولاحظ أن القاعدة الأخيرة بدون اسم، وهي إلزامية لأنها ترد على أي اسم غير معروف. افحص الملف قبل التشغيل، ثم اختبر أي قاعدة تطابق رابطاً معيناً:

```bash
docker run --rm -v "$PWD/config.yml:/etc/cloudflared/config.yml:ro" cloudflare/cloudflared:2026.9.3 tunnel --config /etc/cloudflared/config.yml ingress validate
docker run --rm -v "$PWD/config.yml:/etc/cloudflared/config.yml:ro" cloudflare/cloudflared:2026.9.3 tunnel --config /etc/cloudflared/config.yml ingress rule https://git.example.com/user/repo
```

والمخرج سوف يكون كما يلي:

```bash
Validating rules from /etc/cloudflared/config.yml
OK
Using rules from /etc/cloudflared/config.yml
Matched rule #1
	hostname: git.example.com
	service: http://gitea:3000
```

ولاحظ أن الترقيم يبدأ من صفر، فالقاعدة رقم 1 هي الثانية في الملف. بعد ذلك شغل ال Container بالأمر `tunnel --no-autoupdate --config /etc/cloudflared/config.yml run`، وركب Mount فيه المجلد الذي فيه `config.yml` وملف بيانات الاعتماد Credentials `.json`.

## أي طريق أقل خطراً؟

|                                   | توجيه المنافذ     | Cloudflare Tunnel                                                                                                                                                                                                                                 | VPS وسيط مع WireGuard                                      |
| --------------------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| منافذ واردة في المنزل             | 80 و443 على الأقل | لا توجد منافذ واردة                                                                                                                                                                                                                               | لا توجد منافذ واردة، فالسيرفر المنزلي هو الذي يتصل بال VPS |
| عنوان المنزل مكشوف                | نعم               | لا                                                                                                                                                                                                                                                | لا                                                         |
| من يطلع على الحركة Traffic        | أنت وحدك          | Cloudflare، لأنها تنهي جلسة TLS (TLS Termination) وترى الحركة غير مشفرة                                                                                                                                                                           | أنت وحدك                                                   |
| البروتوكولات Protocols            | كلها              | HTTP وHTTPS للجمهور، وغيرها يحتاج إلى تطبيق cloudflared أو WARP عند المستخدم                                                                                                                                                                      | كلها                                                       |
| القيود                            | لا يعمل خلف CGNAT | [شروط الاستخدام](https://www.cloudflare.com/service-specific-terms-application-services/?ref=arabroot.io) تقيد بث الفيديو والملفات الكبيرة دون خدمات مدفوعة، والطلب الواحد في الخطة المجانية محدود بحجم 100 ميجابايت وبمهلة انتظار للرد 125 ثانية | تكلفة VPS وإدارته                                          |
| الاعتماد على طرف ثالث Third Party | لا يوجد           | كامل، فإذا تعطل حسابك أو تعطلت Cloudflare تعطلت خدماتك                                                                                                                                                                                            | مزود VPS فقط                                               |

وقد يتساءل البعض: إذا كان النفق يخفي عنوان المنزل ولا يفتح أي منفذ، فلماذا لا نستخدمه لكل شيء؟ والإجابة على ذلك أن جلسة TLS تنتهي عند Cloudflare، فهي قادرة تقنياً على رؤية كل ما يمر بها، ومنه كلمات المرور والملفات، وهذا ما يفعله ال Proxy في أي شبكة CDN، وهو مقبول عادة لمدونة أو لأداة يستخدمها فريق. أما البيانات الحساسة أو الخاضعة لمتطلبات تنظيمية Compliance، أو إذا كانت الخصوصية هي سبب استضافتك الذاتية Self-Hosting أصلاً، فالحل الأنسب هو سيرفر VPS وسيط تملكه، يشغل ال Reverse Proxy وWireGuard، ويتصل به سيرفر المنزل عبر نفق صادر، وبالتالي تبقى مفاتيح التشفير Encryption Keys عندك.

📌

في 18 نوفمبر 2025 أدى تغيير في صلاحيات إحدى قواعد البيانات لدى Cloudflare إلى مضاعفة حجم ملف إعداد يستخدمه نظام إدارة البوتات Bot Management، فتجاوز الحد الذي يتحمله ال Proxy الأساسي، وظهرت أخطاء 5xx لزوار عدد كبير من المواقع من الساعة 11:20 بتوقيت UTC، ولم تعد الحركة الأساسية إلى وضعها الطبيعي إلا قرابة 14:30، كما فشل تسجيل الدخول عبر Cloudflare Access لكثير من المستخدمين، بحسب [التقرير الرسمي من Cloudflare](https://blog.cloudflare.com/18-november-2025-outage/?ref=arabroot.io). والدرس أن خدماتك خلف النفق تتوقف عندما يتوقف المزود مهما كان سيرفرك المنزلي سليماً، لذلك اعرف مسبقاً طريقاً بديلاً للوصول الإداري مثل VPN، ولا تجعل خدمة لا تحتمل التوقف تعتمد على مزود واحد.

⚠️

النفق لا يجعل التطبيق آمناً، وإنما يغير طريق الوصول إليه فقط، فالتطبيق ما زال مكشوفاً للعالم بثغراته Vulnerabilities وكلمات مروره الضعيفة. لذلك حدثه باستمرار، وفعل فيه التحقق بخطوتين 2FA، وضع اللوحات الإدارية خلف Cloudflare Access أو خلف نظام دخول موحد SSO، أو لا تنشرها عبر النفق أصلاً.

## كيف تتأكد أن كل شيء يعمل

- الأمر `docker compose ps` يعرض ال Container `cloudflared` بحالة `healthy`، وفي السجل العبارة `Registered tunnel connection`.
- من شبكة أخرى، مثل بيانات الهاتف، يعود الأمر `curl -sI https://app.example.com` بالرمز `200` أو بتحويل إلى صفحة الدخول.
- الأمر `dig +short app.example.com` يعيد عناوين Cloudflare وليس عنوان منزلك.
- لا توجد قواعد لتوجيه المنافذ في ال Router، وUPnP معطلة، وفحص المنافذ لعنوانك العام من الخارج (بالأمر `nmap -Pn` من سيرفر VPS مثلاً) لا يجد أي منفذ مفتوح.
- التطبيق يرى عنوان الزائر الحقيقي في `Cf-Connecting-Ip` أو `X-Forwarded-For`، إذا كنت تحتاجه في السجلات.
- مع DDNS: غير العنوان بإعادة تشغيل ال Router، ثم تأكد أن `journalctl -t cf-ddns` سجل التحديث خلال خمس دقائق.

## ما الذي تنسخه وكيف تستعيده

- **النفق الذي تديره من اللوحة:** على السيرفر يوجد فقط `/opt/cloudflared/compose.yaml` و`.env`، والقواعد محفوظة في حساب Cloudflare. احفظ الملفين في نسخة احتياطية Backup في مكان آمن ومشفر، لأن `.env` فيه التوكن، واكتب قائمة الأسماء والخدمات في مستند داخلي حتى تعيد بناءها عند الحاجة.
- **النفق بملف محلي:** الملف `config.yml`، وملف بيانات الاعتماد `.json`، والملف `cert.pem` الناتج عن `tunnel login` إن كنت احتفظت به.
- **DDNS:** الملفات `/usr/local/bin/cf-ddns.sh` و`/etc/cf-ddns.env` و`/etc/cron.d/cf-ddns`.

```bash
sudo tar czf ~/home-edge-$(date +%F).tar.gz /opt/cloudflared /usr/local/bin/cf-ddns.sh /etc/cf-ddns.env /etc/cron.d/cf-ddns
```

وللاستعادة Restore على جهاز جديد، فك الأرشيف في `/`، ثم نفذ `docker network create proxy` و`docker compose up -d` داخل `/opt/cloudflared`، وسوف يتصل النفق بنفس الاسم دون أي تعديل في DNS. وإذا تسرب التوكن فأعد توليده من لوحة النفق (Refresh token)، ثم حدث ملف `.env`.

## تحديث cloudflared إلى إصدار أحدث

أرقام إصدارات `cloudflared` مبنية على التاريخ (`2026.9.3`)، وتدعم Cloudflare [الإصدارات التي لم يمض على صدورها أكثر من عام من آخر إصدار](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/downloads/?ref=arabroot.io)، لذلك لا تتركه طويلاً دون تحديث Upgrade. راجع [صفحة الإصدارات](https://github.com/cloudflare/cloudflared/releases?ref=arabroot.io)، وغير الوسم، ثم نفذ:

```bash
cd /opt/cloudflared
docker compose pull
docker compose up -d
docker compose logs --tail 20 cloudflared
```

وللتحديث دون انقطاع Zero Downtime، شغل [نسختين Replicas](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/configure-tunnels/tunnel-availability/?ref=arabroot.io) من `cloudflared` بنفس التوكن على جهازين، فتوزع Cloudflare الحركة بينهما، وتحدث واحدة ثم الأخرى.

## مشكلات شائعة وحلولها

### Error 1033 أو صفحة من Cloudflare تقول إن النفق غير متاح

[هذا الخطأ يعني](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-1xxx-errors/error-1033/?ref=arabroot.io) أن النفق غير متصل، فراجع `docker compose logs cloudflared`. والرسالة `Provided Tunnel token is not valid` تعني أن التوكن ناقص أو فيه مسافات، فانسخه من جديد. أما فشل فحص `UDP Connectivity` فيعني أن شبكتك [تحجب QUIC على المنفذ 7844](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/configure-tunnels/tunnel-with-firewall/?ref=arabroot.io)، فأضف `--protocol http2` إلى الأمر.

### 502 Bad Gateway عبر النفق

النفق يعمل، ولكن `cloudflared` لا يصل إلى التطبيق. تأكد أن الخدمة في اللوحة تشير إلى اسم ال Container ومنفذه الداخلي (`whoami:80` وليس `localhost:8080`)، والسبب أن `localhost` داخل ال Container `cloudflared` يعني ال Container نفسه. وتأكد أيضاً أن ال Containers الاثنين على نفس شبكة `proxy`.

### ERR\_TOO\_MANY\_REDIRECTS

التطبيق أو ال Reverse Proxy الذي خلف النفق يحول طلبات HTTP إلى HTTPS، بينما يصله الطلب من `cloudflared` عبر HTTP، فيتكرر التحويل بلا نهاية. اجعل التطبيق يثق بترويسة `X-Forwarded-Proto` أو عطل التحويل فيه، ثم اضبط رابطه العام (`ROOT_URL` أو ما يقابله) على `https://`.

### فشل رفع الملفات الكبيرة أو انقطاع الطلبات الطويلة

الخطة المجانية تفرض [حداً لحجم جسم الطلب الواحد Request Body](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/4xx-client-error/error-413/?ref=arabroot.io) وهو 100 ميجابايت حالياً، وتطبيقات المزامنة Sync التي تقسم الملفات إلى أجزاء تعمل عادة، أما رفع ملف كبير دفعة واحدة فيفشل بالرمز `413`. وكذلك إذا تأخر رد التطبيق أكثر من [125 ثانية](https://developers.cloudflare.com/fundamentals/reference/connection-limits/?ref=arabroot.io)، كتصدير تقرير كبير، فسوف يرى الزائر الخطأ 524\. ولنقل الملفات الكبيرة استخدم VPN أو سيرفر VPS وسيطاً.

### DDNS لا يحدث السجل

شغل السكربت يدوياً بالأمر `sudo bash -x /usr/local/bin/cf-ddns.sh`، فإذا أعادت الواجهة `400` أو `403` فالتوكن خاطئ أو ليست له صلاحية على المنطقة، والرسالة `record ... not found` تعني أن السجل غير موجود أو أن الاسم لا يطابقه. وإذا كان العنوان المكتشف من نطاق CGNAT أو عنواناً خاصاً، فالمشكلة ليست في السكربت، وإنما أنت خلف CGNAT.

### يعمل من الخارج ولا يعمل من داخل المنزل (مع توجيه المنافذ)

ال Router لا يدعم NAT Loopback، والحل سيرفر DNS داخلي يعيد العنوان الداخلي للنطاق، مثل [AdGuard Home](https://github.com/AdguardTeam/AdGuardHome?ref=arabroot.io) أو [Pi-hole](https://pi-hole.net/?ref=arabroot.io)، أو Cloudflare Tunnel الذي لا يتأثر بهذه المشكلة.

## الخلاصة

وصلنا لنهاية الموضوع، وأهم ما فيه:

- ابدأ بمقارنة عنوان WAN بعنوانك العام، فإذا كان من `100.64.0.0/10` فأنت خلف CGNAT ولن يفيدك فتح أي منفذ.
- العنوان المتغير يحله DDNS، ولكن توجيه المنافذ يكشف عنوان منزلك ويجعل جهازك هدفاً للمسح الآلي، فلا توجه إلا 80 و443 إلى Reverse Proxy واحد، ولا توجه المنافذ الإدارية أبداً.
- Cloudflare Tunnel يعمل خلف CGNAT دون أي منفذ وارد، وهو الطريق الأنسب لأغلب الخدمات المنزلية، مع العلم أن Cloudflare ترى الحركة وأن خدماتك تتوقف إذا توقفت.
- للبيانات الحساسة استخدم سيرفر VPS وسيطاً تملكه مع WireGuard، وللإدارة من الخارج استخدم VPN.
- النفق يغير طريق الوصول فقط، فحدث التطبيق وفعل 2FA وضع اللوحات الإدارية خلف Cloudflare Access.

## سجل التحديثات

- سبتمبر 2026: كتابة الدليل واختباره على cloudflared 2026.9.3.
- أكتوبر 2026: مراجعة الدليل، وتحديث خطوات لوحة Cloudflare إلى Networking ثم Tunnels وتبويب Routes، وإضافة مهلة الانتظار 125 ثانية وحدود النفق السريع.
- أكتوبر 2026: إضافة حالة الوصول إلى جهاز المنزل خلف CGNAT عبر نفق SSH عكسي، مع رابط إلى شرح الأنفاق.