コンテンツへスキップ

SSH接続多重化(ControlMaster)とは — 同じサーバーへ何度もつなぐときの待ち時間を減らす設定

WP-CLI を SSH 越しに何度も実行すると、コマンドそのものより前の「接続の確立」に時間を取られていることに気づきます。1回ごとに TCP 接続、鍵交換、認証をやり直しているためです。

OpenSSH には、一度確立した接続を使い回す ControlMaster(接続の多重化)という仕組みがあります。この記事では、何が起きているのか、設定の書き方、注意点を、実サーバーで測った数値とあわせて整理します。

補足: 測定は手元の Mac(OpenSSH 10.2)から国内のレンタルサーバーへ、true コマンドを繰り返し実行して行いました。回線やサーバーによって数値は変わるため、あくまで一例として読んでください。

SSH 接続のたびに何をしているか

ssh host command を実行するたびに、次の手順が最初から行われます。

  1. TCP 接続を開く
  2. 暗号化方式を交渉し、鍵を交換する
  3. サーバーを確認し、公開鍵で認証する
  4. セッションを開き、コマンドを実行する

実際に作業したいのは4だけですが、1〜3 は毎回かかります。1回あたりは気にならなくても、スクリプトから何十回も呼ぶと、待ち時間の大半がここになります。

ControlMaster の考え方

ControlMaster は、最初の接続を「親(マスター)」として残し、2回目以降のコマンドをその接続の上に相乗りさせる仕組みです。

  • 最初の ssh が接続を張り、手元に 制御用のソケットファイルを作る
  • 2回目以降の ssh は、そのソケット経由で既存の接続にセッションだけを追加する
  • 新たな鍵交換や認証は行われない

つまり、1〜3 を最初の1回だけに減らす設定です。

設定の書き方

~/.ssh/config に、ホストごとに次のように書きます。ホスト名・ユーザー名・鍵のパスは例です。

Host myserver
    HostName example.com
    User deploy
    IdentityFile ~/.ssh/example_key
    ControlMaster auto
    ControlPath ~/.ssh/cm-%C
    ControlPersist 60
  • ControlMaster auto: ソケットがなければ自分がマスターになり、あれば相乗りする
  • ControlPath: ソケットファイルの置き場所。%C は接続先情報から作られるハッシュで、ホストごとに別のパスになる
  • ControlPersist 60: 最後のセッションが終わっても、マスター接続を60秒だけ裏で残す

ControlPersist が重要です。これがないと、最初のセッションが終わった時点でマスターも終了し、次のコマンドは再び新規接続になってしまいます。

ControlPath のパスは長すぎるとエラーになることがあります(ソケットのパス長には OS ごとの上限があります)。%C を使うと短く収まります。

実測してみた

同じサーバーへ true を5回続けて実行し、合計時間を測りました(1回の測定です)。

条件 5回の合計
多重化なし 2.64秒
多重化あり(ControlPersist 30) 0.83秒

5回のうち、多重化ありで本当に接続を張ったのは最初の1回だけです。残りは既存の接続に乗るだけなので、1回あたりの時間が小さくなりました。

一方、WP-CLI(wp option get blogname)を3回続けた場合は次のとおりでした。

条件 3回の合計
多重化なし 3.36秒
多重化あり 2.64秒

差は小さくなっています。WP-CLI 自体が PHP を起動して WordPress を読み込む時間を使うため、接続の確立分を省いても、全体に占める割合が下がるためです。多重化で省けるのは接続の確立ぶんだけで、コマンド本体の実行時間は変わりません。短いコマンドを何度も呼ぶ場面ほど効果が見えやすい、という理解が実態に近いと思います。

状態の確認と終了

マスター接続が生きているかは -O check、明示的に終了するには -O exit で操作できます。

ssh -O check myserver
ssh -O exit myserver

測定の際にも、終わったら -O exit でマスターを止めています。

気をつけたい点

  • ソケットファイルの扱い: ソケットを持っている人は、その接続を使える状態になります。置き場所は自分だけが読み書きできるディレクトリにし、共用の場所には置かないのが原則です。
  • 古いソケットが残る: 異常終了でソケットが残ると、接続に失敗することがあります。その場合はソケットファイルを削除してから再接続します。
  • 接続が切れると全部影響する: 相乗りしているセッションは、マスターが落ちると一緒に切れます。長時間の作業や大きなファイル転送は、別接続に分けたほうが安心な場面もあります。
  • ControlPersist を長くしすぎない: 放置した接続が残り続けるため、数十秒〜数分程度にとどめるのが無難です。
  • 認証や設定を変えた直後: マスターが古い設定のまま残っていると、新しい設定が反映されないように見えます。-O exit で止めてから試してください。

まとめ

  • SSH は接続のたびに、TCP・鍵交換・認証をやり直している。
  • ControlMaster は最初の接続を使い回し、2回目以降のその手順を省く。
  • ControlMaster auto・ControlPath・ControlPersist の3つを ~/.ssh/config に書くのが基本。
  • 実測では、短いコマンド5回で 2.64秒 → 0.83秒。ただし WP-CLI のように実行自体が重いコマンドでは差が小さくなる。
  • ソケットの置き場所と、マスター切断時の影響に気をつける。

複数サーバーを扱うなら、まず「~/.ssh/config でホスト別設定を整理する」で設定を整えたうえで、接続を繰り返すホストにだけ多重化を足してみてください。