内网穿透
内网穿透功能允许位于内网(NAT后)的网关服务通过隧道代理暴露到公网,使外部系统可以直接访问网关的Web管理界面和API服务。该功能基于DMTP协议实现,采用Broker-Client架构,支持TCP流式隧道,具备自动重连和崩溃恢复能力。
什么是内网穿透?
基本概念
| 概念 | 说明 |
|---|---|
| 内网穿透 | 将内网服务通过隧道代理暴露到公网,使外部网络可以访问内网资源 |
| Broker(隧道代理) | 运行在公网环境的中继服务,接受外部连接并转发到隧道客户端 |
| Client(隧道客户端) | 运行在内网网关上的客户端,主动连接Broker并注册隧道 |
适用场景
| 场景 | 说明 | 典型应用 |
|---|---|---|
| 远程运维 | 从公网访问内网网关的Web管理界面 | 远程配置、远程监控 |
| 数据对接 | 外部系统通过公网访问网关API | MES/ERP系统对接、数据上报 |
| 多站点管理 | 集中管理分布在不同内网的多个网关 | 多厂区统一运维 |
通信模型
内网穿透的数据流向如下:
外部客户端 ──▶ ExposedAddress(公网暴露端口) ──▶ Broker ──▶ DMTP隧道 ──▶ Client ──▶ OriginAddress(内网服务地址)
- 隧道客户端主动连接到Broker(出站连接,无需开放内网端口)
- 客户端向Broker注册隧道,指定源地址和对外暴露地址
- Broker在对外暴露地址上监听,收到外部连接后通过DMTP隧道转发数据
- 客户端收到数据后,连接本地源地址,实现双向数据转发
架构说明
Broker-Client架构
ThingsGatewayRuntime的内网穿透采用双端架构:
| 角色 | 运行位置 | 对应服务 | 说明 |
|---|---|---|---|
| Broker | Studio端(公网服务器) | StudioTunnelBrokerService | 监听DMTP端口,管理隧道端点,转发外部流量 |
| Client | Watchdog端(内网网关) | WatchdogTunnelClientService | 连接Broker,注册隧道,支持多个客户端实例 |
协议与端口
| 项目 | 说明 |
|---|---|
| 通信协议 | DMTP(基于TouchSocket) |
| Broker监听端口 | 默认 7789,可配置 |
| 隧道模式 | Stream(TCP流式) |
| 鉴权方式 | AuthToken + AccessKey 双重认证 |
Broker端配置(Studio端)
Broker端运行在Studio服务中,负责接受隧道客户端的连接请求,并在指定端口上暴露服务。
功能入口
通过Studio管理界面进入隧道代理配置页面。
代理状态
| 信息 | 说明 |
|---|---|
| 服务状态 | 是否正在运行(带颜色标签) |
| 监听端口 | Broker当前监听的DMTP端口 |
| 已绑定端点数 | 当前活跃的隧道端点数量 |
| 详细信息 | 运行状态描述 |
代理配置
| 字段 | 说明 | 默认值 |
|---|---|---|
| 启用 | 是否启用隧道代理服务 | 否 |
| 代理端口 | Broker监听的DMTP端口,客户端通过此端口连接 | 7789 |
| 验证令牌 | DMTP连接验证令牌,客户端必须提供相同的令牌才能连接 | Dmtp |
| 访问密钥 | 隧道绑定鉴权密钥,客户端注册隧道时必须提供正确的密钥 | 空(不鉴权) |
- 验证令牌用于DMTP连接认证,Broker和Client必须配置相同的令牌
- 访问密钥用于隧道绑定鉴权,建议在生产环境中设置复杂密钥以提高安全性
- 修改代理端口后,Broker会自动重启以应用新配置
已绑定端点
Broker运行时,可查看当前已绑定的隧道端点列表:
| 列 | 说明 |
|---|---|
| 标签 | 客户端名称标识 |
| 隧道ID | 隧道唯一标识(GUID) |
| 隧道模式 | Stream(TCP流式) |
| 暴露地址 | 对外暴露的监听地址和端口 |
| 源地址 | 内网服务的地址和端口 |
| DMTP通道ID | DMTP通信通道标识 |
| 绑定时间 | 隧道建立的时间 |
Broker端API
| 方法 | 路由 | 说明 |
|---|---|---|
| GET | api/tunnel/status | 获取代理运行状态 |
| GET | api/tunnel/listeners | 分页查询已绑定端点 |
| GET | api/tunnel/config | 获取代理配置 |
| PUT | api/tunnel/config | 持久化并应用代理配置 |
| POST | api/tunnel/start | 激活代理 |
| POST | api/tunnel/stop | 停用代理 |
Client端配置(Watchdog端)
Client端运行在Watchdog服务中,负责主动连接Broker并注册隧道,将内网服务暴露到公网。
功能入口
登录 Watchdog Web 管理界面(默认地址 http://<网关IP>:6200),点击仪表盘页面的"隧道设置"按钮,或直接访问 /tunnel 路径进入隧道设置页面。
全局配置
| 字段 | 说明 | 默认值 |
|---|---|---|
| 启用隧道 | 全局开关,控制是否启用隧道客户端功能 | 否 |
启用隧道后,Watchdog启动时会自动激活所有标记为启用的隧道客户端。
客户端状态
页面以表格形式展示每个隧道客户端的实时状态:
| 列 | 说明 |
|---|---|
| 客户端名称 | 隧道客户端标识 |
| 连接状态 | 已连接/已断开(带颜色标签) |
| 绑定状态 | 已绑定/未绑定(带颜色标签) |
| 隧道ID | 隧道唯一标识 |
| 隧道模式 | Stream/Inactive |
| 源地址 | 内网服务地址 |
| 暴露地址 | 对外暴露地址 |
| 活跃连接数 | 当前活跃的数据转发连接数 |
| 操作 | 激活/停用按钮 |
客户端状态每10秒自动刷新,也可手动点击刷新按钮立即更新。
客户端配置
支持添加多个隧道客户端,每个客户端独立配置。点击"添加客户端"按钮新增一个客户端配置。
| 字段 | 说明 | 默认值 | 校验规则 |
|---|---|---|---|
| 客户端名称 | 隧道客户端唯一标识,不可重复 | 空 | 必填,不可与其他客户端重名 |
| 启用 | 是否启用该客户端 | 是 | - |
| 隧道服务器地址 | Broker的IP地址或域名 | 127.0.0.1 | 必填 |
| 隧道服务器端口 | Broker的DMTP监听端口 | 7789 | 范围1-65535 |
| 验证令牌 | DMTP连接验证令牌,须与Broker端一致 | Dmtp | 必填 |
| 访问密钥 | 隧道绑定鉴权密钥,须与Broker端一致 | 空 | - |
| 源IP/主机 | 内网服务的地址和端口 | 127.0.0.1:6100 | 必填 |
| 对外IP/主机 | Broker端对外暴露的监听地址和端口 | 0.0.0.0:8889 | 必填 |
| 重连间隔 | 断线后自动重连的间隔时间(秒) | 10 | 范围1-300 |
- 客户端名称在同一个Watchdog实例中必须唯一,保存时会校验重复
- 验证令牌和访问密钥必须与Broker端配置一致,否则连接或绑定会失败
- 源IP/主机是内网服务的实际访问地址,如网关Web界面地址
127.0.0.1:6100 - 对外IP/主机是Broker端对外暴露的监听地址,
0.0.0.0表示监听所有网卡,端口为外部访问端口
操作说明
| 操作 | 说明 | 确认级别 |
|---|---|---|
| 激活 | 激活指定隧道客户端,建立到Broker的连接并注册隧道 | 信息确认 |
| 停用 | 停用指定隧道客户端,释放隧道并断开连接 | 警告确认 |
| 全部激活 | 一键激活所有已启用的隧道客户端 | 信息确认 |
| 全部停用 | 一键停用所有隧道客户端 | 警告确认 |
| 保存 | 保存全局配置或客户端配置 | - |
配置文件
Watchdog端配置
隧道客户端配置位于 appsettings.json 的 WatchdogOptions 节点:
{
"WatchdogOptions": {
"TunnelEnabled": false,
"TunnelClients": [
{
"Label": "Default",
"IsActive": true,
"BrokerHost": "127.0.0.1",
"BrokerPort": 7789,
"AuthToken": "Dmtp",
"AccessKey": "",
"OriginAddress": "127.0.0.1:6100",
"ExposedAddress": "0.0.0.0:8889",
"ReconnectDelaySeconds": 10
}
]
}
}
Broker端配置
Broker端配置持久化在 Data/tunnel_broker_config.json 文件中:
{
"Id": "guid",
"IsActive": false,
"BrokerPort": 7789,
"AuthToken": "Dmtp",
"AccessKey": "",
"CreateTime": "2024-01-01T00:00:00Z",
"UpdateTime": "2024-01-01T00:00:00Z"
}
典型部署示例
场景:远程访问内网网关
假设内网网关运行在 192.168.1.100:6100,公网服务器IP为 203.0.113.10。
步骤一:配置Broker端(公网服务器)
- 在Studio管理界面中配置隧道代理
- 设置代理端口为
7789 - 设置验证令牌和访问密钥
- 启用并激活代理
步骤二:配置Client端(内网网关)
- 登录Watchdog Web管理界面,进入隧道设置页面
- 启用隧道全局开关
- 配置隧道客户端:
| 字段 | 值 |
|---|---|
| 客户端名称 | RemoteAccess |
| 启用 | 是 |
| 隧道服务器地址 | 203.0.113.10 |
| 隧道服务器端口 | 7789 |
| 验证令牌 | 与Broker端一致 |
| 访问密钥 | 与Broker端一致 |
| 源IP/主机 | 127.0.0.1:6100 |
| 对外IP/主机 | 0.0.0.0:8889 |
| 重连间隔 | 10 |
- 保存配置并激活客户端
步骤三:远程访问
配置完成后,通过 http://203.0.113.10:8889 即可访问内网网关的Web管理界面。
自动重连与崩溃恢复
自动重连
隧道客户端内置自动重连机制:
- 客户端检测到连接断开后,按配置的重连间隔自动尝试重新连接Broker
- 重连成功后自动重新注册隧道,恢复数据转发
- 重连间隔可通过客户端配置中的"重连间隔"参数调整
崩溃恢复
隧道客户端实现了崩溃恢复机制:
- 每次成功绑定隧道后,将隧道ID持久化到本地文件(
Data/tunnel_id_{name}.txt) - 客户端重启连接Broker后,先尝试预释放上次的隧道ID,避免残留端点占用
- 预释放成功后,再发起新的隧道绑定请求
常见问题
Q1: 客户端连接状态显示"已断开"
解决方案:
- 检查Broker端代理是否已激活
- 检查隧道服务器地址和端口是否正确
- 检查验证令牌是否与Broker端一致
- 检查网络连通性(防火墙是否放行Broker端口)
- 查看Watchdog日志获取详细错误信息
Q2: 客户端已连接但绑定状态显示"未绑定"
解决方案:
- 检查访问密钥是否与Broker端一致
- 检查对外暴露地址的端口是否被Broker端占用
- 查看Broker端日志确认绑定请求是否被拒绝
Q3: 外部无法访问暴露地址
解决方案:
- 确认Broker端服务器的防火墙已放行暴露端口
- 确认暴露地址的IP绑定正确(
0.0.0.0表示监听所有网卡) - 确认客户端的源地址可以正常访问内网服务
- 检查活跃连接数是否正常
Q4: 修改Broker端口后代理未生效
解决方案: 修改Broker端口后,系统会自动重启代理服务。如果代理未自动重启,请手动停用后重新激活代理。