name: tailscale
description: “Tailscale VPN 共享、Serve 和 Funnel 用于远程访问”
emoji: “🔗”
gates:
envs:
anyOf:
- TAILSCALE_AUTHKEY
Tailscale - 完整 API 参考
通过 Tailscale Serve(私有)和 Funnel(公共互联网访问)共享本地服务。
聊天命令
共享本地服务(私有)
/tailscale serve 3000 在 tailnet 上共享端口
/tailscale serve 3000 --path /api 在特定路径共享
/tailscale serve stop 3000 停止共享端口
/tailscale serve status 查看活动共享
公共访问(Funnel)
/tailscale funnel 3000 暴露到互联网
/tailscale funnel 3000 --https 强制 HTTPS
/tailscale funnel stop 3000 停止公共访问
/tailscale funnel status 查看 funnels
网络状态
/tailscale status 网络状态
/tailscale ip 显示 Tailscale IP
/tailscale peers 列出连接的对等节点
/tailscale ping <peer> ping 对等节点
文件传输
/tailscale send <file> <peer> 发送文件到对等节点
/tailscale receive 接收传入文件
TypeScript API 参考
创建 Tailscale 客户端
import { createTailscaleClient } from 'clodds/tailscale';
const tailscale = createTailscaleClient({
// 认证(如果已登录则可选)
authKey: process.env.TAILSCALE_AUTHKEY,
// 套接字路径
socketPath: '/var/run/tailscale/tailscaled.sock',
});
Serve(私有共享)
// 在 tailnet 上共享本地端口
await tailscale.serve({
port: 3000,
protocol: 'https', // 'http' | 'https'
});
console.log(`共享地址: https://${tailscale.hostname}:3000`);
// 在特定路径共享
await tailscale.serve({
port: 8080,
path: '/api',
protocol: 'https',
});
// 使用自定义主机名共享
await tailscale.serve({
port: 3000,
hostname: 'clodds', // clodds.tailnet-name.ts.net
});
// 停止共享
await tailscale.serveStop(3000);
// 获取 serve 状态
const serves = await tailscale.serveStatus();
for (const serve of serves) {
console.log(`端口 ${serve.port} → ${serve.url}`);
}
Funnel(公共互联网)
// 暴露到公共互联网
await tailscale.funnel({
port: 3000,
protocol: 'https',
});
console.log(`公共 URL: https://${tailscale.hostname}.ts.net`);
// 使用自定义域名(如果配置了)
await tailscale.funnel({
port: 3000,
hostname: 'api.example.com',
});
// 停止 funnel
await tailscale.funnelStop(3000);
// 获取 funnel 状态
const funnels = await tailscale.funnelStatus();
for (const funnel of funnels) {
console.log(`端口 ${funnel.port} → ${funnel.publicUrl}`);
}
网络状态
// 获取状态
const status = await tailscale.status();
console.log(`主机名: ${status.hostname}`);
console.log(`IP: ${status.ip}`);
console.log(`Tailnet: ${status.tailnet}`);
console.log(`在线状态: ${status.online}`);
// 列出对等节点
const peers = await tailscale.peers();
for (const peer of peers) {
console.log(`${peer.hostname} (${peer.ip})`);
console.log(` 操作系统: ${peer.os}`);
console.log(` 在线: ${peer.online}`);
console.log(` 最后出现: ${peer.lastSeen}`);
}
// Ping 对等节点
const ping = await tailscale.ping('other-machine');
console.log(`延迟: ${ping.latencyMs}ms`);
文件传输
// 发送文件到对等节点
await tailscale.sendFile({
file: '/path/to/file.zip',
peer: 'other-machine',
});
// 接收文件(在文件接收时返回)
const received = await tailscale.receiveFile({
savePath: '/downloads',
timeout: 60000,
});
console.log(`已接收: ${received.filename}`);
console.log(`来自: ${received.sender}`);
console.log(`大小: ${received.size} 字节`);
获取 Tailscale IP
const ip = await tailscale.getIP();
console.log(`Tailscale IP: ${ip}`); // 100.x.x.x
Serve 与 Funnel
URL 格式
| 类型 |
格式 |
| Serve |
https://machine.tailnet-name.ts.net:port |
| Funnel |
https://machine.ts.net |
| 自定义域名 |
https://your-domain.com |
使用案例
共享开发服务器
// 与团队共享本地开发服务器
await tailscale.serve({ port: 3000 });
// 团队可以在 https://your-machine.tailnet.ts.net:3000 访问
暴露 Webhook 端点
// 使 webhook 可公开访问
await tailscale.funnel({ port: 3000, path: '/webhooks' });
// 外部服务可以 POST 到 https://your-machine.ts.net/webhooks
与手机共享机器人
// 从手机访问机器人,远离办公桌时
await tailscale.serve({ port: 18789 });
// 在手机上打开 https://your-machine.tailnet.ts.net:18789/webchat
要求
- 已安装并运行 Tailscale
- 已登录 Tailnet
- 对于 Funnel:在 Tailscale 管理员中启用 Funnel
最佳实践
- 对内使用 Serve — 保持私有服务私有
- 谨慎使用 Funnel — 仅用于真正的公开端点
- 添加认证 — Funnel 绕过 Tailscale 认证
- 监控访问 — 检查谁在连接
- 完成后停止 — 不要暴露服务