Hatena::Grouprubyist

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

Ruby ロゴ (C) Ruby Association LLC

2011年08月30日(火)

SSH サーバを作る(その 17) トランスポート層プロトコルのおさらい(8)

| 23:59 | SSH サーバを作る(その 17) トランスポート層プロトコルのおさらい(8) - Going My Ruby Way を含むブックマーク はてなブックマーク - SSH サーバを作る(その 17) トランスポート層プロトコルのおさらい(8) - Going My Ruby Way SSH サーバを作る(その 17) トランスポート層プロトコルのおさらい(8) - Going My Ruby Way のブックマークコメント

メッセージについておさらいです。

メッセージ

(一部、以前の日記の再掲です)

パケットの 'payload' にはメッセージが格納されます。

メッセージの最初のフィールドは以下のようになっています。

フィールド名説明
bytetypeメッセージ番号
... ... (以降のフィールドはメッセージ毎に定義されている)

メッセージ番号はメッセージの種類を示します。以下のようにカテゴライズされています。

カテゴリ番号説明
トランスポート層プロトコル 1 .. 19 トランスポート層一般
20 .. 29 アルゴリズムのネゴシエーション
30 .. 49 鍵交換方式ごとに特有(再利用可能)
認証プロトコル 50 .. 59 ユーザ認証一般
60 .. 79 ユーザ認証法ごとに特有(再利用可能)
コネクション・プロトコル 80 .. 89 コネクションプロトコル一般
90 .. 127 チャネルに関連したメッセージ
クライアントプロトコルのための予約 128 .. 191 予約
ローカルな拡張 192 .. 255 ローカルな拡張

再利用可能と説明されているカテゴリは、メッセージ番号に対応するメッセージがアルゴリズムやスキームによって決まります。

トランスポート層のメッセージ

番号メッセージ方向備考
1DISCONNECTC->S, S->C
2IGNOREC->S, S->C
3UNIMPLEMENTEDC->S, S->C
4DEBUGC->S, S->C
5SERVICE_REQUESTC->S
6SERVICE_ACCEPTS->C
--------------
20KEXINITC->S, S->C
21NEWKEYSC->S, S->C
--------------
30KEXDH_INITC->S鍵交換法が DH の場合
31KEXDH_REPLYS->C鍵交換法が DH の場合
--------------
30KEX_DH_GEX_REQUEST_OLD 後方互換性のため残されている
31KEX_DH_GEX_GROUPS->C鍵交換法が DH(GEX) の場合
32KEX_DH_GEX_INITC->S鍵交換法が DH(GEX) の場合
33KEX_DH_GEX_REPLYS->C鍵交換法が DH(GEX) の場合
34KEX_DH_GEX_REQUESTC->S鍵交換法が DH(GEX) の場合

サービス要求メッセージ

SERVICE_REQUEST
クライアントがサービスを要求するため送信する
SERVICE_ACCEPT
サーバが要求されたサービスは要求を受け付けることを通知するため送信する

NEWKEYS が走った後、クライアントは サービス 'ssh-userauth'(ユーザー認証) を要求するため、SERVICE_REQUEST を送信してきます。

サーバは(要求を受けつけるなら)SERVICE_ACCEPT を返信します。

  <client>                         <server>
    |                                |
    |  <SERVICE_RESUQST(5)>          |
    |------------------------------->|  
    |                                |  * 要求サービスの受け付け
    |           <SERVICE_ACCEPT(6)>  |   (ここでは service = 'ssh-userauth')
    |<-------------------------------|
    |                                |
        (以降、ユーザ認証プロトコル)

トランスポート層一般のメッセージ

DISCONNECT
コネクションの切断を通知する
IGNORE
無視すべきメッセージ
UNIMPLEMENTED
相手から送信されたメッセージが未実装であることを通知する
DEBUG
デバッグ用データを送信する

パラメータなど詳細については RFC 4253 を参照してください。

gmrw-ssh2-server でのメッセージ定義コードを示しておきます。

module GMRW::SSH2::Message
  disconnect_reason = proc do |tag|
    {
      :HOST_NOT_ALLOWED_TO_CONNECT    =>   1,
      :PROTOCOL_ERROR                 =>   2,
      :KEY_EXCHANGE_FAILED            =>   3,
      :RESERVED                       =>   4,
      :MAC_ERROR                      =>   5,
      :COMPRESSION_ERROR              =>   6,
      :SERVICE_NOT_AVAILABLE          =>   7,
      :PROTOCOL_VERSION_NOT_SUPPORTED =>   8,
      :HOST_KEY_NOT_VERIFIABLE        =>   9,
      :CONNECTION_LOST                =>  10,
      :BY_APPLICATION                 =>  11,
      :TOO_MANY_CONNECTIONS           =>  12,
      :AUTH_CANCELLED_BY_USER         =>  13,
      :NO_MORE_AUTH_METHODS_AVAILABLE =>  14,
      :ILLEGAL_USER_NAME              =>  15,
    }[tag] || tag
  end

  def_message :disconnect, [
    [ :byte,   :type         ,1                      ],
    [ :uint32, :reason_code  ,nil, disconnect_reason ],
    [ :string, :description                          ],
    [ :string, :language_tag                         ],
  ]

  def_message :ignore, [
    [ :byte,   :type  ,2 ],
    [ :string, :data     ],
  ]

  def_message :unimplemented, [
    [ :byte,   :type            ,3 ],
    [ :uint32, :sequence_number    ],
  ]

  def_message :debug, [
    [ :byte,   :type         ,4 ],
    [ :string, :message         ],
    [ :string, :language_tag    ],
  ]
  def_message :service_request, [
    [ :byte,   :type         ,5 ],
    [ :string, :service_name    ],
  ]

  def_message :service_accept, [
    [ :byte,   :type         ,6 ],
    [ :string, :service_name    ],
  ]
end