littledivy/tailnet-do
运维与部署把 Cloudflare Durable Object 变成 Tailscale 尾网设备,拥有独立 100.x 地址,可提供 HTTP/TCP 服务和出站访问。
项目介绍
tailnet-do 让 Cloudflare Durable Object 成为 Tailscale 尾网中的普通设备,拥有自己的 100.x 地址。这个对象可以向其他尾网设备提供 HTTP 或 TCP 服务、主动连接私有机器,也能充当出口节点(exit node)或子网路由。
底层是 Tailscale 自带的用户态客户端(WireGuard、netstack、DERP)编译成 WebAssembly。控制平面和 DERP 中继通过出站 WebSocket 连接,经由出口节点离开的流量则走 cloudflare:sockets。
快速使用
在 Worker 中配置密钥,然后继承 TailnetObject 并实现 onTailnet 来对外服务:
import { TailnetObject } from "tailnet-do";
export class Node extends TailnetObject {
async onTailnet(tailnet) {
tailnet.serve(80, (req, who) => new Response(`hi ${who.loginName}`));
}
}
export default {
async fetch(req, env) {
const node = env.NODE.getByName("main");
return node.tailnetFetch("http://homelab:8080/status");
},
};
把 TS_AUTHKEY(以及可选的 TS_HOSTNAME、TS_CONTROL_URL)配置为 secret。没有 auth key 时,节点会进入交互式登录,登录地址可从 status().loginURL 取得。
如需从源码构建 WebAssembly 引擎,先初始化固定版本的 Tailscale 子模块,再构建并运行出口节点示例:
git submodule update --init --depth 1
npm run build
cd examples/exit-node && npx wrangler dev
API 概览
在 Durable Object 内,Tailnet.start(ctx, options) 返回一个节点,TailnetObject 是对它的封装。connect("host:port") 向尾网主机打开 TCP(支持 MagicDNS 名称),fetch(url, init) 通过尾网发 HTTP,serve(port, handler) 在节点的尾网地址上运行 HTTP 服务器,listen(port, handler) 接受原始 TCP。whois、status、ready、logout 分别负责身份查询、状态、就绪检查和登出。TailnetObject 还通过 RPC 提供 tailnetConnect、tailnetFetch 和 tailnetStatus,让没有自己节点的 Worker 经由 DO stub 使用尾网。
可用选项包括 authKey、hostname、controlURL、ephemeral、tags、exitNode、advertiseRoutes、dohURL、keepAlive、statePrefix 和 onLog。
使用约束
出口节点只转发 TCP,以及通过 DoH 应答的 DNS;Workers 没有 UDP socket,因此 QUIC 会回退到 TCP。出站 25 端口被封锁,发往 Cloudflare IP 段的出站 socket 也可能被封锁。Durable Object 只存在于一个位置,流量从对象创建的地区出去,可用 locationHint 把出口节点放到特定区域。
仓库未声明许可证,所提供的材料里也没有发布版本或包元数据;依赖 npm 导入或长期部署前需要自行确认这些信息。
HotRepo 点评
该项目在 2026-11-08 进入 HotRepo 新项目榜,记录到 103 stars、2 forks,一小时的统计窗口内净增 3 stars。单条快照只能说明早期关注度,不足以判断趋势。真正有意思的是架构:它把完整的用户态 Tailscale 客户端(含 WireGuard 和 DERP)放进 Cloudflare Durable Object,为 Workers 打通私有尾网服务提供了一种不需要额外网关机器的做法。
本文由 AI 根据项目 README 生成,更新于 ,以项目官方文档为准。