Caddy كـ Reverse Proxy لـ TCP وبروكسي SSH عبر caddy-l4
Caddy الأساسي يمرر HTTP فقط. لحركة TCP الخام وSSH، ابنِ Caddy مع تطبيق layer4 من caddy-l4، أو مرّر المنافذ، أو شارك المنفذ 443 بين SSH وHTTPS حسب البروتوكول.
باختصار: لا يستطيع Caddy القياسي تمرير TCP الخام أو SSH، لأن `reverse_proxy` لديه لا يتحدث إلا HTTP. لتمرير TCP تبني Caddy مع وحدة caddy-l4 (github.com/mholt/caddy-l4) باستخدام xcaddy، ثم تضبط تطبيق `layer4` الخاص بها ليستمع على منفذ ويمرر الاتصالات، مع إمكانية اختيار الخادم الخلفي حسب البروتوكول، بحيث يتشارك SSH وHTTPS المنفذ 443.
caddy-l4 وحدة منفصلة وليست جزءاً من توزيعة Caddy الافتراضية، ولا يزال ملف README الخاص بها يصفها بأنها قيد التطوير وأن إعداداتها قد تتغير بين الإصدارات. يستخدم هذا الدليل إعدادات JSON، التي تطابق مباشرة البنية الموثقة للوحدة. إن كنت تحتاج فقط إلى تمرير HTTP أو HTTPS، فإن دليل Caddy كـ reverse proxy هو كل ما تحتاجه.
لماذا يقتصر Caddy الأساسي على HTTP
التطبيقات المدمجة في Caddy هي `http` و`tls` و`pki`. معالج `reverse_proxy` يعيش داخل تطبيق HTTP، لذا يحتاج إلى طلب HTTP محلَّل قبل أن يوجّه أي شيء. عميل SSH أو عميل PostgreSQL أو بروتوكول لعبة لا يرسل طلباً كهذا أبداً، فيرد Caddy بخطأ TLS أو HTTP.
يضيف caddy-l4 تطبيقاً منفصلاً اسمه `layer4` يعمل على الاتصالات الخام. يستطيع مطابقة البايتات الأولى من الاتصال (ترويسة SSH، ورسالة TLS ClientHello مع SNI، وسطر طلب HTTP، وبدء اتصال PostgreSQL وغيرها)، ثم التمرير أو إنهاء TLS أو تسليم التدفق إلى معالج آخر. ولأنه تطبيق مثل `http`، يمكن تشغيل الاثنين في العملية نفسها.
| الحاجة | Caddy الأساسي | Caddy + caddy-l4 |
|---|---|---|
| Reverse proxy لـ HTTPS مع TLS تلقائي | نعم | نعم |
| تمرير منافذ TCP عادي | لا | نعم (معالج `proxy`) |
| تمرير UDP | لا | نعم (الاستماع على `udp/:port`) |
| تمرير TLS كما هو حسب SNI | لا | نعم (مطابِق `tls` مع `sni`) |
| SSH وHTTPS على المنفذ نفسه | لا | نعم (مطابِقا `ssh` و`tls`) |
| دعم Caddyfile | كامل | جزئي؛ JSON هو الصيغة المرجعية |
ابنِ Caddy مع وحدة layer4
تُصرّف xcaddy برنامج Caddy مع وحدات إضافية. وبدلاً من ذلك، اختر `mholt/caddy-l4` في صفحة تنزيل Caddy الرسمية ونزّل ملفاً تنفيذياً جاهزاً. في الحالتين، تحقق بالأمر `list-modules` من ظهور وحدات `layer4` قبل كتابة الإعدادات.
# Current Caddy needs a recent Go toolchain; distro golang-go packages are
# often too old, so install the latest release from https://go.dev/dl/
# and make sure /usr/local/go/bin is in PATH, then:
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
# Build Caddy with the layer4 app
~/go/bin/xcaddy build --with github.com/mholt/caddy-l4
# Confirm the modules are present
./caddy list-modules | grep layer4استبدل الملف التنفيذي المثبت من الحزمة بأمان
إن ثُبّت Caddy من مستودع apt الرسمي، فالطريقة الموثقة لاستبداله بنسخة مخصصة هي `dpkg-divert` مع `update-alternatives`، كي لا تكتب ترقيات الحزمة فوق ملفك التنفيذي. تذكّر أنك صرت مضطراً لإعادة البناء للحصول على تحديثات Caddy.
sudo dpkg-divert --divert /usr/bin/caddy.default --rename /usr/bin/caddy
sudo mv ./caddy /usr/bin/caddy.custom
sudo update-alternatives --install /usr/bin/caddy caddy /usr/bin/caddy.default 10
sudo update-alternatives --install /usr/bin/caddy caddy /usr/bin/caddy.custom 50
sudo systemctl restart caddyالمثال 1: reverse proxy عادي لـ TCP
تستمع هذه الإعدادات على المنفذ 5432 وتمرر كل اتصال إلى خادم PostgreSQL على عنوان خاص، مثل الطرف الآخر من نفق WireGuard. غياب المطابِق يعني أن كل اتصال يسلك هذا المسار. تقبل الخوادم الخلفية عدة عناوين `dial` للتحويل عند الفشل، ويدعم معالج `proxy` موازنة الحمل وفحوص السلامة على غرار `reverse_proxy` في HTTP.
ترى الخلفية عنوان IP الخاص بـ Caddy، لا عنوان العميل. إن كانت الخلفية تفهم بروتوكول PROXY، فاضبط `"proxy_protocol": "v2"` على معالج proxy لتمرير العنوان الأصلي.
{
"apps": {
"layer4": {
"servers": {
"postgres": {
"listen": [":5432"],
"routes": [
{
"handle": [
{
"handler": "proxy",
"upstreams": [{"dial": ["10.8.0.2:5432"]}]
}
]
}
]
}
}
}
}
}المثال 2: SSH وHTTPS معاً على المنفذ 443
يرسل عملاء SSH ترويسة الإصدار (`SSH-2.0-...`) فور اتصالهم، لذا يستطيع caddy-l4 التعرف على SSH قبل أي رد من الخادم. ترسل الإعدادات أدناه SSH إلى sshd المحلي، وTLS الخاص بـ `git.example.com` إلى خدمة تنهي TLS بنفسها، وكل TLS آخر إلى تطبيق HTTP في Caddy الذي يستمع على 8443. ولأن layer4 صار يملك المنفذ 443، يجب ألا يرتبط به تطبيق HTTP أيضاً: اضبط `https_port 8443` في الخيارات العامة لـ Caddyfile، أو عنوان `listen` المكافئ في JSON، وأبقِ المنفذ 80 مفتوحاً لتحديات HTTP-01. ومع `https_port 8443` ستشير إعادة التوجيه التلقائية من HTTP إلى HTTPS في Caddy إلى المنفذ 8443، لذا اضبط `auto_https disable_redirects` وأضف موقعك الخاص `http:// { redir https://{host}{uri} permanent }`.
البروتوكولات التي يبدأ فيها الخادم بالكلام، مثل SMTP أو FTP أو MySQL، لا يمكن اكتشافها بهذه الطريقة، لأن العميل ينتظر صامتاً. خصص لها منفذاً خاصاً بها.
{
"apps": {
"layer4": {
"servers": {
"mux443": {
"listen": [":443"],
"routes": [
{
"match": [{"ssh": {}}],
"handle": [
{"handler": "proxy", "upstreams": [{"dial": ["127.0.0.1:22"]}]}
]
},
{
"match": [{"tls": {"sni": ["git.example.com"]}}],
"handle": [
{"handler": "proxy", "upstreams": [{"dial": ["127.0.0.1:3443"]}]}
]
},
{
"match": [{"tls": {}}],
"handle": [
{"handler": "proxy", "upstreams": [{"dial": ["127.0.0.1:8443"]}]}
]
}
]
}
}
}
}
}شغّله واختبره
- 01.احفظ ملف JSON باسم `/etc/caddy/caddy.json` وتحقق من صحته.
- 02.أوقف الخدمة وشغّل Caddy في الواجهة لمراقبة السجل أثناء الاتصال.
- 03.وجّه وحدة systemd إلى ملف JSON عبر ملف تجاوز drop-in، ثم `sudo systemctl daemon-reload` و`sudo systemctl start caddy`.
- 04.اتصل بالأمر `ssh -p 443` وافتح موقع HTTPS في المتصفح للتأكد من عمل المسارين.
# Validate and test in the foreground first
sudo caddy validate --config /etc/caddy/caddy.json
sudo systemctl stop caddy
sudo caddy run --config /etc/caddy/caddy.json
# Make the service use the JSON file: sudo systemctl edit caddy
[Service]
ExecStart=
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/caddy.json
ExecReload=
ExecReload=/usr/bin/caddy reload --config /etc/caddy/caddy.json --force
# Client side
ssh -p 443 [email protected]متى تستخدم HAProxy أو sslh بدلاً منه
يناسب caddy-l4 حين تشغّل Caddy أصلاً وتريد عملية واحدة لـ HTTPS وبضعة مسارات TCP. أما للإعدادات التي يغلب عليها TCP، فقد تكون البدائل الناضجة في مستودعات Debian وUbuntu أبسط تشغيلاً: HAProxy في `mode tcp` يوجّه حسب SNI عبر `req.ssl_sni` ويوفر إحصاءات وفحوص سلامة مفصلة، بينما sslh برنامج خدمي صغير مبني فقط لمشاركة منفذ واحد بين SSH وTLS وOpenVPN وغيرها. كلاهما يُثبَّت عبر apt ويُحدَّث مع بقية النظام، من دون نسخة مخصصة تحتاج صيانة.
كشف SSH على المنفذ 443 يفيد في الشبكات التي لا تسمح إلا بمنافذ الويب، لكنه ليس ميزة أمنية. حافظ على المصادقة بالمفاتيح فقط وفق دليل تحصين SSH. على VPS من NoctisNode لديك صلاحيات root كاملة، فتستطيع أي من هذه الأدوات الارتباط بالمنافذ التي تحتاجها؛ ولسلوك الشهادات في جانب HTTPS راجع HTTPS التلقائي في Caddy، وللحاويات Caddy كـ reverse proxy لـ Docker.
| الأداة | نقاط القوة | المقايضات |
|---|---|---|
| Caddy + caddy-l4 | عملية واحدة لـ HTTPS التلقائي وTCP، مطابِقات للبروتوكولات، واجهة JSON API | نسخة مخصصة، الوحدة لا تزال تتطور |
| HAProxy | بروكسي TCP/HTTP ناضج، توجيه حسب SNI، فحوص سلامة وإحصاءات غنية | إعدادات أكثر، لا عميل ACME مدمج |
| sslh | صغير جداً، مصمم خصيصاً لمشاركة المنافذ بين SSH/TLS/VPN | يقتصر على تقاسم المنفذ؛ لا إنهاء لـ TLS ولا موازنة حمل |
الأسئلة الشائعة
Qهل يستطيع Caddy تمرير حركة TCP؟
Aليس افتراضياً. Caddy الأساسي يمرر HTTP فقط؛ ولـ TCP أو UDP الخام تحتاج إلى نسخة من Caddy تتضمن وحدة caddy-l4 (layer4) الخارجية.
Qكيف أمرر SSH عبر Caddy؟
Aابنِ Caddy مع caddy-l4، وأضف خادم layer4 يطابق `ssh` ويمرر إلى `127.0.0.1:22`، ثم اتصل بالأمر `ssh -p <port>`. على المنفذ 443 يمكنك دمجه مع مسار `tls` كي يبقى HTTPS عاملاً.
Qهل يمكن أن يتشارك SSH وHTTPS المنفذ 443؟
Aنعم. تستطيع caddy-l4 وsslh وHAProxy كلها فحص البايتات الأولى من الاتصال وتوجيه SSH وTLS إلى خلفيات مختلفة على المنفذ نفسه.
Qهل يدعم caddy-l4 ملف Caddyfile؟
Aلديه دعم لـ Caddyfile عبر الخيار العام `layer4`، لكن JSON يبقى الصيغة الأكمل والأفضل توثيقاً. راجع README الوحدة للإصدار الذي تبنيه.