Tailscale Serve hay Funnel: nên dùng cái nào?
Serve chỉ cấp HTTPS trong tailnet, còn Funnel mở cùng port ra Internet. Xem policy gate khiến Funnel bị chặn và chọn đúng lệnh cho VPS.
tailscale serve và funnel: ai có thể truy cập URL
Điểm khác biệt giữa tailscale serve và tailscale funnel là đối tượng truy cập, không có gì khác. serve đặt một frontend HTTPS (hypertext transfer protocol secure) trước một cổng local và chỉ publish cổng đó trong tailnet của bạn. funnel publish cùng cổng local đó ra toàn bộ Internet công cộng thông qua các relay server do Tailscale vận hành. Hai lệnh dùng cùng các flag và cùng target. Chỉ một từ quyết định dashboard là private hay mọi người trên Internet đều truy cập được.
Cả hai đều cấp cho bạn một certificate mà các trình duyệt đã tin cậy, trên một tên kết thúc bằng ts.net, và không lệnh nào yêu cầu mở inbound port trên firewall của VPS. Daemon tailscaled của bạn đã duy trì một connection đi ra tailnet, nên traffic sẽ đi qua connection đó. Đưa server vào tailnet là một việc riêng; chạy VPS làm Tailscale exit node hoặc quảng bá subnet router cho một mạng private sẽ xử lý phần đó. Publish một service đã có trong tailnet là nội dung của phần này.
Điều kiện cần có trước khi chạy được một trong hai lệnh
- Tailscale 1.38.3 trở lên trên VPS và đã đăng nhập vào tailnet. Kiểm tra bằng
tailscale versionvàtailscale status. - Đã bật MagicDNS. MagicDNS là DNS tích hợp sẵn của Tailscale (hệ thống tên miền). Tính năng này cấp cho máy một tên như
blog-vps.your-tailnet.ts.netthay vì chỉ có địa chỉ100.x. - Đã bật chứng chỉ HTTPS cho tailnet trên trang DNS của admin console. Nếu chưa bật, bạn không có chứng chỉ để đặt trước cổng của mình.
- Chỉ áp dụng cho
funnel: cần có thuộc tính nodefunneltrong file policy của tailnet. Đây là bước khiến phần lớn lần thử đầu tiên bị dừng, và nội dung này được trình bày bên dưới.
Mọi lệnh trong phần này đều bắt đầu bằng sudo, vì CLI giao tiếp với tailscaled qua một socket mà chỉ root mới có quyền ghi. Cấp cho một user quyền bỏ qua yêu cầu đó:
sudo tailscale set --operator=$USERPublic lên tailnet bằng tailscale serve
Trỏ serve đến một cổng local, Tailscale sẽ xử lý phần còn lại.
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 dạng rút gọn tương đương với http://127.0.0.1:3000. Tailscale lắng nghe trên cổng 443 của địa chỉ tailnet trên máy, thực hiện TLS termination (transport layer security) bằng chứng chỉ ts.net, rồi chuyển tiếp HTTP thuần đến cổng local của bạn. Ứng dụng không cần biết chứng chỉ tồn tại. Đây là lý do chính để dùng cách này phía trước một admin panel mà nếu không sẽ phải để chạy bằng HTTP thuần.
Bây giờ xem dòng cuối: Press Ctrl+C to exit. Lệnh chạy ở foreground và mapping chỉ tồn tại trong process đó. Đóng terminal thì URL ngừng hoạt động vì không có cấu hình nào được ghi xuống disk. Thêm --bg để lưu mapping vào serve config của node. Cấu hình này vẫn tồn tại sau khi đóng terminal và sau reboot.
sudo tailscale serve --bg 3000Serve không chỉ nhận số cổng. --set-path mount một service dưới subpath, nên nhiều app có thể dùng chung một hostname:
sudo tailscale serve --bg --set-path=/grafana 3000
sudo tailscale serve --bg --set-path=/metrics 9090Target cũng có thể là một thư mục chứa static file hoặc một backend đã dùng TLS với chứng chỉ mà bạn không muốn kiểm tra:
sudo tailscale serve --bg /srv/reports
sudo tailscale serve --bg https+insecure://localhost:8443Serve cũng không bị giới hạn ở HTTP. --tcp=<port> chuyển tiếp một luồng TCP (transmission control protocol) thô. --tls-terminated-tcp=<port> thực hiện TLS termination tại node rồi chuyển tiếp dữ liệu plaintext, nhờ đó đặt một chứng chỉ được tin cậy phía trước một service hoàn toàn không hỗ trợ HTTP:
sudo tailscale serve --bg --tls-terminated-tcp=443 tcp://127.0.0.1:9899Vì sao Funnel báo thuộc tính của node chưa được đặt?
Funnel bị tắt mặc định cho toàn bộ tailnet. Lần chạy đầu tiên sẽ in thông báo này rồi dừng:
Funnel not available; "funnel" node attribute not set. See https://tailscale.com/kb/1223/tailscale-funnel/.Lệnh không sai. Policy của tailnet chưa cấp quyền publish cho node này, nên client từ chối trước khi liên hệ với relay. Hãy chỉnh sửa file policy của tailnet trong admin console, tại Access Controls, rồi thêm thuộc tính:
"nodeAttrs": [
{
"target": ["autogroup:member"],
"attr": ["funnel"],
},
],autogroup:member cấp quyền này cho mọi thành viên trong tailnet. Nếu chỉ một máy được phép publish, hãy gắn tag cho máy đó rồi dùng tag để giới hạn quyền, ví dụ tag:public. Lưu policy, sau đó chạy lại lệnh Funnel.
Nếu tài khoản của bạn là tailnet admin, các client gần đây có shortcut: CLI in một consent URL tại login.tailscale.com. Mở URL đó sẽ bật chứng chỉ HTTPS và tự thêm thuộc tính cho bạn. Nếu bạn không phải admin, URL đó sẽ không giúp được gì. Người có quyền truy cập policy phải thực hiện chỉnh sửa này.
Công bố dịch vụ lên Internet bằng Tailscale Funnel
Sau khi đặt thuộc tính, lệnh sử dụng chính là lệnh bạn đã biết, chỉ khác verb.
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.Mỗi lần hãy đọc dòng đầu tiên đó. Available within your tailnet và Available on the internet là khác biệt duy nhất có thể nhìn thấy giữa một dịch vụ private và một dịch vụ public; các lệnh tạo ra chúng chỉ khác nhau một từ.
Tính đến tháng 08/2026, Funnel chỉ lắng nghe trên cổng 443, 8443 hoặc 10000, không lắng nghe trên cổng nào khác. Mặc định là cổng 443; --https=8443 hoặc --https=10000 là các lựa chọn thay thế. Các cổng khác đều bị từ chối vì relay của Funnel chỉ chấp nhận kết nối trên những cổng này. Vì vậy, URL của Funnel luôn chỉ gồm hostname, hoặc hostname nối thêm :8443 ở cuối.
Làm thế nào để xem hiện đang publish những gì?
Đoán là cách khiến một dashboard vẫn public suốt một tháng. Hãy hỏi trực tiếp node.
tailscale serve status
tailscale funnel status
tailscale serve status --jsonCả hai lệnh status đều đọc cùng một cấu hình, nên dùng lệnh nào cũng xem được toàn bộ trạng thái. Dùng dạng --json trong script hoặc scheduled check, vì output thông thường được viết cho người đọc. Khi chưa cấu hình gì, bạn sẽ nhận được một dòng:
No serve configNếu thấy kết quả này sau khi setup đã hoạt động, mapping đã được tạo ở foreground và process đã thoát. Hãy tạo lại bằng --bg.
Để xóa một mapping, lặp lại lệnh đã tạo mapping đó rồi thêm off ở cuối. Để xóa toàn bộ mapping serve và funnel trên node, dùng reset.
sudo tailscale funnel --https=443 3000 off
sudo tailscale serve resetChạy lại tailscale serve status sau mỗi thao tác trên và đọc những gì còn lại, thay vì mặc định rằng lệnh đã thực hiện đúng điều bạn muốn.
Bạn nhận được gì, và phải đánh đổi gì
Các lợi ích là có thật, và đó là lý do nhiều người chọn cách này thay vì reverse proxy.
- Chứng chỉ được trình duyệt tin cậy và được tự động gia hạn. Bạn không cần cài client ACME (automatic certificate management environment) và cũng không phải nhớ tạo job gia hạn.
- Không cần mở cổng inbound trên firewall của VPS.
tailscaledtạo kết nối outbound, nên firewall ufw mặc định deny trên VPS của bạn có thể giữ nguyên mức hạn chế như trước. - Không cần mua, trỏ hoặc chờ bản ghi DNS.
- Không cần port forwarding. Đây là điểm quan trọng khi máy nằm sau NAT (network address translation), thay vì là VPS có public IP.
Các chi phí cũng có thật và funnel bao gồm tất cả những hạn chế đó.
- Tên miền không thuộc về bạn. Người truy cập bên ngoài sẽ thấy
host.your-tailnet.ts.net. Funnel không hỗ trợ custom domain, nên bạn không thể đặtapp.example.comphía trước nó. - Đường dẫn không thuộc về bạn. Traffic trước tiên đi đến một relay của Tailscale, rồi relay proxy stream đến node của bạn qua tailnet. Tailscale cho biết traffic của funnel chịu giới hạn băng thông chưa được công bố và không thể cấu hình, vì vậy hãy tự đo throughput trước khi dựa vào một con số cụ thể.
- Không có các tính năng kiểm soát. Reverse proxy do bạn vận hành cung cấp access log, rate limit, giới hạn kích thước request và vị trí để thêm authentication. Funnel chỉ cung cấp cho bạn một URL. Mọi thứ khác phải được xử lý bên trong ứng dụng.
- Danh sách port là cố định như đã nêu ở trên.
Cả hai tính năng này cũng phụ thuộc vào hạ tầng do Tailscale vận hành: việc cấp chứng chỉ cho tên ts.net và chính các relay của funnel. Nếu bạn đang cân nhắc một control server Headscale tự host, đừng mặc định rằng hai tính năng này sẽ đi theo bạn. Hãy kiểm tra release notes của phiên bản Headscale mà bạn định chạy.
Nên dùng loại nào?
Quy tắc rất ngắn gọn.
Dùng serve cho mọi thứ chỉ dùng nội bộ: giao diện quản trị, dashboard, giao diện metrics không muốn cho công cụ tìm kiếm lập chỉ mục, hoặc bản staging của một website. Việc một thiết bị thuộc tailnet chính là cơ chế kiểm soát truy cập, và đây là một cơ chế tốt. Thiết bị không thuộc tailnet thậm chí không thể phân giải tên.
Dùng funnel cho link demo, webhook receiver mà bên thứ ba phải POST đến, hoặc OAuth callback trong quá trình phát triển. Đây là cách nhanh nhất để có một URL HTTPS public, và chỉ cần một lệnh off là kết thúc. Public nghĩa là public: hostname không phải bí mật, và funnel đứng trước một app không có đăng nhập là một dịch vụ mở. Thành phần phía sau phải tự xác thực các request của nó, với mức độ cẩn trọng giống như khi xử lý một endpoint Ollama bị expose.
Dùng reverse proxy thực sự cho mọi thứ bạn xem là production. Bạn quản lý domain, certificate, log và rate limit của mình, không có bên nào khác nằm trên đường đi của request. So sánh nginx, Caddy và Traefik khi dùng làm reverse proxy trình bày cách chọn một công cụ.
Các trường hợp lỗi và chuỗi bạn sẽ thấy
Funnel không khởi động. Funnel not available; "funnel" node attribute not set. là vấn đề về policy, không phải vấn đề về command. Thêm attribute funnel vào cuối file policy của tailnet, lưu file rồi thử lại.
Đã chạy được, nhưng giờ tailscale serve status báo No serve config. Mapping được tạo ở foreground và process đó đã kết thúc. Chạy lại command tương tự với --bg.
Tên phân giải được nhưng không có phản hồi. Serve proxy đến target bạn đã chỉ định. Vì vậy, nếu không có gì listening ở đó thì không có gì để proxy đến. Xác nhận bằng ss -ltnp | grep 3000 trên chính máy đang chạy tailscaled. Nguyên nhân thường gặp là container publish port trên địa chỉ Docker bridge thay vì 127.0.0.1. Khi đó host không thấy listener tại vị trí bạn mong đợi. Cách networking của Docker Compose hoạt động giải thích port được publish thực sự nằm ở đâu.
Lỗi certificate trên tên ts.net. Nhiều khả năng HTTPS chưa được bật cho tailnet. Bật HTTPS trong admin console, sau đó chạy riêng bước cấp certificate để lỗi của bước này không bị trộn với output của serve:
sudo tailscale cert your-host.your-tailnet.ts.netFunnel tải được khi dùng mobile data nhưng hoạt động khác trên laptop. Laptop của bạn đang ở trong tailnet, nên MagicDNS phân giải tên thành địa chỉ 100.x và bạn truy cập service trực tiếp mà không đi qua relay. Đây là hành vi đúng. Điều đó cũng có nghĩa là laptop không thể kiểm tra khả năng truy cập public. Dùng curl từ một máy không ở trong tailnet.
FAQ
tailscale serve và tailscale funnel khác nhau như thế nào?
Ai có thể truy cập kết quả. tailscale serve publish một port local tại URL HTTPS mà chỉ các thiết bị trong tailnet của bạn mới truy cập được. tailscale funnel publish cùng port đó tại một URL mà bất kỳ ai trên Internet cũng truy cập được, thông qua các relay server do Tailscale vận hành. Các flag và target được dùng chung giữa hai lệnh. Dòng output đầu tiên cho biết bạn đang dùng loại nào: Available within your tailnet hoặc Available on the internet.
Vì sao tailscale funnel báo node attribute chưa được thiết lập?
Vì funnel bị tắt cho một tailnet cho đến khi có người bật tính năng này. Thông báo là Funnel not available; "funnel" node attribute not set. và xuất phát từ chính client của bạn, trước khi client liên hệ với bất kỳ relay nào. Thêm một mục nodeAttrs cấp attribute funnel cho autogroup:member, hoặc cấp cho một tag nếu chỉ một máy được phép publish, trong file policy của tailnet tại mục Access Controls. Admin của tailnet cũng có thể mở consent URL mà CLI in ra.
Tailscale Funnel có thể dùng những port nào?
Chỉ dùng được 443, 8443 và 10000. Mặc định là 443. Bạn chọn port khác bằng --https=8443 hoặc --https=10000. Đây là giới hạn của các funnel relay, không phải của server, nên không thể bỏ giới hạn này bằng cách thay đổi firewall hoặc cấu hình trên VPS. tailscale serve không có giới hạn này vì traffic không bao giờ rời khỏi tailnet của bạn.
URL của serve hoặc funnel có còn hoạt động sau khi reboot không?
Chỉ khi bạn dùng --bg. Nếu không dùng, lệnh chạy ở foreground, in ra Press Ctrl+C to exit., và mapping biến mất cùng với process. Khi dùng --bg, mapping được ghi vào serve config của node và khôi phục bằng tailscaled sau khi reboot. Kiểm tra bằng tailscale serve status. Lệnh này in No serve config khi chưa có cấu hình nào.
Để funnel chạy liên tục có an toàn không?
Xét về transport thì an toàn: kết nối dùng HTTPS và không có port nào được mở trên firewall. Nhưng xét theo nghĩa thông thường của “an toàn” thì không, vì URL là public, nên ứng dụng phía sau URL cũng public. Chỉ để funnel chạy trước một ứng dụng tự xác thực các request của nó. Khi demo hoặc kiểm thử webhook xong, hãy tắt funnel bằng lệnh đã dùng để tạo nó và thêm off ở cuối.
Nguồn về cách các lệnh trên hoạt động: tài liệu Tailscale Serve và Funnel cùng tài liệu tham chiếu CLI tại tailscale.com/docs.