mirror of
https://github.com/bolucat/Archive.git
synced 2025-12-24 13:28:37 +08:00
12 KiB
12 KiB
NodePass 工作原理
本页解释了 NodePass 的内部架构和数据流机制,提供了不同组件如何交互以创建高效、安全的隧道的深入见解。
架构概述
NodePass 创建了一个具有独立控制和数据通道的网络架构:
-
控制通道(隧道):
- 客户端和服务器之间的未加密 TCP 连接
- 专门用于信号传输和协调
- 在隧道生命周期内维持持久连接
-
数据通道(目标):
- 可配置的 TLS 加密选项:
- 模式 0:未加密数据传输(最快,安全性最低)
- 模式 1:自签名证书加密(良好安全性,无验证)
- 模式 2:验证证书加密(最高安全性,需要有效证书)
- 按需为每个连接或数据报创建
- 用于实际应用数据传输
- 可配置的 TLS 加密选项:
-
服务端模式操作:
- 在隧道端点监听控制连接
- 当流量到达目标端点时,通过控制通道向客户端发送信号
- 在需要时使用指定的 TLS 模式建立数据通道
- 支持双向数据流:可以从服务端或客户端发起连接
-
客户端模式操作:
- 连接到服务端的控制通道
- 监听指示传入连接的信号
- 使用服务端指定的 TLS 安全级别创建数据连接
- 在安全通道和本地目标之间转发数据
- 支持双向数据流:根据目标地址自动选择数据流方向
-
客户端单端转发模式:
- 当隧道地址为本地地址时(如127.0.0.1)自动启用
- 客户端直接在本地监听端口,无需服务端的控制通道协调
- 对于TCP连接使用连接池技术,显著提高转发性能
- 适用于纯本地转发场景,减少网络开销和延迟
- 支持TCP和UDP协议的高性能单端转发
-
协议支持:
- TCP:具有持久连接的全双工流式传输,在客户端单端转发模式下支持连接池优化
- UDP:具有可配置缓冲区大小和超时的数据报转发
数据传输流
NodePass 通过其隧道架构建立双向数据流,支持 TCP 和 UDP 协议。系统支持三种数据流模式:
数据流模式说明
- 服务端接收模式(dataFlow: "-"):服务端在目标地址监听,客户端在本地监听,数据从目标地址流向客户端本地
- 服务端发送模式(dataFlow: "+"):服务端连接到远程目标地址,客户端在本地监听,数据从客户端本地流向远程目标
- 客户端单端转发模式:客户端在本地直接监听并转发到目标地址,无需服务端协调,使用连接池技术实现高性能转发
数据流模式根据隧道地址和目标地址自动确定:
- 如果隧道地址是本地地址(localhost、127.0.0.1等),启用客户端单端转发模式
- 如果目标地址是本地地址,使用服务端接收模式
- 如果目标地址是远程地址,使用服务端发送模式
服务端流程(服务端接收模式)
-
连接初始化:
[目标客户端] → [目标监听器] → [服务器:目标连接已创建]- 对于 TCP:客户端建立到目标监听器的持久连接
- 对于 UDP:服务器在绑定到目标地址的 UDP 套接字上接收数据报
-
信号生成:
[服务端] → [生成唯一连接 ID] → [通过未加密的 TCP 隧道向客户端发送信号]- 对于 TCP:生成
//<connection_id>#1信号 - 对于 UDP:生成
//<connection_id>#2信号
- 对于 TCP:生成
-
连接准备:
[服务端] → [在池中创建具有配置的 TLS 模式的远程连接] → [等待客户端连接]- 两种协议都使用相同的具有唯一连接 ID 的连接池机制
- 根据指定模式(0、1 或 2)应用 TLS 配置
-
数据交换:
[目标连接] ⟷ [交换/传输] ⟷ [远程连接]- 对于 TCP:使用
conn.DataExchange()进行持续的双向数据流传输 - 对于 UDP:使用可配置的缓冲区大小转发单个数据报
- 对于 TCP:使用
客户端流程
-
信号接收:
[客户端] → [从 TCP 隧道读取信号] → [解析连接 ID]- 客户端根据 URL 方案区分 TCP 和 UDP 信号
-
连接建立:
[客户端] → [从池中检索连接] → [连接到远程端点]- 此阶段的连接管理与协议无关
-
本地连接:
[客户端] → [连接到本地目标] → [建立本地连接]- 对于 TCP:建立到本地目标的持久 TCP 连接
- 对于 UDP:创建用于与本地目标交换数据报的 UDP 套接字
-
数据交换:
[远程连接] ⟷ [交换/传输] ⟷ [本地目标连接]- 对于 TCP:使用
conn.DataExchange()进行持续的双向数据流传输 - 对于 UDP:读取单个数据报,转发它,使用超时等待响应,然后返回响应
- 对于 TCP:使用
客户端单端转发流程
-
模式识别:
[客户端] → [检测隧道地址为本地地址] → [启用单端转发模式]- 自动检测隧道地址是否为localhost、127.0.0.1等本地地址
- 启用单端转发模式,跳过服务端控制通道建立
-
本地监听:
[客户端] → [在隧道端口启动监听器] → [等待本地连接]- 直接在指定的隧道端口启动TCP或UDP监听器
- 无需连接到远程服务端,实现零延迟启动
-
连接池初始化(仅TCP):
[客户端] → [初始化目标连接池] → [预建立连接到目标地址]- 为TCP转发创建高性能连接池
- 预先建立多个到目标地址的连接,显著减少连接建立延迟
- 连接池大小可根据并发需求动态调整
-
高性能转发:
[本地连接] → [从连接池获取目标连接] → [直接数据交换] → [连接复用或释放]- 对于TCP:从连接池中快速获取预建立的目标连接,进行高效数据交换
- 对于UDP:直接转发数据报到目标地址,无需连接池
- 优化的数据路径,最小化转发开销和延迟
特定协议特性
-
TCP 交换:
- 用于全双工通信的持久连接
- 连接终止前的持续数据流传输
- 具有自动重连的错误处理
- 客户端单端转发优化:通过连接池技术预建立连接,显著减少连接建立延迟
-
UDP 交换:
- 具有可配置缓冲区大小的一次性数据报转发 (
UDP_DATA_BUF_SIZE) - 响应等待的读取超时控制 (
UDP_READ_TIMEOUT) - 针对低延迟、无状态通信进行了优化
- 客户端单端转发优化:直接转发机制,无需连接池,实现最低延迟
- 具有可配置缓冲区大小的一次性数据报转发 (
信号通信机制
NodePass 通过 TCP 隧道使用复杂的基于 URL 的信号协议:
信号类型
-
隧道信号:
- 格式:
#<tls> - 目的:通知客户端 TLS 代号
- 时机:在隧道握手时发送
- 格式:
-
TCP 启动信号:
- 格式:
//<connection_id>#1 - 目的:请求客户端为特定 ID 建立 TCP 连接
- 时机:当接收到目标服务的新 TCP 连接时发送
- 格式:
-
UDP 启动信号:
- 格式:
//<connection_id>#2 - 目的:请求客户端处理特定 ID 的 UDP 流量
- 时机:当在目标端口接收到 UDP 数据时发送
- 格式:
信号流程
-
信号生成:
- 服务端为特定事件创建 URL 格式的信号
- 信号以换行符终止,以便正确解析
-
信号传输:
- 服务端将信号写入 TCP 隧道连接
- 使用互斥锁防止对隧道的并发写入
-
信号接收:
- 客户端使用缓冲读取器从隧道读取信号
- 信号被修剪并解析为 URL 格式
-
信号处理:
- 客户端将有效信号放入缓冲通道 (signalChan)
- 专用 goroutine 处理来自通道的信号
- 信号量模式防止信号溢出
-
信号执行:
- 远程信号更新客户端的远程地址配置
- 启动信号触发
clientOnce()方法建立连接
信号弹性
- 具有可配置容量的缓冲通道防止在高负载下信号丢失
- 信号量实现确保受控并发
- 对格式错误或意外信号的错误处理
连接池架构
NodePass 实现了一个高效的连接池系统来管理网络连接:
池设计
-
池类型:
- 客户端池:预先建立到远程端点的连接
- 服务器池:管理来自客户端的传入连接
-
池组件:
- 连接存储:线程安全的连接 ID 到 net.Conn 对象的映射
- ID 通道:用于可用连接 ID 的缓冲通道
- 容量管理:基于使用模式的动态调整
- 间隔控制:连接创建之间的基于时间的限流
- 连接工厂:可定制的连接创建函数
连接生命周期
-
连接创建:
- 连接创建数量不超过配置的容量
- 每个连接都分配一个唯一 ID
- ID 和连接存储在池中
-
连接获取:
- 客户端使用连接 ID 检索连接
- 服务端从池中检索下一个可用连接
- 在返回前验证连接
-
连接使用:
- 获取时从池中移除连接
- 用于端点之间的数据交换
- 无连接重用(一次性使用模型)
-
连接终止:
- 使用后关闭连接
- 正确释放资源
- 错误处理确保干净终止
池管理
-
容量控制:
MIN_POOL_CAPACITY:确保最小可用连接数MAX_POOL_CAPACITY:防止过度资源消耗- 基于需求模式的动态缩放
-
间隔控制:
MIN_POOL_INTERVAL:连接创建尝试之间的最小时间MAX_POOL_INTERVAL:连接创建尝试之间的最大时间- 自适应基于时间的限流以优化资源使用
-
动态池适应: 连接池采用双重自适应机制以确保最佳性能:
A. 容量调整
- 池容量根据实时使用模式动态调整
- 如果连接创建成功率低(<20%),容量减少以最小化资源浪费
- 如果连接创建成功率高(>80%),容量增加以适应更高的流量
- 渐进缩放防止振荡并提供稳定性
- 遵守配置的最小和最大容量边界
B. 间隔调整
- 创建间隔根据池空闲连接数调整
- 当空闲连接较少(容量的<20%)时,间隔向最小间隔减少
- 当空闲连接较多(容量的>80%)时,间隔向最大间隔增加
- 防止在低需求期间压垮网络资源
- 在池耗尽的高需求期间加速连接创建
主控API架构
在主控模式下,NodePass提供RESTful API进行集中管理:
API组件
-
HTTP/HTTPS服务器:
- 在配置的地址和端口上监听
- 可选的TLS加密,与隧道服务器使用相同模式
- 可配置的API前缀路径
-
实例管理:
- NodePass实例的内存注册表
- 基于UID的实例标识
- 每个实例的状态跟踪(运行中、已停止等)
-
RESTful端点:
- 实例的标准CRUD操作
- 实例控制操作(启动、停止、重启)
- 健康状态报告
- API文档的OpenAPI规范
实例生命周期管理
-
实例创建:
- 基于URL的配置,类似于命令行
- 基于实例类型的动态初始化
- 实例创建前的参数验证
-
实例控制:
- 启动/停止/重启能力
- 可配置超时的优雅关闭
- 终止时的资源清理
-
API安全:
- API连接的TLS加密选项
- 与隧道服务端相同的安全模式
- HTTPS的证书管理