SSHプロトコル備忘録
- ページ: システム/AI?
- 投稿者: 名無しさん
- 優先順位: 低
- 状態: 提案
- カテゴリー:
- 投稿日: 2014-10-06 (月) 09:49:30
- バージョン:
#snapshot
- SSHプロトコル備忘録
- トランスポート層プロトコル
- トランスポート層(SSHプロトコル)の下
- プロトコルバージョンの交換
- シーケンスナンバー
- アルゴリズムネゴシエーション
- KEXINIT 以降
- DH 鍵合意
- KEXDH_INIT (Client -> Server)
- KEXDH_REPLY (Server -> Client)
- 共有秘密 K と 交換ハッシュ H
- 出力された鍵
- DH 鍵合意 (GEX)
- KEX_DH_GEX_REQUEST (Client -> Server)
- KEX_DH_GEX_GROUP (Server -> Client)
- KEX_DH_GEX_INIT (Client -> Server)
- KEX_DH_GEX_REPLY (Server -> Client)
- 共有秘密 K と 交換ハッシュ H
- 出力された鍵
- 鍵 と IV の生成
- 暗号化、MAC、圧縮の開始
- 鍵のエンコーディング
- 署名検証
- 暗号、MAC圧縮とDH
- メッセージ
- トランスポート層のメッセージ
- サービス要求メッセージ
- トランスポート層一般のメッセージ
- SSH 鍵ファイルのフォーマット
- ユーザ認証プロトコル
- コネクションプロトコル
- グローバルリクエストのプロトコル
- チャネルリクエストのプロトコル
- チャネルのオープンとクローズ
- チャネルリクエスト
- データ転送
- CHANNEL_DATA
- CHANNEL_EXTENDED_DATA
- CHANNEL_WINDOW_ADJUST
- CHANNEL_EOF
- チャネルリクエストのタイプ
- リクエストタイプ "pty-req" (Client -> Server)
- リクエストタイプ "env" (Client -> Server)
- リクエストタイプ "shell" (Client -> Server)
- リクエストタイプ "exec" (Client -> Server)
- リクエストタイプ "subsystem" (Client -> Server)
- リクエストタイプ "exit-status" (Server -> Client)
- リクエストタイプ "exit-signal" (Server -> Client)
- リクエストタイプ "signal" (Client -> Server)
- リクエストタイプ "window-change" (Client -> Server)
- リクエストタイプ "xon-xoff" (Server -> Client)
- リクエストタイプ "x11-req"
- リクエストタイプ "break"
- リクエストタイプ "keepalive@openssh.com" (などの未定義なタイプ)...SSH KEEPALIVE
トランスポート層プロトコル
トランスポート層プロトコルは、主に 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_algorithms | KEX(鍵交換)アルゴリズム |
server_host_key_algorithms | ホスト鍵アルゴリズム |
encryption_algorithms_client_to_server | 対称暗号アルゴリズム(クライアントtoサーバ) |
encryption_algorithms_server_to_client | 対称暗号アルゴリズム(サーバtoクライアント) |
mac_algorithms_client_to_server | MACアルゴリズム(クライアントtoサーバ) |
mac_algorithms_server_to_client | MACアルゴリズム(サーバ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-sha1 | REQUIRED | ||
diffie-hellman-group1-sha1 | REQUIRED | ||
ホスト鍵 | ssh-dss | REQUIRED | ○ |
ssh-rsa | RECOMMENDED | ||
対称暗号 | aes128-cbc | RECOMMENDED | ○ |
aes256-cbc | |||
aes192-cbc | |||
blowfish-cbc | |||
cast128-cbc | |||
3des-cbc | REQUIRED | ||
MAC | hmac-sha1 | REQUIRED | |
hmac-sha1-96 | RECOMMENDED | ||
hmac-md5 | ○ | ||
hmac-md5-96 | |||
圧縮 | none | REQUIRED | ○ |
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_INIT | 30 |
SSH_MSG_KEXDH_REPLY | 31 |
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 の意味合いは、鍵交換のアルゴリズムに関わらず同じです。
内容 | |
共有秘密 K | DH により計算される共有鍵 |
交換ハッシュ H | K やその他のプロトコルのパラメータの連結文字列から生成するハッシュ。 |
セッション識別子 | 最初の 交換ハッシュ 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_OLD | 30 | 後方互換性のため残されている |
SSH_MSG_KEX_DH_GEX_REQUEST | 34 | |
SSH_MSG_KEX_DH_GEX_GROUP | 31 | |
SSH_MSG_KEX_DH_GEX_INIT | 32 | |
SSH_MSG_KEX_DH_GEX_REPLY | 33 |
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 を返信します。
パラメータは以下です。
パラメータ | 内容 |
p | DH パラメータの p |
g | DH パラメータの 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 の意味合いは、鍵交換のアルゴリズムに関わらず同じです。
パラメータ | 内容 |
共有秘密 K | DH により計算される共有鍵 |
交換ハッシュ H | K やその他のプロトコルのパラメータの連結文字列から生成するハッシュ。 |
セッション識別子 | 最初の 交換ハッシュ 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-md5 | MD5 | 16 | 16 |
hmac-md5-96 | MD5 | 16 | 12 |
hmac-sha1 | SHA1 | 20 | 20 |
hmac-sha1-96 | SHA1 | 20 | 12 |
圧縮
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' にはメッセージが格納されます。
メッセージの最初のフィールドは以下のようになっています。
型 | フィールド名 | 説明 |
byte | type | メッセージ番号 |
... | ... | (以降のフィールドはメッセージ毎に定義されている) |
メッセージ番号はメッセージの種類を示します。以下のようにカテゴライズされています。
カテゴリ | 番号 | 説明 |
トランスポート層プロトコル | 1 .. 19 | トランスポート層一般 |
20 .. 29 | アルゴリズムのネゴシエーション | |
30 .. 49 | 鍵交換方式ごとに特有(再利用可能) | |
認証プロトコル | 50 .. 59 | ユーザ認証一般 |
60 .. 79 | ユーザ認証法ごとに特有(再利用可能) | |
コネクション・プロトコル | 80 .. 89 | コネクションプロトコル一般 |
90 .. 127 | チャネルに関連したメッセージ | |
クライアントプロトコルのための予約 | 128 .. 191 | 予約 |
ローカルな拡張 | 192 .. 255 | ローカルな拡張 |
再利用可能と説明されているカテゴリは、メッセージ番号に対応するメッセージがアルゴリズムやスキームによって決まります。
トランスポート層のメッセージ
番号 | メッセージ | 方向 | 備考 |
1 | DISCONNECT | C->S, S->C | |
2 | IGNORE | C->S, S->C | |
3 | UNIMPLEMENTED | C->S, S->C | |
4 | DEBUG | C->S, S->C | |
5 | SERVICE_REQUEST | C->S | |
6 | SERVICE_ACCEPT | S->C | |
-- | ---- | ---- | ---- |
20 | KEXINIT | C->S, S->C | |
21 | NEWKEYS | C->S, S->C | |
-- | ---- | ---- | ---- |
30 | KEXDH_INIT | C->S | 鍵交換法が DH の場合 |
31 | KEXDH_REPLY | S->C | 鍵交換法が DH の場合 |
-- | ---- | ---- | ---- |
30 | KEX_DH_GEX_REQUEST_OLD | 後方互換性のため残されている | |
31 | KEX_DH_GEX_GROUP | S->C | 鍵交換法が DH(GEX) の場合 |
32 | KEX_DH_GEX_INIT | C->S | 鍵交換法が DH(GEX) の場合 |
33 | KEX_DH_GEX_REPLY | S->C | 鍵交換法が DH(GEX) の場合 |
34 | KEX_DH_GEX_REQUEST | C->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-connection | SSHプロトコルの最上層 |
認証にはいくつかの認証メソッドがあります。*3
認証メソッド名 | 説明 | SSH仕様での要求レベル |
publickey | 公開鍵認証 | REQUIRED |
password | パスワード認証 | OPTIONAL |
hostbased | ホストベース認証 | OPTIONAL |
none*4 | 認証なし | NOT RECOMMENDED |
ユーザ認証プロトコルで使用されるメッセージです。
メッセージ | 番号 | 方向 | 説明 |
SSH_MSG_USERAUTH_REQUEST | 50 | C->S | 認証の要求 |
SSH_MSG_USERAUTH_FAILURE | 51 | S->C | 認証の要求に対する応答(失敗の場合) |
SSH_MSG_USERAUTH_SUCCESS | 52 | S->C | 認証の要求に対する応答(成功の場合) |
SSH_MSG_USERAUTH_BANNER | 53 | S->C | バナーの通知(非同期、随時) |
認証メソッドが "publickey" の場合に使用されるメッセージです。
メッセージ | 番号 | 方向 | 説明 |
SSH_MSG_USERAUTH_PK_OK | 60 | S->C | 認証の要求に対する応答(部分的な成功の場合) |
認証メソッドが "password" の場合に使用されるメッセージです。
メッセージ | 番号 | 方向 | 説明 |
SSH_MSG_USERAUTH_PASSWD_CHANGEREQ | 60 | S->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_password | true です | |
old_password | 旧パスワードです | |
new_password | 新パスワードです | |
USERAUTH_SUCCESS (S->C) | (パラメータはありません。) | |
USERAUTH_FAILURE (S->C) | auths_can_continue | サーバが継続可能な認証メソッドのリストです(例:["password","publickey"]) |
partial_success | true または 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_name | USERAUTH_REQUEST で送られた鍵アルゴリズム名です |
key_blob | USERAUTH_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 | プログラムのリモート実行 |
x11 | X11クライアント接続 |
forwarded-tcpip | 内向きTCPフォワーディング |
direct-tcpip | 外向きTCPフォワーディング |
チャネルにはリクエストが定義されています*3。リクエストは以下のものに大別できます。
リクエスト大別 | 種類 | 内容 | チャネルタイプ | 相手側プログラム実行 |
グローバルリクエスト (接続全体に影響するリクエスト) | tcpip-forward | TCPフォワーディングのリクエスト | - | - |
cancel-tcpip-forward | TCPフォワーディングのキャンセル | - | - | |
チャネルリクエスト ( 特定のチャネルに対するリクエスト) | pty-req | 疑似端末(pty)の割り当て要求 | session | x |
x11-req | X11転送の要求 | x11 | x | |
env | 環境変数の設定 | session | x | |
shell | シェルのリモート実行 | session | リモートログインしてシェルを操作する際に使用される | |
exec | 任意のプログラムのリモート実行 | session | プログラムのワンショット実行で使用される。また scp でも使用される | |
subsystem | サブシステムのリモート実行 | session | sftp など特定のサービス(を行うプログラム)を起動する際に使用される | |
window-change | 端末ウィンドウサイズの変更 | session | x | |
xon-xoff | X-ON/X-OFFによるフロー制御要求 | session | x | |
signal | シグナルの送信 | session | x | |
exit-status | exitステータスの返却 | session | x | |
exit-signal | シグナルによるプロセス終了時の終了ステータスの返却 | session | x |
プロトコル上はリクエストは、
クライアント->サーバ
サーバ->クライアント
のいずれの方向への送信も許されています。
グローバルリクエストのプロトコル
グローバルリクエストで使用されるメッセージです。
グローバルリクエストで使用されるメッセージ | 番号 | 通常の方向 | 説明 |
SSH_MSG_GLOBAL_REQUEST | 80 | C->S | リクエスト |
SSH_MSG_REQUEST_SUCCESS | 81 | S->C | リクエストの応答(成功の場合) |
SSH_MSG_REQUEST_FAILURE | 82 | S->C | リクエストの応答(失敗の場合) |
メッセージの流れです。
サーバはリクエストの want_reply が true の場合に応答します。
<client> <server> | <GLOBAL_REQUEST(80)> | |------------------------------->| |................................|............................ | |※REQUEST の want_reply が true の場合 | <REQUEST_SUCCESS(51)> | |<-------------------------------| (※成功の場合) | | | <REQUEST_FAILURE(82)> | |<-------------------------------| (※失敗の場合) | |
メッセージのパラメータの詳細については割愛します。
チャネルリクエストのプロトコル
チャネルリクエストのプロトコルで使用されるメッセージです。
チャネルリクエストのプロトコルで使用されるメッセージ | 番号 | 通常の方向 | 説明 |
SSH_MSG_CHANNEL_OPEN | 90 | C->S | チャネルオープンの要求 |
SSH_MSG_CHANNEL_OPEN_CONFIRMATION | 91 | S->C | チャネルオープンの要求への応答(成功の場合) |
SSH_MSG_CHANNEL_OPEN_FAILURE | 92 | S->C | チャネルオープンの要求への応答(失敗の場合) |
SSH_MSG_CHANNEL_WINDOW_ADJUST | 93 | C->S,S->C | ウィンドウサイズ調整の通知 |
SSH_MSG_CHANNEL_DATA | 94 | C->S,S->C | データ転送 |
SSH_MSG_CHANNEL_EXTENDED_DATA | 95 | C->S,S->C | 拡張データ転送 |
SSH_MSG_CHANNEL_EOF | 96 | C->S,S->C | EOFの通知 |
SSH_MSG_CHANNEL_CLOSE | 97 | C->S,S->C | チャネルクローズの通知 |
SSH_MSG_CHANNEL_REQUEST | 98 | C->S,S->C | チャネルリクエスト |
SSH_MSG_CHANNEL_SUCCESS | 99 | C->S,S->C | チャネルリクエストへの応答(成功の場合) |
SSH_MSG_CHANNEL_FAILURE | 100 | C->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 tag | description の言語タグ(RFC3066参照) |
CHANNEL_OPEN_FAILURE理由
Symbolic name | 理由コード |
SSH_OPEN_ADMINISTRATIVELY_PROHIBITED | 1 |
SSH_OPEN_CONNECT_FAILED | 2 |
SSH_OPEN_UNKNOWN_CHANNEL_TYPE | 3 |
SSH_OPEN_RESOURCE_SHORTAGE | 4 |
チャネルリクエスト
オープンされたチャネルに対してチャネルリクエストを送ることができます。
<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 name | data_type_code |
SSH_EXTENDED_DATA_STDERR | 1 |
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 tag | error 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"
- RFC4335で追加定義
http://www.ietf.org/rfc/rfc4335.txt
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_FAILURE 82 SSH_MSG_UNIMPLEMENTED 3 SSH_MSG_IGNORE 2
- これらのメッセージを送受信した場合でも、idle-timeoutは継続するように実装されています(dropbearで確認)