SSH 连接协议

3 篇文章 0 订阅

前言

这篇文章时在吾之理解的基础上,加以翻译,其中肯定包含很多个人理解的东西,
如有不对之处,请赐教!

信道机制 Channel Mechanism

所有的终端会话,转发连接等等都是信道。
任何一方都可以打开一个信道。多个信道是复用同一个连接。

通信双方是根据编号来识别信道的。通信双方所涉及到的同一个信道的编号可能是不一样的(因为其用的是各自本机的编号)。打开信道的请求应该包含发送方的信道编号。其他信道有关的消息应该包含接收方的信道编号。

信道是通过流来控制的。在没有明确的指示窗口空间为可用之前,都不可以向信道发送数据。如何明确指示呢?就是通过发送一个消息,来告诉对方,这个信道可用!

打开一个信道 Opening a Channel

当任何一方希望打开一个新的信道,其会为该信道分配一个本地编号。
接着发送以下消息到另一方,并且在消息中要包含本地信道编号和初始化窗口大小。

 byte      SSH_MSG_CHANNEL_OPEN
 string    channel type in US-ASCII only
 uint32    sender channel
 uint32    initial window size
 uint32    maximum packet size
 ....      channel type specific data follows

channel type 是个名称,其在【SSH-ARCH】和【SSH-NUMBERS】中有描述,其具有类似的扩展机制。

sender channel 是本消息的发送方用于识别信道的一个本地标识。

initial window size 在没有调整窗口大小的情况下,可以通过信道发送多少字节数据给本消息的发送方。
maximum packet size 指定可以发送给本消息的发送方的单个最大数据包的大小。

例如:可能希望在交互式连接中使用较小的数据包,使得在慢连接中获得更好的交互响应。

然后,远程端(另一方)决定是否打开这个信道,并且响应SSH_MSG_CHANNEL_OPEN_CONFIRMATION或者SSH_MSG_CHANNEL_OPEN_FAILURE

byte      SSH_MSG_CHANNEL_OPEN_CONFIRMATION
uint32    recipient channel
uint32    sender channel
uint32    initial window size
uint32    maximum packet size
....      channel type specific data follows

recipient channel 是 原打开信道请求中给出的信道编号,并且sender channel是另一方分配的信道编号。

byte      SSH_MSG_CHANNEL_OPEN_FAILURE
uint32    recipient channel
uint32    reason code
string    description in ISO-10646 UTF-8 encoding [RFC3629]
string    language tag [RFC3066]

说明:
RFC3629
RFC3066

如果SSH_MSG_CHANNEL_OPEN消息的接收方不支持指定的channel type,其只需要简单的响应SSH_MSG_CHANNEL_OPEN_FAILURE
客户端可将description字符串信息显示给使用者。如果这样做了,客户端软件应该采取在SSH-ARCH中讨论的预防措施。

SSH_MSG_CHANNEL_OPEN_FAILURE 消息中的reason code的值早已定义好了如下表。注意,下面的reason code的值为了可读性给出的是十进制,但是它们实际是uint32

Symbolic namereason code
SSH_OPEN_ADMINISTRATIVELY_PROHIBITED1
SSH_OPEN_CONNECT_FAILED2
SSH_OPEN_UNKNOWN_CHANNEL_TYPE3
SSH_OPEN_RESOURCE_SHORTAGE4

要请求为SSH_MSG_CHANNEL_OPEN分配新的范围在0x000000050xFDFFFFFF之间的reason_code值(及相关的description文本),必须使用IETF CONSENSUS方法,见[RFC2434]。信道连接失败时,在0xFE0000000xFFFFFFFF范围的值,IANA不会分配给reason code
该范围内的信道连接失败的reason code值留给PRIVATE USE。见【RFC2434】。

虽然IANA不会控制0xFE0000000xFFFFFFFF这个范围的值,但是,这个范围的值,会被分割成两个部分,并通过以下的约定来管理。

  • 0xFE0000000xFEFFFFFF将与本地分配的信道一起使用。例如,如果提议打开一个channel typeexample_session@example.com的信道,但是失败了,接着响应将包含一个IANA分配的reason code,其范围为0x000000010xFDFFFFFF,或者是本地分配的值,其范围是在0xFE0000000xFEFFFFFF。自然的,如果服务器不理解提议的channel type,那么如果发送reason code,则必须为0x00000003。如果服务器理解channel type,但是该信道仍然打开失败,接着服务器应响应一个本地分配的和提议中相一致的reason code
    假设系统实现人员首先尝试使用IANA分配的reason code的值,然后再使用他们本地分配的reason code的值。
  • 对于从0xFF开始的范围没有任何限制,其一般用于测试。

数据传输

窗口大小规定在对方必须等待窗口调整之前,可以发送多少字节。
双方使用下面消息格式来调整窗口。

byte      SSH_MSG_CHANNEL_WINDOW_ADJUST
uint32    recipient channel
uint32    bytes to add

在收到这个消息之后,接收方可能发送给定的字节数要多于以前允许的字节数(感觉是句废话);窗口大小是增量。系统实现必须正确的处理2^32-1字节的窗口大小。窗口大小的增加不能超过2^32-1字节。

数据传输时通过下面类型的消息实现的:

byte      SSH_MSG_CHANNEL_DATA
uint32    recipient channel
string    data

数据的最大长度是由信道中最大包的大小与当前窗口大小中最小者来决定的。窗口大小会根据已发送的数据进行递减。双方都可以忽略掉当可用的窗口空间耗尽后,发送的所有额外数据。

系统实现预计会对SSH传输层数据包的大小会有限制(对于接收包的任何限制必须大于等于32768字节,见SSH-TRANS
SSH连接层实现:

  • 决不能公布数据包的最大大小,否则可能会产生比传输层可接收大的数据包。
  • 决不能生成比传输层可发送的还要大的数据包,即使远程端可以接收非常大的包。

此外,有些信道可以传输几种类型的数据。例如:来自交互式会话的stderr数据。这种数据可以通过SSH_MSG_CHANNEL_EXTENDED_DATA消息格式传送,其使用一个整数来指定数据类型。可用的类型和他们的解释依赖于信道类型。

byte      SSH_MSG_CHANNEL_EXTENDED_DATA
uint32    recipient channel
uint32    data_type_code
string    data

通过该消息发送的数据,和普通消息消耗的窗口空间相同。

目前,只定义了以下类型。注意,为了可读性,data_type_code显示是十进制,其实实际是uint32

Symbolic name                  data_type_code
  -------------                  --------------
SSH_EXTENDED_DATA_STDERR               1

扩展信道数据传输中的data_type_code的值,必须按顺序分配。
请求分配新的扩展信道数据传输的data_type_code的值的范围0x000000020xFDFFFFFFdata_type_code和相关的data都是通过IETF CONSENSUS方法,详情见RFC2434IANA不会分配0xFE0000000xFFFFFFFF的值给data_type_code。该范围内的扩展信道数据传输中的data_type_code的值是留给PRIVATE USE,见RFC2434。如上所述,关于IANA的说明,见SSH-NUMBERS

关闭一个信道

当一方不打算再发送更多的数据给信道时,其应该发送SSH_MSG_CHANNEL_EOF

byte      SSH_MSG_CHANNEL_EOF
uint32    recipient channel

对本消息不发送明确响应。但是,应用软件可以给信道的另一端发送EOF
注意,在发送本消息之后,信道依然是保持打开,并且对方依然可以发送更多数据。本消息不会消耗窗口空间,也就是即使没有可利用的窗口空间,依然可以发送本消息。

当任何一方希望终止信道时,其应该发送SSH_MSG_CHANNEL_CLOSE
一方收到本消息后,另一方必须也发送SSH_MSG_CHANNEL_CLOSE,除非其之前已经发送过了。信道 在 一方 发送并接收到SSH_MSG_CHANNEL_CLOSE时视为关闭,这时,该方可以重用该信道编号。任何一方可以在没有发送或者接收到SSH_MSG_CHANNEL_EOF时,发送SSH_MSG_CHANNEL_CLOSE

byte      SSH_MSG_CHANNEL_CLOSE
uint32    recipient channel

本消息不会消耗窗口空间,也就是即使没有可利用的窗口空间,依然可以发送本消息。

推荐如果可以的话,应该把在本消息发送之前的所有数据都递送到目的地。

特定信道的请求

许多channel type都有特定于channel type的扩展。例如,为交互式会话请求一个pty(伪终端)。

所有的 特定信道的请求 都使用下面的形式:

byte      SSH_MSG_CHANNEL_REQUEST
uint32    recipient channel
string    request type in US-ASCII characters only
boolean   want reply
....      type-specific data follows

如果want replyfalse,将不会对本请求发送响应。否则,接收方响应给另一方为SSH_MSG_CHANNEL_SUCCESSSSH_MSG_CHANNEL_FAILURE或者特定请求的延续消息。
如果请求不被识别或者是该信道不支持,返回SSH_MSG_CHANNEL_FAILURE

本消息不会消耗窗口空间,也就是即使没有可利用的窗口空间,依然可以发送本消息。request type的值对于每个channel type是局部的。

客户端可以继续发送消息,而不需要等待该请求的响应。

request type 名称遵循DNS扩展命名惯例,详见SSH-ARCHSSH-NUMBERS

byte      SSH_MSG_CHANNEL_SUCCESS
uint32    recipient channel
byte      SSH_MSG_CHANNEL_FAILURE
uint32    recipient channel

本消息不会消耗窗口空间,也就是即使没有可利用的窗口空间,依然可以发送本消息。

交互式 会话

会话是远程执行一个程序。程序可能是一个shell,一个应用程序,一个系统命令或者某些内置的子系统。它可以有也可以没有tty,可以涉及也可以不涉及X11转发。多个会话可以同时活动。

打开一个会话

通过发送以下消息开启一个会话。

byte      SSH_MSG_CHANNEL_OPEN
string    "session"
uint32    sender channel
uint32    initial window size
uint32    maximum packet size

客户端系统实现应该拒绝任何打开会话信道的请求,来加大通过已被攻破的服务器 攻击客户端的难度。

通俗的说:会话信道只能是客户端请求服务端,而不能服务端请求客户端。

请求一个伪终端

通过发送下面消息来为会话 分配一个伪终端

byte      SSH_MSG_CHANNEL_REQUEST
uint32    recipient channel
string    "pty-req"
boolean   want_reply
string    TERM environment variable value (e.g., vt100)
uint32    terminal width, characters (e.g., 80)
uint32    terminal height, rows (e.g., 24)
uint32    terminal width, pixels (e.g., 640)
uint32    terminal height, pixels (e.g., 480)
string    encoded terminal modes

encoded terminal modes 在 第8节有描述。尺寸参数为0的必须忽略。character或者row 尺寸覆盖pixel尺寸(当不为0)。Pixel尺寸指窗口可绘制区域。

尺寸参数只为提示。

客户端应该忽视掉pty请求

X11 转发

请求X11转发

会话通过发送一个SSH_MSG_CHANNEL_REQUEST消息来请求X11转发。

byte      SSH_MSG_CHANNEL_REQUEST
uint32    recipient channel
string    "x11-req"
boolean   want reply
boolean   single connection
string    x11 authentication protocol
string    x11 authentication cookie
uint32    x11 screen number

推荐发送的x11 authentication cookie是一个假的、随机的cookie,当连接请求被接收时,检查该cookie并替换真的cookie

当会话信道关闭时,X11 连接转发应该关闭。但是当会话信道关闭时,已经打开的转发不应该自动关闭。

如果single connectiontrue,只应转发单个连接。在第一个连接之后,或者会话信道关闭之后,均不会转发更多的连接。

x11 authentication protocol 是所使用X11验证方法的名称。如:MIT-MAGIC-COOKIE-1

x11 authentication cookie 必须是十六进制编码。

X 协议文档 详见 SCHEIFLER

X11 信道

X11 信道通过打开信道请求来打开。所打开的信道独立于会话,关闭会话信道不会关闭X11转发信道。

byte      SSH_MSG_CHANNEL_OPEN
string    "x11"
uint32    sender channel
uint32    initial window size
uint32    maximum packet size
string    originator address (e.g., "192.168.7.38")
uint32    originator port

接收方应该响应SSH_MSG_CHANNEL_OPEN_CONFIRMATION或者SSH_MSG_CHANNEL_OPEN_FAILURE

如果系统没有实现X11信道转发请求,那么其得拒绝任何打开X11信道请求。

环境变量传递

环境变量可以被传递给后续将启动的shell/command
在一个享有特权的进程中设置不被控制的环境变量是安全风险的。
推荐系统实现维持一个允许的变量名称列表或者只在没有特权的服务器进程中进行环境变量的设置。

byte      SSH_MSG_CHANNEL_REQUEST
uint32    recipient channel
string    "env"
boolean   want reply
string    variable name
string    variable value

启动一个Shell 或者一个 Command

一旦会话被设定,远程端将启动一个程序。这个程序可以是一个shell、一个应用程序或者一个与主机名称无关的子系统。
每个信道只会有一个请求会成功。

byte      SSH_MSG_CHANNEL_REQUEST
uint32    recipient channel
string    "shell"
boolean   want reply

该消息将会请求启动远程端用户默认的shell(通常是在UNIX系统中的/etc/passwd)。

byte      SSH_MSG_CHANNEL_REQUEST
uint32    recipient channel
string    "exec"
boolean   want reply
string    command

byte      SSH_MSG_CHANNEL_REQUEST
uint32    recipient channel
string    "exec"
boolean   want reply
string    command

这个消息将请求服务器开始执行给定的命令。command字串可包含一个路径。必须采取一般性措施来防止执行未经授权的命令。

byte      SSH_MSG_CHANNEL_REQUEST
uint32    recipient channel
string    "subsystem"
boolean   want reply
string    subsystem name

最后这个消息时用于执行一个预定义的子系统。可预计该行为将包含一个通用的文件传输机制,和可能的其他功能。系统实现也可需要设置更多的机制。由于通常是用户的shell来执行子系统,建议子系统协议在协议在传输开始包含一个magic cookie,来区别shell初始化脚本等生成的任意输出。这些shell的伪输出可以在服务器或者客户端中过滤掉。

当启动一个shell或者一个程序时,服务器不应该停止执行协议栈。所有的输入和输出都应该重定向到信道或者加密隧道。

推荐对这些消息进行回复并且其进行检查。客户端应该忽略掉这些消息。

也就是说 上面的三个消息,都应该是客户端请求服务器端,反之不行。

子系统名称遵循DNS扩展名称约定 见SSH-NUMBERS

会话数据传输

会话数据传输使用SSH_MSG_CHANNEL_DATASSH_MSG_CHANNEL_EXTENDED_DATA数据包和窗口机制来完成的。
stderr数据 定义了 扩展数据类型SSH_EXTENDED_DATA_STDERR

窗口大小变化消息

当客户端窗口(terminal)大小变化时,客户端可向另一方发送一个消息通知其新的大小。

byte      SSH_MSG_CHANNEL_REQUEST
uint32    recipient channel
string    "window-change"
boolean   FALSE
uint32    terminal width, columns
uint32    terminal height, rows
uint32    terminal width, pixels
uint32    terminal height, pixels

对该消息不应发送响应。

总结

暂时就翻译这些

参考地址:

https://tools.ietf.org/html/rfc4254

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山鬼谣me

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值