Tailscale serve 和 funnel 有什么区别,怎么选
serve 仅通过 tailnet 提供 HTTPS,funnel 则将同一端口公开到互联网。本文解释访问范围、相同配置参数,以及阻止 funnel 的 ACL 节点属性策略门槛。
tailscale serve 与 funnel:谁可以访问该 URL
tailscale serve 与 tailscale funnel 的区别在于访问者,除此之外没有其他区别。serve 为本地端口提供 HTTPS(超文本传输协议安全)前端,并且只将其发布到您的 tailnet。funnel 通过 Tailscale 运行的中继服务器,将同一本地端口发布到整个公共互联网。这两个命令使用相同的 flags 和相同的目标。一个单词,就能决定这是仅供内部访问的仪表板,还是全世界都能访问的服务。
两者都会为您提供浏览器已信任的证书,证书名称以 ts.net 结尾;两者都不需要在 VPS 防火墙上开放入站端口。您的 tailscaled daemon 已经建立了到 tailnet 的出站连接,因此流量会通过该连接到达。将服务器接入 tailnet 是一项工作,将 VPS 运行为 Tailscale exit node 或 为私有网络发布 subnet router 都属于这一范围。发布已经位于 tailnet 上的服务,则是本文要介绍的工作。
两条命令生效前的准备工作
- VPS 上安装 Tailscale 1.38.3 或更高版本,并登录到您的 tailnet。使用
tailscale version和tailscale status检查。 - 启用 MagicDNS。MagicDNS 是 Tailscale 内置的 DNS(域名系统),用于为机器分配类似
blog-vps.your-tailnet.ts.net的名称,而不只是100.x地址。 - 在管理控制台的 DNS 页面中,为 tailnet 启用 HTTPS 证书。如果未启用,就没有可配置在端口前的证书。
- 仅对
funnel而言,还需要在 tailnet 策略文件中设置funnel节点属性。大多数首次尝试都会卡在这里,下面将对此进行说明。
这里的每条命令都以 sudo 开头,因为 CLI 只能通过 root 可写的套接字与 tailscaled 通信。为一个用户授予跳过该前缀的权限:
sudo tailscale set --operator=$USER使用 tailscale serve 发布到 tailnet
将 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 会监听计算机 tailnet 地址的 443 端口,使用 ts.net 证书终止 TLS(传输层安全),然后将普通 HTTP 转发到本地端口。您的应用无需知道证书的存在。这是将它放在管理面板前面使用的主要原因,否则该面板只能通过普通 HTTP 提供服务。
现在查看最后一行:Press Ctrl+C to exit.。该命令在前台运行,映射关系保存在该进程中。关闭终端后,URL 就会停止工作,因为没有任何内容写入磁盘。添加 --bg 后,映射关系会写入节点的 serve 配置,并在终端关闭或系统重启后继续生效。
sudo tailscale serve --bg 3000Serve 不仅支持端口号。--set-path 可以将服务挂载到子路径下,因此多个应用可以共用一个主机名:
sudo tailscale serve --bg --set-path=/grafana 3000
sudo tailscale serve --bg --set-path=/metrics 9090目标也可以是包含静态文件的目录,或者已经使用 TLS 提供服务、但您不希望验证其证书的后端:
sudo tailscale serve --bg /srv/reports
sudo tailscale serve --bg https+insecure://localhost:8443它也不限于 HTTP。--tcp=<port> 会转发原始 TCP(传输控制协议)流,--tls-terminated-tcp=<port> 会在节点上终止 TLS,然后转发明文数据。这样,不支持 HTTP 的服务前面也可以使用受信任的证书:
sudo tailscale serve --bg --tls-terminated-tcp=443 tcp://127.0.0.1:9899为什么 Funnel 提示未设置节点属性?
默认情况下,整个 tailnet 都未启用 Funnel。首次运行时会显示以下信息,然后退出:
Funnel not available; "funnel" node attribute not set. See https://tailscale.com/kb/1223/tailscale-funnel/.命令本身没有问题。tailnet policy 尚未授予此节点发布权限,因此客户端会在联系 relay 之前拒绝操作。请在管理控制台的 Access Controls 中编辑 tailnet policy 文件,并添加以下属性:
"nodeAttrs": [
{
"target": ["autogroup:member"],
"attr": ["funnel"],
},
],autogroup:member 会将该属性授予 tailnet 中的所有成员。如果只有一台机器需要发布,则应为该机器添加标签,并改为指定该标签,例如 tag:public。保存 policy,然后再次运行 Funnel 命令。
如果您的账户是 tailnet 管理员,较新的客户端提供了快捷方式:CLI 会在 login.tailscale.com 中打印 consent URL。打开该 URL 后,客户端会为您启用 HTTPS 证书并添加该属性。如果您不是管理员,该 URL 对您没有帮助。必须由拥有 policy 访问权限的人员完成修改。
通过 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 是私有服务与公网服务之间唯一可见的区别,而生成它们的命令只差一个单词。
截至 August 2026,funnel 仅监听端口 443、8443 或 10000,不监听其他端口。默认端口是 443,--https=8443 或 --https=10000 是可选端口。其他端口都会被拒绝,因为 funnel 中继只接受这些端口上的连接。因此,funnel URL 始终是裸主机名,或在主机名末尾直接附加 :8443。
当前发布了哪些内容?
不要靠猜测判断。这样可能让仪表板公开一个月。应直接查询节点。
tailscale serve status
tailscale funnel status
tailscale serve status --json这两个状态命令读取相同的配置,因此使用任意一个都能查看完整状态。在脚本或计划任务中使用 --json 形式,因为普通输出面向人工阅读。未配置任何内容时,输出一行:
No serve config如果设置完成后看到该输出,说明映射是在前台创建的,而进程已经退出。使用 --bg 重新创建映射。
要删除一个映射,请重复创建该映射时使用的命令,并在末尾添加 off。要删除节点上的所有 serve 和 funnel 映射,请使用 reset。
sudo tailscale funnel --https=443 3000 off
sudo tailscale serve reset执行任一操作后,再次运行 tailscale serve status 并查看剩余内容,不要想当然地认为命令已按预期执行。
你获得的功能,以及需要放弃的功能
这些优势确实存在,也是人们选择它而不是反向代理的原因。
- 浏览器信任的证书会自动续期。无需安装 ACME(自动证书管理环境)客户端,也不会忘记配置续期任务。
- VPS 防火墙无需开放入站端口。
tailscaled会主动建立出站连接,因此 VPS 上默认拒绝连接的 ufw 防火墙 可以保持原有的严格配置。 - 无需购买、指向或等待生效的 DNS 记录。
- 无需端口转发。对于位于 NAT(网络地址转换)之后的主机,而不是拥有公网 IP 的 VPS,这就是全部配置。
这些代价同样确实存在,Funnel 会带来以下所有限制。
- 该名称不属于您。公网访问者看到的是
host.your-tailnet.ts.net。Funnel 不支持自定义域名,因此无法在其前面使用app.example.com。 - 该路径不属于您。流量会先到达 Tailscale 中继,然后由中继通过 tailnet 将流代理到您的节点。Tailscale 说明,Funnel 流量受带宽限制约束,但这些限制未公开且无法配置。因此,在依赖某个带宽数值前,请先测量您自己的吞吐量。
- 缺少控制功能。您自行运行的反向代理可以提供访问日志、速率限制、请求大小上限,以及用于配置身份验证的位置。Funnel 只提供一个 URL。其他功能都必须由您的应用自行实现。
- 端口列表是固定的,具体如上所述。
这两项功能还依赖 Tailscale 运营的基础设施:为 ts.net 名称签发证书,以及运行 Funnel 中继。如果您正在考虑使用 自行托管的 Headscale 控制服务器,不要假设这些功能也会随之提供。请查看计划运行的 Headscale 版本的发行说明。
应使用哪一个?
规则很简单。
内部用途使用 serve:管理界面、仪表盘、不希望被索引的指标界面,以及网站的预发布副本。访问控制由 tailnet 成员资格提供,而且足够可靠。不在 tailnet 上的设备甚至无法解析该名称。
演示链接、第三方必须向其发送 POST 请求的 webhook 接收端,或开发期间的 OAuth 回调,使用 funnel。这是获取公网 HTTPS URL 的最快方式,执行一条 off 命令即可结束公开访问。但公网意味着任何人都可以访问:主机名不是机密;如果应用没有登录验证,前面的 funnel 就是一个开放服务。其后端必须自行验证请求,所需的安全性与 暴露在公网的 Ollama API 端点相同。
生产环境使用真正的反向代理。域名、证书、日志和速率限制都由您控制,并且请求路径中不包含其他方。比较 nginx、Caddy 和 Traefik 反向代理介绍了如何选择。
故障模式及其对应的提示信息
Funnel 拒绝启动。 Funnel not available; "funnel" node attribute not set. 是策略问题,不是命令问题。将 funnel 属性添加到 tailnet 策略文件中,保存后重试。
刚才还能运行,现在 tailscale serve status 显示 No serve config。 该映射是在前台创建的,而创建它的进程已经结束。使用 --bg 重新运行相同的命令。
名称可以解析,但没有响应。 Serve 会将请求代理到你指定的目标。如果目标没有进程监听,就没有可代理的服务。在运行 tailscaled 的同一台机器上使用 ss -ltnp | grep 3000 进行确认。常见原因是容器将端口发布到了 Docker bridge 地址,而不是 127.0.0.1,因此主机在预期位置看不到监听进程。Docker Compose 网络的工作方式说明了已发布端口的实际落点。
ts.net 名称出现证书错误。 tailnet 很可能尚未启用 HTTPS 证书。在管理控制台中启用证书,然后单独运行证书步骤,避免其错误与 serve 输出混在一起:
sudo tailscale cert your-host.your-tailnet.ts.netFunnel 在移动数据网络下可以加载,但在笔记本电脑上的行为不同。 笔记本电脑已连接到 tailnet,因此 MagicDNS 会将该名称解析为 100.x 地址,随后直接访问服务,不会经过中继。这是正常行为,也意味着笔记本电脑完全无法测试公网可达性。请在未连接到 tailnet 的机器上使用 curl。
FAQ
tailscale serve 和 tailscale funnel 有什么区别?
谁可以访问发布结果。tailscale serve 会将本地端口发布到一个 HTTPS URL,只有 tailnet 中的设备可以访问。tailscale funnel 会将同一个端口发布到一个任何互联网用户都可以访问的 URL,并通过 Tailscale 运行的中继服务器进行路由。两者使用相同的标志和目标。输出的第一行会告诉您使用的是哪一种:Available within your tailnet 或 Available on the internet。
为什么 tailscale funnel 提示节点属性未设置?
因为在有人启用 funnel 之前,tailnet 默认禁用 funnel。该消息是 Funnel not available; "funnel" node attribute not set.,由您自己的客户端生成,发生在联系任何中继服务器之前。在 Access Controls 下的 tailnet 策略文件中添加一个 nodeAttrs 条目,将 funnel 属性授予 autogroup:member,或者授予某个标签,以便只允许一台机器发布。tailnet 管理员也可以按照 CLI 输出的同意 URL 操作。
Tailscale Funnel 可以使用哪些端口?
只能使用 443、8443 和 10000。默认端口是 443;您可以使用 --https=8443 或 --https=10000 选择其他端口。这是 funnel 中继服务器的限制,不是服务器本身的限制,因此修改 VPS 上的防火墙或配置都无法解除该限制。tailscale serve 没有此限制,因为它的流量不会离开您的 tailnet。
serve 或 funnel URL 在重启后仍然有效吗?
只有使用了 --bg 才会保留。不使用该选项时,命令会在前台运行,输出 Press Ctrl+C to exit.,映射会随进程结束而消失。使用 --bg 时,映射会写入节点的 serve 配置,并在重启后通过 tailscaled 恢复。使用 tailscale serve status 检查;未设置任何内容时,该命令会输出 No serve config。
让 funnel 持续运行是否安全?
从传输安全角度看是安全的:连接使用 HTTPS,并且防火墙上不会开放端口。但从通常所说的安全角度看并不安全,因为 URL 是公开的,后端应用也会公开。只有在前面运行能够自行验证请求的应用时,才应保留 funnel;演示或 webhook 测试结束后,应使用创建它的命令,并在末尾加上 off 将其关闭。
上述命令行为的来源:Tailscale Serve 和 Funnel 文档及 CLI 参考,位于 tailscale.com/docs。