Files
SimpleRemoter/server/go/README.md

15 KiB
Raw Blame History

SimpleRemoter Go TCP Server Framework

基于 Go 语言实现的高性能 TCP 服务端框架,用于替代原有的 C++ IOCP 服务端。

项目结构

server/go/
├── go.mod                    # Go 模块定义
├── auth/
│   └── auth.go              # 授权验证模块 (TOKEN_AUTH + Heartbeat HMAC)
├── buffer/
│   └── buffer.go            # 线程安全的动态缓冲区
├── connection/
│   ├── context.go           # 连接上下文
│   ├── errors.go            # 错误定义
│   └── manager.go           # 连接管理器
├── protocol/
│   ├── parser.go            # 协议解析器
│   ├── codec.go             # 编解码和压缩 (ZSTD)
│   ├── header.go            # 协议头解密 (8种加密方式)
│   └── commands.go          # 命令常量和LOGIN_INFOR解析
├── server/
│   ├── server.go            # TCP 服务器核心
│   └── pool.go              # Goroutine 工作池
├── logger/
│   └── logger.go            # 日志模块 (基于 zerolog)
├── hub/
│   └── hub.go              # 在线设备注册表 + 事件订阅
├── wsauth/
│   └── wsauth.go           # Web 鉴权 (challenge-response + 不透明 token)
├── web/
│   ├── embed.go            # //go:embed 嵌入 HTML/xterm.js 等 web 资源
│   ├── server.go           # HTTP server (静态页面 + REST + WS 路由)
│   ├── ws.go               # WebSocket 连接生命周期
│   ├── ws_handlers.go      # WS 消息分发与处理
│   └── assets/
│       ├── index.html      # 从 ../../web/index.html sync 而来 (gitignored)
│       └── static/         # 第三方 xterm.js 资源 (checked in)
└── cmd/
    └── main.go              # 程序入口

核心特性

底层基础设施:

  • 高并发: 基于 Goroutine 池管理并发连接
  • 协议兼容: 支持原有客户端的多种协议标识 (Hell/Hello/Shine/Fuck)
  • 协议头解密: 支持 8 种协议头加密方式 (V0-V6 + Default)
  • 授权验证: TOKEN_AUTH 和 Heartbeat HMAC-SHA256 双重授权
  • XOR 编码 / ZSTD 压缩: 与客户端完全兼容
  • 字符编码自适应: 根据客户端能力位选择 UTF-8 直通或 GBK→UTF-8 转换
  • 线程安全 / 优雅关闭 / 多端口监听 / 结构化日志

Web 应用能力 (Phase 3-7)

  • Web 鉴权: challenge-response 登录 + 不透明 token与 users.json schema 互通
  • 设备列表与监控: 在线设备 / RTT / 活动窗口 / 分辨率 实时下发
  • Web 远程桌面: 浏览器 WebCodecs 解码 H.264,二进制 WS 帧低延迟中继late-join 自动重发最近 IDR优雅 BYE 关闭防止客户端无意义重连
  • 鼠标 / 键盘输入: Win32 消息映射 (WM_* / VK_* / MK_*)MSG64 48 字节布局直传客户端
  • Web 终端: xterm.js + Windows ConPTY / 旧 cmd 管道双模式;二进制 "TRM1" 帧分流;尺寸自适应;单设备单 viewer
  • 用户与分组: admin 可创建/删除 viewer 账号、配置 allowed_groupsusers.json 原子写入

支持的命令

客户端 → 服务端

Token 用途
TOKEN_AUTH 100 授权请求SN + Passcode + HMAC
TOKEN_HEARTBEAT 101 心跳包(携带 ActiveWnd / Ping / SN
TOKEN_LOGIN 102 主连接登录
TOKEN_BITMAPINFO 115 屏幕子连接首包,含分辨率 + clientID
TOKEN_FIRSTSCREEN 116 原始 BGRA 首帧Go 侧丢弃)
TOKEN_NEXTSCREEN 117 H.264 屏幕帧
TOKEN_SHELL_START 128 旧 cmd-pipe 终端子连接首包
TOKEN_KEYFRAME 134 GOP 关键帧DEFAULT_GOP 无限大,实际未用)
TOKEN_TERMINAL_START 232 PTY 终端子连接首包
TOKEN_TERMINAL_CLOSE 233 终端关闭通知
TOKEN_CONN_AUTH 246 子连接身份握手,含 clientID
(raw bytes) 终端 sub-conn 绑定后裸字节即 shell 输出

服务端 → 客户端

Command 用途
COMMAND_SCREEN_SPY 16 启动屏幕捕获
COMMAND_SCREEN_CONTROL 20 鼠标 / 键盘输入MSG64 批次)
COMMAND_NEXT 30 解除客户端读线程阻塞
COMMAND_SHELL 40 请求开启 shell 子连接
CMD_TERMINAL_RESIZE 81 PTY 尺寸 (cols / rows int16 LE)
COMMAND_BYE 204 优雅断开屏幕 / 终端
CMD_MASTERSETTING 215 主控配置 + HMAC 签名 (1000B)
CMD_HEARTBEAT_ACK 216 心跳响应(携带 Authorized 字段)
TOKEN_CONN_AUTH 246 子连接身份握手响应 (256B)

未列出的命令字节会被记录为 Debug 日志,按需扩展。

快速开始

安装依赖

cd server/go
go mod tidy

编译

推荐用 Makefile编译前会自动从 server/web/ 同步 HTML 到 web/assets/

make build           # 当前平台
make windows         # Windows amd64
make linux           # Linux amd64

也可以直接用 go build,但要先手动 sync

make sync && go build -o simpleremoter-server ./cmd

VSCode F5 调试时由 sync-web-assets preLaunchTask 自动同步。

运行

./simpleremoter-server

默认监听 TCP 端口 6543被控设备HTTP 端口 8080(浏览器 Web UI。日志写到 logs/server.log

命令行参数

参数 默认值 说明
-port / -p 6543 TCP 监听端口,分号分隔可多端口(如 6543;6544
-http-port 8080 HTTP 监听端口Web UI0 禁用
-no-console false 关闭控制台输出(守护进程模式)

环境变量

变量 说明 示例
YAMA_PWDHASH 密码的 SHA256 哈希值 (64位十六进制) 61f04dd6...
YAMA_PWD 超级密码,用于 HMAC 签名验证;也作为 Web admin 密码的默认来源 your_super_password
YAMA_WEB_ADMIN_PASS Web UI 的 admin 密码(明文);优先于 YAMA_PWD。两者都未设置时 Web 登录禁用 your_admin_password
YAMA_SIGN_PASSWORD HMAC-SHA256 key used to sign CMD_MASTERSETTING replies; must match the client's expected value. Provision out-of-band. Unset → client refuses screen/file ops. <deployment-shared-secret>
YAMA_USERS_FILE Path to the JSON file that persists non-admin web users (allowed_groups, password hash, salt). Default is users.json in the working directory. users.json
# Linux/macOS
export YAMA_PWDHASH="61f04dd637a74ee34493fc1025de2c131022536da751c29e3ff4e9024d8eec43"
export YAMA_PWD="your_super_password"
./simpleremoter-server

# Windows PowerShell
$env:YAMA_PWDHASH="61f04dd637a74ee34493fc1025de2c131022536da751c29e3ff4e9024d8eec43"
$env:YAMA_PWD="your_super_password"
.\simpleremoter-server.exe

使用示例

完整的 TCP + Hub + Web 集成示例就是 cmd/main.go,那是程序入口本身、也是最权威的范例 —— 包含 handler 装配、hub 注册、web HTTP/WS 服务、信号优雅关闭等。

如果只想用 TCP 框架做自定义服务端(不要 Web/Hub最小示例如下

package main

import (
    "os"
    "os/signal"
    "syscall"

    "github.com/yuanyuanxiang/SimpleRemoter/server/go/connection"
    "github.com/yuanyuanxiang/SimpleRemoter/server/go/logger"
    "github.com/yuanyuanxiang/SimpleRemoter/server/go/protocol"
    "github.com/yuanyuanxiang/SimpleRemoter/server/go/server"
)

type MyHandler struct{ log *logger.Logger }

func (h *MyHandler) OnConnect(ctx *connection.Context)    {}
func (h *MyHandler) OnDisconnect(ctx *connection.Context) {}
func (h *MyHandler) OnReceive(ctx *connection.Context, data []byte) {
    if len(data) == 0 {
        return
    }
    if data[0] == protocol.TokenLogin {
        info, _ := protocol.ParseLoginInfo(data)
        h.log.Info("login: %s (%s)", info.PCName, info.OsVerInfo)
    }
}

func main() {
    log := logger.New(logger.DefaultConfig())
    srv := server.New(server.DefaultConfig())
    srv.SetLogger(log.WithPrefix("Server"))
    srv.SetHandler(&MyHandler{log: log})
    if err := srv.Start(); err != nil {
        log.Fatal("start: %v", err)
    }

    sig := make(chan os.Signal, 1)
    signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
    <-sig
    srv.Stop()
}

配置选项

配置项 默认值 说明
Port 8080 监听端口
MaxConnections 10000 最大连接数
MinWorkers 4 最小工作协程数
MaxWorkers 100 最大工作协程数
ReadBufferSize 8192 读缓冲区大小
WriteBufferSize 8192 写缓冲区大小
KeepAliveTime 5min 连接保活时间
ReadTimeout 2min 读超时时间
WriteTimeout 30s 写超时时间

日志配置

配置项 默认值 说明
Level Info 日志级别 (Debug/Info/Warn/Error/Fatal)
Console true 是否输出到控制台
File "" 日志文件路径 (空则不写文件)
MaxSize 100 单个日志文件最大 MB
MaxBackups 3 保留的旧日志文件数量
MaxAge 30 旧日志保留天数
Compress true 是否压缩轮转的日志

日志示例输出:

{"level":"info","module":"Server","time":"2025-12-19T13:17:32+01:00","message":"Server started on port 6543"}
{"level":"info","module":"Handler","event":"login","client_id":1,"ip":"192.168.0.92","computer":"DESKTOP-BI6RGEJ","os":"Windows 10","version":"Dec 19 2025","time":"2025-12-19T13:17:32+01:00"}
{"level":"debug","module":"Handler","time":"2025-12-19T13:17:47+01:00","message":"Heartbeat from client 1 (DESKTOP-BI6RGEJ)"}

协议格式

数据包格式与 C++ 版本兼容:

+----------+------------+------------+------------------+
|  Flag    | TotalLen   | OrigLen    |  Compressed Data |
| (N bytes)| (4 bytes)  | (4 bytes)  |  (variable)      |
+----------+------------+------------+------------------+

协议标识

标识 Flag长度 压缩方式 说明
HELL 8 bytes ZSTD 主要协议
Hello? 8 bytes None 无压缩协议
Shine 5 bytes ZSTD 备用协议
<> 11 bytes ZSTD 备用协议

协议头加密

支持8种加密方式服务端自动检测并解密

  • V0 (Default): 动态密钥4种操作
  • V1: 交替加减
  • V2: 带旋转的异或
  • V3: 带位置的动态密钥
  • V4: 对称的伪随机异或
  • V5: 带位移的动态密钥
  • V6: 带位置的伪随机
  • V7: 纯异或

LOGIN_INFOR 结构

客户端登录信息结构体 (考虑 C++ 内存对齐)

字段 偏移 大小 说明
bToken 0 1 命令标识 (102)
OsVerInfoEx 1 156 操作系统版本
(padding) 157 3 对齐填充
dwCPUMHz 160 4 CPU 频率
moduleVersion 164 24 模块版本
szPCName 188 240 计算机名
szMasterID 428 20 主控 ID
bWebCamExist 448 4 是否有摄像头
dwSpeed 452 4 网速
szStartTime 456 20 启动时间
szReserved 476 512 扩展字段(多字段以 | 分隔)

Heartbeat 结构

客户端心跳包结构 (1024 字节)

字段 偏移 大小 说明
Time 0 8 时间戳 (uint64)
ActiveWnd 8 512 当前活动窗口
Ping 520 4 延迟 (int)
HasSoftware 524 4 软件标识 (int)
SN 528 20 序列号 (用于授权验证)
Passcode 548 44 授权码 (格式: v0-v1-v2-v3-v4-v5)
PwdHmac 592 8 HMAC 签名 (uint64)
Reserved 600 424 保留字段

HeartbeatACK 结构

服务端心跳响应结构 (32 字节)

字段 偏移 大小 说明
Time 0 8 原始时间戳 (uint64)
Authorized 8 1 授权状态 (1=已授权, 0=未授权)
Reserved 9 23 保留字段

授权验证流程

客户端 Heartbeat                     服务端
    │                                   │
    │  SN + Passcode + PwdHmac          │
    │ ────────────────────────────────► │
    │                                   │ 1. 验证 Passcode 格式
    │                                   │ 2. 验证 Passcode 哈希
    │                                   │ 3. 验证 HMAC 签名
    │          HeartbeatACK             │
    │ ◄──────────────────────────────── │
    │       (Authorized=1 或 0)         │

API 参考

Server

// 创建服务器
srv := server.New(config)

// 设置日志
srv.SetLogger(log)

// 设置事件处理器
srv.SetHandler(handler)

// 启动服务器
srv.Start()

// 停止服务器
srv.Stop()

// 发送数据到指定连接
srv.Send(ctx, data)

// 广播数据到所有连接
srv.Broadcast(data)

// 获取当前连接数
count := srv.ConnectionCount()

Connection Context

// 发送数据
ctx.Send(data)

// 关闭连接
ctx.Close()

// 获取客户端 IP
ip := ctx.GetPeerIP()

// 检查连接状态
closed := ctx.IsClosed()

// 获取/更新最后活跃时间 (线程安全)
lastActive := ctx.LastActive()
ctx.UpdateLastActive()
duration := ctx.TimeSinceLastActive()

// 设置/获取客户端信息
ctx.SetInfo(clientInfo)
info := ctx.GetInfo()

// 设置/获取用户数据
ctx.SetUserData(myData)
data := ctx.GetUserData()

Protocol

// 解析登录信息
info, err := protocol.ParseLoginInfo(data)
if err == nil {
    fmt.Println(info.PCName)      // 计算机名
    fmt.Println(info.OsVerInfo)   // 操作系统
    fmt.Println(info.ModuleVersion) // 版本
    fmt.Println(info.WebCamExist) // 是否有摄像头
}

// 获取扩展字段
reserved := info.ParseReserved()  // 返回 []string
clientType := info.GetReservedField(0)  // 客户端类型
cpuCores := info.GetReservedField(2)    // CPU 核数
filePath := info.GetReservedField(4)    // 文件路径
publicIP := info.GetReservedField(11)   // 公网 IP

与 C++ 版本对比

特性 C++ (IOCP) Go
并发模型 IOCP + 线程池 Goroutine 池
跨平台 Windows 全平台
内存管理 手动 GC
代码复杂度
压缩 / XOR / 头加密 完整 8 套加密方式 + XOREncoder16 + ZSTD 完全对齐
字符编码 GBK UTF-8 直通 / GBK→UTF-8 (按客户端能力位)
设备列表与监控 MFC 列表控件 Web UI
Web 远程桌面 内嵌浏览器 + H.264 完全对齐WebCodecs 解码)
鼠标键盘转发 已实现 完全对齐
Web 终端 内嵌 xterm.js + ConPTY 完全对齐(含旧 cmd-pipe 兼容)
用户 / 分组管理 已实现 users.json schema 互通
文件传输 / 摄像头 / 录音 等 已实现 暂未实现(按需扩展)

依赖

License

MIT License