下拉查看上一篇

Tunnelto:Rust 编写的免费开源隧道工具,ngrok 的轻量替代方案


在本地开发 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 项目标识

快速上手

使用官方托管服务

最简单的使用方式是注册 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

自托管模式下,你需要准备:

  1. 一台有公网 IP 的服务器(最低配置 1 核 512MB 内存即可)
  2. 一个域名,并配置泛域名解析(*.your-domain.com)
  3. 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 可能更适合。

参考来源

评论

上滑查看下一篇