在本地开发 Web 应用时,我们经常需要将本地服务暴露到公网——无论是为了展示给客户看 demo、测试 Webhook 回调,还是让远程同事访问你的开发环境。ngrok 是这个领域最知名的工具,但其免费版限制越来越多,付费计划对个人开发者来说也不算便宜。Tunnelto 提供了另一个选择:它完全开源、用 Rust 编写,既可以使用官方托管服务(月费仅 $4),也可以完全自托管实现零成本运行。
为什么需要隧道工具?
在现代 Web 开发中,隧道工具的使用场景比你想象的要广泛:
- Webhook 调试:Stripe、GitHub、Slack 等服务的 Webhook 需要一个公网可达的 URL
- 移动端测试:在真实手机设备上测试本地开发中的网页
- 客户演示:无需部署即可让客户看到最新的开发进度
- IoT 开发:让云端服务访问本地运行的物联网设备
- AI 开发:本地运行的模型 API 需要被外部服务调用
ngrok 在 2025 年进一步收紧了免费版的限制,包括连接数上限、带宽配额和自定义域名等功能都需要付费。对于不愿被供应商锁定的开发者来说,开源方案显得尤为重要。
Tunnelto 的技术架构
Tunnelto 用 Rust 编写,基于 tokio 异步运行时构建,具有极高的性能和极低的资源占用。其架构分为三个组件:
┌──────────┐ ┌──────────────┐ ┌────────────┐
│ 客户端 │────▶│ 中继服务器 │◀────│ 外部访问者 │
│ (本地) │ │ (公网) │ │ (浏览器) │
└──────────┘ └──────────────┘ └────────────┘
▲ │
│ WebSocket 长连接 │
└───────────────────────────────────────┘
- 客户端(tunnelto client):运行在本地机器上,与中继服务器建立 WebSocket 长连接
- 中继服务器(tunnelto server):运行在公网上,接收外部 HTTP 请求并通过 WebSocket 转发给对应的客户端
- 认证服务:可选组件,管理子域名分配和访问控制
由于使用了 Rust 的零成本抽象和 tokio 的高效异步 I/O,Tunnelto 的内存占用通常在 5-10MB 左右,CPU 使用率几乎为零(空闲时),这使得它非常适合在资源受限的环境中运行。

快速上手
使用官方托管服务
最简单的使用方式是注册 Tunnelto 的官方托管服务,月费 $4,无需自己部署服务器:
# macOS
brew install tunnelto
# Linux
curl -sSL https://tunnelto.dev/install.sh | bash
# 设置认证密钥(注册后获取)
tunnelto set-auth --key YOUR_AUTH_KEY
# 将本地 3000 端口暴露到公网
tunnelto --port 3000
执行后,Tunnelto 会输出一个公网可访问的 URL,类似 https://your-subdomain.tunnelto.dev,所有发送到这个 URL 的请求都会被转发到你本地的 3000 端口。
指定自定义子域名
# 使用固定的子域名
tunnelto --port 3000 --subdomain my-project
# 输出:https://my-project.tunnelto.dev
自托管部署
如果你不想依赖第三方服务,可以自己部署 Tunnelto 的中继服务器。项目提供了完整的服务端代码:
# 克隆仓库
git clone https://github.com/agrinman/tunnelto.git
cd tunnelto
# 编译服务端
cargo build --release --bin tunnelto_server
# 运行服务端(需要公网服务器和域名)
CTRL_HOST=your-domain.com \
CTRL_TLS_CERT=/path/to/cert.pem \
CTRL_TLS_KEY=/path/to/key.pem \
./target/release/tunnelto_server
自托管模式下,你需要准备:
- 一台有公网 IP 的服务器(最低配置 1 核 512MB 内存即可)
- 一个域名,并配置泛域名解析(
*.your-domain.com) - SSL 证书(推荐使用 Let's Encrypt 的泛域名证书)
# 自托管客户端连接
tunnelto --port 3000 \
--host your-domain.com \
--auth-key YOUR_SELF_HOSTED_KEY
与 ngrok 的详细对比
| 特性 | Tunnelto | ngrok (免费版) | ngrok (付费版) |
|---|---|---|---|
| 价格 | 免费(自托管) / $4/月 | 免费 | $8-$20/月 |
| 开源 | 是 (MIT) | 否 | 否 |
| 自托管 | 支持 | 不支持 | 不支持 |
| 自定义子域名 | 支持 | 不支持 | 支持 |
| HTTPS | 自动 | 自动 | 自动 |
| 连接数限制 | 无(自托管) | 20/分钟 | 更高 |
| 请求检查 | 基础 | 丰富 | 丰富 |
| TCP 隧道 | 不支持 | 不支持 | 支持 |
ngrok 的优势在于功能丰富——内置的请求检查器、流量回放、IP 限制等高级功能对企业用户很有价值。但对于只需要基础隧道功能的开发者,Tunnelto 的开源特性和自托管能力是无法替代的优势。
实际使用场景示例
场景一:Webhook 开发调试
以 Stripe 支付回调为例,使用 Tunnelto 可以在本地直接调试 Webhook 处理逻辑:
// server.js - 本地 Express 服务器
import express from 'express';
const app = express();
app.post('/webhook/stripe', express.raw({ type: 'application/json' }), (req, res) => {
const event = JSON.parse(req.body);
console.log('收到 Stripe 事件:', event.type);
switch (event.type) {
case 'payment_intent.succeeded':
console.log('支付成功:', event.data.object.id);
break;
case 'payment_intent.payment_failed':
console.log('支付失败:', event.data.object.id);
break;
}
res.json({ received: true });
});
app.listen(3000, () => console.log('服务器运行在 http://localhost:3000'));
# 启动隧道
tunnelto --port 3000 --subdomain stripe-dev
# 然后在 Stripe Dashboard 中将 Webhook URL 设置为:
# https://stripe-dev.tunnelto.dev/webhook/stripe
场景二:前端开发移动端测试
# 启动 Vite 开发服务器
npm run dev -- --port 5173
# 启动隧道
tunnelto --port 5173 --subdomain my-app
# 在手机浏览器访问 https://my-app.tunnelto.dev
2026 年开源隧道工具生态
除了 Tunnelto,2026 年的开源隧道工具市场还有几个值得关注的选手:
- bore:同样用 Rust 编写,更加简约,专注于最小功能集
- frp:Go 语言编写,功能全面,支持 TCP/UDP/HTTP 多种协议
- Cloudflare Tunnel:免费但非开源,依赖 Cloudflare 基础设施
Tunnelto 在这些选项中的定位是"恰到好处"——比 bore 功能多一些(支持自定义域名和 HTTPS),比 frp 配置简单得多,同时又不像 Cloudflare Tunnel 那样与特定服务商绑定。
总结
Tunnelto 是一款优秀的开源隧道工具,特别适合以下场景:注重数据隐私、不愿被供应商锁定、需要自托管部署、或者只是想找一个免费且靠谱的 ngrok 替代品。Rust 编写带来的高性能低资源占用是额外的加分项。
如果你的需求是简单的本地服务暴露和 Webhook 调试,Tunnelto 完全可以胜任。但如果你需要 TCP 隧道、复杂的流量管理或企业级的访问控制,ngrok 的付费版或 frp 可能更适合。
评论