تونل های HTTP خود میزبان با SSH و Nginx
آدرس مقاله: https://vincent.bernat.ch/fa/blog/2026-http-over-ssh آدرس نظرات: https://news.ycombinator.com/item?id=49958569 امتیاز: 165 # نظرات: 34
یکی از دوستان می خواهد پست وبلاگ در حال انجام شما را تصحیح کند، اما پیش نمایش آن فقط در localhost:8080 اجرا می شود. چندین ابزار می تواند کمک کند. برخی به عنوان یک سرویس تجاری اجرا می شوند، مانند ngrok یا Cloudflare Quick Tunnels. برخی از آنها خود میزبان هستند اما به مشتری خاصی مانند frp یا localtunnel نیاز دارند. برخی فقط به یک کلاینت ساده SSH نیاز دارند اما به سرور SSH خاصی مانند sish متکی هستند. بیایید یک راه حل خود میزبان را تنها با OpenSSH و nginx پیاده سازی کنیم!
ابتدا اتصالات را از یک پورت روی یک سرور راه دور به سرویس محلی شما ارسال می کنیم:
هنگامی که 0 را به عنوان پورت راه دور مشخص می کنید، سرور یک پورت رایگان را اختصاص می دهد. سپس، nginx را برای درخواست های پراکسی از https://p41535.ssh.luffy.cx به http://127.0.0.1:41535 پیکربندی می کنیم:
ما همچنین باید رکوردهای DNS را برای *.ssh.luffy.cx اضافه کنیم و از طریق Let’s Encrypt یک گواهی عام دریافت کنیم:
acme.luffy.cx منطقه ای است که در مسیر 53 میزبانی می شود. من از آن برای چالش های ACME DNS-01 استفاده می کنم، هم برای گواهی نامه های عام و هم برای دامنه هایی که توسط چندین وب سرور ارائه می شوند. در مورد من، NixOS گواهی ها را به طور خودکار دریافت می کند.
پورت تنها "راز" 1 است که محتوا را محرمانه نگه می دارد. راهحلهای دیگر ارسال یک رشته تصادفی به نام دامنه اضافه میکنند تا از شمارش مقادیر احتمالی توسط مهاجم جلوگیری شود.
به لطف ngx_http_secure_link_module، می توانیم این تنظیمات را کمی ایمن کنیم. این ماژول یک هش 2 را بر روی مجموعه ای از مقادیر، از جمله یک رمز، محاسبه می کند و آن را با هش درخواست مقایسه می کند. هش با کد base64 است، بنابراین نمیتوانیم آن را در نام دامنه قرار دهیم که به حروف بزرگ و کوچک حساس است. در عوض، آن را به عنوان نام کاربری در URL به همراه مهر زمانی انقضا قرار می دهیم: 3
مشتری نام کاربری را با احراز هویت اولیه HTTP به سرور ارسال می کند. این با اکثر سرویس گیرندگان HTTP، از جمله curl، کار می کند. Nginx نام کاربری را در متغیر $remote_user نشان می دهد. ماژول انتظار دارد هش و مهر زمانی انقضا با کاما از هم جدا شوند. ما از یک دستورالعمل نقشه برای استخراج دو قسمت از $remote_user استفاده می کنیم و آنها را با کاما به هم متصل می کنیم. 4 همچنین رشته را به ماژول می دهیم تا هش کند. این شامل مهر زمان انقضا، پورت و یک راز است:
ماژول وضعیت چک را در متغیر $secure_link برمیگرداند:
اگر هش نادرست است یا از دست رفته است، یک خطای 401 را با یک هدر WWW-Authenticate برای درخواست اعتبار برمی گردانیم. اگر لینک منقضی شده باشد، خطای 410 را برمی گردانیم. قبل از بازارسال درخواست، سرصفحه مجوز را حذف میکنیم و چند دستورالعمل به اتصالات WebSocket پروکسی اضافه میکنیم. این پیکربندی کامل است: 5
فکر میکنم اکنون این سوال واضح را از خود میپرسید: "چگونه باید هش تولید کنم؟" آسان peasy!
خب، گمان میکنم اکنون دارید میگویید: "وینسنت، این خیلی راحت نیست! اگر اشکالی ندارد، من با ngrok میمانم." باشه من میشنوم بیایید یک اسکریپت کمکی بنویسیم.
مشکل اصلی یافتن پورت زودگذری است که OpenSSH اختصاص می دهد، زیرا در هیچ متغیر محیطی ظاهر نمی شود. 6 برای رفع این مانع، ما به دنبال فرآیندهای اجداد sshd-session می گردیم: 7
سپس، پورت های شنیداری مرتبط با این فرآیندهای sshd-sesion را دریافت می کنیم: 8
در نهایت، URL ها را نمایش می دهیم و جلسه را باز نگه می داریم:
من این اسکریپت را به صورت http-over-ssh روی سرور نصب می کنم و این ورودی را به ~/.ssh/config خود اضافه می کنم:
با این راه حل، من فقط به OpenSSH و nginx تکیه می کنم، دو نرم افزار که قبلا روی این سرور در حال اجرا هستند. یک دستور کوتاه به من یک تونل خود میزبان و یک URL برای به اشتراک گذاشتن می دهد. برای امتحان کردن آن، اسکریپت کمکی کامل را بگیرید که شامل چند پیشرفت جزئی است. اگر شما NixOS را اجرا می کنید، همانطور که هر فرد با سلیقه ای انجام می دهد، در عوض به http-over-ssh.nix من نگاهی بیندازید. ❄️
متن اصلی (انگلیسی)
Self-hosted HTTP tunnels with SSH and Nginx
Article URL: https://vincent.bernat.ch/en/blog/2026-http-over-ssh Comments URL: https://news.ycombinator.com/item?id=49958569 Points: 165 # Comments: 34