هر دو دستور یک سرویس محلی را از طریق یک نام HTTPS در Tailscale منتشر می‌کنند و از روی ماشینی که آن‌ها را اجرا می‌کند تقریباً یکسان به نظر می‌رسند. تفاوت در این است که چه کسی بعداً می‌تواند به URL برسد و همین تفاوت تعیین می‌کند که برنامه شما هنوز به کدام کنترل‌ها نیاز دارد. Serve مخاطب را درون tailnet نگه می‌دارد و Funnel آن را به اینترنت عمومی منتقل می‌کند. نخست مخاطب را انتخاب کنید و سپس دستوری را انتخاب کنید که با آن هم‌خوانی دارد.

Serve به پرسشی درون tailnet شما پاسخ می‌دهد

Serve یک پورت محلی را پروکسی می‌کند یا محتوای محلی را به دستگاه‌های tailnet شما ارائه می‌دهد و قواعد دسترسی tailnet همچنان برای هر درخواست اعمال می‌شود. یک داشبورد روی پورت 3000 از طریق نام HTTPS در دسترس می‌شود که تنها دستگاه‌های شما می‌توانند آن را تجزیه و به آن متصل شوند. این پیش‌فرض درست برای ابزارهای داخلی است، چون مخاطب از قبل توسط tailnet احراز هویت شده و شما سطح عمومی اضافه نمی‌کنید. URL مانند یک وب‌سایت عادی به نظر می‌رسد و دقیقاً به همین دلیل است که مردم آن را چنین چیزی می‌پندارند.

Serve همچنین می‌تواند سرآیندهای هویتی را که کاربر tailnet را توصیف می‌کنند به درخواست‌هایی که ارسال می‌کند پیوست کند. اگر برنامه شما به این سرآیندها به عنوان احراز هویت اعتماد می‌کند، بک‌اند را به localhost ببندید تا هیچ چیز دیگری نتواند مستقیم به آن برسد؛ بک‌اندی که روی نشانی مسیریابی‌پذیر گوش می‌دهد می‌تواند درخواست‌هایی دریافت کند که هرگز از پروکسی عبور نکرده‌اند.

Funnel مخاطب را به اینترنت باز تغییر می‌دهد

Funnel سرویس انتخاب‌شده را برای هر کسی که URL را دارد منتشر می‌کند و بازدیدکنندگان به کلاینت، حساب یا عضویت در tailnet شما نیاز ندارند. بنابراین منبع به احراز هویت، محدودسازی نرخ و وصله‌هایی نیاز دارد که روی هر سرویس عمومی اعمال می‌کنید. درخواست‌های عمومی سرآیندهای هویت tailnet مربوط به Serve را حمل نمی‌کنند، پس برنامه‌ای که به آن‌ها تکیه کرده بود تحت Funnel هیچ هویت کاربری ندارد. انتخاب دستور انتشار متفاوت، پرسش احراز هویت را به جای شما پاسخ نمی‌دهد.

Funnel محدودیت‌هایی هم دارد که ممکن است آموزش یک نسخه قدیمی‌تر به آن‌ها اشاره نکند. این سرویس TLS را با گواهی‌ای که Tailscale برای نام دریافت می‌کند پایان می‌دهد و فقط پورت‌های شنود مشخصی را پشتیبانی می‌کند، همان‌طور که مستندات Funnel توضیح می‌دهد. اگر سرویس شما روی یکی از آن پورت‌ها پروتکلی غیر از HTTPS انتظار دارد، Funnel ابزار نادرست است و نه یک معما در پیکربندی.

حالت را از کلاینت بخوانید، نه از پورت

پیش از به اشتراک گذاشتن هر چیزی وضعیت کنونی را بررسی کنید، چون دو حالت می‌توانند در زمان‌های مختلف برای همان پورت محلی پیکربندی شوند. دستورهای وضعیت گزارش می‌دهند که چه چیزی واقعاً منتشر شده و برای چه کسی. مخاطب را از این واقعیت که URL پاسخ می‌دهد استنتاج نکنید.

tailscale serve status
tailscale funnel status
tailscale status --json | head -40

نحو دستورها در نسخه‌های مختلف کلاینت تغییر کرده است، پس یک فراخوان کپی‌شده ممکن است حالتی متفاوت از آنچه قصد داشتید انتخاب کند. شکل مستندشده برای نسخه‌ای که اجرا می‌کنید را ترجیح دهید و به جای فرض کردن، تأییدی را که کلاینت چاپ می‌کند بخوانید. اگر هم پیکربندی Serve و هم Funnel وجود دارد، پیکربندی عمومی همان است که برای قرار گرفتن در معرض اهمیت دارد. پیکربندی‌ای را که قصدش را نداشتید بازنشانی کنید، نه اینکه یکی دیگر روی آن بگذارید.

اگر خروجی مخاطب را نام نمی‌برد، متوقف شوید و وضعیت را دوباره بخوانید. URL منتشرشده بدون مخاطب اعلام‌شده یک حدس است و حدس‌ها همان راهی است که داشبوردهای داخلی به اینترنت عمومی می‌رسند.

با مخاطبی که واقعاً قصد داشتید آزمایش کنید

از بیرون tailnet آزمایش کنید، نه از ماشینی که سرویس را منتشر کرده است. درخواست از یک دستگاه tailnet ثابت می‌کند پروکسی کار می‌کند، اما ثابت نمی‌کند که یک غریبه کنار گذاشته شده است. از شبکه‌ای استفاده کنید که کلاینت Tailscale و مسیری به tailnet ندارد.

curl -sI https://host.tailnet-name.ts.net
curl -sI https://host.tailnet-name.ts.net --resolve host.tailnet-name.ts.net:443:203.0.113.10

برای یک داشبورد داخلی، درخواست بیرونی باید در اتصال شکست بخورد یا در مجوزدهی شکست بخورد و درخواست داخلی باید با هویتی که انتظار دارید موفق شود. برای یک سرویس عمومی، درخواست بیرونی باید موفق شود و برنامه باید اعتبارنامه‌های خودش را بخواهد. ثبت کنید کدام یک از این دو نتیجه را مشاهده کردید، چون URL تنها این را به شما نمی‌گوید. اگر نتیجه برخلاف قصد بود، نخست پیکربندی عمومی را بردارید و سپس بررسی کنید.

انتشار یک سرویس هم همان تصمیم انتخاب گره خروج نیست، گره خروج کنترل می‌کند ترافیک خروجی شما از کجا خارج می‌شود. Serve و Funnel پاسخ می‌دهند چه کسی می‌تواند به چیزی که اجرا می‌کنید برسد؛ گره خروج پاسخ می‌دهد اتصال‌های خود شما از کجا به نظر می‌رسد می‌آیند. دو پرسش را جدا نگه دارید و مقایسه ساده می‌ماند.

مقالات مرتبط