概要
iOSアプリのMoshiを使って、Windows上のWSL2にMosh接続し、iPhoneからClaude Codeを操作できるようにした。SSHだとネットワークが切れるとセッションが死ぬが、Moshなら接続が維持される。セットアップに注意点がいくつかあったので、そのまとめ。

背景
自分はWindowsマシンを個人の開発サーバーとして使い始めている。特に最近Claude Codeをよく使うようになり、iPhoneからもターミナルを操作したいと考えた。
普通のSSH接続だと、Wi-Fiの切り替え、スリープ、移動中のネットワーク変動などで接続が切れる。接続が切れるとセッションごと消える。Claude Codeで長時間のタスクを走らせている最中にこれが起きると困る。
実際にSSHサーバーをセットアップして電車の中から使ってみたが、Xやinstagramを見てから戻ると接続が切れている。Claude Codeに大きなタスクを投げても、ちょっとアプリを切り替えただけですぐ失われてしまう。
そこでMoshiというiOSアプリに出会った。Moshプロトコルによるネットワーク耐障害性のある接続ができるアプリで、これが解決策になった。
Moshiとは
MoshiはiOS向けのターミナルアプリ。AIコーディングエージェント(Claude Codeなど)をモバイルから使うためのターミナルとして設計されている。
主な特徴は以下。
- Moshプロトコルによるネットワーク耐障害性(Wi-Fi切替、スリープ、移動中でもセッション維持)
- Face IDでSSHキーを保護
- tmuxのネイティブ統合
- タスク完了時の通知
- Nord、Dracula、Solarizedなどのテーマ
- Ctrl、Esc、矢印キー付きの専用キーボード
- App Storeで4.9/5の評価、無料
WSLとWSL2の違い
まずWSLとWSL2の違いを整理しておく。名前が似ているが、内部のアーキテクチャはまったく別物。
| WSL1 | WSL2 | |
|---|---|---|
| カーネル | 変換レイヤー(LinuxのシステムコールをWindows NTカーネルに変換) | 本物のLinuxカーネル(軽量VM上で動作) |
| ファイルI/O | Windowsファイル(/mnt/c/)が高速 | Linuxファイル(~/)が高速、/mnt/c/は低速 |
| ネットワーク | Windowsのネットワークスタックを直接共有 | 独自の仮想ネットワーク(デフォルトはNAT) |
| 互換性 | 一部のLinuxツールが動かない | 完全なLinux互換 |
WSL2はWSL1の上に構築されたものではない。同じ「WindowsでLinuxを動かす」というコンセプトに対して、Microsoftがアプローチを置き換えたもの。WSL2が現在のデフォルトで、今「WSL」と言えばほぼWSL2を指す。
この記事で重要なのはネットワークの違い。WSL1はWindowsのネットワークをそのまま共有していたが、WSL2は軽量VM内で動くため、独自のIPアドレスを持つ。この違いがMoshのセットアップを複雑にしている。
WSL2のネットワーク構造
WSL2のネットワーク構造を理解しないと、なぜ単純にSSH接続しただけではmosh-serverが動かないのかがわからない。
デフォルトの構成(NATモード)
iPhoneやMacからWindowsのLAN IPに接続すると、Windows OpenSSH(Port 22)が応答する。ここで開くのはWindowsのシェル(PowerShellやCMD)。mosh-serverはWSL2の中にインストールされているので、Windowsのシェルからは見つからない。
さらにWSL2はデフォルトでNATの内部にいて、独自のIPアドレス(172.18.x.xなど)を持っている。外部からWSL2に直接アクセスするにはポートフォワーディングが必要だが、MoshはUDPを使うため、UDPのポートフォワーディングが面倒になる。
正しい接続構成(ミラーモード)
WSL2の.wslconfigでnetworkingMode=mirroredを設定すると、WSL2がWindowsと同じIPアドレスを共有する。これにより、外部からWSL2内のサービスに直接アクセスできるようになる。
WSL2内にopenssh-server(Port 2222)を設置し、そこにSSH接続する。Windows OpenSSH(Port 22)とは別のポートを使う。SSH経由でmosh-serverが起動し、以降はUDPで通信する。
Windows OpenSSHではダメなのか
Windows OpenSSH(Port 22)はデフォルトでWindowsのシェル(PowerShell/CMD)を開く。mosh-serverはWSL2内のLinuxバイナリなので、Windowsのシェルからは見つからない。これが「Failed to start Mosh on server」エラーの原因。
別のアプローチとして、Windows OpenSSHのデフォルトシェルをWSL2に変更する方法もある。PowerShell(管理者)で以下を実行する。
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Windows\System32\wsl.exe" -PropertyType String -ForceこうするとWindows OpenSSH経由でもWSL2のシェルが開くので、mosh-serverが見つかる。WSL2内に別途openssh-serverをインストールする必要がなくなる。
ただし、この方法はそのWindowsマシンへの全SSH接続のデフォルトシェルが変わる。PowerShellでSSHしたい場合に不便になるので、WSL2専用にSSHを使う場合向け。この記事ではWSL2内にopenssh-server(Port 2222)を別途設置する方法を採用している。
Moshの通信フロー
MoshはSSHを最初の認証に1回だけ使う。mosh-serverが起動したらSSH接続は切断され、以降はクライアントとmosh-serverがUDPで直接通信する。このUDP通信がネットワーク変動に強い。
セットアップ手順
前提条件
- Windows + WSL2(Ubuntu 24.04)
- WSL2内にmoshがインストール済み(
sudo apt install mosh) - Windows OpenSSHが動作中(Port 22)
- iOSにMoshiアプリをインストール済み
Step 1: WSL2のネットワークをミラーモードにする
Windows側のC:\Users\takaz\.wslconfigに以下を作成する。
[wsl2]
networkingMode=mirroredこれによりWSL2がWindowsと同じIPアドレスを共有する。デフォルトのNATモードではUDPポートフォワーディングが困難なため、これが最もシンプルな解決策。
Step 2: WSL2にopenssh-serverをインストール
sudo apt update && sudo apt install -y openssh-serverWindows OpenSSHが既にPort 22を使用しているため、WSL2のSSHはPort 2222に変更する。
sudo sed -i 's/^#Port 22$/Port 2222/' /etc/ssh/sshd_configSSHサーバーを起動する。
sudo service ssh startWSL2はデフォルトではサービスを再起動後に維持しない。wsl --shutdownやPC再起動のたびにsshdが止まる。自動起動させるには、Step 1の.wslconfigとは別に、WSL2内の/etc/wsl.confに以下を追加する。
[boot]
command=service ssh startStep 3: SSH公開鍵の設定
Windows OpenSSH用の公開鍵はWSL2には自動的に共有されない。Windows側の管理者用authorized_keysからWSL2にコピーする。
cp /mnt/c/ProgramData/ssh/administrators_authorized_keys ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keysStep 4: Windowsファイアウォール設定
PowerShell(管理者)で以下を実行する。
New-NetFirewallRule -DisplayName "WSL2 SSH" -Direction Inbound -Protocol TCP -LocalPort 2222 -Action Allow
New-NetFirewallRule -DisplayName "Mosh UDP range" -Direction Inbound -Protocol UDP -LocalPort 60000-60010 -Action AllowTCPの2222(SSH)とUDPの60000-60010(Mosh)の2つを開ける必要がある。
Step 5: WSLを再起動
PowerShellで以下を実行する。
wsl --shutdownその後WSLターミナルを再度開く。ミラーモードの設定を反映するには再起動が必要。
Step 6: Moshiアプリの設定
Moshiアプリで以下を設定する。
- Host: WindowsマシンのLAN IP
- SSH Port: 2222
- Username: takazudo(WSL2のユーザー名)
- Auth: SSHキー
- Mosh port range: 60000-60010
これで接続できた。後述のtmuxを使えば切れても途中からまた再開される。

トラブルシューティング
セットアップ中に遭遇したエラーと対処法をまとめておく。
"Failed to start Mosh on server"
SSH接続がWindows OpenSSH(Port 22)に向いていたのが原因。Windowsのシェルにはmosh-serverが存在しないので、mosh-serverの起動に失敗する。
解決策: WSL2内にopenssh-server(Port 2222)を設置し、そちらに接続する。
"Authentication failed"
WSL2の~/.ssh/authorized_keysが存在しなかったのが原因。Windows OpenSSH用の鍵とWSL2の鍵は別管理になっている。Windowsに公開鍵を登録してあっても、WSL2には自動で共有されない。
解決策: /mnt/c/ProgramData/ssh/administrators_authorized_keysからWSL2にコピーする。
Mac moshで "Address already in use"
MoshのUDPポートは1セッション1ポート。iOSのMoshiセッションが60001を使用中だと、Macから同じポートは使えない。
解決策: ポートレンジ(60000-60010)を使い、自動で空きポートを選択させる。--portを指定しなければ自動選択される。
Macからの接続
Macからも同じWSL2にMoshで接続できる。
brew install mosh # 未インストールの場合
mosh --ssh="ssh -p 2222" takazudo@<WindowsのLAN IP>--portを省略すれば60000-61000の空きポートを自動選択する。
tmuxとの組み合わせ
なぜtmuxが必要か
Moshとtmuxは守っている範囲が違う。
- Moshは「接続」を維持する。ネットワーク変更、スリープに耐える。ただし「プロセス」は維持しない。mosh-serverが終了すればセッションは消える
- tmuxは「セッション」を維持する。切断しても、再起動しても、tmuxセッション内のプロセスは生き続ける
Mosh + tmuxを組み合わせると、ネットワークの切断にも、mosh-serverの再起動にも耐えられる。
セッション共有
tmuxセッションは同一マシン上の全接続で共有可能。iPhoneのMoshiとMacのmoshから同じtmuxセッションにattachすると、リアルタイムで同じ画面を見ることができる。スクリーンシェアのような感じ。
別々のワークスペースが欲しい場合は別セッションを作成する。
tmux new -s ios
tmux new -s macMac、iPhone、iPadなど複数デバイスからtmuxセッションを共有できる。同じセッションにattachすれば同じ画面、別セッションを使えば別作業。
Moshの仕組み Q&A
MoshはSSHの上に乗る技術?
いいえ。MoshはSSHを最初の認証時に1回だけ使う。その後SSHは切断され、実際のセッションはUDPで通信する。SSHの上位レイヤーではなく、認証後は完全に別のプロトコルになる。
SSHとの違い
SSH(TCP)は順序付き・信頼性のあるストリーム。パケットロスが発生するとすべてが再送待ちになる。接続が断たれるとセッションが死亡する。
Mosh(UDP)はステートレスなデータグラム。各パケットが現在のスクリーン状態を含んでいる。パケットロスが起きても、次のパケットが最新の状態を持ってくる。
Moshのほうがデータ量が多い?
逆。MoshはSSHよりも効率的。
SSHはすべてのバイトを順番に送信する。10,000行のログ出力があれば全行送信される。途中でパケットロスが発生するとストールする。
Moshは最新のスクリーン状態のみ送信する。中間フレームはスキップする。画面に表示されている内容だけを同期すればいいので、大量のログ出力中でも帯域を圧迫しない。
ただしスクロールバックはMosh単体では不可能。中間のデータをスキップしているため。ここでtmuxが活躍する。tmuxがサーバー側で全出力をキャプチャしているので、tmuxのスクロール(Ctrl+b [)を使えば過去の出力を遡れる。
tmuxのスクロールはMosh経由で動く?
動く。tmuxはサーバー側で完全に動作する。tmuxでスクロール(Ctrl+b [)すると、tmuxが画面表示を更新し、Moshはその画面状態をクライアントに同期するだけ。Moshはあくまでスクリーンの差分を送るトランスポート層であり、tmuxは端末の中で動くアプリケーション。両者は独立して動いているが、組み合わせるとうまくいく。
まとめ
Moshi + Mosh + tmuxの組み合わせにより、iPhoneからWindows WSL2上のClaude Codeを操作できる環境ができた。ネットワークの切断を気にせず、移動中でもAIエージェントと対話できる。Mac、iPhone、iPadなど複数デバイスからtmuxセッションを共有できるのも良い。
セットアップの手順は多いが、WSL2のネットワーク構造さえ理解すれば一つ一つは難しくない。注意が必要なのはWSL2のミラーモード設定と、Windows OpenSSH / WSL2 openssh-serverの使い分け。