Vite 在 ts.net 地址上报 Blocked request 怎么办
Vite 拒绝 ts.net 主机并提示 Blocked request。把 .ts.net 加入 server.allowedHosts,或通过 TSLink 地址访问开发服务器。
最后更新于
如果 Vite 在 Tailscale 地址上显示下面的报错:
Blocked request. This host ("<device>.<tailnet>.ts.net") is not allowed.
To allow this host, add "<device>.<tailnet>.ts.net" to server.allowedHosts in vite.config.js.原因是 Vite 的 Host 校验:请求带着 ts.net 的 Host 头到达,而这个主机名不在 server.allowedHosts 里,开发服务器就拒绝了它。 有两种修法。一种是把 .ts.net 加入 server.allowedHosts,另一种是通过 TSLink 地址访问开发服务器。TSLink 默认把 Host 头改写成上游地址,Vite 看到的就是它自己的地址。2026-10-22 我们用 Vite 8.3.5 实测,没有修改 Vite 配置,页面和 HMR WebSocket 都能正常工作。TSLink 是独立项目,并非由 Tailscale 出品。
修法一:在 Vite 里放行这个主机
Vite 的 server.allowedHosts 列出开发服务器可以响应的主机名。默认值是空列表,localhost、.localhost 下的域名和所有 IP 地址默认放行。以点开头的字符串会放行该主机名及其全部子域名:
// vite.config.js
import { defineConfig } from 'vite';
export default defineConfig({
server: {
allowedHosts: ['.ts.net'],
},
});.ts.net 是公开报告里使用的写法(portless issue 310 展示了这个报错,jhin 的一个 pull request 加入了 allowedHosts: [".ts.net"])。Vite 文档建议只添加解析归你控制的主机,并提醒不要添加顶级域名这类过宽的条目。更收紧的选择是你自己的 tailnet 后缀,例如 .<tailnet>.ts.net,只放行你自己 tailnet 下的名字。如果运行的是 vite preview 而不是开发服务器,则要设置 preview.allowedHosts,它默认取 server.allowedHosts 的值。
修法二:通过 TSLink 地址打开开发服务器
不用修改 vite.config.js,直接注册开发服务器(假设监听 5173):
tslink add web --proxy localhost:5173 --allow you@example.com
tslink url web --wait把登录名换成你的 Tailscale 账号,然后在手机或 tailnet 里的其他设备上打开打印出的 <name>.<tailnet>.ts.net 地址。用完执行 tslink remove web。首次运行可能打印一个入网链接(needs_login),在浏览器里打开一次即可。
能生效的原因在于 TSLink 的一个默认行为:它的 HTTP 代理把 Host 头改写成本地目标,并转发 WebSocket 升级请求。--preserve-host 参数会改变这一点,让节点转发自己的外部 Host。如果传了这个参数,Vite 又会看到 ts.net 名字,这时需要用修法一。
我们测了什么
- 环境: 全新的
npm create vite@latestvanilla 应用,Vite 8.3.5,监听127.0.0.1:5197,TSLink0.0.0-local.20261020.0149.1+3739bb9b,日期 2026-10-22。 - 不经过 TSLink: 直接请求并带上
Host: vite-probe.<tailnet>.ts.net,返回 403,正文是Blocked request. This host ("vite-probe.<tailnet>.ts.net") is not allowed. - 经过 TSLink: 用
tslink add vite-probe --proxy localhost:5197 --allow <login> --ephemeral注册。通过返回的vite-probe.<tailnet>.ts.net地址访问,/返回 200(text/html),没有 Blocked 字样;/@vite/client和/src/main.js返回 200;HMR WebSocket(Sec-WebSocket-Protocol: vite-hmr)返回 101 Switching Protocols。vite.config没有改动。 - 收尾:
tslink remove vite-probe成功,列表中不再出现该服务,URL 也不再响应。
这次测试只覆盖一个 Vite 版本和 vanilla 模板,没有覆盖自带额外检查的插件、其他框架,也没有测试带 --preserve-host 的注册。如果你的环境属于这些情况,请先自己验证,再依赖这个结论。
Next.js 有自己的校验
Next.js 有另一个设置,叫 allowedDevOrigins。它的文档说明,开发服务器已经放行 localhost、它的子域名和启动时使用的主机名,其他主机名都需要一条配置。我们没有测试过 TSLink 配合 Next.js 的情况,请假定你的 ts.net 名字仍然需要这条配置:
// next.config.js
module.exports = {
allowedDevOrigins: ['*.<tailnet>.ts.net'],
};按这套语法,* 恰好代表一级标签,因此这条规则匹配 web.<tailnet>.ts.net。公开例子里有 agent 添加这一行的 Scouthosting pull request 131 和 kingdom-sites pull request 23。
何时不该用 TSLink
- 只想在一台机器上消除这个报错。
vite.config.js里加一行就够了,不需要多一个工具。 - 希望修复写在项目里。 修法一随仓库一起走,修法二依赖 TSLink 的默认 Host 处理。
- 你用的是 Next.js。 无论如何都要计划添加
allowedDevOrigins。 - 需要跨主机的稳定名字或自己的域名。 关于 Tailscale Services,见一台机器多个服务;TSLink 只提供
*.ts.net名字。 - 开发服务器必须在没有 Tailscale 的情况下可访问。 TSLink 的私有应用要求打开它的设备装有 Tailscale。
相关页面
- 在手机上使用编程 agent 的 Web UI:完整的手机流程,包括入网、取地址和清理。
- 让编程 agent 分享私有预览:连接 Claude Code、Codex、Cursor 或 Gemini CLI,让 agent 自己执行这些命令。
- 一台机器多个服务,每个都有自己的 ts.net 名字:每个开发服务器一个名字。
- tailscale serve 子路径导致 JS/CSS 404 怎么办:路径挂载的另一种常见故障。
以上 Tailscale、Vite 与 Next.js 官方来源访问日期:2026-10-22。TSLink 行为以 v0.2.0 为准。TSLink 是 anydoor7 的独立项目,并非由 Tailscale 制作或背书。