1仕組みと動作原理
「接続タイプ」に基づいて最初に分岐し、その後に証拠を収集します。AVD/WVD/W365 は「Connection Info」パネル + ゲートウェイヘルスチェック + Shortpath ログを使用します。直接 PC 接続には同パネルが存在しないため、まず RDP プロトコルプローブを実行してサーバーの稼働を証明し、その後にクライアント側の ID/ログを調査します。この分岐により、次に収集すべき証拠が決定されます。
| Scenario | Key Characteristic | Primary Evidence Source | |---|---|---| | **AVD/WVD/W365** | User connects to a cloud desktop through a workspace/gateway | Connection Info panel, gateway health checks, UDP Shortpath logs | | **Direct PC** | User connects to a named PC by hostname or IP (e.g., a home workstation) | RDP protocol probe, Windows App log auth chain, Windows-side reboot events |
中核となる証拠収集手法は Windows App クライアントログの解析です。トランスポートネゴシエーションの詳細は「いかなるネットワーク層テストでも判明しない」ため、本スキルにとって代替不可能な情報源となります。
This is the most critical step. Windows App logs contain transport negotiation details that no network-level test can reveal.
付属のプローブスクリプトは、「認証情報不要」の手法でサーバー側 RDP スタックの正常性を証明します。X.224 Connection Request + RDP_NEG_REQ を送信し、RDP_NEG_RSP を解析してネゴシエートされた暗号化プロトコルを取得した上で、同一ソケットを TLS にアップグレードします。
RDP_NEG_REQ_PACKET = bytes.fromhex("030000130ee000000000000100080003000000")
プローブは意図的に TLS 証明書検証を無効化しており、その理由と限界がドキュメントに明記されています。目的は「サーバーが TLS を受け入れること」の確認であり、サーバーの認証ではありません。
> **Note on TLS verification:** The probe intentionally disables certificate verification so it can confirm the RDP stack accepts TLS even with self-signed or domain-issued certificates. It does not authenticate the server. For a full certificate audit, use a separate TLS inspection tool.
診断原則として「まずクライアント側かサーバー側かを証明する」ことを要求します。プローブが成功した場合はクライアント側(認証/アプリ状態/プロキシ/ID)、失敗した場合はサーバー側またはネットワークの問題となります。これにより、二元的な原因帰属を実行可能な成否判定基準に落とし込みます。
A successful probe reports `RDP server <host>:<port> is reachable and healthy (RDP + TLS).` and means the problem is **client-side** (auth, app state, proxy, or identity). A failed probe means the problem is **server-side or network** (PC off, firewall, port unreachable, TLS interception).
6 種類の根本原因を対照可能な証拠シグネチャ表(VPN/プロキシ干渉、ISP の UDP 制限、クライアントヘルスチェック失敗、サーバー側 Shortpath 未有効化、クライアント ID/アカウント汚染、サーバー再起動)として整理し、各カテゴリに「証拠 → 修正 → 検証」の 3 段階を提供します。
#### Category E: Client Identity / Expired Microsoft Account Poisoning (Direct PC and AVD)
検証段階では、単に「接続できたか」だけでなく、クライアントの挙動に関する証拠の確認を求めます。ログに入力イベントが記録され、UserCancelled(8) が再発しないことが条件となります。
2. The Windows App log for the new session should show mouse/keyboard input events (`IHAddMouseEventToPDU`, `IHAddKeyboardEventToPDU`) and no `UserCancelled(8)` errors.
2コア機能
3外部依存関係
| Kind | Dependency / Endpoint |
|---|---|
| cli | python3(运行自带 RDP 探针与文档内联的 STUN 检测脚本) |
| cli | macOS 网络工具(ifconfig / netstat / scutil / lsof / ps / env / tailscale) |
| cli | grep(日志模式提取,文档给成套 grep -E 模板) |
| cli | ssh + PowerShell -EncodedCommand(经 WSL/Tailscale 到 Windows 主机取证) |
| cli | curl(读 ShadowRocket 配置 API 以核对代理状态) |
| api | Azure Virtual Desktop 网关/工作区端点(日志中出现,用于 DIRECT 规则配置示例) |
| network | STUN 公共服务器(测试 UDP 是否被 ISP 封锁) |
| network | 目标 RDP 主机(用户指定的 host:3389 或自定义端口,探针与日志分析的对象) |
| network | Windows 侧 RDP 主机(经 SSH/Tailscale 执行 PowerShell 取证) |
| network | Tailscale(netcheck/status,用于 NAT 类型与 UDP 能力评估) |
4推奨統制措置と判定根拠
- scripts/: ローカルスクリプトまたはコマンドの実行: python3 scripts/probe_rdp_server.py <host> [port](リポジトリ内包。対象ホストへの TCP 接続 + RDP プローブを実行)
- 网络端点: 外部ネットワークアクセスの宣言: ユーザー指定の RDP ホスト:3389(またはカスタムポート)への TCP 接続、RDP ネゴシエーションパケットの送信、および TLS へのアップグレード
5二重目の独立検証
- [ok] 探针「无凭据」声明是否有反例(是否真的不读认证材料) — 反例检索失败:probe_rdp_server.py 的 import 为 socket/ssl/struct/sys/typing,无 os.environ/getenv、无 open()、无 keychain 调用;全流程是 create_connection → sendall(19 字节固定握手包) → recv → wrap_socket。凭据类 token 在全目录 grep(password/token/secret/api_key/credential)除文档描述「认证失败」的语义词外零命中。声明成立。
- [ok] TLS 校验关闭是否为「未交代的松绑」 — 已充分交代:代码内注释 'We intentionally disable verification because the diagnostic goal is to confirm the RDP stack accepts TLS, not to validate the certificate chain.';reference 内有专门引用块说明 'The probe intentionally disables certificate verification... It does not authenticate the server. For a full certificate audit, use a separate TLS inspection tool.'。属有意识、有边界说明的设计,不是隐藏降级。已记入 security.injection_surface 与 grade.reason。
- [ok] 是否漏记外发目标(域名/IP 全量回查) — 提取结果:stun.l.google.com:19302、stun1.l.google.com:19302、rdweb.wvd.microsoft.com、<prefix>-rdgateway-r1.wvd.microsoft.com、*.wvd.microsoft.com(DIRECT 规则示例)、13.104.0.0/14(IP-CIDR 示例)、<local-ip>:8080(ShadowRocket 配置 API)、<host>:3389(用户指定目标)。均已归入 external_deps 的 12 个条目;无未记载的隐蔽外发。
- [ok] frontmatter 的 allowed-tools 声明与文档行为是否一致 — 声明为 `allowed-tools: Read, Grep, Bash`。文档要求的动作是:读日志(Read/grep)、跑 ifconfig/netstat/scutil/lsof/tailscale/ps(Bash)、跑探针与内联 python(Bash)——全部落在声明范围内;且文档不要求写文件(无 chmod/编辑配置/生成文件的步骤,AVD 的 DIRECT 规则是以「给用户的修法」形式给出,由用户在代理工具里配置,而非本 skill 直接改配置)。声明与行为一致,且比同仓库的 tunnel-doctor(含 Edit)更保守。
- [ok] 是否有未实现的宣称(能力 vs 文档) — 逐项抽查成立:承诺「分析传输协议选择」→ 有 Connection Info 字段表与日志 FetchClientOptions/WebRTC 条目;承诺「解析日志找 Shortpath 失败」→ 有日志模式→含义对照表与 GUID 聚合方法;承诺「解决卡在 Configuring remote PC」→ 有 Category E 完整签名集与修复步骤;承诺「检测 VPN/代理干扰」→ 有 198.18.0.x、STUN/TURN routed through VPN 的判据与 DIRECT 规则修法。均有对应实现/流程支撑,未见夸大。
- [ok] 文档内部是否存在自相矛盾(如是否同时建议放宽校验又不建议) — 抽查与 tunnel-doctor 类似的张力点:本 skill 未出现 ssh -o StrictHostKeyChecking=no;唯一放宽是探针的 CERT_NONE,且被解释为「验证服务端接受 TLS」的必需手法并有明确局限说明。未发现未消解的内部矛盾。
- [ok] pin commit 与 skill.path 是否与任务书表格一致 — git rev-parse HEAD = d5c4678cb5d4fd6acc9c922690df035dbd33d247,与任务书表格『库内 HEAD』逐字一致;目录位于仓库根,相对路径 windows-remote-desktop-connection-doctor;本目录最后一次提交 878f947(2026-09-07)。GitHub API 复核 MIT / stars 1392 / pushed 2026-09-15T09:30:04Z。
- [ok] evidence 逐字性是否经磁盘级复核 — 【evidence 逐字性校正】首稿该条 quote 把源码第 152 行的 grep 模板截断且过度转义(把 `\|` 写成 `\\|`),导致未与源文逐字匹配;已改为源码中的真实前缀(截到 `"$LATEST_LOG"` 为止,避开后续含反斜杠的 `grep -v` 段)。该 grep 模板确实存在,结论未变,属引用精度问题。
6結論
c5c2e8a79a426da5…