Hatena::Grouprubyist

Going My Ruby Way このページをアンテナに追加 RSSフィード

Ruby ロゴ (C) Ruby Association LLC

2011年09月11日(日)

SSH サーバを作る(その 22) コネクションプロトコル

| 19:03 | SSH サーバを作る(その 22) コネクションプロトコル - Going My Ruby Way を含むブックマーク はてなブックマーク - SSH サーバを作る(その 22) コネクションプロトコル - Going My Ruby Way SSH サーバを作る(その 22) コネクションプロトコル - Going My Ruby Way のブックマークコメント

コネクションプロトコル

コネクションプロトコルは、主に RFC4254 の範囲になります。

位置プロトコル提供する機能
最下層トランスポート層プロトコル*1気密性(暗号化)、完全性、サーバ認証、圧縮
中間層認証プロトコルクライアント認証(ユーザ認証)
最上層コネクションプロトコル多重化チャネル<==ここ

コネクションプロトコルでは多重化されたチャネルを提供します。

SSH のサービスはこのチャネル上で動作します。

チャネルは両方の端点(クライアントとサーバ)それぞれで一意のチャネル番号で識別されます。

(チャネルの例)
  <client>                      <server>
  channel #0 ------------------ channel #0  (ひとつのチャネル)

  channel #10 ----------------- channel #1  (別のチャネル)

チャネルはクライアント、サーバいずれの側からも開くことができます。

チャネルには以下のタイプがあります*2

タイプ説明
sessionプログラムのリモート実行
x11X11クライアント接続
forwarded-tcpip内向きTCPフォワーディング
direct-tcpip外向きTCPフォワーディング

チャネルにはリクエストが定義されています*3。リクエストは以下のものに大別できます。

  • グローバルリクエスト: 接続全体に影響するリクエスト
  • チャネルリクエスト: 特定のチャネルに対するリクエスト

グローバルなリクエストには以下があります。

リクエスト説明
tcpip-forwardTCPフォワーディングのリクエスト
cancel-tcpip-forwardTCPフォワーディングのキャンセル

チャネルリクエストには以下があります。

リクエスト説明チャネルタイプ
pty-req疑似端末(pty)の割り当て要求session
x11-reqX11転送の要求x11
env環境変数の設定session
shellシェルのリモート実行session
exec任意のプログラムのリモート実行session
subsystemサブシステムのリモート実行session
window-change端末ウィンドウサイズの変更session
xon-xoffX-ON/X-OFFによるフロー制御要求session
signalシグナルの送信session
exit-statusexitステータスの返却session
exit-signalシグナルによるプロセス終了時の終了ステータスの返却session

チャネルリクエストの中でプログラムの実行を行うものは以下です。

  • shell : リモートログインしてシェルを操作する際に使用される
  • exec : プログラムのワンショット実行で使用される。また scp でも使用される
  • subsystem : sftp など特定のサービス(を行うプログラム)を起動する際に使用される

プロトコル上はリクエストは、

  • クライアント->サーバ
  • サーバ->クライアント

のいずれの方向への送信も許されています。

--------

gmrw-ssh2-server でサポートするチャネルタイプは session のみです。

グローバルリクエスト(X11TCP転送)には未対応です。

チャネルリクエスト pty-req、x11-req、envexec、subsystem、window-change、xon-xoff、signal にも未対応です。(execRuby1.9 でサーバ実行する場合のみ動作)

グローバルリクエストのプロトコル

グローバルリクエストで使用されるメッセージです。

メッセージ番号通常の方向説明
SSH_MSG_GLOBAL_REQUEST80C->Sリクエスト
SSH_MSG_REQUEST_SUCCESS81S->Cリクエストの応答(成功の場合)
SSH_MSG_REQUEST_FAILURE82S->Cリクエストの応答(失敗の場合)

メッセージの流れです。

サーバはリクエストの want_reply が true の場合に応答します。

  <client>                         <server>
    |  <GLOBAL_REQUEST(80)>          |
    |------------------------------->|
    |................................|............................           
    |                                |※REQUEST の want_reply が true の場合
    |         <REQUEST_SUCCESS(51)>  |
    |<-------------------------------| (※成功の場合)
    |                                |
    |         <REQUEST_FAILURE(82)>  |
    |<-------------------------------| (※失敗の場合)
    |                                |

メッセージのパラメータの詳細については割愛します。

gmrw-ssh2-server での定義を代わりに記載します。

module GMRW::SSH2::Message
  def_message :global_request, [
    [ :byte,    :type,                  80                                            ],
    [ :string,  :request_name                                                         ],
    [ :boolean, :want_reply                                                           ],
    [ :string,  :address_to_bind,       nil, {:request_name => 'tcpip-forward'}       ],
    [ :uint32,  :port_number_to_bind,   nil, {:request_name => 'tcpip-forward'}       ],

    [ :string,  :address_to_cancel,     nil, {:request_name => 'cancel-tcpip-forward'}],
    [ :uint32,  :port_number_to_cancel, nil, {:request_name => 'cancel-tcpip-forward'}],
  ]

  def_message :request_success, [
    [ :byte, :type,                  81   ],
    [ :uint32, :port_that_was_bound, false],
  ]

  def_message :request_failure, [
    [ :byte, :type, 82 ],
  ]
end

チャネルリクエストについては次回です。

*1OSI 7階層モデルでいうトランスポート層ではありません

*2SSH仕様ではチャネルタイプのローカルな拡張も許されています

*3:ローカルな拡張が許されています