【发布时间】:2017-12-04 19:54:43
【问题描述】:
我想用 Go 创建一个服务器进程,它可以通过 scp 接收或发送文件,例如:
scp -P 2200 -i ssh/tester_rsa foo@localhost:/test output.txt
或
scp -P 2200 -i ssh/tester_rsa input.txt foo@localhost:/test
在this gist 的帮助下,我已经能够创建一个交互式 ssh 服务器,它能够通过以下方式接收连接/命令
ssh -i ssh/tester_rsa foo@localhost -p 2200 'somecommand'
而且效果很好。
我了解到,对于第一个显示的 scp 请求,有效负载包含“scp -f /test”。我被困在如何从服务器返回实际内容,我尝试用一个字符串回复(就像普通的 ssh 回复一样),但我没有得到任何文件。
这是我的 scp -vv 输出
...
debug2: callback done
debug2: channel 0: open confirm rwindow 2097152 rmax 32768
debug2: channel_input_status_confirm: type 99 id 0
debug2: exec request accepted on channel 0
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
debug2: channel 0: rcvd close
debug2: channel 0: output open -> drain
debug2: channel 0: close_read
...
当我尝试使用 propper 服务器时,我得到以下几行
...
debug2: exec request accepted on channel 0
debug2: channel 0: rcvd ext data 43
Sending file modes: C0644 98 output.txt
debug2: channel 0: written 43 to efd 7
Sink: C0644 98 output.txt
output.txt
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
debug1: client_input_channel_req: channel 0 rtype eow@openssh.com reply 0
debug2: channel 0: rcvd eow
debug2: channel 0: close_read
...
所以我想我在 Go 中缺少一些协议/流参数或命令。
只有 Go Code 的 sn-p,因为项目很大,这里不容易复制粘贴:
func (a *Shell) handleExec(connection ssh.Channel, payload []byte) {
...
for _, c := range a.ExecCmds {
if matchCmds(str, c.Cmd) {
connection.Write([]byte("Here comes the file content")
}
}
...
我知道该代码不适用于 scp,但它适用于普通 ssh。我不知道如何处理连接,以及究竟要返回什么才能完成正确的文件传输。
谷歌搜索了一会儿,我找到了this question on stack overflow,这几乎是一样的,但没有得到完全的回答,因为我正在寻找这个部分
runYourCommand(msg.Command, ch)
我猜其中包含逻辑:)
更新:我不再寻找外部资源,我从 this java snippet 获得了更多信息
看起来他们正在模拟 scp 协议,如果有人帮我把它翻译成 Go,我会很好:
StringBuilder params = new StringBuilder("C0").append(perms);
params.append(" ").append(data.length).append(" ");
params.append(remoteFileName).append("\n");
out.write(params.toString().getBytes());
out.flush();
if (!waitForInputStream(logger, in)) {
cleanup(logger, out, channel);
logger.log(Level.SEVERE, "Error before writing SCP bytes");
return UNKNOWN_ERROR; /* TODO: Improve */
}
out.write(data);
out.write(new byte[]{0}, 0, 1);
out.flush();
到目前为止我尝试过,但没有帮助
o:="Some content of a faked file"
connection.Write([]byte("C0644 "+string(len(o))+"test.txt\n"))
connection.Write([]byte(o))
connection.Write([]byte{0,0,1})
澄清一下:我不想提供真实的文件,而是通过 scp 模拟文件传递(使用字符串作为文件的内容)。
提前致谢!
【问题讨论】:
-
我发现这个问题既引人入胜又写得很好,但实际上它应该被关闭,因为它是作为对 SO 上不允许的外部资源的请求而编写的。可以改写成meet the guidelines吗?
-
scp不是 ssh 协议的一部分,它是一个外部程序。 ssh 服务器并没有特别针对scp做任何事情,它只是执行客户端发送的scp命令。