WebRTC P2P信令服务架构设计文档
0. 项目概述
WebRTC P2P 隧道代理系统,通过 WebRTC 数据通道实现安全的 SSH、SFTP 连接以及 TCP/UDP 隧道中转。支持浏览器模式和本地代理模式。
项目演进计划
本项目采用三阶段演进策略,确保系统从基础功能到高级特性的平滑过渡:
第一阶段:基础功能实现
- 核心目标:实现基本的WebRTC连接建立、SSH/SFTP代理和隧道转发功能
- 关键特性 :
- 信令服务器基本功能
- WebRTC P2P连接建立
- SSH/SFTP代理功能
- 基本的会话管理
- 简单的错误处理
第二阶段:性能、容错与安全增强
- 核心目标:提升系统性能、增强容错能力和安全性
- 关键特性 :
- 连接质量监控与动态调整
- 完善的错误处理和异常恢复
- 增强的安全认证机制
- 性能优化(数据压缩、批量处理等)
- 负载均衡和故障转移
第三阶段:监控、集群与高级特性
- 核心目标:实现系统监控、集群部署和高级特性
- 关键特性 :
- 完整的监控和告警系统
- 信令服务器集群部署
- 远程代理集群管理
- 高级负载均衡策略
- 多租户支持
- API和管理界面
0.1 三阶段详细实现计划
第一阶段:基础功能实现
架构设计
- 单节点信令服务器:实现基本的WebSocket连接管理和消息转发
- 远程代理:实现基本的WebRTC连接建立和SSH/SFTP客户端功能
- 本地代理:实现基本的TCP/UDP隧道转发功能
- 浏览器客户端:实现基本的WebSSH/WebFile界面和WebRTC连接
核心组件
-
信令服务器
- WebSocket服务器
- 消息处理器
- 代理注册表
- 连接管理器
-
WebRTC连接管理
- WebRTC连接创建和管理
- SDP和ICE候选者交换
- 数据通道建立和管理
-
会话管理
- 基本的会话创建和销毁
- 会话状态管理
- 简单的会话复用
-
SSH/SFTP代理
- SSH客户端基本功能
- SFTP客户端基本功能
- 简单的认证机制
-
隧道转发
- TCP/UDP数据转发
- 基本的隧道配置
技术要求
- 开发语言:Go(服务端)、JavaScript(浏览器端)、Python(测试)
- 核心库 :
- WebRTC:pion/webrtc(Go)、native WebRTC API(浏览器)
- WebSocket:gorilla/websocket(Go)
- SSH/SFTP:golang.org/x/crypto/ssh(Go)
- 测试工具:websocket-client(Python)、aiortc(Python)
关键指标
- 连接建立时间:< 5秒
- 数据传输延迟:< 100ms(P2P模式)
- 并发会话数:< 100
- 错误率:< 1%
第二阶段:性能、容错与安全增强
架构设计
- 增强的信令服务器:添加连接质量监控和负载均衡
- 智能WebRTC连接管理:实现连接质量评估和自动模式切换
- 完善的会话管理:添加会话负载均衡和故障转移
- 增强的安全机制:实现完整的认证和授权
核心组件
-
连接质量监控
- 网络延迟监测
- 丢包率监测
- 带宽监测
- 自动模式切换
-
错误处理与恢复
- 完善的错误处理机制
- 网络异常自动恢复
- 会话状态同步
-
性能优化
- 数据压缩
- 批量处理
- 连接复用
- 内存优化
-
安全增强
- 令牌认证机制
- SSH主机密钥验证
- 敏感信息加密
- 访问控制
-
负载均衡
- 会话负载均衡
- 连接池管理
- 故障转移
技术要求
- 新增库 :
- 监控库:prometheus(可选)
- 加密库:crypto/tls(Go)
- 负载均衡:自定义实现
关键指标
- 连接建立时间:< 3秒
- 数据传输延迟:< 50ms(P2P模式)
- 并发会话数:< 500
- 错误率:< 0.1%
- 恢复时间:< 10秒(网络故障)
第三阶段:监控、集群与高级特性
架构设计
- 信令服务器集群:实现高可用和水平扩展
- 远程代理集群:实现多代理负载均衡和故障转移
- 完整的监控系统:实现全系统监控和告警
- 高级特性:实现多租户、API和管理界面
核心组件
-
信令服务器集群
- 集群发现和管理
- 负载均衡
- 高可用
- 数据同步
-
远程代理集群
- 代理发现和注册
- 智能负载均衡
- 故障自动转移
- 健康检查
-
监控与告警
- 系统指标监控
- 服务状态监控
- 网络质量监控
- 智能告警
-
高级特性
- 多租户支持
- RESTful API
- 管理界面
- 配置中心
技术要求
- 新增库 :
- 集群管理:etcd(可选)
- 监控:prometheus + grafana
- API框架:gin(Go)
- 前端框架:React/Vue(可选)
关键指标
- 系统可用性:> 99.9%
- 并发会话数:> 1000
- 响应时间:< 200ms(API)
- 故障恢复:< 30秒(节点故障)
- 扩展性:支持水平扩展
业务模式
- 浏览器模式 : WebSSH/WebFile 终端和文件管理
- 直连模式:浏览器 → 信令服务器 → 目标服务器
- 代理模式:浏览器 → WebRTC隧道 → 远程代理 → 目标服务器
- 本地代理模式 : APP 和目标服务器 TCP/UDP 通讯
- APP → 本地代理 → WebRTC隧道 → 远程代理 → 目标服务器
1. 名词定义
| 名词 | 解释 |
|---|---|
| WebRTC | 一种支持网页浏览器进行实时语音通话或视频聊天的技术标准 |
| P2P | Peer-to-Peer,点对点通信模式 |
| 信令服务 | 用于建立WebRTC连接的中间服务器,负责交换SDP和ICE信息 |
| SDP | Session Description Protocol,会话描述协议,用于描述媒体会话的参数 |
| ICE | Interactive Connectivity Establishment,交互式连接建立,用于NAT穿透 |
| 代理 | 负责转发流量的中间组件,可以是本地代理或远程代理 |
| 隧道 | 建立在两个代理之间的虚拟连接,用于转发特定端口的流量 |
| 中继 | 当P2P连接失败时,使用coturn服务器作为中间节点转发流量,coturn服务器提供STUN/TURN功能 |
| coturn | 开源的STUN/TURN服务器实现,用于WebRTC的NAT穿透和中继服务 |
| STUN | Session Traversal Utilities for NAT,NAT会话遍历实用程序,用于获取公网IP地址 |
| TURN | Traversal Using Relays around NAT,通过NAT中继进行遍历,当P2P连接失败时作为中继服务器 |
| WebSSH | 通过Web界面访问SSH终端的技术 |
| 代理ID | 唯一标识代理的字符串 |
| 代理角色 | 代理的类型,可以是local(本地代理)、remote(远端代理)或browser(浏览器客户端) |
2. 通讯接口
2.1 WebSocket接口
接口地址:
- HTTP版本:
ws://{host}:{port}/ws- 开发环境示例:
ws://localhost:3800/ws - 生产环境示例:
ws://gx.ppy123.xyz:3700/ws
- 开发环境示例:
- HTTPS版本:
wss://{host}:{port}/ws- 开发环境示例:
wss://localhost:3800/ws - 生产环境示例:
wss://gx.ppy123.xyz:3700/ws
- 开发环境示例:
URI参数说明:
| 参数 | 类型 | 描述 | 示例值 |
|---|---|---|---|
host |
string | 信令服务器的主机名或IP地址 | localhost, gx.ppy123.xyz |
port |
int | 信令服务器的端口号 | 3800(开发), 3700(生产) |
服务类型说明 :
所有客户端使用统一的WebSocket端点,服务类型和连接模式信息通过注册指令体现:
- 客户端类型:浏览器类、本地代理类、远程代理类
- 功能类型:WebSSH终端、文件传输、TCP/UDP隧道中转等
连接模式说明:
- 直连模式 (direct):浏览器直接通过信令服务器连接目标服务器
- 适用于WebSSH和WebFile功能
- 不需要建立WebRTC连接
- 远程代理模式 (remote_proxy):通过WebRTC隧道连接到远程代理,再访问目标服务器
- 适用于需要穿透防火墙的场景
- 支持P2P和中继连接方式
- P2P模式 :浏览器/本地代理与远程代理之间建立直接的P2P连接
- 优先使用,提供更低的延迟和更高的带宽
- 中继模式 :通过TURN服务器中继浏览器/远程代理与远程代理之间的通信
- 当P2P连接失败时使用
- 确保在复杂网络环境下的连接可靠性
服务类型说明:
- WebSSH (webssh):提供SSH终端访问服务
- 通过xterm.js实现Web终端界面
- 支持终端大小调整、颜色方案等高级功能
- WebFile (webfile):提供文件传输和管理服务
- 支持文件上传、下载、删除、重命名等操作
- 支持大文件分块传输和断点续传
连接建立流程:
所有客户端通用流程
- 客户端构建统一的WebSocket URI:
ws://{host}:{port}/ws(或HTTPS版本的wss://{host}:{port}/ws) - 客户端通过WebSocket协议连接到指定URI
- 服务器验证连接请求
- 连接建立成功后,客户端通过
register消息发送注册信息,包括角色、类别、功能等 - 服务器根据注册信息进行服务路由和配置
- 客户端可以通过
connect_request消息发起具体的连接请求,指定连接模式等参数
2.2 STUN/TURN服务器配置机制
核心原则:
- STUN服务器:本地代理、浏览器客户端和远程代理分别使用自己配置文件中的STUN服务器
- TURN服务器:本地代理、浏览器客户端和远程代理统一使用远程代理配置文件中的TURN服务器
- TURN配置获取:本地代理和浏览器客户端通过信令服务器从远程代理获取TURN服务器配置
详细流程:
-
远程代理启动时:
- 加载自身配置文件中的STUN服务器和TURN服务器
- 为TURN服务器生成动态凭证(如果需要)
- 向信令服务器注册,并提供TURN服务器配置信息
-
本地代理启动时:
- 加载自身配置文件中的STUN服务器
- 向信令服务器注册
-
浏览器客户端连接时:
- 直接通过WebSocket连接信令服务器
- 浏览器客户端可以使用自身配置的STUN服务器(如果有)
-
连接建立时:
- 客户端(本地代理/浏览器)发起连接请求(
connect_request) - 信令服务器将请求转发给远程代理
- 远程代理返回连接响应(
connect_response),包含自身的TURN服务器配置 - 信令服务器将远程代理的TURN服务器配置转发给客户端
- 客户端(本地代理/浏览器)发起连接请求(
-
WebRTC连接建立:
- 本地代理使用自身配置的STUN服务器 和远程代理提供的TURN服务器建立WebRTC连接
- 浏览器客户端使用自身配置的STUN服务器(如果有)和远程代理提供的TURN服务器建立WebRTC连接
- 远程代理使用自身配置的STUN服务器 和自身配置的TURN服务器建立WebRTC连接
配置文件说明:
- 本地代理配置文件:仅包含STUN服务器配置
- 浏览器客户端:可在页面配置或使用默认STUN服务器
- 远程代理配置文件:包含STUN服务器和TURN服务器配置
安全考虑:
- TURN服务器凭证由远程代理动态生成,确保安全性
- 信令服务器仅转发TURN服务器配置,不存储敏感信息
- 浏览器客户端的STUN服务器配置应从安全可靠的来源获取
连接请求信息
客户端在注册后,通过connect_request消息传递以下信息:
- 客户端详细信息(类型、子类型、版本等)
- 连接参数(模式、协议、超时设置等)
- SSH访问参数(仅浏览器类ssh子类型时使用)
- 目标代理ID
- 能力需求
- 代理令牌
核心用途:
- 统一连接入口:为所有客户端(浏览器和APP)提供统一的WebSocket连接入口
- 信令交换通道:作为WebRTC连接建立和管理的信令传输通道
- 服务协商机制:通过注册协议实现客户端类型、连接模式和功能需求的动态协商
- 跨平台支持:同时支持浏览器类和APP类客户端,实现统一的通信架构
- 灵活的服务路由:服务器根据客户端注册信息进行动态服务路由和配置
- 多种功能支持:同时支持WebSSH终端、文件传输、P2P连接和中继传输等多种功能
重要约束:
- 信令服务器和远程代理都作为 SSH/SFTP 客户端连接目标服务器
- 直连模式:信令服务器直接连接目标服务器
- 代理模式:远程代理连接目标服务器
- 所有 SSH/SFTP 连接使用项目统一的连接管理器
支持的消息类型:
| 消息类型 | 方向 | 功能描述 |
|---|---|---|
| register | 浏览器/APP/本地代理/远程代理 → 信令服务 | 客户端注册请求 |
| register_response | 信令服务 → 浏览器/APP/本地代理/远程代理 | 注册响应 |
| connect_request | 浏览器/APP/本地代理/远程代理 → 信令服务 | 连接请求 |
| connect_response | 信令服务 → 浏览器/APP/本地代理/远程代理 | 连接响应 |
| ssh_config | 浏览器 → 信令服务 → 远程代理 | SSH配置消息 |
| sftp_config | 浏览器 → 信令服务 → 远程代理 | SFTP配置消息 |
| sftp_command | 浏览器 → 信令服务 → 远程代理 | SFTP命令消息 |
| sdp_offer | 本地代理/浏览器/APP → 信令服务 → 远程代理 | SDP Offer交换 |
| sdp_answer | 远程代理 → 信令服务 → 本地代理/浏览器/APP | SDP Answer交换 |
| ice_candidate | 本地代理/远程代理/浏览器/APP → 信令服务 → 另一方 | ICE Candidate交换 |
| heartbeat | 浏览器/APP/本地代理/远程代理 ↔ 信令服务 | 心跳检测 |
| mode_switch | 信令服务 → 本地代理/远程代理/浏览器/APP | 连接模式切换通知 |
消息体参数定义:
1. register (注册请求)
json
{
"type": "register", // 消息类型,固定为"register"
"request_id": "req_123456789", // 请求唯一标识符,用于匹配请求和响应
"from": "browser_abc123", // 发送者ID,与proxy_id保持一致
"timestamp": "2023-01-01T12:00:00Z", // 消息发送时间,ISO8601格式
"proxy_id": "browser_abc123", // 客户端唯一标识符,必须全局唯一,前缀格式:browser_(浏览器类)、app_(APP类)、local_(本地代理类)、remote_(远程代理类)
"role": "browser", // 连接类型:browser(浏览器类)、app(APP类)、local(本地代理类)、remote(远程代理类)
"version": "v1.0.0" // 客户端软件版本号
}
注册指令说明 :
注册指令包含以下核心信息,用于标识客户端的角色、类别和功能:
- 角色与类别 :通过
role字段和proxy_id前缀共同标识role字段:明确客户端类型(browser/app/local/remote)proxy_id前缀:与role字段保持一致(browser_/app_/local_/remote_)
- 版本信息 :通过
version字段提供客户端软件版本
服务路由逻辑 :
服务器根据注册信息进行动态服务路由和配置:
- 浏览器类客户端:根据后续的连接请求中的
service_type提供相应的WebSSH或WebFile功能 - APP类客户端:支持P2P和中继连接功能
- 本地代理类客户端:提供TCP/UDP隧道中转服务
- 远程代理类客户端:作为目标服务器的接入点
连接模式信息 :
连接模式信息通过后续的connect_request消息传递:
- 浏览器类:支持直连模式和代理模式
- APP类:支持自动模式、P2P模式和中继模式
2. register_response (注册响应)
json
{
"type": "register_response", // 消息类型,固定为"register_response"
"request_id": "req_123456789", // 请求唯一标识符,与对应的注册请求保持一致
"from": "signaling_server", // 发送者ID,通常是信令服务器的标识
"to": "browser_abc123", // 接收者ID,即对应的客户端ID
"timestamp": "2023-01-01T12:00:01Z", // 消息发送时间,ISO8601格式
"code": 200, // 响应状态码:200表示成功,其他表示失败
"message": "Register successful", // 响应消息,描述注册结果
"success": true // 注册是否成功:true表示成功,false表示失败
}
3. connect_request (连接请求)
json
{
"type": "connect_request", // 消息类型,固定为"connect_request"
"request_id": "req_987654321", // 请求唯一标识符,用于匹配请求和响应
"from": "browser_abc123", // 发送者ID,与注册时的proxy_id保持一致
"timestamp": "2023-01-01T12:00:02Z", // 消息发送时间,ISO8601格式
"target_proxy_id": "remote_abc123", // 目标代理的唯一标识符,使用remote_前缀
"mode_preference": "p2p", // 连接模式偏好:auto, force-p2p, force-relay, p2p
"proxy_token": "token_secure123", // 代理通讯令牌,用于身份验证和授权
"connection_mode": "remote_proxy", // 连接模式:remote_proxy(远程代理)、direct(直连)
"service_type": "webssh" // 服务类型:webssh(SSH终端)、webfile(文件传输)
}
4. connect_response (连接响应)
json
{
"type": "connect_response", // 消息类型,固定为"connect_response"
"request_id": "req_987654321", // 请求唯一标识符,与对应的连接请求保持一致
"from": "signaling_server", // 发送者ID,通常是信令服务器的标识
"to": "browser_abc123", // 接收者ID,与对应的连接请求保持一致
"timestamp": "2023-01-01T12:00:03Z", // 消息发送时间,ISO8601格式
"code": 200, // 响应状态码:200表示成功,其他表示失败
"message": "Connect request accepted", // 响应消息,描述连接请求结果
"success": true, // 连接请求是否成功:true表示成功,false表示失败
"p2p_info": {
"status": "available" // P2P连接状态:available(可用)、unavailable(不可用)
// 注意:本地代理使用自己配置文件中的STUN服务器,不通过响应获取
},
"relay_info": {
"status": "available", // 中继连接状态:available(可用)、unavailable(不可用)
"turn_servers": [ // 远程代理提供的TURN服务器配置列表,用于中继连接
{
"urls": ["turn:turn.gx.ppy123.xyz:3478"], // TURN服务器URL列表
"username": "user123", // TURN服务器用户名(必须)
"credential": "pass123" // TURN服务器密码(必须)
}
]
}
}
5. sdp_offer (SDP Offer)
json
{
"type": "sdp_offer", // 消息类型,固定为"sdp_offer"
"request_id": "req_offer_123", // 请求唯一标识符,用于匹配请求和响应
"from": "browser_abc123", // 发送者ID,通常是客户端的唯一标识
"to": "remote_abc123", // 接收者ID,即目标代理的唯一标识
"timestamp": "2023-01-01T12:00:04Z", // 消息发送时间,ISO8601格式
"call_id": "call_abc123", // 通话会话唯一标识符,用于关联SDP和ICE消息
"sdp": {
"type": "offer", // SDP类型:offer(提供)或answer(应答)
"sdp": "v=0\r\no=- 1234567890 1 IN IP4 192.168.1.1..." // SDP协议内容,包含媒体会话的详细参数
},
"proxy_token": "token_secure123", // 代理通讯令牌,用于身份验证和授权
"mode_preference": "auto" // 连接模式偏好:auto(自动选择)、p2p(强制P2P)、relay(强制中继)
}
6. sdp_answer (SDP Answer)
json
{
"type": "sdp_answer", // 消息类型,固定为"sdp_answer"
"request_id": "req_answer_123", // 请求唯一标识符,用于匹配请求和响应
"from": "remote_abc123", // 发送者ID,通常是代理的唯一标识
"to": "browser_abc123", // 接收者ID,即客户端的唯一标识
"timestamp": "2023-01-01T12:00:05Z", // 消息发送时间,ISO8601格式
"call_id": "call_abc123", // 通话会话唯一标识符,与对应的SDP Offer保持一致
"sdp": {
"type": "answer", // SDP类型:offer(提供)或answer(应答)
"sdp": "v=0\r\no=- 0123456789 1 IN IP4 10.0.0.1..." // SDP协议内容,包含对媒体会话的应答参数
},
"proxy_token": "token_secure123", // 代理通讯令牌,用于身份验证和授权
"mode_preference": "auto" // 连接模式偏好:auto(自动选择)、p2p(强制P2P)、relay(强制中继)
}
7. ice_candidate (ICE Candidate)
json
{
"type": "ice_candidate", // 消息类型,固定为"ice_candidate"
"request_id": "req_ice_123", // 请求唯一标识符,用于匹配请求和响应
"from": "browser_abc123", // 发送者ID,通常是客户端的唯一标识
"to": "remote_abc123", // 接收者ID,即目标代理的唯一标识
"timestamp": "2023-01-01T12:00:06Z", // 消息发送时间,ISO8601格式
"call_id": "call_abc123", // 通话会话唯一标识符,与对应的SDP消息保持一致
"candidate": {
"candidate": "a=candidate:1 1 UDP 2130706431 192.168.1.1 50000 typ host...", // ICE候选地址详细信息
"sdpMLineIndex": 0, // SDP媒体行索引,指向SDP中对应的媒体描述
"sdpMid": "audio" // SDP媒体标识符,用于标识特定的媒体流
}
}
8. heartbeat (心跳检测)
json
{
"type": "heartbeat", // 消息类型,固定为"heartbeat"
"request_id": "req_heartbeat_123", // 请求唯一标识符,用于匹配请求和响应
"from": "remote_abc123", // 发送者ID,通常是代理的唯一标识
"timestamp": "2023-01-01T12:00:30Z", // 消息发送时间,ISO8601格式
"status": "online" // 发送者当前状态:online(在线)、offline(离线)、connecting(连接中)
}
9. mode_switch (模式切换通知)
json
{
"type": "mode_switch", // 消息类型,固定为"mode_switch"
"request_id": "req_switch_123", // 请求唯一标识符,用于匹配请求和响应
"from": "signaling_server", // 发送者ID,通常是信令服务器的标识
"to": "remote_abc123", // 接收者ID,即目标代理或客户端的唯一标识
"timestamp": "2023-01-01T12:00:10Z", // 消息发送时间,ISO8601格式
"from_mode": "p2p", // 切换前的连接模式:p2p(P2P模式)、relay(中继模式)
"to_mode": "relay", // 切换后的连接模式:p2p(P2P模式)、relay(中继模式)
"reason": "P2P connection lost" // 模式切换原因,如网络状况变化、连接质量下降等
}
3. 关键数据结构
3.1 基础数据结构
SessionType(会话类型)
go
type SessionType uint8
const (
SessionTypeWebSSHDirect SessionType = 0x01 // WebSSH直连:浏览器→信令服务器→SSH服务器
SessionTypeWebSSHProxy SessionType = 0x02 // WebSSH代理:浏览器→远程代理→SSH服务器
SessionTypeTunnel SessionType = 0x03 // 隧道转发:APP→本地代理→远程代理→目标服务器
)
SessionID(全局唯一会话ID)
go
type SessionID struct {
Type SessionType
ClientID string // 客户端唯一标识
LocalID uint32 // 本地会话ID
Timestamp uint32 // 创建时间戳
}
PacketType(数据包类型)
go
type PacketType uint8
const (
PacketTypeConnect PacketType = 0x01 // 连接请求
PacketTypeData PacketType = 0x02 // 数据传输
PacketTypeDisconnect PacketType = 0x03 // 断开连接
PacketTypeSSHConfig PacketType = 0x04 // SSH配置
PacketTypeControl PacketType = 0x05 // 控制命令(如终端调整大小)
)
Packet(隧道数据包)
go
type Packet struct {
Type PacketType
SessionID SessionID
Data []byte
}
ProxyRole(代理角色)
go
type ProxyRole string
const (
ProxyRoleLocal ProxyRole = "local" // 本地代理
ProxyRoleRemote ProxyRole = "remote" // 远端代理
ProxyRoleBrowser ProxyRole = "browser" // 浏览器客户端
)
ProxyStatus(代理状态)
go
type ProxyStatus string
const (
ProxyStatusOnline ProxyStatus = "online" // 在线状态
ProxyStatusOffline ProxyStatus = "offline" // 离线状态
ProxyStatusConnecting ProxyStatus = "connecting" // 连接中
)
Capability(代理能力)
go
type Capability string
const (
CapabilityTCP Capability = "tcp" // TCP代理能力
CapabilityUDP Capability = "udp" // UDP代理能力
CapabilityRelay Capability = "relay" // 中继能力
)
SDPInfo(SDP信息)
go
type SDPInfo struct {
Type string `json:"type"` // SDP类型:offer(提供)或answer(应答)
SDP string `json:"sdp"` // SDP协议内容
}
ICECandidate(ICE候选地址)
go
type ICECandidate struct {
Candidate string `json:"candidate"` // ICE候选地址字符串
SDPMLineIndex int `json:"sdpMLineIndex"` // SDP媒体行索引
SDPMid string `json:"sdpMid"` // SDP媒体标识
}
STUNServer(STUN服务器配置)
go
type STUNServer struct {
URL string `json:"url"` // STUN服务器URL
}
TURNServer(TURN服务器配置)
go
type TURNServer struct {
URLs []string `json:"urls"` // TURN服务器URL列表
Username string `json:"username"` // TURN服务器用户名
Credential string `json:"credential"` // TURN服务器密码或凭证
}
3.2 配置数据结构
TunnelConfig(隧道配置)
go
type TunnelConfig struct {
LocalPort int `json:"local_port" yaml:"local_port"` // 本地端口
TargetHost string `json:"target_host" yaml:"target_host"` // 目标主机
TargetPort int `json:"target_port" yaml:"target_port"` // 目标端口
Protocol string `json:"protocol" yaml:"protocol"` // 协议类型:tcp或udp
}
3.3 信令消息结构
BaseMessage(基础消息结构)
go
type BaseMessage struct {
Type MessageType `json:"type"` // 消息类型
RequestID string `json:"request_id,omitempty"` // 请求ID
From string `json:"from,omitempty"` // 发送者
To string `json:"to,omitempty"` // 接收者
Timestamp time.Time `json:"timestamp"` // 时间戳
}
RegisterMessage(注册消息)
go
type RegisterMessage struct {
BaseMessage
ProxyID string `json:"proxy_id"` // 代理ID
Role ProxyRole `json:"role"` // 代理角色
Capabilities []Capability `json:"capabilities"` // 代理能力
Tunnels []TunnelConfig `json:"tunnels"` // 隧道配置
TurnServers []TURNServer `json:"turn_servers,omitempty"` // TURN服务器配置(仅远程代理提供)
Version string `json:"version"` // 版本号
}
ConnectRequestMessage(连接请求)
go
type ConnectRequestMessage struct {
BaseMessage
TargetProxyID string `json:"target_proxy_id"` // 目标代理ID
ModePreference string `json:"mode_preference"` // 连接模式偏好:auto, force-p2p, force-relay, p2p
ProxyToken string `json:"proxy_token"` // 代理通讯令牌
ConnectionMode string `json:"connection_mode,omitempty"` // 连接模式:remote_proxy, direct
ServiceType string `json:"service_type,omitempty"` // 服务类型:webssh, webfile
}
ClientInfo(客户端信息)
go
type ClientInfo struct {
ClientType string `json:"client_type"` // 客户端类型:browser(浏览器)、app(APP)
SubType string `json:"sub_type,omitempty"` // 功能子类型(仅浏览器):ssh(SSH终端)、file(文件传输)
}
ConnectionParams(连接参数)
go
type ConnectionParams struct {
Mode string `json:"mode"` // 连接模式
Protocol string `json:"protocol"` // 传输协议:tcp、udp
Timeout int `json:"timeout"` // 连接超时时间(秒)
RetryCount int `json:"retry_count"` // 连接失败重试次数
}
SSHParams(SSH访问参数)
go
type SSHParams struct {
Host string `json:"host"` // SSH目标主机地址(直连模式下使用)
Port int `json:"port"` // SSH目标端口(默认22)
Terminal TerminalConfig `json:"terminal"` // 终端配置
AuthMethod string `json:"auth_method"` // 认证方式:password、public_key
InitialCommand string `json:"initial_command"` // 登录后执行的初始命令
KeepaliveInterval int `json:"keepalive_interval"` // 心跳保持间隔(秒)
}
SFTPParams(SFTP访问参数)
go
type SFTPParams struct {
Host string `json:"host"` // SFTP目标主机地址(直连模式下使用)
Port int `json:"port"` // SFTP目标端口(默认22)
AuthMethod string `json:"auth_method"` // 认证方式:password、public_key
DefaultPath string `json:"default_path"` // 连接后默认进入的目录
MaxFileSize int64 `json:"max_file_size,omitempty"` // 最大文件传输大小(字节,可选)
ChunkSize int `json:"chunk_size,omitempty"` // 分块传输大小(字节,可选)
EnableCompression bool `json:"enable_compression,omitempty"` // 是否启用压缩传输
}
TerminalConfig(终端配置)
go
type TerminalConfig struct {
Width int `json:"width"` // 终端宽度(字符数)
Height int `json:"height"` // 终端高度(字符数)
Type string `json:"type"` // 终端类型
}
ConnectResponseMessage(连接响应)
go
type ConnectResponseMessage struct {
BaseMessage
Code int `json:"code"` // 响应状态码:200表示成功,其他表示失败
Message string `json:"message"` // 响应消息,描述连接请求结果
Success bool `json:"success"` // 连接请求是否成功
P2PInfo *P2PInfo `json:"p2p_info,omitempty"` // P2P连接信息
RelayInfo *RelayInfo `json:"relay_info,omitempty"` // 中继信息
}
SSHConfigMessage(SSH配置消息)
go
type SSHConfigMessage struct {
BaseMessage
TargetProxyID string `json:"target_proxy_id"` // 目标代理ID
SSHConfig map[string]interface{} `json:"ssh_config"` // SSH配置
}
SFTPConfigMessage(SFTP配置消息)
go
type SFTPConfigMessage struct {
BaseMessage
TargetProxyID string `json:"target_proxy_id"` // 目标代理ID
SFTPConfig map[string]interface{} `json:"sftp_config"` // SFTP配置
}
P2PInfo(P2P连接信息)
go
type P2PInfo struct {
Status string `json:"status"` // P2P连接状态:available(可用)、unavailable(不可用)
ICEServers []ICEServer `json:"ice_servers"` // ICE服务器配置列表
}
RelayInfo(中继连接信息)
go
type RelayInfo struct {
Status string `json:"status"` // 中继连接状态:available(可用)、unavailable(不可用)
ICEServers []ICEServer `json:"ice_servers"` // 远程代理提供的ICE服务器配置列表
}
ICEServer(ICE服务器配置)
go
type ICEServer struct {
URLs []string `json:"urls"` // ICE服务器URL列表
Username string `json:"username,omitempty"` // ICE服务器用户名
Credential string `json:"credential,omitempty"` // ICE服务器密码或凭证
}
WebRTCConnection(WebRTC连接)
go
type WebRTCConnection struct {
CallID WebRTCCallID // WebRTC通话ID
PeerConn *webrtc.PeerConnection // WebRTC对等连接
DataChannels map[string]*webrtc.DataChannel // 数据通道映射
SignalClient *SignalClient // 信令客户端
Config *ProxyConfig // 代理配置
SessionManager *SessionManager // 会话管理器
IsConnected bool // 连接状态
LastActive time.Time // 最后活动时间
connectTimeout time.Duration // 连接建立超时时间
connectDone chan bool // 连接建立完成的通道
mode ConnectionMode // 当前连接模式
modeSwitching bool // 是否正在切换模式
iceServers []ICEServer // ICE服务器列表
OnPacketReceived func(conn *WebRTCConnection, packet *Packet) // 数据包处理回调
RemoteProxyID string // 远程代理ID
AssociatedSSHConfigs []*SSHSessionMapping // 关联的SSH配置映射
}
WebRTCManager(WebRTC连接管理器)
go
type WebRTCManager struct {
Connections map[WebRTCCallID]*WebRTCConnection // WebRTC连接映射
ClientMappings map[string]*ClientConnectionInfo // 客户端ID到连接信息的映射
SignalClient *SignalClient // 信令客户端
Config *ProxyConfig // 代理配置
metrics *WebRTCMetrics // 监控指标
healthChecker *WebRTCHealthChecker // 健康检查
}
ClientConnectionInfo(客户端连接信息)
go
type ClientConnectionInfo struct {
ClientID string // 客户端ID
CallIDs []WebRTCCallID // 关联的通话ID列表
ActiveCallID WebRTCCallID // 当前活跃的连接ID
ConnectedAt time.Time // 连接建立时间
LastActivity time.Time // 最后活动时间
SSHSessionCount int // SSH会话数量
}
SSHSessionMapping(SSH会话映射信息)
go
type SSHSessionMapping struct {
SessionID SessionID // 会话ID
ClientID string // 客户端ID
TargetHost string // 目标主机
TargetPort int // 目标端口
Username string // 用户名
EstablishedAt time.Time // 建立时间
}
WebRTCCallID(WebRTC通话ID)
go
type WebRTCCallID string
ConnectionMode(连接模式)
go
type ConnectionMode string
const (
ConnectionModeP2P ConnectionMode = "p2p" // P2P连接模式
ConnectionModeRelay ConnectionMode = "relay" // 中继连接模式
)
SessionManager(会话管理器)
go
type SessionManager struct {
sessions map[SessionID]*Session
mu sync.RWMutex
}
// Session 会话信息
type Session struct {
ID SessionID
ClientID string
LocalConn net.Conn
TunnelInfo *TunnelInfo
CreatedAt time.Time
LastActive time.Time
}
// TunnelInfo 隧道信息
type TunnelInfo struct {
TargetHost string
TargetPort int
Protocol string
}
SignalClient(信令客户端)
go
type SignalClient struct {
conn *websocket.Conn
proxyID string
messageHandler func(message []byte)
reconnectStrategy *ReconnectStrategy
mu sync.Mutex
}
// ReconnectStrategy 重连策略
type ReconnectStrategy struct {
MaxRetries int
RetryInterval time.Duration
BackoffFactor float64
}
ProxyConfig(代理配置)
go
type ProxyConfig struct {
ID string
Host string
Port int
STUNServers []ICEServer
TURNServers []ICEServer
MaxConnections int
HeartbeatInterval time.Duration
LogLevel string
}
WebRTCMetrics(WebRTC监控指标)
go
type WebRTCMetrics struct {
TotalConnections int64 `json:"total_connections"`
ActiveConnections int64 `json:"active_connections"`
FailedConnections int64 `json:"failed_connections"`
ReconnectAttempts int64 `json:"reconnect_attempts"`
ICEFailures int64 `json:"ice_failures"`
DataChannelsOpened int64 `json:"data_channels_opened"`
DataChannelsClosed int64 `json:"data_channels_closed"`
DataSentBytes int64 `json:"data_sent_bytes"`
DataReceivedBytes int64 `json:"data_received_bytes"`
LastActivity int64 `json:"last_activity"`
}
WebRTCHealthChecker(WebRTC健康检查)
go
type WebRTCHealthChecker struct {
interval time.Duration
checkFunc func() HealthStatus
status HealthStatus
lastCheck time.Time
alertHandler func(status HealthStatus)
}
// HealthStatus 健康状态
type HealthStatus string
const (
HealthStatusHealthy HealthStatus = "healthy"
HealthStatusDegraded HealthStatus = "degraded"
HealthStatusUnhealthy HealthStatus = "unhealthy"
)
SDPMessage(SDP交换消息)
go
type SDPMessage struct {
BaseMessage
CallID string `json:"call_id"` // 通话ID
SDP SDPInfo `json:"sdp"` // SDP信息
ProxyToken string `json:"proxy_token"` // 代理通讯令牌
ModePreference string `json:"mode_preference"` // 连接模式偏好
}
ICEMessage(ICE Candidate消息)
go
type ICEMessage struct {
BaseMessage
CallID string `json:"call_id"` // 通话ID
Candidate ICECandidate `json:"candidate"` // ICE候选地址
}
HeartbeatMessage(心跳消息)
go
type HeartbeatMessage struct {
BaseMessage
Status string `json:"status"` // 当前状态:online, connecting
Timestamp int64 `json:"timestamp"` // 时间戳(毫秒)
Version string `json:"version"` // 版本号
}
HeartbeatResponseMessage(心跳响应)
go
type HeartbeatResponseMessage struct {
BaseMessage
Success bool `json:"success"` // 心跳响应状态
Timestamp int64 `json:"timestamp"` // 时间戳(毫秒)
ServerTime int64 `json:"server_time"` // 服务器时间(毫秒)
}
ModeSwitchMessage(模式切换消息)
go
type ModeSwitchMessage struct {
BaseMessage
CallID string `json:"call_id"` // 通话ID
FromMode string `json:"from_mode"` // 切换前的连接模式:p2p(P2P模式)、relay(中继模式)
ToMode string `json:"to_mode"` // 切换后的连接模式:p2p(P2P模式)、relay(中继模式)
Reason string `json:"reason"` // 模式切换原因
Timestamp int64 `json:"timestamp"` // 切换时间戳(毫秒)
}
4. 关键业务流程
4.0 三阶段业务流程实现
第一阶段:基础业务流程
- 代理注册流程:基本的代理注册和状态管理
- P2P连接建立流程:基本的WebRTC连接建立
- WebSSH代理流程:基本的SSH终端功能
- WebSFTP代理流程:基本的文件传输功能
- 心跳检测流程:基本的心跳机制
第二阶段:增强业务流程
- 智能连接管理:连接质量监控和自动模式切换
- 高级会话管理:会话负载均衡和故障转移
- 增强的错误处理:完善的错误处理和异常恢复
- 安全认证流程:增强的认证和授权机制
- 性能优化流程:数据压缩和批量处理
第三阶段:高级业务流程
- 集群管理流程:信令服务器和远程代理集群管理
- 监控告警流程:全系统监控和智能告警
- 多租户管理流程:租户隔离和资源管理
- API管理流程:RESTful API和管理界面
- 配置中心流程:集中配置管理和动态更新
4.1 代理注册流程
-
代理客户端启动:
- 生成唯一代理ID
- 加载本地配置文件
-
远程代理注册流程:
- 通过WebSocket连接到信令服务器
- 加载本地配置文件中的TURN服务器配置(仅在本地使用)
- 信令服务器不存储TURN服务器的完整配置
- 发送
register消息,包含代理ID、角色(remote)、能力和隧道配置 - 信令服务器验证代理信息并记录代理状态
- 信令服务器返回
register_response消息,指示注册是否成功 - 注册成功后,远程代理进入在线状态并开始发送心跳消息
-
本地代理注册流程:
- 通过WebSocket连接到信令服务器
- 发送
register消息,包含代理ID、角色(local)、能力和隧道配置 - 信令服务器验证代理信息并记录代理状态
- 信令服务器返回
register_response消息,指示注册是否成功 - 注册成功后,本地代理进入在线状态并开始发送心跳消息
4.2 P2P连接建立流程
-
发起连接请求:
- 浏览器客户端或本地代理发送
connect_request消息,指定目标代理ID和连接模式偏好 - 本地代理使用自身配置的STUN服务器进行NAT穿透准备
- 浏览器客户端或本地代理发送
-
信令服务器处理:
- 检查目标代理是否在线
- 向目标代理转发连接请求
-
目标代理响应:
- 远程代理接受请求,使用自身配置的STUN服务器进行NAT穿透准备
- 远程代理动态生成TURN服务器的临时凭证
- 远程代理发送包含临时TURN凭证的响应
- 信令服务器返回
connect_response消息给发起方,包含远程代理动态生成的TURN服务器临时配置 - 注意:完整的TURN服务器配置仅存储在远程代理本地,不通过信令服务器持久化存储
-
WebRTC连接建立:
- 发起方使用自身配置的STUN服务器 和远程代理提供的TURN服务器创建SDP Offer
- 发起方发送
sdp_offer消息 - 信令服务器转发
sdp_offer到目标代理 - 目标代理使用自身配置的STUN服务器 和自身配置的TURN服务器创建SDP Answer
- 目标代理发送
sdp_answer消息 - 信令服务器转发
sdp_answer到发起方 - 双方开始交换ICE Candidate消息
- 当ICE协商成功后,建立P2P连接
-
连接失败处理:
- 如果P2P连接失败,系统自动尝试切换到中继模式
- 使用远程代理提供的TURN服务器作为中继节点
4.3 中继连接建立流程
直接使用中继模式
-
发起连接请求:
- 浏览器客户端或本地代理发送
connect_request消息,明确指定连接模式为force-relay - 本地代理使用自身配置的STUN服务器进行NAT穿透准备
- 浏览器客户端或本地代理发送
-
信令服务器处理:
- 检查目标代理是否在线
- 向目标代理转发连接请求
-
目标代理响应:
- 远程代理接受请求,使用自身配置的STUN服务器进行NAT穿透准备
- 远程代理动态生成TURN服务器的临时凭证
- 远程代理发送包含临时TURN凭证的响应
- 信令服务器返回
connect_response消息给发起方,包含远程代理动态生成的TURN服务器临时配置 - 注意:完整的TURN服务器配置仅存储在远程代理本地,不通过信令服务器持久化存储
-
中继连接建立:
- 发起方使用自身配置的STUN服务器 和远程代理提供的TURN服务器临时配置创建SDP Offer
- 发起方发送
sdp_offer消息 - 信令服务器转发
sdp_offer到目标代理 - 目标代理使用自身配置的STUN服务器 和自身配置的TURN服务器创建SDP Answer
- 目标代理发送
sdp_answer消息 - 信令服务器转发
sdp_answer到发起方 - 双方开始交换ICE Candidate消息
- 当ICE协商成功后,建立中继连接
- coturn服务器在两个连接之间转发流量
从P2P模式切换到中继模式
-
连接质量检测:
- 任一方向检测到P2P连接质量下降或中断
-
模式切换触发:
- 检测方触发模式切换逻辑
- 信令服务器发送
mode_switch消息通知双方切换到中继模式
-
中继连接建立:
- 双方断开当前P2P连接
- 使用已获取的远程代理提供的TURN服务器临时配置重新建立连接
- 发起方使用自身配置的STUN服务器 和远程代理提供的TURN服务器临时配置创建SDP Offer
- 目标代理使用自身配置的STUN服务器 和自身配置的TURN服务器创建SDP Answer
- 双方交换SDP和ICE Candidate消息
- 建立中继连接,通过coturn服务器转发流量
4.4 WebSSH代理流程
-
浏览器客户端初始化:
- 访问WebSSH代理页面
- 页面加载完成后自动与信令服务器建立WebSocket连接
-
用户配置与连接请求:
- 用户输入目标代理ID和SSH连接信息(包括主机地址、端口、认证方式等)
- 浏览器客户端发送
connect_request消息,包含:- 目标代理ID
- 连接模式偏好
- 代理通讯令牌
- 连接模式(connection_mode: remote_proxy)
- 服务类型(service_type: webssh)
-
信令与连接建立:
- 信令服务器处理连接请求,检查目标代理状态
- 远程代理接受请求,使用自身配置的STUN服务器进行NAT穿透准备
- 远程代理动态生成TURN服务器的临时凭证
- 信令服务器返回
connect_response消息,包含远程代理动态生成的TURN服务器临时配置 - 浏览器客户端使用自身配置的STUN服务器 (如果有)和远程代理提供的TURN服务器临时配置建立P2P或中继连接
- 注意:完整的TURN服务器配置仅存储在远程代理本地,不通过信令服务器持久化存储
-
SSH配置与会话建立:
- 连接建立成功后,浏览器客户端发送
ssh_config消息,包含详细的SSH配置信息 - 远程代理接收SSH配置,与目标SSH服务器建立连接,执行认证
- 认证成功后,浏览器客户端可以在xterm.js终端中发送SSH命令
- 远程代理执行SSH命令并返回结果
- 结果通过WebRTC连接实时返回给浏览器客户端显示
- 连接建立成功后,浏览器客户端发送
-
多会话支持:
- 系统支持通过同一个WebRTC通道建立多个SSH会话
- 每个会话使用唯一的标识符进行区分
- 远程代理维护会话映射,确保数据正确路由到对应的会话
-
会话结束:
- 用户关闭浏览器标签或显式断开连接
- 浏览器客户端发送断开连接请求
- 双方断开WebRTC连接和WebSocket连接
4.5 WebSFTP代理流程
-
浏览器客户端初始化:
- 访问WebSFTP代理页面
- 页面加载完成后自动与信令服务器建立WebSocket连接
-
用户配置与连接请求:
- 用户输入目标代理ID和SFTP连接信息(包括主机地址、端口、认证方式等)
- 浏览器客户端发送
connect_request消息,包含:- 目标代理ID
- 连接模式偏好
- 代理通讯令牌
- 连接模式(connection_mode: remote_proxy)
- 服务类型(service_type: webfile)
-
信令与连接建立:
- 信令服务器处理连接请求,检查目标代理状态
- 远程代理接受请求,使用自身配置的STUN服务器进行NAT穿透准备
- 远程代理动态生成TURN服务器的临时凭证
- 信令服务器返回
connect_response消息,包含远程代理动态生成的TURN服务器临时配置 - 浏览器客户端使用自身配置的STUN服务器 (如果有)和远程代理提供的TURN服务器临时配置建立P2P或中继连接
- 注意:完整的TURN服务器配置仅存储在远程代理本地,不通过信令服务器持久化存储
-
SFTP配置与会话建立:
- 连接建立成功后,浏览器客户端发送
sftp_config消息,包含详细的SFTP配置信息 - 远程代理接收SFTP配置,与目标SFTP服务器建立连接,执行认证
- 认证成功后,浏览器客户端可以发送
sftp_command消息进行文件操作
- 连接建立成功后,浏览器客户端发送
-
文件操作:
- 浏览器客户端可以进行以下文件操作:
- 列出目录内容(ls命令)
- 创建目录(mkdir命令)
- 删除文件/目录(rm/rmdir命令)
- 重命名文件/目录(rename命令)
- 上传文件(put命令)
- 下载文件(get命令)
- 大文件传输采用分块上传/下载机制,支持断点续传
- 文件操作命令和结果通过WebRTC连接实时传输
- 浏览器客户端可以进行以下文件操作:
-
文件传输优化:
- 支持文件压缩传输,减少网络流量
- 大文件上传/下载时显示进度条
- 支持同时传输多个文件
- 实现文件传输队列管理
-
会话结束:
- 用户关闭浏览器标签或显式断开连接
- 浏览器客户端发送断开连接请求
- 双方断开WebRTC连接和WebSocket连接
- 未完成的文件传输自动中断并记录状态
4.6 心跳检测流程
-
心跳发送机制:
- 代理客户端默认每30秒发送一次
heartbeat消息 - 心跳消息包含当前状态、时间戳和版本号
- 支持动态调整心跳间隔,根据网络状况自适应
- 代理客户端默认每30秒发送一次
-
心跳接收与处理:
- 信令服务器收到心跳消息后立即更新代理的最后心跳时间
- 信令服务器返回
heartbeat_response消息,包含响应状态和服务器时间 - 代理客户端根据响应调整自身状态和心跳间隔
-
容错与网络抖动处理:
- 允许连续3次心跳失败(约90秒),仍保持代理为在线状态
- 超过3次连续失败后,将代理标记为
connecting状态(连接中) - 在
connecting状态下,代理客户端尝试加速重连(每5秒一次) - 如果120秒内未恢复正常心跳,则标记为
offline(离线)
-
离线恢复机制:
- 当代理重新上线时,先尝试恢复之前的WebSocket连接
- 如果恢复失败,则重新建立WebSocket连接
- 重新建立连接后,发送
register消息重新注册 - 信令服务器恢复代理的在线状态并更新相关连接信息
-
异常处理:
- 代理客户端检测到网络异常时,主动减少心跳间隔,加速检测
- 信令服务器定期清理长时间离线(超过24小时)的代理记录
- 提供心跳统计和监控接口,便于运维人员查看代理状态
4.7 连接模式切换流程
-
连接质量监测:
- 双方定期监测WebRTC连接的质量指标(延迟、丢包率、带宽等)
- 当指标超过阈值(如延迟>500ms或丢包率>5%)时,触发切换检测
- 支持手动和自动两种切换触发方式
-
切换决策与准备:
- 检测方评估当前网络状况,决定是否需要切换模式
- 如果决定切换,提前获取所需的TURN服务器临时配置(如从P2P切换到中继)
- 准备新连接所需的资源和参数
-
无缝切换实现:
- 信令服务器发送
mode_switch消息通知双方准备切换 - 双方在保持当前连接的同时,并行建立新的连接模式
- 新连接建立成功后,进行数据传输测试
- 测试通过后,平滑切换流量到新连接
- 旧连接在流量完全切换后延迟10秒关闭,确保数据完整性
- 信令服务器发送
-
切换类型支持:
- P2P → 中继:当P2P连接质量下降时
- 中继 → P2P:当网络状况改善,支持P2P连接时
- 手动切换:用户或管理员可通过API或界面强制切换
-
状态管理与通知:
- 信令服务器实时记录和更新连接模式状态
- 向双方发送模式切换状态通知
- 提供连接模式切换历史记录
-
异常处理:
- 如果新连接建立失败,保持使用当前连接
- 重试切换操作,最多尝试3次
- 记录切换失败原因,便于后续分析和优化
-
性能优化:
- 预加载TURN服务器配置,减少切换延迟
- 使用快速重传和拥塞控制算法,确保切换过程中数据不丢失
- 支持连接复用,减少资源消耗
4.8 WebRTC数据路由流程
4.8.1 数据包结构
WebRTC数据通道使用自定义的数据包结构进行通信,确保数据的正确路由和处理:
+----------------+----------------+----------------+----------------+----------------+----------------+
| 数据包类型(1B) | ClientID长度(4B)| ClientID(NB) | 会话类型(4B) | 本地ID(4B) | 时间戳(4B) |
+----------------+----------------+----------------+----------------+----------------+----------------+
| 数据内容(变长) |
+--------------------------------------------------------------------------------------------+
- 数据包类型:标识数据包的类型,如连接请求、数据传输、断开连接等
- ClientID:客户端唯一标识,确保数据包正确路由到对应的客户端
- 会话类型:标识会话的类型,如WebSSH直连、WebSSH代理、隧道转发等
- 本地ID:本地会话ID,确保在同一客户端内的会话唯一性
- 时间戳:创建时间戳,用于会话管理和超时检测
- 数据内容:实际的业务数据,如SSH命令、终端输出等
4.8.2 路由关系
-
浏览器 → 远程代理路由:
- 浏览器通过WebRTC数据通道发送数据包
- 数据包包含SessionID,用于标识会话
- 远程代理根据SessionID中的ClientID和LocalID路由数据包到对应的SSH会话
-
远程代理 → 浏览器路由:
- 远程代理从SSH服务器接收数据
- 包装成数据包,添加对应的SessionID
- 通过WebRTC数据通道发送回浏览器
-
本地代理 → 远程代理路由:
- 本地代理从APP接收TCP/UDP数据
- 包装成数据包,添加对应的SessionID
- 通过WebRTC数据通道发送到远程代理
-
远程代理 → 本地代理路由:
- 远程代理从目标服务器接收数据
- 包装成数据包,添加对应的SessionID
- 通过WebRTC数据通道发送回本地代理
4.8.3 会话管理
-
会话创建:
- 当客户端发起新的连接请求时,创建新的SessionID
- 关联SessionID与对应的连接信息(如目标主机、端口等)
-
会话维护:
- 会话管理器跟踪所有活跃的会话
- 定期检查会话的活跃状态
- 清理超时或无效的会话
-
会话复用:
- 支持在同一WebRTC连接上复用多个SSH会话
- 通过SessionID区分不同的会话
- 减少连接建立的开销,提高系统性能
4.8.4 数据包处理流程
-
数据接收:
- WebRTC连接接收数据通道消息
- 解码数据包,提取SessionID和数据内容
-
路由决策:
- 根据SessionID中的ClientID和LocalID确定目标会话
- 检查会话是否存在,不存在则创建或拒绝
-
数据处理:
- 根据数据包类型调用相应的处理函数
- 处理连接请求、数据传输、断开连接等操作
-
数据转发:
- 将处理后的数据转发到目标服务器或客户端
- 确保数据的完整性和顺序
-
错误处理:
- 处理数据包解码错误
- 处理会话不存在的情况
- 处理网络错误和超时
4.8.5 性能优化
-
数据压缩:
- 对传输的数据进行压缩,减少网络流量
- 提高传输速度,特别是在低带宽环境下
-
批量处理:
- 批量发送小型数据包,减少数据通道的开销
- 提高传输效率,减少网络拥塞
-
连接复用:
- 在同一WebRTC连接上复用多个会话
- 减少连接建立的开销,提高系统性能
-
负载均衡:
- 在多个远程代理之间分配会话
- 提高系统的并发处理能力
-
故障转移:
- 当当前连接失败时,自动切换到备用连接
- 提高系统的可靠性和可用性
4.9 消息处理详细说明
4.9.1 ssh_config 消息
消息结构:
json
{
"type": "ssh_config",
"request_id": "req_ssh_config_123",
"from": "browser_abc123",
"to": "remote_abc123",
"timestamp": "2023-01-01T12:00:00Z",
"target_proxy_id": "remote_abc123",
"ssh_config": {
"host": "192.168.1.100",
"port": 22,
"username": "user",
"password": "password",
"terminal": {
"width": 80,
"height": 24,
"type": "xterm-256color"
},
"auth_method": "password",
"initial_command": "",
"keepalive_interval": 60
}
}
处理逻辑:
- 接收消息 :远程代理接收
ssh_config消息 - 验证配置:验证SSH配置的有效性,如主机地址、端口等
- 建立连接:使用配置信息与目标SSH服务器建立连接
- 认证处理:根据配置的认证方式执行认证,如密码认证、公钥认证等
- 会话映射:创建SSH会话与WebRTC连接的映射关系
- 返回响应:向浏览器客户端返回连接结果
4.9.2 sftp_config 消息
消息结构:
json
{
"type": "sftp_config",
"request_id": "req_sftp_config_123",
"from": "browser_abc123",
"to": "remote_abc123",
"timestamp": "2023-01-01T12:00:00Z",
"target_proxy_id": "remote_abc123",
"sftp_config": {
"host": "192.168.1.100",
"port": 22,
"username": "user",
"password": "password",
"default_path": "/home/user",
"max_file_size": 104857600,
"chunk_size": 65536,
"enable_compression": true
}
}
处理逻辑:
- 接收消息 :远程代理接收
sftp_config消息 - 验证配置:验证SFTP配置的有效性
- 建立连接:使用配置信息与目标SFTP服务器建立连接
- 认证处理:执行SFTP认证
- 会话映射:创建SFTP会话与WebRTC连接的映射关系
- 返回响应:向浏览器客户端返回连接结果
4.9.3 sftp_command 消息
消息结构:
json
{
"type": "sftp_command",
"request_id": "req_sftp_command_123",
"from": "browser_abc123",
"to": "remote_abc123",
"timestamp": "2023-01-01T12:00:00Z",
"target_proxy_id": "remote_abc123",
"session_id": "0x02:browser_abc123:1:1672531200",
"command": "ls",
"params": {
"path": "/home/user"
}
}
支持的命令:
ls:列出目录内容mkdir:创建目录rm:删除文件rmdir:删除目录rename:重命名文件或目录put:上传文件get:下载文件stat:获取文件或目录状态
处理逻辑:
- 接收消息 :远程代理接收
sftp_command消息 - 验证会话:验证会话ID的有效性
- 执行命令:根据命令类型执行相应的SFTP操作
- 处理结果:处理命令执行结果,如文件列表、操作状态等
- 返回响应:向浏览器客户端返回命令执行结果
4.10 WebRTC数据通道消息处理机制
4.10.1 消息结构
WebRTC数据通道使用二进制消息格式,包含以下字段:
- 消息类型:标识消息的类型,如会话创建、数据传输、会话关闭等
- 会话ID:唯一标识会话的ID
- 数据长度:消息数据的长度
- 数据内容:实际的业务数据
4.10.2 处理流程
-
消息接收:
- WebRTC数据通道接收二进制消息
- 解析消息头,提取消息类型和会话ID
-
消息路由:
- 根据会话ID查找对应的会话
- 将消息路由到对应的处理函数
-
消息处理:
- 会话创建消息:建立新的会话连接
- 数据传输消息:转发数据到目标服务器
- 会话关闭消息:清理会话资源
-
错误处理:
- 处理消息解析错误
- 处理会话不存在的情况
- 处理网络错误和超时
4.10.3 会话管理实现
-
会话创建:
- 生成唯一的会话ID
- 创建会话对象,关联WebRTC连接
- 初始化会话状态
-
会话维护:
- 定期更新会话的活动时间
- 检测会话的健康状态
- 处理会话的异常情况
-
会话清理:
- 清理超时的会话
- 释放会话占用的资源
- 通知相关组件会话状态变化
4.11 会话生命周期管理
4.11.1 WebSSH会话生命周期
-
会话创建:
- 浏览器发送
connect_request消息 - 建立WebRTC连接
- 浏览器发送
ssh_config消息 - 远程代理与SSH服务器建立连接
- 创建会话ID和会话映射
- 浏览器发送
-
会话维护:
- 浏览器发送SSH命令
- 远程代理执行命令并返回结果
- 浏览器显示终端输出
- 定期更新会话活动时间
-
会话关闭:
- 浏览器发送断开连接请求
- 远程代理关闭SSH连接
- 清理会话资源
- 关闭WebRTC数据通道
4.11.2 SFTP会话生命周期
-
会话创建:
- 浏览器发送
connect_request消息 - 建立WebRTC连接
- 浏览器发送
sftp_config消息 - 远程代理与SFTP服务器建立连接
- 创建会话ID和会话映射
- 浏览器发送
-
会话维护:
- 浏览器发送
sftp_command消息 - 远程代理执行SFTP操作
- 浏览器显示操作结果
- 定期更新会话活动时间
- 浏览器发送
-
会话关闭:
- 浏览器发送断开连接请求
- 远程代理关闭SFTP连接
- 清理会话资源
- 关闭WebRTC数据通道
4.11.3 隧道转发会话生命周期
-
会话创建:
- APP连接到本地代理
- 本地代理发送
connect_request消息 - 建立WebRTC连接
- 远程代理与目标服务器建立连接
- 创建会话ID和会话映射
-
会话维护:
- APP发送TCP/UDP数据
- 本地代理转发数据到远程代理
- 远程代理转发数据到目标服务器
- 目标服务器返回数据
- 远程代理转发数据到本地代理
- 本地代理转发数据到APP
- 定期更新会话活动时间
-
会话关闭:
- APP关闭连接
- 本地代理发送断开连接请求
- 远程代理关闭与目标服务器的连接
- 清理会话资源
4.12 WebRTC连接状态管理
4.12.1 连接状态
WebRTC连接有以下状态:
- disconnected:连接未建立
- connecting:连接正在建立
- connected:连接已建立
- disconnecting:连接正在关闭
- failed:连接失败
4.12.2 状态转换
-
disconnected → connecting:
- 发起连接请求
- 开始ICE协商
-
connecting → connected:
- ICE协商成功
- 数据通道打开
-
connected → disconnecting:
- 发起断开连接请求
- 关闭数据通道
-
disconnecting → disconnected:
- 关闭对等连接
- 清理连接资源
-
connecting → failed:
- ICE协商失败
- 连接建立超时
-
connected → failed:
- 网络连接中断
- 数据通道错误
4.12.3 状态管理实现
-
状态追踪:
- 定期检查WebRTC连接状态
- 记录状态变化历史
- 通知相关组件状态变化
-
状态恢复:
- 当连接失败时尝试重连
- 根据网络状况调整重连策略
- 重连成功后恢复会话
-
状态监控:
- 监控连接的健康状态
- 检测连接的质量指标
- 触发状态切换策略
4.13 错误处理和异常情况
4.13.1 WebRTC连接失败处理
-
ICE协商失败:
- 尝试使用不同的ICE服务器
- 切换到中继连接模式
- 记录失败原因,便于后续分析
-
数据通道建立失败:
- 重试数据通道建立
- 重新建立WebRTC连接
- 通知应用层连接失败
-
连接断开:
- 检测断开原因
- 尝试自动重连
- 保持会话状态,重连后恢复
4.13.2 SSH连接失败处理
-
认证失败:
- 通知浏览器认证失败
- 允许用户重新输入认证信息
- 记录认证失败次数,防止暴力破解
-
连接超时:
- 通知浏览器连接超时
- 检查网络连接状态
- 允许用户重新尝试连接
-
服务器拒绝连接:
- 通知浏览器连接被拒绝
- 检查目标服务器状态
- 记录拒绝原因,便于后续分析
4.13.3 SFTP连接失败处理
-
认证失败:
- 通知浏览器认证失败
- 允许用户重新输入认证信息
- 记录认证失败次数,防止暴力破解
-
文件操作失败:
- 通知浏览器操作失败
- 提供详细的错误信息
- 允许用户重试操作
-
传输错误:
- 处理文件传输中断
- 支持断点续传
- 记录传输错误,便于后续分析
4.13.4 隧道转发失败处理
-
APP连接失败:
- 检查本地代理状态
- 检查网络连接状态
- 通知APP连接失败
-
目标服务器连接失败:
- 检查目标服务器状态
- 通知本地代理连接失败
- 尝试自动重连
-
数据传输错误:
- 处理传输中断
- 保证数据完整性
- 记录传输错误,便于后续分析
4.14 性能优化和可扩展性设计
4.14.1 性能优化策略
-
数据压缩:
- 对传输的数据进行压缩,减少网络流量
- 支持不同的压缩算法,根据网络状况选择合适的算法
- 对大文件传输特别有效
-
批量处理:
- 批量发送小型数据包,减少数据通道的开销
- 提高传输效率,减少网络拥塞
- 特别适用于频繁的小数据传输,如SSH终端操作
-
连接复用:
- 在同一WebRTC连接上复用多个会话
- 减少连接建立的开销,提高系统性能
- 支持在单个浏览器标签页中打开多个SSH会话
-
负载均衡:
- 在多个远程代理之间分配会话
- 基于远程代理的负载情况进行动态分配
- 提高系统的并发处理能力
-
缓存机制:
- 缓存常用的配置信息
- 缓存文件传输的中间状态
- 减少重复计算和网络传输
4.14.2 可扩展性设计
-
模块化架构:
- 采用模块化设计,便于添加新功能
- 清晰的组件边界和接口定义
- 支持插件机制,扩展系统功能
-
水平扩展:
- 支持多个信令服务器的集群部署
- 支持多个远程代理的负载均衡
- 支持动态添加和移除节点
-
垂直扩展:
- 优化单个节点的性能
- 支持资源的动态分配
- 支持配置的热更新
-
服务发现:
- 自动发现可用的远程代理
- 基于健康检查的服务发现机制
- 支持动态调整服务路由
4.15 安全性和认证机制
4.15.1 代理令牌机制
-
令牌生成:
- 远程代理生成安全的代理令牌
- 令牌包含时间戳和签名,防止伪造
- 支持令牌的有效期设置
-
令牌验证:
- 信令服务器验证代理令牌的有效性
- 远程代理验证代理令牌的有效性
- 令牌验证失败时拒绝连接请求
-
令牌管理:
- 支持令牌的刷新机制
- 支持令牌的撤销机制
- 定期轮换令牌,提高安全性
4.15.2 SSH认证实现
-
密码认证:
- 安全传输密码,防止密码泄露
- 支持密码复杂度检查
- 支持密码尝试次数限制
-
公钥认证:
- 支持SSH公钥认证
- 验证公钥的有效性
- 支持多种公钥算法
-
认证日志:
- 记录认证尝试和结果
- 检测异常认证行为
- 提供认证审计功能
4.15.3 SFTP认证实现
-
认证机制:
- 复用SSH认证机制,减少重复实现
- 支持密码和公钥认证
- 保持与SSH认证的一致性
-
权限控制:
- 基于SSH服务器的权限控制
- 支持文件操作的权限检查
- 防止越权访问
-
数据安全:
- 加密传输文件数据
- 验证文件完整性
- 防止数据泄露
4.15.4 WebSocket连接认证
-
连接认证:
- 验证WebSocket连接的来源
- 支持基于令牌的连接认证
- 防止未授权的连接
-
消息认证:
- 验证消息的完整性和真实性
- 防止消息篡改
- 支持消息签名机制
-
速率限制:
- 限制WebSocket连接的速率
- 防止DoS攻击
- 保护系统资源
4.16 监控和运维机制
4.16.1 监控指标
-
系统指标:
- CPU使用率
- 内存使用率
- 磁盘使用率
- 网络流量
-
服务指标:
- WebSocket连接数
- WebRTC连接数
- SSH会话数
- SFTP会话数
- 隧道转发会话数
-
性能指标:
- 连接建立时间
- 数据传输延迟
- 操作响应时间
- 错误率
-
健康检查:
- 服务可用性
- 连接状态
- 资源使用情况
- 系统负载
4.16.2 运维管理
-
配置管理:
- 集中管理配置
- 支持配置的版本控制
- 支持配置的热更新
-
日志管理:
- 集中管理日志
- 支持日志的级别控制
- 支持日志的轮转和归档
- 提供日志分析工具
-
告警机制:
- 基于阈值的告警
- 多渠道告警通知
- 告警的分级和聚合
- 告警的自动处理
-
部署管理:
- 支持容器化部署
- 支持自动化部署
- 支持滚动更新
- 支持回滚机制
4.16.3 故障排查
-
诊断工具:
- 提供系统诊断工具
- 支持连接测试
- 支持性能测试
-
故障定位:
- 提供详细的错误信息
- 支持日志追踪
5. 系统演进策略
5.1 第一阶段到第二阶段的演进
架构演进
-
信令服务器:
- 添加连接质量监控模块
- 实现基本的负载均衡
- 增强错误处理机制
-
WebRTC连接管理:
- 添加连接质量评估算法
- 实现自动模式切换逻辑
- 增强重连机制
-
会话管理:
- 添加会话负载均衡
- 实现会话故障转移
- 增强会话状态管理
-
安全机制:
- 实现完整的令牌认证
- 添加SSH主机密钥验证
- 实现敏感信息加密
技术迁移
-
代码结构:
- 保持核心代码结构不变
- 采用插件式架构添加新功能
- 确保向后兼容
-
数据结构:
- 扩展现有数据结构
- 添加新的字段和方法
- 确保数据兼容性
-
API接口:
- 保持现有API不变
- 添加新的API接口
- 支持API版本控制
关键挑战
-
性能优化:
- 实现数据压缩和批量处理
- 优化网络传输
- 减少资源消耗
-
容错机制:
- 实现完善的错误处理
- 添加网络异常自动恢复
- 确保系统稳定性
-
安全增强:
- 实现完整的认证和授权
- 保护敏感信息
- 防止安全漏洞
5.2 第二阶段到第三阶段的演进
架构演进
-
信令服务器集群:
- 实现集群发现和管理
- 部署多节点信令服务器
- 实现数据同步和一致性
-
远程代理集群:
- 实现代理自动发现和注册
- 部署多节点远程代理
- 实现智能负载均衡
-
监控系统:
- 部署完整的监控堆栈
- 实现全系统指标收集
- 配置智能告警规则
-
高级特性:
- 实现多租户支持
- 开发RESTful API
- 构建管理界面
技术迁移
-
集群管理:
- 引入集群管理工具(如etcd)
- 实现服务发现机制
- 配置负载均衡器
-
监控集成:
- 集成Prometheus和Grafana
- 实现自定义指标
- 配置告警渠道
-
API开发:
- 实现RESTful API框架
- 开发API文档
- 实现API认证和授权
-
前端开发:
- 构建管理界面
- 实现实时监控
- 支持配置管理
关键挑战
-
集群一致性:
- 确保集群数据一致性
- 处理网络分区
- 实现节点故障转移
-
扩展性:
- 支持水平扩展
- 处理大规模并发
- 优化资源使用
-
可靠性:
- 实现高可用架构
- 减少单点故障
- 提高系统稳定性
-
可维护性:
- 实现自动化部署
- 支持配置管理
- 提供监控和告警
5.3 演进保障措施
1. 架构设计原则
- 模块化设计:采用模块化架构,便于功能扩展
- 接口标准化:定义标准接口,确保组件兼容性
- 向后兼容:确保新功能不破坏现有功能
- 可测试性:设计可测试的系统,确保质量
2. 技术债务管理
- 代码重构:定期进行代码重构,保持代码质量
- 技术评估:定期评估技术栈,及时更新
- 文档维护:保持文档与代码同步
- 测试覆盖:确保测试覆盖关键功能
3. 部署策略
- 滚动更新:采用滚动更新,减少服务中断
- 蓝绿部署:支持蓝绿部署,确保零 downtime
- 灰度发布:实现灰度发布,降低风险
- 回滚机制:确保能够快速回滚
4. 监控和告警
- 全链路监控:实现端到端监控
- 智能告警:配置智能告警规则
- 故障预测:基于历史数据预测故障
- 性能分析:定期进行性能分析
5.4 演进时间表
| 阶段 | 时间 | 主要任务 | 关键里程碑 |
|---|---|---|---|
| 第一阶段 | 1-2个月 | 基础功能实现 | WebRTC连接建立、SSH/SFTP代理、基本会话管理 |
| 第二阶段 | 2-3个月 | 性能、容错与安全增强 | 连接质量监控、自动模式切换、增强安全机制 |
| 第三阶段 | 3-4个月 | 监控、集群与高级特性 | 信令服务器集群、远程代理集群、完整监控系统 |
5.5 成功指标
第一阶段
- 功能完整性:实现所有基础功能
- 稳定性:系统运行稳定,无严重错误
- 性能:满足基本性能要求
- 安全性:基本的安全机制
第二阶段
- 性能提升:性能指标显著改善
- 可靠性:系统能够自动恢复故障
- 安全性:完善的安全机制
- 可扩展性:支持中等规模部署
第三阶段
-
高可用性:系统可用性>99.9%
-
可扩展性:支持大规模部署
-
可维护性:完善的监控和管理工具
-
业务价值 :满足企业级需求
│ │
│ │
┌─────────┴────────┐ ┌──────────────────┐ │
│ 目标服务器 │◄───────────────┤ 流量转发 │ │
│(SSH/SFTP/其他服务)│ │ (本地→远程) │ │
└──────────────────┘ └──────────────────┘ └───────────────►架构图说明:
-
客户端层:
- APP客户端:支持自动模式、P2P模式和中继模式,仅通过本地通信访问本地代理,不直接连接信令服务
- 浏览器客户端:支持直连模式和代理模式,直接通过WebSocket访问信令服务
- 本地代理:提供TCP/UDP隧道中转服务,作为APP客户端与信令服务/远程代理之间的唯一桥梁
-
核心服务层:
- 信令服务/WEB服务:统一的WebSocket连接入口,负责代理注册、连接建立、信令交换
- coturn服务:提供STUN服务用于NAT穿透,TURN服务用于P2P连接失败时的中继
-
目标接入层:
- 远程代理:部署在目标网络,接收来自本地代理或coturn的流量并转发到目标服务器
- 目标服务器:提供最终服务的服务器,如SSH、SFTP、Web服务等
-
通信方式:
- APP与本地代理:通过本地通信(如TCP/UDP)进行数据交换
- 本地代理/浏览器与信令服务:通过WebSocket进行信令交换
- 本地代理与远程代理:优先使用WebRTC P2P数据通道,P2P失败时使用WebRTC Relay数据通道
-
STUN/TURN服务器使用机制:
- STUN服务器:本地代理和远程代理分别使用自己配置文件中的STUN服务器
- TURN服务器:本地代理和远程代理统一使用远程代理配置文件中的TURN服务器
- TURN配置获取:本地代理通过信令服务器从远程代理获取TURN服务器配置
-
流量路径:
- APP流量:APP客户端 → 本地代理 → 远程代理 → 目标服务器(P2P模式,使用各自的STUN服务器)
- APP流量:APP客户端 → 本地代理 → coturn服务 → 远程代理 → 目标服务器(中继模式,统一使用远程代理的TURN服务器)
- 浏览器直连模式:浏览器 → 信令服务 → 目标服务器
- 浏览器代理模式:浏览器 → 信令服务 → 远程代理 → 目标服务器
6. 技术栈
类别 技术 用途 后端语言 Go 开发信令服务和代理服务 Web框架 自定义 处理HTTP和WebSocket请求 WebSocket库 gorilla/websocket 实现WebSocket通信 配置解析 gopkg.in/yaml.v2 解析YAML配置文件 终端仿真 xterm.js 实现WebSSH终端界面 网络协议 WebRTC, TCP, UDP 实现P2P和代理通信 加密协议 TLS 保障通信安全 STUN/TURN服务 coturn 提供NAT穿透和中继服务 -