-
v1.4.1 Stable
released this
2026-10-20 17:09:55 +00:00 | 4 commits to main since this releasev1.4.1 (2026.10.20)
⚠️ 安全提示
本软件涉及远程控制功能,请谨慎下载,建议在虚拟机中测试。主控程序会连接授权服务器进行必要的通讯和防破解检测。下载并使用本软件,即视为接受上述条款。
Web 运维控制台 & 安全加固 & 单向 TLS
本次发布距 v1.4.0 约 13 天,跨 45 次提交。主线是把 Web 远程管理从「单机远控」扩展为「多设备运维控制台」:MFC 与 Go 主控同步上线屏幕墙、安全审计日志与查询页(Go 端另加离线设备历史与远程卸载),设备端口新增可选单向 TLS;同时补齐每 IP 限流、入站缓冲上限、子连接源 IP 绑定与 ConnAuth HMAC 校验等公网暴露面加固,并带来 Web 剪贴板双向同步、手机 IME 输入框、跨标签页会话共享与应用内对话框等体验改进。
新功能
Web 屏幕墙(MFC + Go)
- 多设备同屏监控:Web UI 新增第三种视图「屏幕墙」,同一标签页以 1×1 / 2×2 / 3×3 / 4×4 / 5×5 布局同时观看多台设备,左侧为可搜索的设备侧边栏
- 监控与控制分离:墙上的 tile 仅监控;点击 tile 放大到现有单画面页进行控制,Back 返回墙并恢复
- 同一设备多 tile:同一设备可重复添加,所有 tile 共享一个解码器与一路流;订阅在客户端按 owner 集合引用计数(0→1 connect,1→0 disconnect),墙与单画面页可共用一路流而不会互相拆流
- 解码预算:桌面最多 9 路、触控 4 路实时解码;超出预算的 tile 继续收帧但关闭解码器,保留末帧并显示 Paused,有实时 tile 释放后自动晋升
- 服务端 watch 集合:
WebClient的单个watch_device_id改为集合(每连接上限 32 台);新增multiWatch命令标志选择集合语义,不带该标志的旧前端仍走「替换全部」语义,避免反复切换设备导致集合无限增长 - 响应与输入路由:
connect/disconnect响应回显id与req;鼠标 / 键盘 / 剪贴板 /rdp_reset/audio_toggle带id并按 watch 集合解析,多设备且无id时丢弃,避免跨设备输入注入 - 快速出图:二进制帧按设备 ID 低 32 位路由并检测冲突;服务端缓存每台设备的 raw IDR,在 connect 与新增
keyframe命令时立即回放,再下发COMMAND_SCREEN_KEYFRAME_REQ(169) 让客户端强制新 IDR;旧客户端忽略该命令时最坏等一个自然 GOP - 关键帧缓存修复:修复
BroadcastH264Frame缓存完整包、HandleConnect再次封装的「双重封装」问题;冷启动与分辨率变化时清空缓存;StopRemoteDesktop一律在m_ClientsMutex之外调用 - Go 端对齐:Go 服务端实现同样的 watch 集合、
caps.multiWatch/caps.keyframeRequest能力协商与keyframe命令(每设备 1 次/秒);修复TOKEN_KEYFRAME(134) 被当作 no-op 丢弃、导致浏览器 P 帧参考链损坏的持续花屏
安全审计日志
- Go 服务端:登录尝试、授权拒绝、WebSocket 生命周期、屏幕 / 终端会话、剪贴板操作(仅字节数)、设备认证与管理变更写入独立 JSON 行审计事件(
audit=true/event=<name>),落盘logs/audit.log并镜像到server.log;路径可由YAMA_AUDIT_LOG配置、独立文件可关闭 - MFC 服务端:进程内保留最近 1000 条审计事件(环形缓冲、不落盘),事件名与回复格式与 Go 端对齐
- Web 审计日志页:管理员可按时间范围、事件(精确或前缀)、操作者、IP、设备 ID、关键字、仅告警过滤,倒序分页;页面仅在服务端广告
caps.auditLog时显示,旧 C++ 服务端优雅降级 - 查询有界:单次查询最多扫描当前审计文件最新 32 MB,查询本身记为
admin.audit.query,并容忍截断行与非审计行 - 脱敏:审计记录不包含密码、密码哈希、Token、Nonce 或剪贴板内容;不可信字符串字段去除控制字符并截断,防止伪造日志行
- 真实客户端 IP:MFC Web 服务在 TCP peer 为 loopback 时从 WebSocket 升级请求解析真实地址,
X-Forwarded-For优先于X-Real-IP(取代理追加的最后一跳);非 loopback peer 忽略转发头,防止直连客户端伪造身份或轮换地址绕过限流;FRP 部署继续使用 Proxy Protocol v2
离线设备历史(Go)
- 持久化:所有登录过的设备写入
devices.json(可用YAMA_DEVICES_FILE指定、YAMA_DEVICES_MAX限制,默认保留最新 1000 条);沿用users.json的原子临时文件 + fsync + rename 约定,重连突发 500ms 去抖,first_seen跨登录保留,淘汰时优先移除离线记录 - 列表合并:服务端广告
offlineDevices能力,device_list追加不在线的历史设备并标记online:false/last_seen;Web 设备列表新增 Offline 复选框(状态存 localStorage),离线卡片变暗、虚线边框,屏幕墙侧边栏始终列出离线设备 - 删除与远程卸载:Grid / List 卡片在终端按钮后新增删除按钮(仅管理员,带确认框);删除离线设备直接移除历史记录,删除在线设备先下发
TOKEN_UNINSTALL再移除记录,客户端断开后走既有清理路径;墙模式不提供删除操作
单向 TLS 传输
- 同端口兼容:设备端口(6543)按首字节嗅探 TLS ClientHello,TLS 客户端走加密通道、旧明文客户端保持原行为;Go 端仅在
YAMA_TLS_CERT/YAMA_TLS_KEY均设置时启用 TLS,证书加载失败则启动失败而不是静默回退明文 - 客户端 Schannel:Windows 客户端在信任锚存在时,对所有出站连接(主连接 + 子连接)完成 TLS 1.2 握手,并以
hExclusiveRoot严格 pin 到该锚;握手或证书失败 fail-closed,绝不降级明文。信任锚来源为注册表settings\tls_cert(PEM),回退settings.ini或 exe 旁的yama-ca.pem - MFC 运行时配置:「扩展 > TLS证书」打开运行时构建的对话框,设置启用开关、证书与私钥路径;OK 后写入
[tls] Enabled/CertPath/KeyPath并立即加载,对新连接生效 - 按客户端开关:在线列表在权限列后新增 TLS 列(客户端经
RES_TLS上报信任锚是否存在);右键「实验功能 > TLS传输 / 取消TLS」经COMMAND_TLS_ENABLE/COMMAND_TLS_DISABLE(166/167) 把服务端证书 PEM 写入客户端注册表或删除,客户端下次启动生效(非实时切换) - 传输可靠性:修复 TLS 发送路径把多次小发送并发到同一可变缓冲导致的
ERROR_DECRYPTION_FAILED,以及客户端 Recv 未消费握手残留字节的问题
Web 远程桌面增强
- 剪贴板双向同步:Ctrl+C / Ctrl+X / Ctrl+V 复用原生剪贴板协议(
COMMAND_SCREEN_GET_CLIPBOARD24 /COMMAND_SCREEN_SET_CLIPBOARD25 /TOKEN_CLIPBOARD_TEXT118),客户端无需改动;本地→远端读取浏览器剪贴板(UTF-8→GBK)并合成远端 Ctrl+V,远端→本地在转发后延迟拉取并写入浏览器剪贴板;MFC 与 Go 服务端行为一致 - 手机 IME 输入框:「I」按钮打开固定在虚拟键盘上方的聊天式输入框,文本经剪贴板桥注入;空框时 Enter / Backspace 转发为远端按键,输入框最多四行自动增高;桌面按键转发同时跳过
TEXTAREA - 跨标签页会话:登录 Token 与角色从
sessionStorage改为localStorage,同一 origin 的新标签页自动恢复会话,不再重复登录;过期与显式登出仍会清除 - 管理员 SSO:Go Web 新增
/sso,用YAMA_SSO_JWT_SECRET校验父门户 JWT,仅admin角色可桥接;其他角色回退内建登录页,保证低权限门户账号无法绕过认证 - 应用内对话框:原生
alert()/confirm()全部替换为复用登出确认样式主题化模态框(info 单按钮 / danger 双按钮);标题与正文使用textContent防注入,支持 Esc、点击背景关闭、后弹对话框取消前一个,且对话框打开时暂停远程键盘转发 - 审计页保持:浏览器最小化导致 WebSocket 重连后,审计日志页不再被重置回设备页;其他页面仍按原逻辑回退
客户端安装位置选择
- BuildDlg 新增「安装目录」下拉框:
ProgramData(默认)/ProgramFiles - Admin/SystemRoot - Admin/APPDATA/LOCALAPPDATA;选择经登录信息新增的installFlag传给客户端(原预留字段改为int,结构体大小不变),由GetInstallDirectory按环境变量解析
Go Web UI 白标
- 子路径部署(
YAMA_WEB_BASE_PATH非空)时可设置YAMA_WEB_BRAND_NAME替换产品名与 PWA manifest 名称,并移除安全提示与官网外链;品牌名做 JSON / HTML 转义,避免畸形输出;从域名根路径提供服务时保持官方 SimpleRemoter 品牌
安全加固
- 每 IP 限流:Go 设备端口按源 IP 限制并发连接(默认 256)与 accept 速率(默认 120/分钟,
YAMA_PERIP_MAX_CONNS/YAMA_PERIP_CONN_RATE),在分配缓冲或 goroutine 前拒绝;TOKEN_AUTH每 IP 120/分钟,超限返回正常失败响应;Web 登录限流 map 定期清理,防止攻击者控制的用户名键无限增长 - 入站缓冲上限:单连接未解析字节超过
MaxBufferedBytes(默认 50 MiB + 64 KiB)即断开,防止不完整 HTTP mask 包无限增长内存;0表示不限制,与每 IP 限制语义一致 - 子连接源 IP 绑定:屏幕 / 终端子连接必须与设备主连接来自同一源 IP,否则拒绝;
MasterID可被任意 TCP peer 提供,此绑定阻止互联网主机冒用在线设备的MasterID劫持画面或 shell - ConnAuth HMAC:设置
YAMA_CONN_AUTH_KEY后校验设备子连接的 HMAC-SHA256 签名与时间戳,失败回非 OK 状态并断开;未设置时保持旧行为。密钥只从环境读取,不进入仓库;源 IP 绑定作为纵深防御继续保留
克隆机 ID 去重
- V2
client_id哈希折叠主机名,同镜像克隆机(相同 MachineGuid)不再撞 ID 导致只显示一台;已持久化的 ID 不变,清除settings/client_id后按新算法重算 - 服务端检测到
client_id相同但主机名不同时下发COMMAND_REGEN_CLIENT_ID,客户端掺随机 UUID 重算并重连;触发条件仅看主机名,排除 IP 漂移与纯用户名变化 - 服务端对重复
client_id且 hostname / IP / username 不同的登录记录 WARN 诊断(仅观测,不改变行为)
改进
- 文件传输速度下发:速度参数折叠进
MasterSettings(TransferChunkKb/TransferDurationMs,两个uint16,结构体仍为 1000 字节),登录时下发、对话框保存时广播在线客户端;修复此前CMD_FILE_SPEED与COMMAND_SCREEN_SPY被 IOCP 合批导致单次点击弹出两个远程桌面窗口的问题;CMD_FILE_SPEED(252) 保留兼容但主控不再发送 - 实时传输速度:
CDlgFileSend标题约每 200ms 刷新平滑字节速率(如「发送文件 - 5.3M/s」),经 Unicode API 设置,非中文系统不再乱码 - 聊天窗口:客户端关闭聊天窗口(结束按钮或标题栏 X)改为隐藏并保留会话,服务端下一条消息或
SW_RESTORE时重新显示;真正销毁仍由COMMAND_CHAT_CLOSE或断连触发 - 日志右键白名单:消息日志右键在「解除封禁」后新增「白名单」,提取选中日志的 IP 并确认后加入共享
IPWhitelist,新连接立即生效、无需重启;已在白名单或黑名单中的 IP 分别提示跳过 - MCP 菜单勾选:设置对话框关闭后立即刷新「MCP 设置」菜单勾选,无需重启
- 非中文系统解码:对话框 / 工具栏文本、进程列表名称与路径、远端文件列表与路径、客户端路径、地理位置、主机管理与剪贴板文本统一按 GBK / UTF-8 解码,修复德语等系统上的乱码
- 翻译补齐:
FileManagerDlg、TLS 菜单、白名单、授权续期提示等新增中文字符串补齐 en_US / zh_TW / de_DE
Bug 修复
- 共享 / 转移主机后重启主控不重连:
IsStoped()等待存活共享实例排空,而共享实例持有AddCount(1)导致条件永不成立;S_SERVER_EXIT现在立即重连,不再等待共享实例,且重连时不会重复创建并行实例 - 分享 / 转移权限误判:修复无权限分享或转移客户端主机的问题
- 授权续期日期:已过期授权从今天起算续期;预设日期、成功提示与两条日志路径(心跳
SendPendingRenewal与客户端请求GenerateRenewalInfo)均显示实际签发日期,并修正历史预设记录 - 客户端 respawn 与 Web 登录品牌:修复共享主机场景的 respawn 阻塞,以及 MFC Web 登录页
__BRAND_NAME__占位符未替换 - V2 上传环境变量:经桌面 / 下载 / 主目录快捷方式上传时,
%USERPROFILE%模板未展开,文件被写入字面量目录;V2 接收路径现在先展开环境变量 - 无摄像头主机:
CCaptureVideo::Open绑定采集设备失败时返回S_FALSE并退出工作线程,不再发送 0×0BITMAPINFO - 列切换残影:在线主机列表切换列可见性后,最后一列右侧残留上一列像素;每次可见性变化后强制整窗重绘
- Go 设备端口日志刷屏:
SOCKET_DLLLOADER(210) 不再记为 Unhandled;子连接劫持尝试与普通孤儿连接分别记录 - MaxBufferedBytes=0:按「不限制」处理,不再在首字节后断开所有连接
- 审计页重连:浏览器最小化 / WebSocket 重连后保持审计日志页,不跳回设备页
- 关键帧缓存:修复双重封装、冷启动 / 分辨率变化未清空缓存的问题
升级提示
- Web 功能依赖新版服务端:屏幕墙、审计日志页、离线设备历史需要新版服务端(MFC 重编以嵌入新
index.html;Go 更新二进制)。旧服务端不广告caps.multiWatch/caps.auditLog/caps.offlineDevices,前端会自动隐藏对应入口 - 屏幕墙暂停恢复:旧客户端忽略
COMMAND_SCREEN_KEYFRAME_REQ,暂停 / 恢复最多等待一个自然 GOP(约 4–15 秒);升级客户端后由强制 IDR 立即出图 - TLS:服务端需配置证书与私钥(MFC
[tls]或 GoYAMA_TLS_CERT/YAMA_TLS_KEY);客户端信任锚可远程下发,但需重启客户端生效;握手失败 fail-closed,不会回退明文 - 离线设备历史:仅 Go 主控提供,
devices.json默认最多 1000 条 - SSO:仅 Go Web,且需设置
YAMA_SSO_JWT_SECRET,只桥接admin角色 - 克隆机 ID:新装客户端自动使用新算法;已部署的克隆机需清除
settings/client_id后重启,才会重算并各自上线 - 安装位置:选择
ProgramFiles - Admin/SystemRoot - Admin需要客户端具备管理员权限;默认仍为ProgramData
Downloads