SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor · 更新于 2026-09-08

Tailscale serve 和 funnel 怎么选?区别与权限配置

Tailscale serve 仅通过 tailnet URL 提供 HTTPS,funnel 则将同一端口暴露到公网。本文说明两者区别,以及阻止 funnel 的策略属性配置要求。

tailscale serve 与 funnel:谁可以访问该 URL

tailscale servetailscale funnel 的区别在于访问对象,仅此而已。serve 会在本地端口前提供 HTTPS(超文本传输协议安全)入口,并且仅将其发布到您的 tailnet。funnel 会通过 Tailscale 运行的中继服务器,将同一本地端口发布到整个公共互联网。这两个命令使用相同的标志和目标。只需一个单词,就能决定某个仪表板是私有的,还是全世界都可以访问。

两者都会为您提供浏览器已经信任的证书,并使用以 ts.net 结尾的名称;两者都不要求在 VPS 防火墙上开放入站端口。您的 tailscaled daemon 已经建立了连接到 tailnet 的出站连接,因此流量会通过该连接到达。让服务器加入 tailnet 是一项工作,将 VPS 作为 Tailscale exit node 运行为私有网络通告 subnet router 已经涵盖了这部分内容。发布 tailnet 中已有的服务,则是本节要处理的内容。

运行任一命令前的准备工作

  • VPS 上安装 Tailscale 1.38.3 或更高版本,并登录到您的 tailnet。使用 tailscale versiontailscale 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 3000
Available within your tailnet:
https://amelie-workstation.pango-lin.ts.net

 |-- / proxy http://127.0.0.1:3000

Press Ctrl+C to exit.

单独使用 3000http://127.0.0.1:3000 的简写。Tailscale 会监听计算机 tailnet 地址的 443 端口,使用 ts.net 证书终止 TLS(传输层安全),然后将普通 HTTP 转发到本地端口。您的应用无需知道证书的存在。这正是将它置于管理面板前端的主要原因,否则该面板只能通过普通 HTTP 提供服务。仅绑定到 127.0.0.1 的 Web UI 是最适合的对象,3080 端口上的 dsh Web UI 就是一个很好的例子:无需每次访问时都打开 SSH 隧道,只需将 serve 一次性指向 3080,即可从 tailnet 上的任何设备访问它。

现在查看最后一行:Press Ctrl+C to exit. 该命令在前台运行,映射关系保存在该进程中。关闭终端后,URL 就会停止工作,因为没有任何内容写入磁盘。添加 --bg 后,映射关系会写入节点的 serve 配置,同时在终端关闭和系统重启后继续生效。

sudo tailscale serve --bg 3000

Serve 不仅支持端口号。--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 策略未授予此节点发布权限,因此客户端在联系中继服务器之前就会拒绝请求。请在管理控制台的 Access Controls 中编辑 tailnet 策略文件,并添加以下属性:

"nodeAttrs": [
  {
    "target": ["autogroup:member"],
    "attr":   ["funnel"],
  },
],

autogroup:member 会将该权限授予 tailnet 的所有成员。如果只有一台机器需要发布内容,请为该机器添加标签,然后改为指定该标签,例如 tag:public。保存策略后,再次运行 Funnel 命令。

如果您的账户是 tailnet 管理员,较新的客户端提供了快捷方式:CLI 会在 login.tailscale.com 中输出一个授权 URL。访问该 URL 后,客户端会为您启用 HTTPS 证书并添加该属性。如果您不是管理员,该 URL 将无法帮助您。必须由具有策略访问权限的人员修改策略。

通过 tailscale funnel 发布到互联网

设置属性后,命令与之前相同,只是使用了不同的动词。

sudo tailscale funnel --bg 3000
Available 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 tailnetAvailable on the internet 是私有服务与公共服务之间唯一可见的差异,而生成它们的命令只相差一个单词。

截至 2026 年 8 月,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(网络地址转换)之后的主机,这是完整的解决方案;VPS 则通常具有公网 IP。

代价同样客观,而且 funnel 会带来所有这些限制。

  • 这个名称不属于您。公网访问者看到的是 host.your-tailnet.ts.net。Funnel 不支持自定义域名,因此无法在它前面使用 app.example.com
  • 这个路径不属于您。流量会先到达 Tailscale 中继,然后由中继通过 tailnet 将流转发到您的节点。Tailscale 表示,funnel 流量受未公开且无法配置的带宽限制影响,因此在依赖某个带宽数值前,请先测量您自己的吞吐量。
  • 缺少控制能力。自行运行的反向代理可以提供访问日志、速率限制、请求大小上限,以及用于配置身份验证的位置。Funnel 只提供一个 URL。其他功能都必须在应用内部实现。
  • 可用端口列表是固定的,具体如上所述。

这两项功能都依赖 Tailscale 运营的基础设施:为 ts.net 名称签发证书,以及运行 funnel 中继。是否需要担心这种依赖,取决于这些服务器能够对您的流量执行哪些操作,Tailscale 的信任模型正是对此进行说明。两者均可免费使用,因为免费计划最多支持 6 个用户,且每个用户可使用无限设备;最终将 tailnet 推向付费计划的是用户数,而不是功能列表。超过该范围后,费用按用户而不是按机器计算,因此在 serve 或 funnel 成为关键依赖前,建议先确认付费计划下 tailnet 的实际成本。如果您正在评估自行托管 Headscale 控制服务器,不要假设这两项功能都能随之使用。请查看计划运行的 Headscale 版本的发行说明。

应使用哪一个?

规则很简单。

内部服务使用 serve:管理界面、仪表板、不希望被索引的指标 UI,以及站点的预发布副本。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.net

使用移动数据时 Funnel 可以加载,但在笔记本电脑上的行为不同。 你的笔记本电脑连接到了 tailnet,因此 MagicDNS 会将该名称解析为 100.x 地址,你会直接访问服务,而不会经过中继。这是正常行为,也意味着你的笔记本电脑完全无法测试公网可达性。请在未连接到 tailnet 的机器上使用 curl

FAQ

tailscale serve 与 tailscale funnel 有什么区别?

谁可以访问发布结果。tailscale serve 会将本地端口发布到一个仅 tailnet 中设备可访问的 HTTPS URL。tailscale funnel 会将同一端口发布到一个互联网上任何人都可访问的 URL,流量通过 Tailscale 运行的中继服务器转发。两者使用相同的标志和目标。输出的第一行会告诉您使用的是哪一种:Available within your tailnetAvailable on the internet

为什么 tailscale funnel 提示节点属性未设置?

因为在有人启用 funnel 之前,tailnet 默认不会启用该功能。此消息为 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 前方部署能够自行验证请求身份的服务时,才应让 funnel 持续运行。演示或 webhook 测试结束后,应在创建该映射的命令末尾添加 off 将其关闭。

上述命令行为的来源是 Tailscale Serve 和 Funnel 文档,以及 tailscale.com/docs 上的 CLI 参考。