← Back to Blog
Journal

moshの内部動作とセキュリティ――なぜ接続が切れないのか

moshSSHネットワークセキュリティUDP暗号インフラ

はじめに

SSHで作業中にノートPCのスリープから復帰したら、セッションが固まっていた――リモート開発をする人なら誰もが経験する場面です。mosh(mobile shell)は、この「切れる」「固まる」問題を正面から解決するリモートシェルです。Wi-Fiから4G回線へ切り替わっても、IPアドレスが変わっても、セッションは生き続けます。

本記事では、moshがなぜ接続を切らさないのかを、その中核であるSSP(State Synchronization Protocol)の設計から読み解きます。あわせて、moshが採用する暗号方式と、root権限を持たないという設計判断がもたらすセキュリティ上の含意を、原著論文と公式資料に基づいて整理します。

背景・課題

SSHが「切れる」のは、その土台にあるTCPの性質に由来します。TCPコネクションは送信元・宛先のIPアドレスとポート番号の4つ組で識別されるため、クライアントのIPアドレスが変わるとコネクションは成立しなくなります。モバイル環境では、回線の切り替えやNAT再割り当てによってIPアドレスが頻繁に変化するため、これは致命的です。

加えてSSHは、TCPのバイトストリームの上で端末をやり取りします。高遅延な回線では、1文字打つたびにサーバーからのエコーを待つことになり、入力が引っかかるように感じられます。moshの原著論文(Winstein & Balakrishnan, 2012)は、商用のEV-DO(3G)回線において、SSHのキーストローク応答遅延の中央値が503msだったと報告しています。半秒の遅延は、対話的な操作では明確に体感できる遅さです。

moshはこの2つの課題――「IP変化への脆弱さ」と「高遅延での操作性」――を、TCPを捨てて独自のUDPベースプロトコルを設計することで解決しました。

本論

バイトストリームではなく「画面の状態」を同期する

moshの最大の発想転換は、同期する対象をバイトストリームから「画面の状態(スクリーン)」に変えた点にあります。moshはクライアントとサーバーの双方で端末エミュレータを動かし、現在の画面スナップショットを保持します。公式サイトの表現を借りれば、問題は「クライアントを、可能な限り効率的に最新のサーバー側スクリーンへ到達させる」という状態同期の問題へと帰着します(mosh.org)。

これを担うのがSSP(State Synchronization Protocol)です。SSPはUDP上で2つのオブジェクトを同期します。クライアントからサーバーへは「ユーザーが打鍵したキー列」を、サーバーからクライアントへは「現在のスクリーン状態」を同期します(mosh.org)。重要なのは、ネットワークを流れるのが「差分(diff)」だという点です。各データグラムは、番号の付いた元状態から目標状態への差分を表します。

冪等性とシーケンス番号

SSPの安全性は冪等性(idempotency)の原則に支えられています。各データグラムは番号付きの状態間の差分であり、受信側で何度適用しても結果が変わりません。各データグラムには増加するシーケンス番号が付与され、これによってリプレイ(再送)攻撃への耐性と、古いパケットの安全な破棄が両立します(Winstein & Balakrishnan, 2012)。

データグラムはAES-128のOCB3モードで暗号化・認証されます(mosh.org)。OCB3は、機密性と完全性(認証)を1パスで同時に提供するAEAD(認証付き暗号)方式で、RFC 7253として標準化されています(Krovetz & Rogaway, 2014)。つまり、暗号化されていない、あるいは改ざんされたパケットは、そもそも受理されません。

ハートビートによるステートレス・ローミング

IPローミングの仕組みはシンプルです。クライアントは増加するシーケンス番号を付けてデータグラムを送り続け、無通信時でも少なくとも3秒に1回「ハートビート」を送ります。サーバーは、これまで受け取った中で最大のシーケンス番号を上回る正規(認証済み)パケットを受信するたびに、その送信元IPアドレスを新たな送信先として採用します(mosh.org)。

サーバー側に「現在のクライアントIPはこれ」という固定的な登録情報を持たせず、認証済みパケットの送信元から動的に学習する――この「ステートレス」な設計により、ローミングはNATの内外をまたいでも機能します。それ自体が移動するNATの背後であっても動作する、と論文は述べています(Winstein & Balakrishnan, 2012)。

投機的ローカルエコーで体感遅延を消す

高遅延対策として、moshはクライアント側でサーバーの挙動を予測します。各キーストロークはカーソル位置にエコーされるはずだ、backspaceや矢印キーは従来通りの効果を持つはずだ、と仮説を立てて先回りで画面に反映します。ただし、サーバーからの確認が取れた予測だけを確定表示する、という慎重な設計です(mosh.org)。論文によれば、moshはユーザーのキーストロークの70%を即座に表示でき、前述のEV-DO回線における応答遅延の中央値はSSHの503msに対し5ms未満でした(Winstein & Balakrishnan, 2012)。

実践への応用・考察

moshの設計は、セキュリティの観点でも示唆に富みます。moshはまずSSHでログインして認証を済ませ、そのSSH接続を使ってリモートでmosh-serverを起動し、AESセッション鍵を共有したうえでUDP(既定では60000〜61000番ポート)に切り替えます(mosh.org)。認証はSSHに委ね、自前で認証機構を作らない点がまず堅実です。

さらに本質的なのは権限モデルです。mosh-serverは接続を待ち受ける常駐デーモンではなく、ログインしたユーザー自身のプロセスとして起動し、root権限のコードを一切含みません(GitHub: mobile-shell/mosh)。これは、SSHやHTTPSのサーバー実装が繰り返し悩まされてきた権限昇格やリモートroot奪取という脆弱性のクラスを、構造的に回避することを意味します。ユーザー同士はカーネルによって分離され、別ポートで動くため互いに干渉しません。

実際、公式サイトは2022年10月時点で「過去10年間、moshにはいかなる種類のセキュリティ脆弱性も報告されていない」と記しています(mosh.org)。もっとも、これは「攻撃対象領域(アタックサーフェス)が小さい設計」がもたらした結果であって、moshを使えば自動的に安全になるという話ではありません。認証の強度は依然としてSSH側の設定(公開鍵認証の徹底など)に依存します。筆者の運用経験でも、moshは踏み台越しの長時間セッションで安定して有用ですが、SSHの鍵管理を疎かにしてよい理由にはなりません。

まとめ

  • moshは画面の状態を同期するSSPにより、TCPのIP依存と高遅延の問題を回避する。
  • データグラムはAES-128 OCB3(RFC 7253)で暗号化・認証され、シーケンス番号がリプレイ耐性を与える。
  • 3秒ごとのハートビートと「送信元IPを動的採用する」ステートレス設計が、NAT越しのローミングを可能にする。
  • mosh-serverはroot権限を持たないため、権限昇格脆弱性のクラスを構造的に回避できる。
  • ただし認証はSSHに依存するため、鍵管理の重要性は変わらない。

次に長時間のリモート作業をするときは、mosh user@host を試し、ノートPCを一度閉じてから開いてみてください。セッションが何事もなく生きていることが、SSPの設計の確かさを実感させてくれるはずです。

参考文献

学術論文

公式ドキュメント