تفاوت Tailscale serve و Funnel چیست؟
تفاوت اصلی در دسترسی است. دستور serve سرویس را فقط در tailnet منتشر میکند، اما Funnel آن را عمومی میسازد. برای استفاده از Funnel باید ACL را در Tailscale تنظیم کنید.
تفاوت tailscale serve و funnel: چه کسی به URL دسترسی دارد
تفاوت بین tailscale serve و tailscale funnel تنها در مخاطبان آن است و هیچ تفاوت دیگری وجود ندارد. دستور serve یک رابط HTTPS (پروتکل انتقال ابرمتن امن) روی یک پورت محلی قرار میدهد و آن را فقط برای tailnet شما منتشر میکند. دستور funnel همان پورت محلی را از طریق سرورهای رلهای که Tailscale اجرا میکند، برای کل اینترنت عمومی منتشر مینماید. هر دو دستور از پرچمها (flags) و مقصدهای یکسانی استفاده میکنند. تنها یک کلمه تفاوت بین یک داشبورد خصوصی و داشبوردی که برای همه جهان قابل دسترسی است، وجود دارد.
هر دو دستور گواهینامهای به شما میدهند که مرورگرها از قبل به آن اعتماد دارند؛ این گواهینامه روی دامنهای با پسوند ts.net قرار میگیرد و هیچکدام نیازی به باز کردن پورت ورودی در فایروال VPS شما ندارند. دیمون tailscaled شما از قبل اتصالی به tailnet برقرار کرده است و ترافیک از همان مسیر منتقل میشود. آوردن یک سرور به داخل tailnet یک وظیفه است، و اجرای یک VPS به عنوان exit node در Tailscale یا معرفی یک subnet router برای یک شبکه خصوصی این موضوع را پوشش میدهد. انتشار سرویسی که هماکنون در tailnet قرار دارد، موضوع این بخش است.
پیشنیازهای لازم برای اجرای دستورات
- نسخه 1.38.3 یا جدیدتر Tailscale روی VPS که به tailnet شما متصل باشد. وضعیت را با
tailscale versionوtailscale statusبررسی کنید. - فعال بودن MagicDNS. این قابلیت، سیستم DNS داخلی Tailscale است که به دستگاه شما نامی مانند
blog-vps.your-tailnet.ts.netمیدهد تا مجبور نباشید فقط از آدرس100.xاستفاده کنید. - فعال بودن گواهیهای HTTPS برای tailnet در صفحه DNS کنسول مدیریت. بدون این مورد، گواهی معتبری برای قرار دادن روی پورت شما وجود نخواهد داشت.
- فقط برای
funnel، ویژگی گرهfunnelدر فایل سیاست (policy file) tailnet. این همان بخشی است که اکثر تلاشهای اولیه در آن متوقف میشود و در ادامه به آن پرداخته شده است.
هر دستوری در اینجا با sudo شروع میشود، زیرا رابط خط فرمان (CLI) از طریق سوکتی با tailscaled ارتباط برقرار میکند که فقط کاربر root اجازه نوشتن در آن را دارد. برای اینکه یک کاربر بتواند بدون نیاز به این دسترسی دستورات را اجرا کند، مجوز زیر را به او بدهید:
sudo tailscale set --operator=$USERانتشار در tailnet با استفاده از tailscale serve
کافی است serve را به یک پورت محلی اشاره دهید تا بقیه کارها بهطور خودکار انجام شود.
sudo tailscale serve 3000Available within your tailnet:
https://amelie-workstation.pango-lin.ts.net
|-- / proxy http://127.0.0.1:3000
Press Ctrl+C to exit.دستور ساده 3000 در واقع مخفف http://127.0.0.1:3000 است. Tailscale روی پورت 443 از آدرس tailnet دستگاه گوش میدهد، TLS (امنیت لایه انتقال) را با گواهی ts.net خاتمه میدهد و ترافیک HTTP ساده را به پورت محلی شما هدایت میکند. برنامه شما نیازی ندارد از وجود گواهی مطلع باشد؛ این اصلیترین دلیل استفاده از این روش برای پنلهای مدیریتی است که در غیر این صورت مجبور بودید روی HTTP ساده رها کنید.
حالا به خط آخر دقت کنید: Press Ctrl+C to exit. این دستور در پیشزمینه (foreground) اجرا میشود و نگاشت (mapping) در همان پردازش باقی میماند. اگر ترمینال را ببندید، URL از کار میافتد، زیرا هیچ چیزی روی دیسک ذخیره نشده است. با افزودن --bg، نگاشت در پیکربندی serve گره (node) ثبت میشود که پس از بستن ترمینال و حتی راهاندازی مجدد (reboot) سیستم نیز باقی میماند.
sudo tailscale serve --bg 3000دستور serve فقط به شماره پورت محدود نمیشود. --set-path یک سرویس را در یک زیرمسیر (subpath) سوار (mount) میکند، بنابراین چندین برنامه میتوانند از یک نام میزبان (hostname) مشترک استفاده کنند:
sudo tailscale serve --bg --set-path=/grafana 3000
sudo tailscale serve --bg --set-path=/metrics 9090مقصد (target) میتواند یک دایرکتوری از فایلهای ایستا (static files) یا یک backend باشد که از قبل با گواهی TLS صحبت میکند و شما نمیخواهید آن گواهی بررسی شود:
sudo tailscale serve --bg /srv/reports
sudo tailscale serve --bg https+insecure://localhost:8443این قابلیت فقط به HTTP محدود نیست. --tcp=<port> یک جریان TCP (پروتکل کنترل انتقال) خام را هدایت میکند و --tls-terminated-tcp=<port> عملیات TLS را در گره شما خاتمه داده و متن ساده (plaintext) را عبور میدهد؛ این کار باعث میشود یک گواهی معتبر در مقابل سرویسی قرار بگیرد که اصلاً از پروتکل HTTP استفاده نمیکند:
sudo tailscale serve --bg --tls-terminated-tcp=443 tcp://127.0.0.1:9899چرا Funnel میگوید ویژگی node تنظیم نشده است؟
قابلیت Funnel بهصورت پیشفرض برای کل tailnet غیرفعال است. اولین اجرا این پیام را نمایش میدهد و متوقف میشود:
Funnel not available; "funnel" node attribute not set. See https://tailscale.com/kb/1223/tailscale-funnel/.دستور وارد شده صحیح بوده است. سیاست (policy) تعریفشده برای tailnet به این گره (node) اجازه انتشار نداده است، بنابراین کلاینت پیش از برقراری هرگونه ارتباط با relay، درخواست را رد میکند. فایل سیاست tailnet را در کنسول مدیریت، بخش Access Controls ویرایش کنید و ویژگی زیر را اضافه نمایید:
"nodeAttrs": [
{
"target": ["autogroup:member"],
"attr": ["funnel"],
},
],autogroup:member این دسترسی را به تمام اعضای tailnet اعطا میکند. اگر فقط یک ماشین باید اجازه انتشار داشته باشد، آن ماشین را tag بزنید و آن tag را هدف قرار دهید، برای مثال tag:public. سیاست را ذخیره کنید و سپس دستور funnel را دوباره اجرا نمایید.
اگر حساب کاربری شما مدیر tailnet است، کلاینتهای جدید میانبری ارائه میدهند: رابط خط فرمان (CLI) یک URL رضایتنامه را در login.tailscale.com چاپ میکند که با دنبال کردن آن، گواهیهای HTTPS فعال شده و این ویژگی بهطور خودکار برای شما اضافه میشود. اگر مدیر نیستید، آن URL کمکی به شما نخواهد کرد. شخصی که دسترسی به سیاستها دارد باید این ویرایش را انجام دهد.
انتشار در اینترنت با استفاده از Tailscale Funnel
هنگامی که این ویژگی تنظیم شد، دستور همان دستوری است که پیشتر میشناختید، با این تفاوت که فعل آن تغییر کرده است.
sudo tailscale funnel --bg 3000Available on the internet:
https://amelie-workstation.pango-lin.ts.net
|-- / proxy http://127.0.0.1:3000
Press Ctrl+C to exit.هر بار آن خط اول را مطالعه کنید. Available within your tailnet و Available on the internet تنها تفاوت ظاهری میان یک سرویس خصوصی و یک سرویس عمومی هستند و دستوراتی که آنها را ایجاد میکنند، تنها در یک کلمه با هم تفاوت دارند.
از اوت 2026، قابلیت Funnel فقط روی پورتهای 443، 8443 یا 10000 گوش میدهد و هیچ پورت دیگری را نمیپذیرد. پورت پیشفرض 443 است و --https=8443 یا --https=10000 گزینههای جایگزین هستند. هر پورت دیگری رد میشود، زیرا رلههای Funnel فقط اتصالات را روی این پورتها میپذیرند. به همین دلیل است که URL یک Funnel همیشه شامل نام میزبان (hostname) به تنهایی، یا نام میزبان به همراه :8443 در انتهای آن است.
چگونه میتوانم ببینم در حال حاضر چه چیزی منتشر شده است؟
حدس زدن باعث میشود یک داشبورد برای یک ماه عمومی باقی بماند. از خود node بپرسید.
tailscale serve status
tailscale funnel status
tailscale serve status --jsonهر دو دستور وضعیت، پیکربندی یکسانی را میخوانند، بنابراین هر کدام از آنها تصویر کاملی به شما نشان میدهد. از فرم --json داخل اسکریپت یا بررسیهای زمانبندیشده استفاده کنید، زیرا خروجی ساده برای خواندن توسط انسان نوشته شده است. وقتی هیچ چیزی پیکربندی نشده باشد، یک خط دریافت میکنید:
No serve configمشاهده این مورد پس از راهاندازی که میدانستید کار میکند، به این معنی است که نگاشت (mapping) در پیشزمینه ایجاد شده و فرآیند پایان یافته است. آن را با --bg دوباره ایجاد کنید.
برای حذف یک نگاشت، دستوری که آن را ایجاد کرده است تکرار کنید و off را در انتها قرار دهید. برای پاک کردن تمام نگاشتهای serve و funnel روی node، از reset استفاده کنید.
sudo tailscale funnel --https=443 3000 off
sudo tailscale serve resetپس از هر کدام از این دستورات، tailscale serve status را دوباره اجرا کنید و آنچه باقی مانده است را بخوانید، به جای اینکه فرض کنید دستور دقیقاً همان کاری را انجام داده که مد نظر شما بوده است.
آنچه به دست میآورید و آنچه از دست میدهید
مزایا واقعی هستند و به همین دلیل است که افراد این روش را به reverse proxy ترجیح میدهند.
- گواهی مورد اعتماد مرورگرها که بهطور خودکار برای شما تمدید میشود. نیازی به نصب کلاینت ACME (محیط مدیریت خودکار گواهی) نیست و هیچ job تمدیدی وجود ندارد که فراموش شود.
- عدم نیاز به باز کردن پورت ورودی در فایروال VPS. ابزار
tailscaledاتصال خروجی برقرار میکند، بنابراین فایروال پیشفرض با سیاست deny در ufw روی VPS شما میتواند دقیقاً به همان اندازه محدود و امن باقی بماند. - عدم نیاز به خرید، تنظیم یا انتظار برای اعمال رکورد DNS.
- عدم نیاز به port forwarding، که این موضوع برای ماشینی که پشت NAT (ترجمه آدرس شبکه) قرار دارد، نسبت به VPS با IP عمومی، کل ماجراست.
هزینهها نیز به همان اندازه واقعی هستند و تمام آنها متوجه funnel است.
- نام دامنه متعلق به شما نیست. بازدیدکنندگان عمومی آدرس
host.your-tailnet.ts.netرا میبینند. Funnel از دامنه اختصاصی پشتیبانی نمیکند، بنابراین نمیتوانیدapp.example.comرا جلوی آن قرار دهید. - مسیر متعلق به شما نیست. ترافیک ابتدا به یک relay در Tailscale میرسد و آن relay جریان داده را از طریق tailnet به node شما پروکسی میکند. Tailscale اعلام کرده است که ترافیک funnel مشمول محدودیتهای پهنای باندی است که منتشر نشدهاند و قابل پیکربندی نیستند؛ بنابراین پیش از تکیه بر یک عدد خاص، throughput خود را اندازهگیری کنید.
- کنترلها وجود ندارند. در reverse proxy که خودتان اجرا میکنید، به لاگهای دسترسی، محدودیت نرخ (rate limits)، سقف اندازه درخواست و مکانی برای پیادهسازی احراز هویت دسترسی دارید. Funnel فقط یک URL به شما میدهد. هر چیز دیگری باید درون خودِ برنامه شما مدیریت شود.
- لیست پورتها همانطور که در بالا ذکر شد، ثابت است.
هر دو قابلیت به زیرساختی که Tailscale مدیریت میکند وابسته هستند: صدور گواهی برای نام ts.net و خودِ relayهای funnel. اگر در حال بررسی یک سرور کنترل Headscale خود-میزبانیشده هستید، فرض نکنید که این قابلیتها همراه شما منتقل میشوند. یادداشتهای انتشار (release notes) نسخه Headscale مورد نظر خود را بررسی کنید.
کدامیک را باید استفاده کنم؟
قانون ساده است.
برای هر چیزی که داخلی است از serve استفاده کنید: رابطهای کاربری مدیریت، داشبوردها، رابط کاربری متریکها که نمیخواهید ایندکس شوند، یا نسخه staging یک وبسایت. عضویت در tailnet کنترل دسترسی شماست و بسیار مطمئن است. دستگاهی که در tailnet نباشد، حتی نمیتواند نام دامنه را resolve کند.
برای لینکهای دمو، گیرنده webhook که یک سرویس ثالث باید به آن POST کند، یا callback مربوط به OAuth در حین توسعه، از funnel استفاده کنید. این سریعترین مسیر برای رسیدن به یک URL عمومی با HTTPS است و با یک دستور off خاتمه مییابد. اما توجه داشته باشید که عمومی به معنای واقعی کلمه عمومی است: نام میزبان (hostname) مخفی نیست و اگر یک funnel را جلوی برنامهای بدون سیستم ورود قرار دهید، آن سرویس برای همه باز خواهد بود. هر چیزی که پشت آن قرار میگیرد باید درخواستهای خود را احراز هویت کند؛ با همان دقتی که یک endpoint عمومی Ollama API به آن نیاز دارد.
برای هر چیزی که آن را محیط عملیاتی (production) مینامید، از یک reverse proxy واقعی استفاده کنید. دامنه متعلق به خودتان، گواهی متعلق به خودتان، لاگهای خودتان، محدودیتهای نرخ (rate limits) خودتان، و بدون حضور هیچ واسطه دیگری در مسیر درخواست. مطلب مقایسه Nginx، Caddy و Traefik به عنوان reverse proxy به شما در انتخاب گزینه مناسب کمک میکند.
حالتهای شکست و پیامهای مربوطه
Funnel اجرا نمیشود. Funnel not available; "funnel" node attribute not set. یک مشکل در سیاستهای دسترسی است، نه یک مشکل در دستور. ویژگی funnel را به فایل سیاست tailnet اضافه کنید، آن را ذخیره کرده و دوباره تلاش کنید.
دستور کار کرد، اما اکنون tailscale serve status پیام No serve config را نمایش میدهد. نگاشت (mapping) در پیشزمینه ایجاد شده بود و با پایان یافتن آن پردازش، نگاشت نیز از بین رفته است. همان دستور را با پرچم --bg دوباره اجرا کنید.
نام دامنه Resolve میشود اما پاسخی دریافت نمیشود. Funnel درخواستها را به مقصدی که تعیین کردهاید پروکسی میکند؛ بنابراین اگر سرویسی در آنجا در حال گوش دادن نباشد، چیزی برای پروکسی کردن وجود ندارد. با استفاده از دستور ss -ltnp | grep 3000 روی همان ماشینی که tailscaled را اجرا میکند، این موضوع را تأیید کنید. دلیل رایج این است که یک کانتینر پورت خود را روی آدرس Docker bridge منتشر کرده است، نه روی 127.0.0.1؛ این یعنی میزبان (host) هیچ سرویس در حال گوش دادنی در جایی که انتظار داشتید نمیبیند. نحوه عملکرد شبکه در Docker Compose نشان میدهد که پورت منتشر شده در واقع کجا قرار میگیرد.
خطاهای گواهی روی نام ts.net. به احتمال زیاد گواهیهای HTTPS برای tailnet فعال نشدهاند. آنها را در کنسول مدیریت (admin console) فعال کنید، سپس مرحله مربوط به گواهی را بهصورت جداگانه اجرا کنید تا خطاهای آن با خروجی دستور serve تداخل پیدا نکند:
sudo tailscale cert your-host.your-tailnet.ts.netFunnel روی اینترنت موبایل بارگذاری میشود اما رفتار متفاوتی نسبت به لپتاپ شما دارد. لپتاپ شما در شبکه tailnet قرار دارد، بنابراین MagicDNS نام را به آدرس 100.x ترجمه میکند و شما بدون عبور از relay، مستقیماً به سرویس متصل میشوید. این رفتار صحیح است و به این معنی است که لپتاپ شما نمیتواند دسترسی عمومی (public reachability) را تست کند. از curl روی دستگاهی استفاده کنید که در شبکه tailnet عضو نیست.
FAQ
تفاوت بین tailscale serve و tailscale funnel چیست؟
تفاوت در این است که چه کسی میتواند به نتیجه دسترسی داشته باشد. tailscale serve یک پورت محلی را در یک URL با پروتکل HTTPS منتشر میکند که فقط دستگاههای موجود در tailnet شما قادر به دسترسی به آن هستند. tailscale funnel همان پورت را در URLای منتشر میکند که هر کسی در اینترنت میتواند به آن دسترسی داشته باشد؛ این ترافیک از طریق سرورهای relay که توسط Tailscale مدیریت میشوند، هدایت میگردد. پرچمها (flags) و مقاصد در هر دو دستور مشترک هستند. اولین خط خروجی به شما میگوید که کدامیک را دریافت کردهاید: Available within your tailnet یا Available on the internet.
چرا tailscale funnel میگوید ویژگی node تنظیم نشده است؟
زیرا قابلیت funnel تا زمانی که توسط شخصی فعال نشود، برای یک tailnet غیرفعال است. پیام خطا Funnel not available; "funnel" node attribute not set. است و از سمت کلاینت خود شما ارسال میشود، پیش از آنکه تماسی با هرگونه relay برقرار گردد. یک ورودی nodeAttrs اضافه کنید که ویژگی funnel را به autogroup:member اعطا کند، یا اگر فقط یک ماشین باید عمل انتشار را انجام دهد، آن را به یک tag اختصاص دهید؛ این کار باید در فایل سیاست tailnet در بخش Access Controls انجام شود. مدیر tailnet همچنین میتواند URL رضایتی که CLI چاپ میکند را دنبال کند.
Tailscale Funnel از چه پورتهایی میتواند استفاده کند؟
فقط 443، 8443 و 10000. پورت پیشفرض 443 است و شما میتوانید با استفاده از --https=8443 یا --https=10000 پورت دیگری را انتخاب کنید. این یک محدودیت در relayهای funnel است، نه در سرور شما؛ بنابراین هیچ تغییر فایروال یا پیکربندی در VPS این محدودیت را برطرف نمیکند. tailscale serve چنین محدودیتی ندارد، زیرا ترافیک هرگز از tailnet شما خارج نمیشود.
آیا URL ایجاد شده توسط serve یا funnel پس از reboot باقی میماند؟
فقط اگر از --bg استفاده کرده باشید. بدون آن، دستور در پیشزمینه (foreground) اجرا میشود، Press Ctrl+C to exit. را چاپ میکند و با بسته شدن پردازش، نگاشت (mapping) نیز از بین میرود. با استفاده از --bg، نگاشت در پیکربندی serve گره نوشته میشود و پس از reboot با tailscaled دوباره فعال میگردد. وضعیت را با tailscale serve status بررسی کنید که در صورت عدم تنظیم هرگونه پیکربندی، No serve config را چاپ میکند.
آیا باز گذاشتن یک funnel امن است؟
از نظر انتقال داده امن است: اتصال HTTPS است و هیچ پورتی روی فایروال شما باز نمیشود. اما از نظر مفهومی که معمولاً مد نظر است امن نیست، زیرا URL عمومی است و در نتیجه برنامهای که پشت آن قرار دارد نیز عمومی خواهد بود. funnel را فقط در مقابل سرویسی قرار دهید که درخواستهای خود را احراز هویت میکند، و پس از پایان دمو یا تست webhook، آن را با استفاده از همان دستوری که آن را ایجاد کرده و افزودن off در انتها، متوقف کنید.
منابع مربوط به رفتار دستورات فوق: مستندات Tailscale Serve و Funnel و مرجع CLI در tailscale.com/docs.