SSH از طریق رلهٔ جریان NGINX بدون خراب کردن آن
سرآیند PROXY پیامی برای گیرندهای است که انتظارش را دارد، و رکورد DNS پروکسیشده یک رلهٔ TCP نیست. لبه و سمت بالادست را جداگانه درست کنید.
SSH عمومی از طریق رله در دو مرز نامرتبط شکست میخورد، و درست کردن یکی معمولاً دیگری را آشکار میکند. یا لبه بهجای انتقال جریان یک پاسخ HTTP برمیگرداند، یا رله سرآیندی را جلو میاندازد که بکاند هرگز نخواسته آن را بخواند. سه شرط تعیین میکند کدام را میبینید: رکورد عمومی واقعاً به چه چیزی اشاره میکند، بلوک جریان چه چیزی به بالادست میفرستد، و کلاینت SSH کدام نام را بررسی میکند. آنها را به همین ترتیب پیش ببرید.
دو مرز، دو نشانه
شکست در لبه شبیه صفحهٔ وضعیت HTTP است که جایی میرسد که باید بنر SSH باشد. اتصال در سطح TCP کامل میشود و بایتهای نخست متنی است که به یک وبسرور تعلق دارد. این ناسازگاری پروتکل است، نه بستهٔ گمشده. همچنین به شما میگوید لبه عمداً چیز دیگری برای آن نام سرو میکند.
شکست در بالادست متفاوت به نظر میرسد. اتصال به sshd میرسد، sshd بایتهایی را میخواند که تبادل شناسایی مورد انتظارش نیستند، و نشست میمیرد یا معلق میماند بدون اینکه هرگز کلیدی ارائه دهد.
اشتباه گرفتن این دو آسان است چون هر دو کلاینتی میسازند که وصل میشود و سپس شکست میخورد. نخستین پاسخ پروتکلی که دریافت میکنید همان چیزی است که آنها را از هم جدا میکند، و به همین دلیل باید در تیکت باشد.
سرآیند PROXY یک پیام است، نه کلید تغییر
در ماژول جریان، proxy_protocol on به NGINX میگوید پیش از بار مفید یک سرآیند پروتکل PROXY به سمت بالادست بنویسد. این کار پروکسی TCP را فعال نمیکند و هیچ ارتباطی با رمزگذاری SSH ندارد. این یادداشتی خطاب به گیرنده است. اگر گیرنده نتواند آن را بخواند، در آغاز جریان زباله میشود.
سرویس گیرنده باید آن سرآیند را عمداً مصرف کند. sshd معمولی تبادل شناسایی SSH را بهعنوان نخستین بایتهای اتصال انتظار دارد، پس یک مقدمهٔ غیرمنتظره دستدادن را به شکلی میشکند که مانند سرور خراب به نظر میرسد.
stream {
server {
listen 2222;
proxy_pass 10.77.0.20:22;
}
}
این قطعه تمام یک رلهٔ کارآمد برای بکاندی است که از طریق VPN قابل دسترسی است. هیچ دستورالعمل PROXY دیده نمیشود چون گیرنده آن پروتکل را نمیفهمد، و این غیاب یک تصمیم است نه یک از قلم افتادگی.
دو جهت را هم جدا کنید. تنظیم proxy_protocol روی خط listen یعنی NGINX انتظار دارد کلاینت خودش ابتدا سرآیند را بفرستد؛ فعال کردنش برای یک کلاینت SSH معمولی دقیقاً عکس مشکلی را میسازد که مردم معمولاً میخواهند حل کنند.
نام میزبان عمومی واقعاً به چه چیزی میرسد
صفحهٔ HTTP 400 در یک نشست SSH شاهدی دربارهٔ لبه است. چیزی در مسیر HTTP صحبت میکند، و هیچ کار روی کلید یا حساب در بکاند آن را تغییر نمیدهد. تا وقتی لبه روشن نشده، تغییر بکاند را متوقف کنید.
رکورد پروکسی معمولی Cloudflare ترافیک HTTP و HTTPS پشتیبانیشدهاش را روی پورتهای مشخص حمل میکند. روشن کردن پروکسی برای یک نام میزبان رلهٔ TCP عمومی نمیسازد، و انتقال SSH به پورت 443 آن را HTTPS نمیکند.
دو جهت عملی وجود دارد. رکورد فقط DNS میتواند به رلهٔ TCP خودتان اشاره کند، که تصمیم دربارهٔ میزان مواجهه را در دست شما میگذارد. در غیر این صورت از محصولی استفاده کنید که حمل SSH را صراحتاً مستند کرده باشد، با تنظیمات مبدأ، کلاینت و دسترسی خودش.
هر کدام را انتخاب کنید، رله همچنان به مسیر VPN به بکاند، اتصال مجاز و مسیر بازگشت نیاز دارد. مسیر اختیاری نیست چون سمت عمومی کار میکند.
هویت SSH را از طریق یک نام مستعار پایدار نگه دارید
کاربران معمولاً میخواهند به تایپ نام میزبان فعلی خود ادامه دهند. یک نام مستعار در پیکربندی SSH میتواند این کار را بدون تغییر هیچ چیز در رله انجام دهد، و تغییر را در سمت کلاینت نگه میدارد که جای آن است.
Host git.example.com
HostName ssh-entry.example.net
Port 2222
User git
HostKeyAlias git.example.com
بدون HostKeyAlias، OpenSSH کلید میزبان را زیر نامی جستوجو میکند که به آن وصل میشود، پس ورودی جابهجا میشود و هر کاربر در نخستین استفاده هشدار تغییر کلید میبیند. تنظیم نام مستعار ورودیهای known-hosts را پایدار نگه میدارد در حالی که اتصال همچنان به رله میرود.
این نام مستعار فقط برای مخازن دور مبتنی بر SSH کاربرد دارد. یک URL گیت از نوع HTTPS آن را در نظر نمیگیرد، و URL معمول مخزن دور باید با روش انتقالی که واقعاً فراهم کردهاید همخوان باشد.
کاری که نباید بکنید خاموش کردن بررسی کلید میزبان برای محو شدن هشدار است. این یک محافظت را حذف میکند که تعمیر ارسال هرگز نخواسته بود به آن دست بزنید، و یک آزار ظاهری را به مواجههٔ واقعی تبدیل میکند.
هر پرش را جداگانه بررسی کنید
شنوندهٔ عمومی را بهتنهایی بیازمایید، سپس اتصال رله به بکاند را از میزبان رله، و تنها پس از آن کلاینت را سرتاسر. هر یک از این سه آزمون لایهٔ متفاوتی را حذف میکند. جا انداختن یکی یعنی دو نتیجهٔ باقیمانده قابل تفسیر نیستند. سه مشاهده، سه جایی که یک شکست میتواند زندگی کند.
نشانی مقصد، پورت و نخستین بایتهای پروتکل را همراه هر نتیجه نگه دارید. این سهگانه خطای لبه را از مشکل مسیریابی VPN و از شکست احراز هویت SSH جدا میکند، و همین تفاوت میان یک تعمیر و یک حدس است.
در پایان، مواجههٔ در نظر گرفتهشده را مستند کنید. رلهٔ TCP که SSH را به یک بکاند خصوصی میرساند یک بازشدگی عمدی در محیط عمومی است، و شایستهٔ همان بازبینی هر سرویس ورودی دیگر است.