
Knocker، خدمة تحكم بالوصول تعتمد على النقر (knock) لمعملك المنزلي.

Knocker هي خدمة ذاتية الاستضافة توفر بوابة "طرق-طرق" (knock-knock) للترخيص أحادي الحزمة (SPA) قائمة على HTTP لبيئة Homelab الخاصة بك، مع عملاء للويب و CLI وجنوم وأندرويد. يمكن استخدامها كمصادقة للوكيل العكسي الخاص بك مثل Caddy، أو حتى على مستوى جدار الحماية باستخدام تكامل FirewallD. تتيح لك إبقاء خدماتك خاصة تمامًا، وفتحها عند الطلب فقط لعناوين IP المصرح بها.
هذا مثالي لبيئات Homelab حيث تريد كشف الخدمات للإنترنت دون اتصال VPN دائم، مع تقليل سطح الهجوم العام المواجه للجمهور.
Knocker-Web تطبيق ويب PWA ثابت يدعم الطرق (الإدراج في القائمة البيضاء) عند إعادة التحميل
Knocker-CLI أداة CLI مكتوبة بلغة Go مع دعم للطرق الخلفية التي تُفعَّل اختياريًا عند تغيير عنوان IP.
Knocker-gnome امتداد جنوم مبني على Knocker-cli.
Knocker-EXPO تطبيق أندرويد تجريبي مكتوب بـ React EXPO مع دعم لطلبات الطرق الخلفية
sequenceDiagram
participant User
participant Caddy as Reverse Proxy (Caddy)
participant Knocker
participant Service as Protected Service
User->>Caddy: HTTP request to protected service
Caddy->>Knocker: GET /verify (copies X-Forwarded-For)
Knocker-->>Knocker: check always_allowed_ips / excluded_paths / whitelist
alt IP whitelisted
Knocker-->>Caddy: 200 OK (empty body)
Caddy->>Service: forward request
Service-->>Caddy: 200 OK
Caddy-->>User: 200 OK
else IP not whitelisted
Knocker-->>Caddy: 401 Unauthorized (empty body)
Caddy-->>User: 401 Unauthorized
end
Note over User,Knocker: Performing a "knock" (to add whitelist entry)
User->>Knocker: POST /knock (X-Api-Key, optional ip_address, ttl)
Knocker->>Knocker: validate API key, determine client IP
Knocker->>Knocker: update whitelist.json with expiry
Knocker-->>User: 200 OK (whitelisted_entry, expires_at, expires_in_seconds)
صُمم هذا المشروع ليُنشر كحاوية Docker باستخدام ملف docker-compose.yml المرفق. يستخدم صور Docker المجمعة مسبقًا مع دعم لـ AMD64 و ARMv8 و ARMv7
يوفر Knocker علامات صور مختلفة لحالات استخدام مختلفة:
latest أحدث إصدار مستقر (موصى به للإنتاج)v1.2.3 علامات إصدارات محددة (إصدارات مثبتة)main فرع التطوير (تحديثات مستمرة، قد يكون غير مستقر)الإعداد:
knocker.example.yaml إلى knocker.yaml.knocker.yaml إلى سلاسل عشوائية آمنة خاصة بك.trusted_proxies في knocker.yaml، يجب أن تطابق الشبكة الفرعية لشبكة الوكيل العكسي (docker network inspect xxx)whitelist.storage_path داخل دليل عمل التطبيق، أو /data، أو /tmp.firewalld.enabled: true وضبط الإعدادات ذات الصلة. ملاحظة: يتطلب ذلك تشغيل الحاوية بصلاحيات الجذر.تشغيل الخدمة:
docker compose up -d
سيقوم هذا بسحب صورة knocker المجمعة مسبقًا وبدء كل من خدمتي knocker و caddy.
يعمل Knocker كبوابة مصادقة للوكيل العكسي الخاص بك. يوفر مسار تحقق (verify) للتحقق مما إذا كان عنوان IP الطالب مدرجًا في القائمة البيضاء أم لا، وإذا لم يكن كذلك، فسيرد برمز 401 وسيرفض الوكيل العكسي الاتصال.
لدى Caddy توجيه forward_auth للتحقق من الاتصالات باستخدام مسار مصادقة.
تعريف مقتطف قابل لإعادة الاستخدام: من أفضل الممارسات تعريف مقتطف في Caddyfile الخاص بك لفحص المصادقة.
حماية خدماتك: استورد المقتطف لأي خدمة تريد حمايتها.
مثال Caddyfile:
# Caddyfile
# Define a reusable snippet for the knock-knock check.
# It points to the knocker service using Docker's internal DNS.
(knocker_auth) {
forward_auth knocker:8000 {
uri /verify
}
}
# The public endpoint for performing the knock.
# Make sure this domain points to your Caddy server's IP.
knock.your-domain.com {
reverse_proxy knocker:8000
}
# An example protected service.
jellyfin.your-domain.com {
import knocker_auth # Apply the forward_auth check
reverse_proxy jellyfin_service_name:8096
}
عندما لا يكون المستخدم مدرجًا في القائمة البيضاء، سيعيد توجيه forward_auth في Caddy استجابة 401 Unauthorized بجسم فارغ.
ملاحظة مهمة: توجيه handle_errors في Caddy لا يعمل مع استجابات forward_auth. تأتي استجابة الخطأ مباشرة من خدمة المصادقة (knocker)، وليس من Caddy نفسه، لذلك لا يمكن لـ handle_errors اعتراض هذه الاستجابات أو تعديلها.
يوفر Knocker تكاملًا متقدمًا مع جدار الحماية عبر firewalld، حيث ينشئ قواعد ديناميكية ومؤقتة لجدار الحماية تنتهي تلقائيًا استنادًا إلى TTL المحدد في طلبات الطرق. تعمل هذه الميزة على مستوى الشبكة، مما يتيح لك استخدام knocker للخدمات غير المعتمدة على HTTP مثل SSH أو خوادم الألعاب.
sequenceDiagram
participant Client as User
participant Firewall as Firewalld (knocker zone)
participant Knocker
participant Service as Protected Service (port 22)
Note over Client,Firewall: Initial state — monitored port is blocked by default
Client->>Firewall: TCP SYN to Service:22
Firewall-->>Client: DROP (no response)
Note over Client,Knocker: User performs a knock to whitelist their IP
Client->>Knocker: POST /knock (X-Api-Key, optional ip_address, ttl)
Knocker->>Knocker: validate API key & determine client IP
Knocker->>Firewall: add rich accept rule for client IP on port 22 with timeout
Firewall-->>Knocker: success
Note over Firewall,Client: New rule overrides DROP due to higher priority
Client->>Firewall: TCP SYN to Service:22
Firewall->>Service: forward packet
Service-->>Client: TCP SYN-ACK (connection established)
Knocker->>Knocker: update whitelist.json with expiry
يتطلب Knocker إصدار FirewallD 2.0+ بسبب الاعتماد على ميزة أولوية المنطقة (zone priority). وهو متوفر في Debian 13 و Ubuntu 24.04 LTS وغيرها من التوزيعات المستقرة الحديثة.
تم اختيار FirewallD لقدرته على فصل واجهة سطر الأوامر (CLI) عن البرنامج الخفي (daemon). يتيح ذلك لـ Knocker التحكم في firewalld من داخل حاوية Docker عن طريق تركيب مقبس D-Bus الخاص بالنظام، كما يدعم FirewallD القواعد المؤقتة، لذا تنتهي قواعد knocker تلقائيًا عند انتهاء TTL.
لن يعمل FIREWALLD مع المنافذ المنشورة عبر Docker (PUBLISHED PORTS)، راجع هذه المشكلة لمزيد من التفاصيل.