TIPS/SSH

Last-modified: 2016-09-02 (金) 17:22:37

SSHプロトコル備忘録

  • ページ: システム/AI?
  • 投稿者: 名無しさん
  • 優先順位: 低
  • 状態: 提案
  • カテゴリー:
  • 投稿日: 2014-10-06 (月) 09:49:30
  • バージョン:

#snapshot

トランスポート層プロトコル

トランスポート層プロトコルは、主に RFC4253 の範囲になります。

http://www.ietf.org/rfc/rfc4253.txt

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

トランスポート層(SSHプロトコル)の下

TCP です。サーバは通常 22 番ポートを listen します。
クライアント-サーバモデルです。

プロトコルバージョンの交換

最初はプロトコルバージョンの交換です。

サーバとクライアント双方がバージョン文字列(識別子)を送信し合います。(※送信順序不定)

 <client>                                                  <server>
   |       <バージョン識別子>                            |
   |<==============================>| (※送信順序不定)
   |                                                                       |

バージョン文字列(識別子)は以下のフォーマットです。

SSH-2.0-xxxxxxxxx [SP] yyyyyyyyy [CR][LF]
  • SP は 空白(ASCII 20h)、CR は復帰(ASCII 0Dh)、LF は改行(ASCII 0Ah) です
  • SSH-2.0 は固定です
  • xxxxxxxxx はソフトウェアバージョンです
  • yyyyyyyyy はコメントです。これ(とその前の空白(SP))はオプションです
  • バージョンがマッチしない場合はコネクションを切断します。

実装では、SSH-2.0 を扱うので(SSH-1.0 には非対応です)、それ以外のバージョンの場合はコネクションを切断して処理を終了させます。*4

プロトコルバージョンの交換以後は、バイナリパケットプロトコルに移行します。

シーケンスナンバー

バイナリパケットプロトコルでは陽に表れないパラメータとしてシーケンスナンバーがあります。

これはパケット送信毎に加算されていく送信方向毎に独立のカウンタです。精度は符号無し32ビット整数で、初期値は 0 です。最大値を超えるとまた 0 に戻ります。

通常、次に紹介する KEXINT がカウント値 0 になります。

アルゴリズムネゴシエーション

鍵交換では最初に KEXINIT(番号=20) をクライアントとサーバ双方が送信し合います(送信順序不定)。

 <client>                                                     <server>
   |         <KEXINIT(20)>                                    |
   |<==============================>| (※送信順序不定)
   |                                                                       |

KEXINIT には各項目毎のアルゴリズムのリストが載っています。

フィールド名説明
kex_algorithmsKEX(鍵交換)アルゴリズム
server_host_key_algorithmsホスト鍵アルゴリズム
encryption_algorithms_client_to_server対称暗号アルゴリズム(クライアントtoサーバ)
encryption_algorithms_server_to_client対称暗号アルゴリズム(サーバtoクライアント)
mac_algorithms_client_to_serverMACアルゴリズム(クライアントtoサーバ)
mac_algorithms_server_to_clientMACアルゴリズム(サーバtoクライアント)
compression_algorithms_client_to_server圧縮アルゴリズム(クライアントtoサーバ)
compression_algorithms_server_to_client圧縮アルゴリズム(サーバtoクライアント)

暗号、MAC、圧縮のアルゴリズムは送信方向ごとに独立に選択されます。

アルゴリズムは、

  • クライアントKEXINIT のリストの先頭から順に見ていき
  • サーバ KEXINIT のリストに存在するもの

を選択します。

例)

 クライアントKEXINIT   [A, B, C]
 サーバKEXINIT         [X, B, A]
 ... この場合 A が選択される

アルゴリズム名については、RFC4253, RFC4250 などに載っています。

gmrw-ssh2-server で現在サポートするアルゴリズム*5は以下です*6。

種類アルゴリズムSSH仕様上の要求OpenSSH5.8p1デフォルト
KEX(KeyEXchange)diffie-hellman-group-exchange-sha256
diffie-hellman-group-exchange-sha1
diffie-hellman-group14-sha1REQUIRED
diffie-hellman-group1-sha1REQUIRED
ホスト鍵ssh-dssREQUIRED
ssh-rsaRECOMMENDED
対称暗号aes128-cbcRECOMMENDED
aes256-cbc
aes192-cbc
blowfish-cbc
cast128-cbc
3des-cbcREQUIRED
MAChmac-sha1REQUIRED
hmac-sha1-96RECOMMENDED
hmac-md5
hmac-md5-96
圧縮noneREQUIRED
zlib

KEXINIT には他の項目に、cookie があります。これはランダムバイト列です。

KEXINIT 以降

KEXINIT の次は、鍵交換アルゴリズム(KeyEXchange = KEX)になります。

鍵交換アルゴリズムでのプロトコルはネゴシエートしたアルゴリズムにより決まります。また、そこで使われるメッセージの番号も 30..49 (鍵交換方式ごとに特有(再割り当て可))になります。

鍵交換が終わると NEWKEYS(番号=21) をクライアントとサーバ双方が送信し合います(送信順序不定)。そこでトランスポートプロトコルが終了します。

 <client>                         <server>
   |         <KEXINIT(20)>          |
   |<==============================>| (※送信順序不定)
   |                                |
   |................................|
   |                                |
   |      鍵交換アルゴリズム        |
   |      (鍵交換法毎に特有)        |
   |................................|
   |                                |
   |         <NEYKEYS(21)>          |
   |<==============================>| (※送信順序不定)
   |                                |
        (暗号、MAC、圧縮の開始)
     (これ以降、ユーザ認証プロトコル)

DH 鍵合意

以下のプロトコル*1を見てみます。

  • diffie-hellman-group14-sha1
  • diffie-hellman-group1-sha1

これらはダイジェスト関数に SHA1 を使います。

また、(素数の)群(=グループ)にそれぞれ Group14、Group1 を使います。

  • Oakley Group14 (2048bit,RFC3526参照)
  • Oakley Group1 (1024bit,RFC2409参照)
 <client>                         <server>
   |         <KEXINIT(20)>          |
   |<==============================>| (※送信順序不定)
   |                                |
   |................................|.............................
   |                                |
   |  <KEXDH_INIT(30)>              |
   |------------------------------->|
   |                                | (※DH鍵合意プロトコル)
   |              <KEXDH_REPLY(31)> |
   |<-------------------------------|
   |................................|.............................
   |                                |
   |         <NEWKEYS(21)>          |
   |<==============================>| (※送信順序不定)
   |                                |
メッセージ番号
SSH_MSG_KEXDH_INIT30
SSH_MSG_KEXDH_REPLY31

KEXDH_INIT (Client -> Server)

クライアントは最初 KEXDH_INIT を送信します。パラメータは以下です。

パラメータ内容
eクライアントDH公開鍵

KEXDH_REPLY (Server -> Client)

DH 初期化の後、サーバは KEX_KEXDH_REPLY を返信します。

パラメータ内容
k_sサーバホスト鍵
fサーバDH公開鍵
sサーバホスト鍵で署名された交換ハッシュ H

共有秘密 K と 交換ハッシュ H

K と H の意味合いは、鍵交換のアルゴリズムに関わらず同じです。

内容
共有秘密 KDH により計算される共有鍵
交換ハッシュ HK やその他のプロトコルのパラメータの連結文字列から生成するハッシュ。
セッション識別子最初の 交換ハッシュ H。鍵交換が再度行なわれても更新されない。

K の生成の手順です。

(1) クライアント DH 公開鍵 e から DH により共有秘密を計算する
(2) OpenSSL::PKey::DH#compute_key は バイナリの文字列形式で結果を返すので数値化する
(3) mpint 型にエンコードする

H の生成の手順です。

(1) SSH のデータ型でエンコードされた各種パラメタの連結文字列 h0 を求める
(2) h0 からダイジェスト関数によりハッシュ h を求める
(3) ハッシュ h にホスト鍵で署名する(署名は署名フォーマットにエンコードする

出力された鍵

セッション識別子は、最初の鍵交換の場合、H をそのままコピーします。

K と H と セッション鍵は保存します。

DH 鍵合意 (GEX)

以下のプロトコル*1を見てみます。

  • diffie-hellman-group-exchange-sha256
  • diffie-hellman-group-exchange-sha1
    ...-sha256、...-sha1 はそれぞれダイジェスト関数に SHA256、SHA1 を使います。

これらのプロトコルの特徴は、(素数の)群(=グループ)が通信時の合意によって決められることです。(GEX = Group Exchange)

 <client>                         <server>
   |         <KEXINIT(20)>          |
   |<==============================>| (※送信順序不定)
   |                                |
   |................................|..............................
   |                                |
   |  <KEX_DH_GEX_REQUEST(34)>      |
   |------------------------------->|
   |                                |
   |         <KEX_DH_GEX_GROUP(31)> |
   |<-------------------------------|
   |                                | (※DH鍵合意(GEX)プロトコル)
   |  <KEX_DH_GEX_INIT(32)>         |
   |------------------------------->|
   |                                |
   |         <KEX_DH_GEX_REPLY(33)> |
   |<-------------------------------|
   |                                |
   |................................|..............................
   |                                |
   |         <NEWKEYS(21)>          |
   |<==============================>| (※送信順序不定)
   |                                |
メッセージ番号備考
SSH_MSG_KEX_DH_GEX_REQUEST_OLD30後方互換性のため残されている
SSH_MSG_KEX_DH_GEX_REQUEST34
SSH_MSG_KEX_DH_GEX_GROUP31
SSH_MSG_KEX_DH_GEX_INIT32
SSH_MSG_KEX_DH_GEX_REPLY33

KEX_DH_GEX_REQUEST (Client -> Server)

クライアントは最初 KEX_DH_GEX_REQUEST を送ってきます。パラメータは以下です。

パラメータ内容
min受け入れられる(素数の)群の最小ビット長(仕様上の推奨 1024)
n希望する(素数の)群のビット長
max受け入れられる(素数の)群の最大ビット長(仕様上の推奨 8192)

サーバはこれらから安全な(素数の)群を生成(or選択)します。

RFC には素数の生成方法が記載されています。

OpenSSH の ssh クライアントはデフォルトで(n, min, max) = (1024, 1024, 8192)
を送信してきます。

KEX_DH_GEX_GROUP (Server -> Client)

素数生成(or選択)、DH 初期化の後、サーバは KEX_DH_GEX_GROUP を返信します。

パラメータは以下です。

パラメータ内容
pDH パラメータの p
gDH パラメータの g

KEX_DH_GEX_INIT (Client -> Server)

次にクライアントは KEX_DH_GEX_INIT を送信します。パラメータは以下です。

パラメータ内容
eクライアントDH公開鍵

KEX_DH_GEX_REPLY (Server -> Client)

サーバは KEX_DH_GEX_REPLY を返信します。パラメータは以下です。

パラメータ内容
k_sサーバホスト鍵
fサーバDH公開鍵
sサーバホスト鍵で署名された交換ハッシュ H

共有秘密 K と 交換ハッシュ H

K と H の意味合いは、鍵交換のアルゴリズムに関わらず同じです。

パラメータ内容
共有秘密 KDH により計算される共有鍵
交換ハッシュ HK やその他のプロトコルのパラメータの連結文字列から生成するハッシュ。
セッション識別子最初の 交換ハッシュ H。鍵交換が再度行なわれても更新されない。

K の生成の手順です。

(1) クライアント DH 公開鍵 e から DH により共有秘密を計算する
(2) OpenSSL::PKey::DH#compute_key は バイナリの文字列形式で結果を返すので   数値化する
(3) mpint 型にエンコードする

H の生成の手順です。

(1) SSH のデータ型でエンコードされた各種パラメタの連結文字列 h0 を求める
(2) h0 からダイジェスト関数によりハッシュ h を求める
(3) ハッシュ h にホスト鍵で署名する(署名は署名フォーマットにエンコードする

出力された鍵

セッション識別子は、最初の鍵交換の場合、H をそのままコピーします。

K と H と セッション鍵は保存します。

鍵 と IV の生成

鍵交換で取得した共有秘密 K と交換ハッシュ H と セッション鍵から、鍵とIV(初期化ベクタ)を生成します*1。

通信の方向毎に以下の鍵とIVが必要です。

  • 暗号化IV
  • 暗号化鍵
  • MAC 鍵
      HASH       = 鍵交換のダイジェスト関数によるハッシュ出力関数
      K          = 共有秘密
      H          = 交換ハッシュ
      session_id = セッション識別子
      salt       = クライアント(からサーバ方向)の暗号化IVの場合 "A"
                 | サーバ(からクライアント方向)の暗号化IVの場合 "B"
                 | クライアント(からサーバ方向)の暗号化鍵の場合 "C"
                 | サーバ(からクライアント方向)の暗号化鍵の場合 "D"
                 | クライアント(からサーバ方向)のMAC鍵の場合    "E"
                 | サーバ(からクライアント方向)のMAC鍵の場合    "F"
  鍵 = HASH(K + H + salt + session_id)
  鍵の長さが足りない場合は、
    鍵 = HASH(K + H + 鍵)
  を長さが足りるまで繰りかえします。
  (最終的に鍵の長さはそれぞれの鍵長にそろえます)

proc の引数の部分適用です。(Ruby1.9 でなら curry でも代用できると思います)

暗号化、MAC、圧縮の開始

NEWKYES の送信と受信が終わった後、鍵と IV を適用して暗号化、MAC、圧縮の開始します。

トランスポート層全体の流れを以下に示します。

 <client>                         <server>
   |       <バージョン識別子>       |
   |<==============================>|  * SSH バージョン交換
   |                                |
   |................................|....................................
   |                                |  * バイナリ通信開始
   |         <KEXINIT(20)>          |
   |<==============================>|  * アルゴリズムネゴシエーション
   |                                |
   |................................|....................................
   |                                |
   |     DH など鍵交換プロトコル    |  * K と H の取得
   |      (30..49番のメッセージ)    |    --> 鍵と IV の生成
   |................................|....................................
   |                                |
   |         <NEYKEYS(21)>          |
   |<==============================>|
   |                                |
   |................................|....................................
   |                                |  * 暗号化、MAC、圧縮の開始

暗号化、MAC、圧縮のアルゴリズムは次に KEXINIT が走り鍵交換されるまで変わりません。

また、最初の NEWKEYS が走るまでの間は、暗号化、MAC、圧縮とも 'none'です。

(暗号化 と MAC の 'none' は仕様では推奨されてません。なので、通常、暗号化 と MAC が 'none' なのはこの最初の間だけです)

鍵のエンコーディング

(鍵のフォーマットの詳細は RFC 4253 を参照してください)

DSA 鍵

DSA 公開鍵は以下のようにエンコーディングします。

DSA 署名

DSA 鍵の署名フォーマットのエンコーディングです。

RSA 鍵

RSA 公開鍵は以下のようにエンコーディングします。

RSA 署名

RSA 鍵の署名フォーマットのエンコーディングです。

署名フォーマットは DSA のそれと同じです。ただし、鍵の識別子は異なります。

署名検証

実際に使う時

OpenSSH の ssh クライアントでは、サーバに初めてアクセスしたとき、サーバホスト鍵を覚えておくか? ということをユーザに問い合わせます。

The authenticity of host '[localhost]:50022 ([127.0.0.1]:50022)' can't be established.
RSA key fingerprint is bd:e3:bf:6a:96:dc:7c:79:77:23:ad:fd:22:c2:09:4b.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[localhost]:50022' (RSA) to the list of known hosts.
上の例では yes と応えています。これで ssh クライアントはサーバホスト鍵を覚えました。

SSH サーバでホスト鍵を更新した後、ssh クライアントがアクセスすると、ホスト鍵が違うといってエラーになります。

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
ef:e3:a9:15:56:e0:30:6c:03:aa:63:25:36:25:7d:fc.
Please contact your system administrator.
Add correct host key in /home/lnznt/.ssh/known_hosts to get rid of this message.
Offending RSA key in /home/lnznt/.ssh/known_hosts:3

 remove with: ssh-keygen -f "/home/lnznt/.ssh/known_hosts" -R [localhost]:50022

RSA host key for [localhost]:50022 has changed and you have requested strict checking.
Host key verification failed.
この時は、メッセージに出ている通り、ホスト鍵の記憶を消去してアクセスしなおします。

ホスト鍵の記憶を消去

$ ssh-keygen -f "/home/lnznt/.ssh/known_hosts" -R [localhost]:50022

暗号、MAC圧縮とDH

暗号

HMAC

HMACダイジェスト鍵長MAC長
hmac-md5MD51616
hmac-md5-96MD51612
hmac-sha1SHA12020
hmac-sha1-96SHA12012

圧縮

DH

DH は以下のようなものです。

 (1) 公開の共通パラメータがある(Oakley Group など)
 (2) A が公開の共通パラメータから DH の公開鍵/私有鍵ペアを作る
 (3) B が公開の共通パラメータから DH の公開鍵/私有鍵ペアを作る
 (4) A は B に自分の公開鍵を渡す
 (5) B は A に自分の公開鍵を渡す
 (6) A は B の公開鍵から DH により共有秘密 K を計算する
 (7) B は A の公開鍵から DH により共有秘密 K を計算する
  A の計算した K と B の計算した K は一致します。
  両者は私有鍵を晒すことなく、共有の秘密鍵を保持したことになります。

SSH では公開の共通パラメータのパラメータとして Oakley Group の P と G を使ったりします。ただし、通常の DH では別の方法で共通パラメータを両者に渡すようです

メッセージ

パケットの '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 を参照してください。

SSH 鍵ファイルのフォーマット

通常使われる OpenSSH の ssh-keygen で作成した公開鍵ファイルのフォーマット*1は以下のようになっています。(~/.ssh/{id_dsa,id_rsa}.pub など)

(DSA の場合)
ssh-dss AACBq3NNHQZWavYnLTpJsZFvwQnWJCKm+RRAAF... foobar@example.org

(RSA の場合)
ssh-rsa AACBq3NNHQZWavYnLTpJsZFvwQnWJCKm+RRAAF... foobar@example.org

1行で1個の鍵なので、鍵が複数個ある場合は複数行になっていると思います。

空白で区切られた 2 番目の文字列が BASE64 でエンコードされた公開鍵です。

(この例では適当な文字列が書かれています。正しくありません)

これらの公開鍵は SSH プロトコルで使用されている以下の形式でエンコーディングされています。

ユーザ認証プロトコル

ユーザ認証プロトコルは、主に RFC4252 の範囲になります。

http://www.ietf.org/rfc/rfc4252.txt

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

ユーザ認証プロトコルでは、ユーザに対する認証を行います。ユーザはサービスの認可を要求してきます。ユーザが認証された場合、要求したサービスが認可されます。

サービスは以下です*2。

サービス名説明
ssh-connectionSSHプロトコルの最上層

認証にはいくつかの認証メソッドがあります。*3

認証メソッド名説明SSH仕様での要求レベル
publickey公開鍵認証REQUIRED
passwordパスワード認証OPTIONAL
hostbasedホストベース認証OPTIONAL
none*4認証なしNOT RECOMMENDED

ユーザ認証プロトコルで使用されるメッセージです。

メッセージ番号方向説明
SSH_MSG_USERAUTH_REQUEST50C->S認証の要求
SSH_MSG_USERAUTH_FAILURE51S->C認証の要求に対する応答(失敗の場合)
SSH_MSG_USERAUTH_SUCCESS52S->C認証の要求に対する応答(成功の場合)
SSH_MSG_USERAUTH_BANNER53S->Cバナーの通知(非同期、随時)

認証メソッドが "publickey" の場合に使用されるメッセージです。

メッセージ番号方向説明
SSH_MSG_USERAUTH_PK_OK60S->C認証の要求に対する応答(部分的な成功の場合)

認証メソッドが "password" の場合に使用されるメッセージです。

メッセージ番号方向説明
SSH_MSG_USERAUTH_PASSWD_CHANGEREQ60S->C(期限切れなどの)パスワードの変更を促す

その他、RFC には、しきい値として

  • 認証失敗限度 20 回*5
  • 認証待ちタイムアウト限度 10分*6
    が SSH 仕様として提示されています。

認証メソッド "none" の場合

 <client>                         <server>
   |  <USERAUTH_REQUEST(50)>        |
   |------------------------------->|
   |                                |
   |        <USERAUTH_FAILURE(51)>  |
   |<-------------------------------|
   |                                |

認証メソッドが "none" の認証要求は失敗させるべきとされています。

クライアントはサーバの応答に含まれる「サーバが継続可能な認証メソッドのリスト」を得ることを期待して、この認証要求を送信します。

メッセージパラメータ内容
USERAUTH_REQUEST (C->S)user_nameユーザ名です
service_nameサービス名です
method_name認証メソッド名です。この場合、"none"です
USERAUTH_FAILURE (S->C)auths_can_continueサーバが継続可能な認証メソッドのリストです(例:["password","publickey"])

認証メソッド "password" (パスワード変更なし)の場合

パスワード変更なしの認証要求の場合は以下のようになります。

 <client>                         <server>
   |  <USERAUTH_REQUEST(50)>        |
   |------------------------------->|
   |                                |
   |        <USERAUTH_SUCCESS(52)>  |
   |<-------------------------------|(※認証成功の場合)
   |                                |
   |        <USERAUTH_FAILURE(51)>  |
   |<-------------------------------|(※認証失敗の場合)
   |                                |
   | <USERAUTH_PASSWD_CHANGEREQ(60)>|
   |<-------------------------------|(※期限切れなどパスワード変更を促す場合)
メッセージパラメータ内容
USERAUTH_REQUEST (C->S)user_nameユーザ名です
service_nameサービス名です
method_name認証メソッド名です。この場合、"password"です
passwordパスワードです
USERAUTH_SUCCESS (S->C)(パラメータはありません。)
USERAUTH_FAILURE (S->C)auths_can_continueサーバが継続可能な認証メソッドのリストです(例:["password","publickey"])
USERAUTH_PASSWD_CHANGEREQ (S->C)promptクライアントに示すプロンプト文字列

認証メソッド "password" (パスワード変更あり)の場合

パスワード変更ありの認証要求の場合は以下のようになります。

 <client>                         <server>
   |  <USERAUTH_REQUEST(50)>        |
   |------------------------------->|
   |                                |
   |        <USERAUTH_SUCCESS(52)>  |
   |<-------------------------------|(※パスワード変更OK、認証OKの場合)
   |                                |
   |        <USERAUTH_FAILURE(51)>  |
   |<-------------------------------|(※パスワード変更OK、認証NGの場合)
   |         [partial_success=true] |
   |                                |
   |        <USERAUTH_FAILURE(51)>  |
   |<-------------------------------|(※パスワード変更未サポート、
   |         [partial_success=false]|   または、旧パスワードNGの場合)
   |                                |
   | <USERAUTH_PASSWD_CHANGEREQ(60)>|
   |<-------------------------------|(※新パスワード受け入れ不可など
                                        パスワード変更を促す場合)
旧パスワード認証パスワード変更新パスワードパスワード認証応答
OKサポート適正有効SUCCESS
OKサポート適正無効FAILURE(partial=true)
---FAILURE(partial=false)
NG---FAILURE(partial=false)
OKサポート不適正有効CHANGEREQ*7
メッセージパラメータ内容
USERAUTH_REQUEST (C->S)user_nameユーザ名です
service_nameサービス名です
method_name認証メソッド名です。この場合、"password"です
with_new_passwordtrue です
old_password旧パスワードです
new_password新パスワードです
USERAUTH_SUCCESS (S->C)(パラメータはありません。)
USERAUTH_FAILURE (S->C)auths_can_continueサーバが継続可能な認証メソッドのリストです(例:["password","publickey"])
partial_successtrue または false。上の図、表のとおりです
USERAUTH_PASSWD_CHANGEREQ (S->C)promptクライアントに示すプロンプト文字列

公開鍵認証

認証メソッド "publickey" は公開鍵認証です。

公開鍵アルゴリズムは任意のものを選択します。(実質的な選択肢は DSS か RSA です)

トランスポート層プロトコルの鍵交換で選択したサーバホスト鍵のアルゴリズムとは無関係に選択できます。

サーバは、

  • ユーザの提示した公開鍵がユーザのものであるか
  • その公開鍵で署名の検証が問題ないか*1

をチェックします。

認証メソッド "publickey"(署名なし) の場合

ユーザは署名なしのリクエストを送信する場合があります。

これは、サーバがその公開鍵アルゴリズムをサポートしているかどうかの事前確認のために行われます。

 <client>                         <server>
   |  <USERAUTH_REQUEST(50)>        |
   |------------------------------->|
   |        [with_signature=false]  |
   |                                |
   |        <USERAUTH_FAILURE(51)>  |
   |<-------------------------------|(※認証NG、その公開鍵アルゴリズムは
   |                                |           サポートされていない)
   |                                |
   |                                |
   |           <USERAUTH_PK_OK(60)> |
   |<-------------------------------|(※リクエストの公開鍵での
   |                                |   検証が可能な場合)
   |                                |
メッセージパラメータ内容
USERAUTH_REQUEST (C->S)user_nameユーザ名です
service_nameサービス名です
method_name認証メソッド名です。この場合、"publickey"です
with_signature署名有無フラグです。この場合 false です
key_algorithm_name鍵アルゴリズム名です。'ssh-dss' や 'ssh-rsa' などです
key_blob公開鍵です。SSH 鍵形式でエンコーディングされてます
USERAUTH_FAILURE (S->C)auths_can_continueサーバが継続可能な認証メソッドのリストです(例:["password","publickey"])
USERAUTH_PK_OK (S->C)key_algorithm_nameUSERAUTH_REQUEST で送られた鍵アルゴリズム名です
key_blobUSERAUTH_REQUEST で送られた公開鍵です

認証メソッド "publickey"(署名あり) の場合

 <client>                         <server>
   |  <USERAUTH_REQUEST(50)>        |
   |------------------------------->|
   |        [with_signature=true,   |
   |              signature=署名]   |
   |                                |
   |        <USERAUTH_FAILURE(51)>  |
   |<-------------------------------|(※認証NG)
   |                                |
   |                                |
   |        <USERAUTH_SUCCESS(52)>  |
   |<-------------------------------|(※認証OK)
   |                                |
   |                                |
メッセージパラメータ内容
USERAUTH_REQUEST (C->S)user_nameユーザ名です
service_nameサービス名です
method_name認証メソッド名です。この場合、"publickey"です
with_signature署名有無フラグです。この場合 true です
key_algorithm_name鍵アルゴリズム名です。'ssh-dss' や 'ssh-rsa' などです
key_blob公開鍵です。SSH 鍵形式でエンコーディングされてます
signature以下のエンコードされたデータに対する、公開鍵(key_blob)のペア私有鍵による署名です
USERAUTH_FAILURE (S->C)auths_can_continueサーバが継続可能な認証メソッドのリストです(例:["password","publickey"])
USERAUTH_SUCCESS (S->C)(パラメータはありません。)

認証メソッド "hostbased" の場合

バナー

 <client>                         <server>
   |                                |
   |           <USERAUTH_BANNER(53)>|
   |<-------------------------------|(※認証プロトコル中随時、任意)

サーバはクライアントにバナーメッセージを送信できます。

通常、クライアントはバナーメッセージをユーザに表示します。

メッセージパラメータ内容
USERAUTH_BANNER (S->C)messageバナーメッセージ

ユーザ認証プロトコルが終わったら

ユーザ認証プロトコルが終わったら、通常コネクションプロトコルに移行します。
認証が成功すると要求していたサービス(通常、'ssh-connection')が認可されます。

コネクションプロトコル

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

http://www.ietf.org/rfc/rfc4254.txt

位置プロトコル提供する機能
最下層トランスポート層プロトコル*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)の割り当て要求sessionx
x11-reqX11転送の要求x11x
env環境変数の設定sessionx
shellシェルのリモート実行sessionリモートログインしてシェルを操作する際に使用される
exec任意のプログラムのリモート実行sessionプログラムのワンショット実行で使用される。また scp でも使用される
subsystemサブシステムのリモート実行sessionsftp など特定のサービス(を行うプログラム)を起動する際に使用される
window-change端末ウィンドウサイズの変更sessionx
xon-xoffX-ON/X-OFFによるフロー制御要求sessionx
signalシグナルの送信sessionx
exit-statusexitステータスの返却sessionx
exit-signalシグナルによるプロセス終了時の終了ステータスの返却sessionx

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

クライアント->サーバ
サーバ->クライアント
のいずれの方向への送信も許されています。

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

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

グローバルリクエストで使用されるメッセージ番号通常の方向説明
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)>  |
   |<-------------------------------| (※失敗の場合)
   |                                |

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

チャネルリクエストのプロトコル

チャネルリクエストのプロトコルで使用されるメッセージです。

チャネルリクエストのプロトコルで使用されるメッセージ番号通常の方向説明
SSH_MSG_CHANNEL_OPEN90C->Sチャネルオープンの要求
SSH_MSG_CHANNEL_OPEN_CONFIRMATION91S->Cチャネルオープンの要求への応答(成功の場合)
SSH_MSG_CHANNEL_OPEN_FAILURE92S->Cチャネルオープンの要求への応答(失敗の場合)
SSH_MSG_CHANNEL_WINDOW_ADJUST93C->S,S->Cウィンドウサイズ調整の通知
SSH_MSG_CHANNEL_DATA94C->S,S->Cデータ転送
SSH_MSG_CHANNEL_EXTENDED_DATA95C->S,S->C拡張データ転送
SSH_MSG_CHANNEL_EOF96C->S,S->CEOFの通知
SSH_MSG_CHANNEL_CLOSE97C->S,S->Cチャネルクローズの通知
SSH_MSG_CHANNEL_REQUEST98C->S,S->Cチャネルリクエスト
SSH_MSG_CHANNEL_SUCCESS99C->S,S->Cチャネルリクエストへの応答(成功の場合)
SSH_MSG_CHANNEL_FAILURE100C->S,S->Cチャネルリクエストへの応答(失敗の場合)

メッセージの方向を記しましたが、これは通常使用される方向です。プロトコル上はチャネルはどちらの方向への要求できます。

メッセージは以下に大別できます。

メッセージ大別メッセージ
チャネルのオープンとクローズに関するものCHANNEL_OPEN(90)
CHANNEL_OPEN_CONFIRMATION(91)
CHANNEL_OPEN_FAILURE(92)
CHANNEL_CLOSE(97)
チャネルリクエストに関するものCHANNEL_REQUEST(98)
CHANNEL_SUCCESS(99)
CHANNEL_FAILURE(100)
データ転送に関するものCHANNEL_WINDOW_ADJUST(93)
CHANNEL_DATA(94)
CHANNEL_EXTENDED_DATA(95)
CHANNEL_EOF(96)

チャネルのオープンとクローズ

 <client>                         <server>
   |  <CHANNEL_OPEN(90)>            |
   |------------------------------->|オープン要求
   |                                |
   | <CHANNEL_OPEN_CONFIRMATION(91)>|
   |<-------------------------------| (※成功の場合)
   |                                |
   |      <CHANNEL_OPEN_FAILURE(92)>|
   |<-------------------------------| (※失敗の場合)
   |                                |
   |................................|
   |                                |
   |  (チャネル間のやりとり...)     |
   |                                |
   |................................|
   |                                |
   |      <CHANNEL_CLOSE(97)>       |クローズ
   |<==============================>|(※送信順不定)
メッセージパラメータ内容
CHANNEL_OPEN(90)
チャネルオープン要求
channel typeチャネルタイプ。"session" など。
sender channel送信側チャネル番号。(通常はクライアント側の番号)
initial window size送信側初期ウィンドウサイズ(後述)
maximum packet size送信側最大パケットサイズ(後述)
以降のパラメータチャネルタイプごとに特有。チャネルタイプ "session" の場合はなし。
CHANNEL_OPEN_CONFIRMATION(91)
成功の場合の返し
recipient channel受信側チャネル番号。(通常はクライアント側の番号)
sender channel送信側チャネル番号。(通常はサーバ側の番号)
initial window size送信側初期ウィンドウサイズ(後述)
maximum packet size送信側最大パケットサイズ(後述)
以降のパラメータチャネルタイプごとに特有。チャネルタイプ "session" の場合はなし。
CHANNEL_OPEN_FAILURE(92)
失敗の場合の返し
recipient channel受信側チャネル番号。(通常はクライアント側の番号)
reason code理由コード(下記)
description説明メッセージ
language tagdescription の言語タグ(RFC3066参照)

CHANNEL_OPEN_FAILURE理由

Symbolic name理由コード
SSH_OPEN_ADMINISTRATIVELY_PROHIBITED1
SSH_OPEN_CONNECT_FAILED2
SSH_OPEN_UNKNOWN_CHANNEL_TYPE3
SSH_OPEN_RESOURCE_SHORTAGE4

チャネルリクエスト

オープンされたチャネルに対してチャネルリクエストを送ることができます。

 <client>                         <server>
   |  <CHANNEL_REQUEST(98)>         |
   |------------------------------->|リクエスト
   |................................|............................
   |                                |※REQUEST の want_reply が true の場合
   |                                |
   |          <CHANNEL_SUCCESS(99)> |
   |<-------------------------------| (※成功の場合)
   |                                |
   |         <CHANNEL_FAILURE(100)> |
   |<-------------------------------| (※失敗の場合)
   |                                |
メッセージパラメータ内容
CHANNEL_REQUEST(98)
チャネルへの要求
recipient channel受信側チャネル番号(通常、サーバ側チャネル番号)
request typeリクエストタイプ
want_reply応答の要/不要フラグ
以降のパラメータrequest type ごとに特有
CHANNEL_SUCCESS(99)
(want_reply が trueで、要求成功の場合に返信)
recipient channel受信側チャネル番号(通常、クライアント側チャネル番号)
CHANNEL_FAILURE(100)
(want_reply が trueで、要求失敗の場合に返信)

データ転送

チャネルのデータ転送ではウィンドウ制御(バイト単位)が行なわれます。

ウィンドウスペースは送信方向毎に以下のように制御されます。

  • 初期値は initial_window_size (CHANNEL_OPEN または CHANNEL_OPEN_CONFIRMATION のもの)です
  • データ転送(CHANNEL_DATA または CHANNEL_EXTENDED_DATA)で消費されます
  • CHANNEL_WINDOW_ADJUST の受信で増加します。

一度に送信できるデータサイズは、

  • ウィンドウサイズ
  • maximum_packet_size (CHANNEL_OPEN または CHANNEL_OPEN_CONFIRMATION)

のいずれか小さい方です。
ウィンドウスペースが残っていない場合は送信できません。

CHANNEL_DATA

<clientまたはserver>             <相手側>
   |  <CHANNEL_DATA(94)>            |
   |------------------------------->|
   |                                |

相手側へデータを転送します。

メッセージパラメータ内容
CHANNEL_DATA(94)recipient channel受信側チャネル番号
dataデータ

CHANNEL_EXTENDED_DATA

<clientまたはserver>             <相手側>
   |  <CHANNEL_EXTENDED_DATA(95)>   |
   |------------------------------->|
   |                                |

相手側へ拡張データタイプを使ってデータを転送します。

メッセージパラメータ内容
CHANNEL_EXTENDED_DATA(95)recipient channel受信側チャネル番号
data type拡張データタイプ(1:SSH_EXTENDED_DATA_STDERR)
dataデータ

拡張データタイプは以下の 1種類が RFC 4254 で定義されています。

Symbolic namedata_type_code
SSH_EXTENDED_DATA_STDERR1

CHANNEL_WINDOW_ADJUST

clientまたはserver> <相手側>

   |  <CHANNEL_WINDOW_ADJUST(93)>   |
   |------------------------------->|
   |                                |

相手から自分側へのウィンドウスペースを増加させます。

メッセージパラメタ内容
CHANNEL_WINDOW_ADJUST(93)recipient channel受信側チャネル番号
bytes_to_add増加するウィンドウサイズ(バイト単位)

CHANNEL_EOF

<clientまたはserver>             <相手側>
   |  <CHANNEL_EOF(96)>             |
   |------------------------------->|
   |                                |

EOF(送信の終了)を通知します。

メッセージパラメタ内容
CHANNEL_EOF(96)recipient channel受信側チャネル番号

チャネルリクエストのタイプ

 <client>                         <server>
   |  <CHANNEL_REQUEST(98)>         |
   |------------------------------->|リクエスト
   |................................|............................
   |                                |※REQUEST の want_reply が true の場合
   |                                |
   |          <CHANNEL_SUCCESS(99)> |
   |<-------------------------------| (※成功の場合)
   |                                |
   |         <CHANNEL_FAILURE(100)> |
   |<-------------------------------| (※失敗の場合)
   |                                |
メッセージパラメータ内容
CHANNEL_REQUEST(98)recipient channel受信側チャネル番号(通常、サーバ側チャネル番号)
request typeリクエストタイプ
want_reply応答の要/不要フラグ
以降のパラメータrequest type ごとに特有

リクエストタイプ "pty-req" (Client -> Server)

リクエストタイプ "pty-req" は後続の shell などで使用する疑似端末の要求です。

CHANNEL_REQUEST フィールド説明
recipient channel受信側チャネル番号(通常、サーバ側チャネル番号)
request typeリクエストタイプ。この場合 "ptr-req"
want reply応答の要/不要フラグ
TERM environment variable value環境変数 TERM の値 (e.g., vt100)
terminal width (characters)端末の幅(文字数) (e.g., 80)。ピクセル数の指定より優先
terminal height (rows)端末の高さ(行数) (e.g., 24)。ピクセル数の指定より優先
terminal width (pixels)端末の幅(ピクセル数) (e.g., 640)
terminal height (pixels)端末の高さ(ピクセル数) (e.g., 480)
encoded terminal modes(符号化された)ターミナルモード

ターミナルモードは以下のようなストリームです。

[opcode + argument ], [opcode + argument], [opcode + argument] ...
  • opcode は byte 型です
  • opcode 0 はストリームの終了を表します
  • opcode 1 ~ 159 は uint32 型の argument を持ちます
  • それ以外の opcode は未定義です

opcode は RFC 4254 で定義(欠番あり)されています。(以下、一部抜粋)

         opcode  mnemonic       description
         ------  --------       -----------
         0     TTY_OP_END  Indicates end of options.
         1     VINTR       Interrupt character; 255 if none.  Similarly
                            for the other characters.  Not all of these
                            characters are supported on all systems.
         2     VQUIT       The quit character (sends SIGQUIT signal on
                            POSIX systems).
         3     VERASE      Erase the character to left of the cursor.
         4     VKILL       Kill the current input line.
                    (以下、略)

http://www.ietf.org/rfc/rfc4254.txt

リクエストタイプ "env" (Client -> Server)

リクエストタイプ "env" は環境変数の設定の要求です。

CHANNEL_REQUEST フィールド説明
recipient channel受信側チャネル番号(通常、サーバ側チャネル番号)
request typeリクエストタイプ。この場合 "env"
want reply応答の要/不要フラグ
variable name環境変数の名前 (e.g., LANG)
variable value環境変数の値 (e.g., ja_JP.UTF-8)

リクエストタイプ "shell" (Client -> Server)

リクエストタイプ "shell" はプログラム(ユーザのデフォルトシェル)の起動の要求です。

CHANNEL_REQUEST フィールド説明
recipient channel受信側チャネル番号(通常、サーバ側チャネル番号)
request typeリクエストタイプ。この場合 "shell"
want reply応答の要/不要フラグ

リクエストタイプ "exec" (Client -> Server)

リクエストタイプ "exec" はプログラム(任意のコマンド)の起動の要求です。

CHANNEL_REQUEST フィールド説明
recipient channel受信側チャネル番号(通常、サーバ側チャネル番号)
request typeリクエストタイプ。この場合 "exec"
want reply応答の要/不要フラグ
command起動を要求するコマンド (e.g, hostname)

リクエストタイプ "subsystem" (Client -> Server)

リクエストタイプ "subsystem" はプログラム(サブシステム)の起動の要求です。

CHANNEL_REQUEST フィールド説明
recipient channel受信側チャネル番号(通常、サーバ側チャネル番号)
request typeリクエストタイプ。この場合 "subsystem"
want reply応答の要/不要フラグ
subsystemサブシステムの名前(e.g., sftp)

リクエストタイプ "exit-status" (Server -> Client)

リクエストタイプ "exit-status" は終了ステータスの返却です。

CHANNEL_REQUEST フィールド説明
recipient channel受信側チャネル番号(通常、クライアント側チャネル番号)
request typeリクエストタイプ。この場合 "exit-status"
want reply応答の要/不要フラグ。この場合 false
exit_status終了ステータス(e.g., 0)

リクエストタイプ "exit-signal" (Server -> Client)

リクエストタイプ "exit-signal" はシグナルによる終了の通知です。

CHANNEL_REQUEST フィールド説明
recipient channel受信側チャネル番号(通常、クライアント側チャネル番号)
request typeリクエストタイプ。この場合 "exit-signal"
want reply応答の要/不要フラグ。この場合 false
signal nameシグナル名 (下記)
core dumpedコアダンプしたか否かのフラグ
error messageエラーメッセージ
language tagerror message の言語タグ(RFC3066参照)

シグナル名は以下のように RFC で定義されています*1。

           ABRT
           ALRM
           FPE
           HUP
           ILL
           INT
           KILL
           PIPE
           QUIT
           SEGV
           TERM
           USR1
           USR2

ちなみに、Ubuntu Linux でのシグナルの一覧です。(kill -l)

$ kill -l
 1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP
 6) SIGABRT	 7) SIGBUS	 8) SIGFPE	 9) SIGKILL	10) SIGUSR1
11) SIGSEGV	12) SIGUSR2	13) SIGPIPE	14) SIGALRM	15) SIGTERM
16) SIGSTKFLT	17) SIGCHLD	18) SIGCONT	19) SIGSTOP	20) SIGTSTP
21) SIGTTIN	22) SIGTTOU	23) SIGURG	24) SIGXCPU	25) SIGXFSZ
26) SIGVTALRM	27) SIGPROF	28) SIGWINCH	29) SIGIO	30) SIGPWR
31) SIGSYS	34) SIGRTMIN	35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3
38) SIGRTMIN+4	39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12	47) SIGRTMIN+13
48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14	51) SIGRTMAX-13	52) SIGRTMAX-12
53) SIGRTMAX-11	54) SIGRTMAX-10	55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7
58) SIGRTMAX-6	59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
63) SIGRTMAX-1	64) SIGRTMAX

リクエストタイプ "signal" (Client -> Server)

リクエストタイプ "signal" はシグナルの通知です。

CHANNEL_REQUEST フィールド説明
recipient channel受信側チャネル番号(通常、サーバ側チャネル番号)
request typeリクエストタイプ。この場合 "signal"
want reply応答の要/不要フラグ。この場合 false
signal nameシグナル名 (上記)

リクエストタイプ "window-change" (Client -> Server)

リクエストタイプ "window-change" は端末のサイズ変更の通知です。

CHANNEL_REQUEST フィールド説明
recipient channel受信側チャネル番号(通常、サーバ側チャネル番号)
request typeリクエストタイプ。この場合 "window-change"
want reply応答の要/不要フラグ。この場合 false
terminal width (characters)端末の幅(文字数) (e.g., 80)。ピクセル数の指定より優先
terminal height (rows)端末の高さ(行数) (e.g., 24)。ピクセル数の指定より優先
terminal width (pixels)端末の幅(ピクセル数) (e.g., 640)
terminal height (pixels)端末の高さ(ピクセル数) (e.g., 480)

リクエストタイプ "xon-xoff" (Server -> Client)

リクエストタイプ "xon-xoff" はフロー制御の可否通知です。

CHANNEL_REQUEST フィールド説明
recipient channel受信側チャネル番号(通常、クライアント側チャネル番号)
request typeリクエストタイプ。この場合 "xon-off"
want reply応答の要/不要フラグ。この場合 false
client can doフロー制御をクライアントが行えるかの可否

リクエストタイプ "x11-req"

説明を割愛します。(詳細は RFC4254 を参照)

リクエストタイプ "break"

CHANNEL_REQUEST フィールド説明
recipient channel受信側チャネル番号(通常、クライアント側チャネル番号)
request typeリクエストタイプ。この場合 "break"
  • portsshdの場合は、このリクエストタイプ受信で、TTYにBREAK信号を送信する

リクエストタイプ "keepalive@openssh.com" (などの未定義なタイプ)...SSH KEEPALIVE

  • リクエストタイプ "keepalive@openssh.com"は、SSHのkeepaliveの送信に利用しています。
    CHANNEL_REQUEST フィールド説明
    recipient channel受信側チャネル番号
    request type"keepalive@openssh.com" (などの未定義なタイプ)
  • 上記のチャネルリクエストを受けた場合、以下のどれかが返ることで、keepaliveを実現します
    メッセージ番号
    SSH_MSG_REQUEST_FAILURE82
    SSH_MSG_UNIMPLEMENTED3
    SSH_MSG_IGNORE2
  • これらのメッセージを送受信した場合でも、idle-timeoutは継続するように実装されています(dropbearで確認)