Go WebAssemblyとgrdpで作られたWebベースのRDPクライアント
(github.com/nakagami)- ブラウザだけでWindowsリモートデスクトップに接続できるWebベースのRDPクライアントで、プラグインなしで動作する
- ブラウザ側のGo WebAssemblyとサーバー側のWebSocket-to-TCPプロキシを分離し、ブラウザが直接開けないRDPのTCP接続を代わりに処理する
- 接続は
Browser -> WebSocket -> proxy -> TCP -> RDP Serverの流れで行われ、接続後はリモート画面がcanvasに表示され、キーボード・マウス入力を転送する - 入力デバイスはRDP scan codesベースのキーボードと、移動・クリック・ホイールを含むマウスをサポートし、リモートオーディオはRDPSNDで受信してWeb Audio APIで再生する
- すべてのoriginを許可するプロキシ構成のため、信頼できるネットワークでのみ実行するか、外部公開前にHTTPS/WSSと認証レイヤーを併設する必要がある
プロジェクト概要
- ブラウザからプラグインなしで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/