ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

MeshCentral 内置 RDP 协议栈深度解析:node-rdpjs 分支、NLA 支持与纯 Node.js 实现

MeshCentral 内置 RDP 协议栈深度解析:node-rdpjs 分支、NLA 支持与纯 Node.js 实现 后端运维【免费下载链接】MeshCentralA complete web-based remote monitoring and management web site. Once setup you can install agents and perform remote desktop session to devices on the local network or over the Internet.项目地址https://gitcode.com/gh_mirrors/me/MeshCentral点击查看免费下载导读MeshCentral 是一个完整的基于 Web 的远程监控与管理平台而远程桌面是其核心能力之一。本文聚焦仓库中的 rdp/ 目录——一个为 MeshCentral 定制维护的 node-rdpjs v0.2.1 分支它在纯 Node.js 环境中实现了完整的 RDP远程桌面协议客户端/服务端协议栈并额外移植了网络层认证NLA / CredSSP支持。读完本文你将掌握该分支的演进背景、RDP 协议栈的分层架构与核心源码调用链、NLANTLMv2认证的完整实现原理以及客户端 API 的全部可配置参数与事件模型并了解其 GPL-3.0 许可边界与可移除性。rdp/ 目录是什么为 MeshCentral 定制的 node-rdpjs 分支根据 rdp/README.md 的说明rdp文件夹包含的是node-rdpjs2 包的一个分支fork其内容与上游 node-rdpjs v0.2.1 基本一致但做了两类关键改造适配最新版本 Node.js上游 v0.2.1 年代较早直接运行在现代 Node.js 上会遇到底层加密 API 缺失的问题详见下文Node.js 兼容性改造一节移除依赖并新增 NLA 支持剥离部分外部依赖更重要的是增加了网络层认证Network Layer AuthenticationNLA能力——这正是现代 Windows RDP 会话CredSSP 流程能够建立的前提。NLA 支持移植自 RDP-RS——一个由 node-rdpjs 原作者维护的 Rust 版 RDP 解决方案。也就是说这套 JavaScript 实现里的 NLA/CredSSP 逻辑是从经过生产验证的 Rust 参考实现逐段移植过来的。入口与模块导出createClient / createServer整个rdp包的对外入口是 rdp/index.js它只做一件事把协议层封装成两个工厂函数并导出var protocol require(./protocol); module.exports { createClient : protocol.rdp.createClient, createServer : protocol.rdp.createServer };对应实现位于 rdp/protocol/rdp.jscreateClient(config)返回一个RdpClient实例基于 Node 的EventEmitter通过util.inherits继承事件能力见 rdp/protocol/rdp.js 第 82-204 行createServer(config, next)内部调用net.createServer为每个 TCP 连接构造一个RdpServer第 360-377 行。服务端模式要求配置中必须携带key和certTLS 密钥与证书否则会直接抛出FatalError(NODE_RDP_PROTOCOL_RDP_SERVER_CONFIG_MISSING)。RDP 协议栈的分层架构RDP 是一个高度分层的协议。从 rdp/protocol/rdp.js 中RdpClient构造函数的初始化代码第 82-135 行可以清晰地看到完整的协议栈装配顺序this.bufferLayer new layer.BufferLayer(new net.Socket()); this.tpkt new TPKT(this.bufferLayer); this.x224 new x224.Client(this.tpkt, config); this.mcs new t125.mcs.Client(this.x224); this.sec new pdu.sec.Client(this.mcs, this.tpkt); this.cliprdr new pdu.cliprdr.Client(this.mcs); this.global new pdu.global.Client(this.sec, this.sec);这对应 RDP 标准的分层模型各层职责如下层源码模块职责传输层rdp/core/layer.js基于net.Socket的BufferLayer提供expect(n)/sendBuffer()等字节流原语是上层所有模块共用的传输抽象TPKTrdp/protocol/tpkt.js负责 RDP 报文的分帧/组帧。文件开头的Action枚举区分 Fastpath0x0与标准 X.2240x3两类报文见 rdp/protocol/tpkt.js 第 30-33 行X.224rdp/protocol/x224.js会话层。定义了连接请求0xE0、连接确认0xD0、断开请求0x80、数据0xF0、错误0x70等 TPDU 类型第 29-35 行并承载安全层协商MCS / GCCrdp/protocol/t125/多路复用层。mcs.js管理信道分配与域内连接gcc.js定义了客户端核心数据屏幕分辨率、键盘布局等的编码安全层rdp/protocol/pdu/sec.js处理 RDP 安全机制包括凭据信息InfoPacket、性能标志、以及 NLA 完成后的会话密钥接管PDU 层rdp/protocol/pdu/业务数据单元data.js位图、输入事件、cliprdr.js剪贴板重定向、global.js能力集/控制/输入 PDU 的分发等辅助模块rdp/core/、rdp/security/、rdp/asn1/提供 RLE 位图解压rle.js调用 C 编译产物、流式类型读取type.js、日志/错误、X.509 证书解析与 RSA 加解密、BER/ASN.1 编解码值得一提的是 rdp/core/type.js 中的Stream类型体系——每一层通过transport.expect(n)声明我需要 n 字节数据到达后由type.*类型如UInt8、UInt16LE顺序解析字段形成一种流式的、非阻塞的分层解码范式。TPKT、X.224、NLA等模块的recvHeader → recvData状态推进都建立在这一机制之上。连接建立流程客户端调用RdpClient.prototype.connect(host, port)rdp/protocol/rdp.js 第 211-219 行后TCP 连建立即在X.224 层发起连接先发连接请求 TPDU 并携带安全协商块Protocols枚举中定义了PROTOCOL_RDP/PROTOCOL_SSL/PROTOCOL_HYBRID/PROTOCOL_HYBRID_EX见 rdp/protocol/x224.js 第 49-54 行随后进入 MCS 连接序列、安全层交换最终由pdu.global触发connect事件此时RdpClient.connected置为true第 166-168 行。NLA从 Rust 移植到 JavaScript 的认证核心NLA 是本文档强调的最大改造点。它让 RDP 客户端在建立会话前通过CredSSP 协议向服务器证明身份——即使服务器尚未发送自己的证书客户端也已完成认证从而有效抵御中间人攻击。实现集中在 rdp/protocol/nla.js。状态机与消息封装NLA构造函数第 12-49 行会接管底层传输保存原有data/close/error监听器并暂时移除改为由 NLA 模块驱动。认证完成后第 149-161 行再把旧监听器重新挂回无缝交还控制权。整个 NLA 过程是一个三状态的状态机this.state状态 1收到服务端 TSRequest内含 NTLM challenge读取 challenge 消息构造TSAuthenticate携带 NTLMv2 响应与用客户端密钥加密的公钥并发送状态 2收到第二段 TSRequest解开其中被加密的服务器公钥与本地保存的服务器证书公钥比对——不一致即判定中间人攻击并断开第 131-133 行RDP man-in-the-middle detected.随后构造TSAuthInfo内含TSPasswordCreds即加密的域/用户名/密码三元组发送状态 3认证完成调用nlaCompletedFunc()交还传输控制权。DER 封装的构造与解析全部使用node-forge的 ASN.1 工具完成rdp/protocol/nla.js 第 188-209 行sendNegotiateMessage、第 485-547 行create_ts_authinfo/create_ts_credentials/create_ts_authenticate。NTLMv2 响应计算认证的密码学核心是 NTLMv2。关键函数rdp/protocol/nla.js 第 276-311 行包括ntowfv2(password, user, domain)先用 MD4 哈希密码的 Unicode 形式再以user.toUpperCase() domain为 key 做 HMAC-MD5得到 NTLMv2 响应密钥compute_response_v2(...)结合服务器 challenge、客户端随机 challenge、时间戳与目标信息生成 NT/LM challenge response 与会话基础密钥kx_key_v2/rc4k用 RC4 加密随机会话密钥完成密钥交换sign_key/seal_key基于微软定义的magic constant字符串派生签名与密封密钥构建build_security_interface第 392-426 行提供gss_wrapex/gss_unwrapex对后续消息加密、签名与防篡改校验。内置单元测试nla.js 文件末尾内置了unitTest()函数第 640-719 行对negotiate_message报文格式、MD4、Unicode 转换、HMAC-MD5、NTOWFv2/LMOWFv2、compute_response_v2三组输出、RC4 加解密、sign_key/seal_key、消息签名、challenge 消息、create_ts_authenticate、create_ts_credentials、create_ts_authinfo等十余项密码学原语逐一与已知正确的字节序列比对。这套固定向量测试既保证了 NLA 移植的正确性也为后续修改提供了回归保障。Node.js 兼容性改造MD4/RC4 的自研回退实现README 中提到为最新版 Node 更新其具体痛点清晰体现在 rdp/protocol/nla.js 第 276-312 行的两处注释里Built in NodeJS MD4, this does not work starting with NodeJS v17/Built in NodeJS RC4, this does not work starting with NodeJS v17自 Node.js 17 起OpenSSL 移除了 MD4 与 RC4 等弱算法crypto.createHash(md4)与crypto.createCipheriv(rc4, ...)会直接抛错。该分支因此提供了双保险策略function md4(buffer) { try { return crypto.createHash(md4).update(buffer).digest(); } catch (ex) { return Buffer.from(require(../security/md4).array(buffer.toString(binary))); } }优先尝试 Node 内置crypto旧版本 Node 上性能更好失败后回退到仓库自研实现 rdp/security/md4.js 与 rdp/security/rc4.js。同时rdp/security/ 目录还提供了自实现的 X.509 证书解析rdp/security/x509.js基于 rdp/asn1/ 实现 RFC 5280 的 ASN.1 结构与 RSArdp/security/rsa.js依赖 rdp/security/jsbn.js 大数运算加上 rdp/core/rle.js 的位图 RLE 解压使得 RDP 栈在移除大部分外部依赖后依然功能完整。客户端 API配置参数、事件与输入方法完整配置项createClient(config)接受一个配置对象所有字段及其语义如下对应 rdp/protocol/rdp.js 第 82-135 行配置项类型说明domainstringWindows 域写入 InfoPacketUnicode 编码并以\x00结尾userNamestring登录用户名passwordstring登录密码workingDirstring登录后的初始工作目录alternateShellstring替代 Shell默认资源管理器perfFlagsint直接指定性能标志位不设置时由enablePerf决定enablePerfboolean为true时自动组合禁用墙纸、菜单动画、光标阴影、主题与整窗拖拽等 5 项性能优化标志PERF_DISABLE_*autoLoginboolean置位INFO_AUTOLOGON指示服务器跳过登录界面直接登入screen.width/screen.heightint桌面分辨率写入 MCS 客户端核心数据desktopWidth/desktopHeightlocalestring浏览器语言标签如en-GB、de-AT、fr-CH用于映射键盘布局。映射表覆盖阿拉伯语、德语、法语、中文等多国布局查找顺序为完整标签 → 语言前缀 → 默认 US第 141-158 行logLevelstring日志级别INFO等映射到 rdp/core/log.js 的Levels默认INFOdecompressboolean为true时对服务器发来的压缩位图BITMAP_COMPRESSION标志在客户端本地用 RLE 解压后再触发bitmap事件第 176-197 行事件模型RdpClient是EventEmitter对外发出的事件第 164-201 行connect会话建立成功connected置位session服务器端会话就绪close连接关闭pointer光标变化携带cursorId与光标数据bitmap屏幕位图更新事件载荷包含destTop/destLeft/destBottom/destRight目标矩形、width/height、bitsPerPixel、isCompress与像素dataclipboard来自服务器的剪贴板内容经cliprdr通道error非致命错误FatalError则直接抛出。输入与交互方法连接建立后可通过以下方法向远程桌面注入交互rdp/protocol/rdp.js 第 239-349 行client.sendPointerEvent(x, y, button, isPressed); // 鼠标button 1/2/3其余值视为移动 client.sendKeyEventScancode(code, isPressed, extended); // 键盘硬件扫描码extended 标记扩展键 client.sendKeyEventUnicode(code, isPressed); // 键盘Unicode 码点 client.sendWheelEvent(x, y, step, isNegative, isHorizontal); // 滚轮step 与 WheelRotationMask 做位与 client.setClipboardData(content); // 向远端写入剪贴板 client.close(); // 关闭会话走 global.close 正常下线这些方法内部统一构造对应的 PDU 事件通过this.global.sendInputEvents([event])批量发送所有方法在未连接!this.connected时都会安全地直接返回。位图渲染与输入编码涉及的标志位PointerFlag、KeyboardFlag、BitmapFlag、InfoFlag、PerfFlag均定义在 rdp/protocol/pdu/ 各文件中。许可边界与可移除性rdp/README.md 末尾明确了许可约束node-rdpjs 的许可证为 GPL 3.0且仅限于 rdp 文件夹。这意味着 MeshCentral 其余部分并不受 GPL-3.0 传染。如果部署方对 GPL-3.0 有顾虑可以直接删除rdp目录——MeshCentral 仍能完整运行仅失去 RDP 远程桌面功能对应的浏览器端 RDP 入口 public/mstsc/ 与相关 public/scripts/agent-rdp-0.0.1.js 等链路将不可用。这一即插即拔设计保证了项目的许可合规灵活性。小结与延伸阅读rdp/目录是 MeshCentral 中一个自包含、可独立移除的 RDP 协议实现它以 node-rdpjs v0.2.1 为基线通过自研 MD4/RC4/X.509/RSA/ASN.1 组件消除了对弱算法 API 的依赖、兼容现代 Node.js并通过移植 RDP-RS 的 NLA/CredSSP 逻辑补上了现代 Windows 强制要求的网络层认证。其分层清晰TPKT → X.224 → MCS/GCC → 安全层 → PDU测试完备NLA 模块内置固定向量单测API 简洁一个配置对象 事件 输入方法。深入阅读建议按此顺序先看 rdp/README.md 与 rdp/index.js 把握模块定位再通读 rdp/protocol/rdp.js 理解栈装配与 API随后按 rdp/protocol/tpkt.js → rdp/protocol/x224.js → rdp/protocol/t125/ 逐层深入最后精读 rdp/protocol/nla.js 的密码学实现许可文本见 rdp/LICENSE。若需要在此基础上二次开发如增加 TLS 证书校验、扩展剪贴板格式、接入 WebSocket 传输上述分层结构提供了清晰的扩展点。赞分享后端运维【免费下载链接】MeshCentralA complete web-based remote monitoring and management web site. Once setup you can install agents and perform remote desktop session to devices on the local network or over the Internet.项目地址https://gitcode.com/gh_mirrors/me/MeshCentral点击查看免费下载相关推荐Jumpserver RDP连接支持NLA认证的配置指南Jumpserver RDP连接支持NLA认证的配置指南 问题背景 在企业环境中Windows服务器的远程桌面协议 RDP 通常要求启用网络级别身份验证 NL后端认证鉴权运维应用安全合规审计Gitea协议支持多种Git协议深度解析Gitea协议支持多种Git协议深度解析 前言 你是否曾经在搭建自托管Git服务时为选择哪种Git协议而犹豫不决或者在使用Gitea时想要深入了解其支持后端代码托管版本控制研发协作代码评审缺陷追踪项目管理CI/CDbRPC多协议支持深度剖析bRPC多协议支持深度剖析 bRPC作为工业级RPC框架在HTTP/HTTPS、HTTP2、gRPC、Redis/Memcached以及RTMP/FLV/HLRPC框架后端微服务网络通信上一篇Visual C运行库修复工具5分钟快速修复Windows软件启动错误的完整方案下一篇ExternalDNS 命令行 Flags 完全指南从自动生成机制到全量参数详解创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表