grdpwasm - WebベースのRDPクライアント
(github.com/nakagami)- ブラウザだけでWindowsリモートデスクトップに接続できる WebベースのRDPクライアント で、pluginなしで 動作する
- ブラウザの Go WebAssembly とサーバー側の WebSocket-to-TCPプロキシ を分離し、ブラウザが直接開けないRDP TCP接続を代わりに処理する
- 接続は
Browser -> WebSocket -> proxy -> TCP -> RDP Serverの流れで続き、接続後はリモート画面が canvas に表示され、キーボード・マウス入力を転送する - 入力デバイスは RDP scan codes ベースのキーボードと、移動・クリック・ホイールを含むマウスをサポートし、リモートオーディオは RDPSND で受け取り Web Audio API で再生する
- すべての origin を許可するプロキシ構造のため、信頼できるネットワーク でのみ実行するか、外部公開前に HTTPS/WSSと認証レイヤー を併設する必要がある
プロジェクト概要
- ブラウザで pluginなしで Windowsリモートデスクトップに接続する WebベースのRDPクライアント として動作する
- 実装は Go WebAssembly と grdp の組み合わせで構成され、ブラウザ実行部とプロキシ中継部が分離された構造を持つ
- ブラウザは raw TCP ソケットを直接開けないため、WebSocket接続をRDPサーバーのTCPポートへつなぐ 軽量Goプロキシ があわせて必要になる
アーキテクチャと動作方式
- 全体の経路は
Browser (WASM) -> WebSocket -> proxy (Go) -> TCP -> RDP Serverの順で構成される - ブラウザでは WASMバイナリ が実行され、プロキシは WebSocket-to-TCP ブリッジと静的ファイルサーバーの役割を兼ねる
make allの成果物は、ブラウザで実行されるstatic/main.wasm、Goランタイム支援ファイルstatic/wasm_exec.js、プロキシサーバーproxy/proxyに分かれる- この構造により、ブラウザ側は標準Web技術で接続を処理し、RDPサーバーとの実際のTCP通信はプロキシが担う
利用の流れとユーザーインターフェース
- ブラウザで
http://localhost:8080を開き、接続フォームに Host, Port, Domain, User, Password, Width, Height の値を入力して Connect を押すとセッションが開始される - Port のデフォルト値は
3389で、Domain はローカルアカウントを使う場合は空欄のままでよい - 接続が完了するとリモートデスクトップが canvas に表示され、キーボード入力を受け取るには canvas をクリックする必要がある
- Disconnect を押すとセッションが終了する
入力デバイスとオーディオ対応
- 標準キーボード入力はすべて RDP scan codes を通じてリモートデスクトップへ転送される
- マウスは移動、ボタンクリック、スクロールホイールまでサポートする
- キーボードイベントを転送するにはブラウザタブがフォーカスを持っている必要があり、キー入力が止まった場合は canvas 領域を再度クリックする必要がある
- リモートオーディオは RDPSND でストリーミングされ、ブラウザでは Web Audio API により再生される
- オーディオ形式は PCM 44100 Hz, stereo, 16-bit signed little-endian と明記されている
動作条件とセキュリティ上の注意点
- 要件は Go 1.24以上 とアクセス可能なRDPサーバー1台で、対象サーバーは Windows または RDP互換ホストであればよい
- プロキシはすべての origin からの接続を許可するため、信頼できるネットワーク でのみ実行するか、インターネット公開前に認証レイヤーを追加する必要がある
- 資格情報はブラウザからプロキシへ WebSocket 経由で渡されるため、信頼できないネットワークでは HTTPS/WSS の利用が必要になる
- README には TLS終端型 reverse proxy として nginx や Caddy を置く方式も記載されている
実行方法と補足情報
- 実行は
make serveまたは./proxy/proxy -listen :8080 -static staticの形で可能 - プロキシオプションは
-listenで受信アドレスとポートを、-staticで静的ファイルディレクトリを指定する - 開発用ターゲットは、WASMだけを再ビルドする
make wasm、プロキシだけを再ビルドするmake proxy、wasm_exec.jsを更新するmake wasm_exec、成果物を削除するmake cleanに分かれる - ライセンスは GPLv3 で、grdp LICENSE への参照も付いている
2件のコメント
でも、正直なところ本当の利点が分からないのですが。
結局ただのクライアントにすぎないので、サーバー側で何らかの要件を強制できるわけでもないですし、
純粋にブラウザだけでアクセスできるわけでもないですし
Hacker Newsのコメント
かなり良さそう。セッション記録とSSO認証対応まで入れば、RDPジャンプホストとしてそのまま使えそう
Azure Bastionで似たような使い方をしたことがあるが、テナントに設定された認証方式でAzureポータルにログインしたあと、ブラウザからVMへRDP接続し、VM側のローカルアカウントでログインすればよい。ファイルとクリップボードの扱いもかなり良く、ブラウザ内でコンソールセッションにも対応している
Windows/RDP側では試していないのでできるかは分からないが、GCPのブラウザSSHはこれまで見た中でも特によくできていた
Linuxでも、ときにはxrdpが他の代替手段より良いと感じた
これが解決する大きな価値の1つは、VM/サーバーの管理インターフェースの分離だ。Webサーバーの管理サービスをHTTPサービスと同じIP/ドメイン/インターフェースに置かないだけでも、セキュリティは大きく向上する
ブラウザRDPではクリップボードが地味な悪夢。ワイヤプロトコルのネゴシエーション自体はうまくいくが、ブラウザ側のClipboard APIは権限とユーザージェスチャー要件に縛られている
読み取り側は、ほとんどのブラウザがほぼ毎回ユーザー確認を求める。なのでページ内に別のクリップボードバッファを作るか、あるいはRDP内への貼り付けはスムーズでも、RDP外へコピーして持ち出すときは毎回クリックを受け入れるしかない
どちらも、人々がWeb RDPクライアントに期待する挙動とはかけ離れている。native mstscと同等だと見る前に、ChromeとFirefoxでどう違うかは必ず確認したほうがいい
HPがAnyware / Teradici / PCoIPを畳み、代替を探す人がかなり増えた。高解像度マルチモニター、60fps、高ビット深度再生、Wacomタブレット対応、そして3つのOSすべてをサポートすることが特に求められている
有料ではParsecやDCVがあり、オープンソースの試みは歓迎したい。rustdesk、kyber、teraguchiのようなプロジェクトがあり、コミュニティには高性能なオープンソースの選択肢がぜひ必要だと思う
https://github.com/rustdesk/rustdesk
https://github.com/thedepartmentofexternalservices/teraguchi
https://kyber.tech/
面白そうではあるが、最も重要な機能に触れられていないのが意外。クリップボード共有が実際どれほどうまく動くのか気になる
クリップボード共有、共有ドライブ経由のアップロード/ダウンロードはFreeRDPの機能なので、比較的そのまま活用できる
そしてセッション録画はPAM環境では妥協できない
[1] https://adaptive.live
デスクトップスケーリング、マルチモニター対応、ファイル転送、ドライブリダイレクト、周辺機器リダイレクトもすべて重要だ
CyberArk PAMから受け取ったRDPファイルを開くときにも、これが動くのか気になる
ブラウザタブ内でAlt-TabをRDPクライアントが横取りできるのかも気になる
以前、GuacamoleのブラウザRDPで最大の問題がそれだった
技術的には興味深いが、ほぼすべてのプラットフォームにnative RDPクライアントがすでにあるので、そもそもなぜ必要なのかはよく分からない
https://guacamole.apache.org/