Skip to content

✨ 新增 VNC 与 RDP 远程连接#227

Open
fr58386612 wants to merge 16 commits into
opskat:mainfrom
fr58386612:codex/vnc-rdp-222
Open

✨ 新增 VNC 与 RDP 远程连接#227
fr58386612 wants to merge 16 commits into
opskat:mainfrom
fr58386612:codex/vnc-rdp-222

Conversation

@fr58386612

Copy link
Copy Markdown
Contributor

概要

  • 新增 vncrdp 两类资产,补齐资产表单、图标、详情页和远程桌面标签页入口。
  • VNC 使用内嵌 noVNC,通过本地 TCP-WebSocket 转发连接目标,并复用现有 SSH、SOCKS5、HTTP 隧道代理链。
  • RDP 在 Windows 上通过本地代理链转发生成 .rdp 配置并启动系统远程桌面客户端,不依赖 guacd
  • VNC 测试连接执行真实 RFB 协商和密码认证,兼容 RealVNC RFB 005.000 降级握手,错误密码不再误报成功。
  • 完善 VNC 连接状态、安全校验、断线提示和缩放操作。
  • 修复中文剪贴板兼容:接收端支持 UTF-8/GB18030,发送端按 GBK 整段传输中英文混合文本,并保证剪贴板同步完成后再发送远端 Ctrl+V
  • 可选绑定 SSH 资产,继续复用现有 SFTP 文件面板进行上传下载。
  • 更新中英文 README 和相关自动化测试。

依赖关系

本 PR 基于代理链 PR #221。建议先合并 #221;合并后本 PR 中重复显示的代理链基础提交会自动从差异中消失。

关联 Issue

Closes #222

验证

  • go test ./internal/app/remote_desktop ./internal/service/remote_desktop_svc ./internal/model/entity/asset_entity
  • corepack pnpm@9.15.9 lint
  • corepack pnpm@9.15.9 test(162 个测试文件,1641 项测试通过)
  • corepack pnpm@9.15.9 build
  • git diff --check

说明

  • VNC 内嵌在 OpsKat 标签页中。
  • RDP 首版使用 Windows 系统远程桌面客户端。
  • 不依赖 guacd;文件上传下载仍需绑定 SSH/SFTP 资产。

新增 VNC/RDP 资产、代理链连接、内嵌 noVNC 会话与系统 RDP 启动,并修复 RealVNC 认证、连接状态及中文 GBK 剪贴板兼容。

Refs opskat#222
@CodFrm

CodFrm commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

“RDP 首版使用 Windows 系统远程桌面客户端。”

我正在实现golang原生的rdp #227 处理完后再合并处理一下

让发布工作流使用当前仓库生成 Release 信息,支持 fork 自动发布。
处理远程桌面连接关闭错误、VNC 协议安全告警、RDP 子进程检查和测试切片初始化问题。\n\nRefs opskat#222
VNC 仅在服务端实际启用密码认证时报告验证成功;RDP 通过代理链执行 NLA/CredSSP 真实凭据认证。\n\nRefs opskat#222
为 Release 工作流增加版本号输入、版本校验和基于当前提交的自动 Tag/Release 创建。

@CodFrm CodFrm Jul 10, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这是做什么?不需要吧

e5c740f

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我fork你仓库的自动编译发布

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

直接打tag就行,不需要修改

@fr58386612

Copy link
Copy Markdown
Contributor Author

合并了最新的上游代码,其中RDP实现使用你的代码,保留我的vnc实现及代理链配置

fr58386612 and others added 3 commits July 11, 2026 22:58
将 main(代理链配置 opskat#221、RDP opskat#225、OSS opskat#223 等)合入 codex/vnc-rdp-222:
- connpool/k8s:统一采用 main 的 chainDialFunc(ctx) 与 ProxyChainDialContext
- proxyConfig/ConnectionMethodFields:采用 main 重设计的代理链 UI(DnD 分层校验)
- README/i18n:保留 main 更完整的代理链描述,补充 VNC 相关文案
- wails.json:pnpm 统一为 10.11.0,与 CI 对齐
@CodFrm CodFrm marked this pull request as ready for review July 13, 2026 09:36
@CodFrm

CodFrm commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Code review

Found 3 issues:

  1. Dead/duplicate RDP code left over from merging with ✨ 接入 RDP 资产能力 #225. RDPConfigSection exported here has no importers — assetTypes/rdp.ts still imports RDPConfigSection from the pre-existing @/components/asset/RDPConfigSection. The isRDP branch in RemoteDesktopPanel is likewise unreachable (RDP routes to pageId: "rdp"RDPPanel, and remote_desktop_svc.Connect rejects any non-VNC asset), and it drags in duplicate i18n keys (asset.domain duplicates the already-shipped asset.rdpDomain). AGENTS.md "Reuse first" warns parallel/dead copies drift; this is exactly the stale code to remove.

https://github.com/opskat/opskat/blob/31421b6eda24910518b7e17b95b2858c211a1e15/frontend/src/components/asset/RemoteDesktopConfigSection.tsx#L165-L168

)}
{isRDP && (
<div className="flex h-full items-center justify-center p-6 text-center text-sm text-white/75">
<div className="max-w-lg rounded-md border border-white/10 bg-white/5 p-5">
<PlugZap className="mx-auto mb-3 h-8 w-8" />
<div className="font-medium text-white">{t("remoteDesktop.rdpExternalTitle")}</div>
<p className="mt-2 leading-6">{session?.message || t("remoteDesktop.rdpExternalDesc")}</p>
</div>
</div>
)}

  1. pasteTextToVNC unconditionally sends Ctrl+V after pasteVNCClipboardText, but when GBK encoding fails the codec has already typed the text directly via keysyms (the third branch). The trailing Ctrl+V then pastes whatever is currently in the remote clipboard on top of it, corrupting input for text outside GBK (emoji / Japanese / Korean). The caller can't tell which branch ran — the function should signal whether it set the clipboard.

if (!rfb || !text) return;
await pasteVNCClipboardText(rfb, text, EncodeVNCClipboardText);
if (rfbRef.current !== rfb) return;
rfb.sendKey(0xffe3, "ControlLeft", true);
rfb.sendKey(0x76, "KeyV", true);
rfb.sendKey(0x76, "KeyV", false);
rfb.sendKey(0xffe3, "ControlLeft", false);
};

}
for (const char of text.replace(/\r\n?/g, "\n")) {
client.sendKey(unicodeToKeysym(char.codePointAt(0)!), "");
await delay(8);
}
}

  1. The new VNC asset type is creatable/updatable via the AI tool (internal/assettype/vnc.go implements ValidateCreateArgs/ApplyCreateArgs), but tools_asset.go still omits "vnc" from the list_assets filter and the add_asset type enumeration, so the model can't discover or create VNC assets. docs/adding-an-asset-type.md says to "update internal/ai/tool/tools_asset.go when the new type has model-facing create/update args".

Properties: map[string]*agent.Property{
"name": {Type: "string", Description: "Display name for the asset."},
"type": {Type: "string", Description: `Asset type: "ssh" (default), "serial", "rdp", "database", "redis", "mongodb", "kafka", "k8s", or "etcd".`},
"host": {Type: "string", Description: "Hostname or IP address. Required except for serial / k8s / kafka (kafka uses brokers, but host+port falls back to a single broker)."},
"port": {Type: "number", Description: "Port number (default: 22 for SSH, 3389 for RDP, 3306 for MySQL, 5432 for PostgreSQL, 6379 for Redis, 27017 for MongoDB, 9092 for Kafka, 2379 for etcd). Not used for serial / k8s; for kafka used only when brokers is omitted."},

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

CodFrm added 4 commits July 13, 2026 20:02
- pasteVNCClipboardText 返回是否已写入剪贴板;keysym 直接键入(GBK 无法编码的 emoji/日韩等)时不再补发 Ctrl+V,避免把远端旧剪贴板内容多粘一次
- 拆分合并的断开 effect(原来 [session?.id, fileSessionId] 共用一个 cleanup),打开文件面板不再误断开在线 VNC 会话
- 顺带移除 VNC 面板中不可达的 RDP 分支与相关 import
- 补充回归测试:去掉修复即失败
- 删除无引用的 RDPConfigSection 导出,将远程桌面表单/详情卡收敛为 VNC-only(去掉 vnc|rdp 类型参数与 RDP 专属字段/校验)
- 删除只被死代码引用的 i18n key(rdpExternal*、width/height/colorDepth/ignoreCert、重复的 asset.domain、formMissingHostOrUsername)与重复的 nav.rdp
- 新标签打开改为按资产类型注册表 connectAction === 'page' 派发,去掉 App.tsx 中 asset.Type === 'vnc' 硬编码分支
- 将 RFB 版本协商/安全类型/密码认证从 app 绑定层移到 remote_desktop_svc.Manager.TestConfig,绑定层收敛为 解析→解密→委派,与 rdp_svc/etcd_svc 一致;协议测试一并迁到 service 包
- manager 补 会话 open/end/fail 三态日志,改用 logger.Ctx(ctx),替换两处裸 zap.L()
- 移除从未赋值的 Session.Message 死字段
- list_assets/add_asset/update_asset schema 补充 vnc 类型枚举及 security_type/file_ssh_asset_id 参数(依据 docs/adding-an-asset-type.md)
- 新增 vnc_test 覆盖 ValidateCreateArgs/ApplyCreateArgs/ApplyUpdateArgs 与 SafeView 脱敏
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] 新增vnc、RDP

2 participants