通过中间件在主机之间传输 scp 文件

通过中间件在主机之间传输 scp 文件

我可以访问 3 台机器,A、B 和 C。唯一可能的 (ssh) 连接是:

A -> B

A -> C

我需要将文件从 B 传输到 C,我只能将文件从 A scp 传输到 B(在 A 上:scp 远程本地),然后从 A scp 传输到 C(在 A 上:scp 本地远程)。但是,A 没有足够的磁盘空间来存储一些相当大的文件。B 和 C 之间有防火墙,还有从 B -> A 和 C -> A 的反向路径。我无法在 B 或 C 上放置密钥,以便从 A 连接到 B 和 C。(说来话长,这是另一个问题)

有没有办法通过将 A 和 B 之间的 scp 输出直接传输到从 A 到 C 的 scp 中来将 B 上的文件 scp 到 C?这样实际文件就不会存储在本地?

查看详细输出,-3 选项似乎向远程主机 B 发送一个远程 scp 命令,由于中间防火墙阻止连接而失败。

答案1

您可以为此使用反向 SSH 隧道:

在主机 A 上,运行:

ssh -R 3000:ip.of.host.c:22 ip.of.host.b

在主机 B 上,运行

scp -P 3000 /source/file username@localhost:/destination_file

这将创建一个隧道,监听主机 B,并通过主机 A 转发到主机 C。因此,您可以在主机 B 上使用 localhost:3000 来连接到 hostc:22。

答案2

您可以使用以下版本tar-ssh-tar 技术执行此操作。从服务器 A 运行以下命令:

ssh B 'cd /src && tar cf - file1 file2...' | ssh C 'cd /target && tar xvf -'

这会在 B 上创建一个包含文件的 tar 格式数据流,然后通过 SSH 将其传输回 A,再通过 SSH 传输到 C,最后传输到 C 上的 tar 程序,该程序会解压文件。A 上无需存储任何文件。

您应该为 B 和 C 设置 SSH 密钥,这样就不会提示您输入密码。两次ssh同时提示输入密码会造成混淆。

如果这是长距离传输,您可以尝试压缩 tar 流以加快速度:

ssh B 'cd /src && tar zcf - file1 file2...' | ssh C 'cd /target && tar zxvf -'

答案3

我认为最简单的解决办法是命名管道在 PC A 上,命名管道是一个行为类似于标准管道的文件,IE它会在内容可用时立即传递内容,而不存储任何内容本身. 它是在 *Nix 系统上实现 IPC(进程间通信)的标准方式。

  mkfifo my-pipe

创建名为我的管道唯一的问题是你不能SCP命名管道(操作系统会抱怨 my-pipe 不是常规文件)。因此,操作方式如下:在 pcA 上的一个终端中,发出以下命令:

  cat my-pipe | ssh me@pcC 'cat > /path/to/destination/file'

此命令将命名管道的内容传输到 pcC,然后重定向到目标文件。

在另一个终端中,再次在 pcA 上发出:

  ssh me@pcB 'cat /path/of/source/file' > my-pipe

此命令将位于远程 pcB 上的源文件放到标准输出,并将其重定向到命名管道。

一旦材料进来,命名管道就会被清空。来自 pcB 的文件结束符会关闭到 B 的两个连接到 C。A 上没有存储任何内容。此时,您可以移除管道,

 rm my-pipe. 

我觉得这很简单。

答案4

如果您经常这样做,我建议在服务器 A 上的 ssh 配置文件中添加一个代理命令,如下所示~/.ssh/config

host serverB
User <user on B>
HostName <hostname of B>

host serverC
User <user on C>
ProxyCommand ssh -q serverB nc -q0 <C hostname> 22

-q 代表安静模式,即较少的输出。

现在,当您想要将文件从机器 A 复制到机器 C 时,您只需输入scp file1 file2 .. serverC:/some/pathYou can do this on server C as well if you want to do it back to. 如果您在不同的机器上有不同的用户名,这将特别有用,当然,如果您不想每次都输入密码,它也可以与 ssh-copy-id 结合使用。

相关内容