通过SSH会话将文件从远程主机带到本地主机的最佳方法是什么?
通过ssh连接到远程主机时,我经常希望将该系统上的文件带到本地系统进行查看或者处理。有没有一种方法可以复制文件而无需(a)打开新终端/暂停ssh会话(b)再次向本地或者远程主机进行身份验证,即使该主机中的一个或者两个都在a或者b后面NAT路由器?
目标是尽可能多地利用当前状态:两台计算机之间存在连接,我在两台计算机上均已通过身份验证,并且我在文件的工作目录中-所以我不必打开另一个终端并复制并粘贴远程主机和路径,这就是我现在要做的。最好的解决方案也不需要在会话开始之前进行任何设置,但是如果设置是一次性的或者能够自动化的,那将是完全可以接受的。
解决方案
回答
我们应该能够设置公钥和私钥,以便不需要身份验证。
采取哪种方式取决于安全性要求等(请注意,有linux / unix ssh蠕虫会查看密钥以查找可以攻击的其他主机)。
我一直在从linksys和dlink路由器后面进行此操作。我认为我们可能需要更改几个设置,但这没什么大不了的。
回答
为此,我将家庭路由器设置为将端口22转发回我的家庭计算机(该防火墙已防火墙保护,仅接受来自工作计算机的ssh连接),并且我还为DynDNS设置了一个帐户来提供动态DNS,会自动解析为我的家庭IP。
然后,当我SSH进入工作计算机时,我要做的第一件事就是运行一个脚本,该脚本启动ssh-agent(如果服务器没有自动执行此操作)。我运行的脚本是:
#!/bin/bash ssh-agent sh -c 'ssh-add < /dev/null && bash'
它要求输入我的ssh密钥密码,这样我就不必每次都键入它。如果我们使用不带密码短语的ssh密钥,则无需执行该步骤。
在剩余的会话中,将文件发送回家用计算机非常简单
scp file_to_send.txt your.domain.name:~/
回答
这是一个名为ssh-xfer的黑客,它可以解决确切的问题,但需要修补OpenSSH,就我而言,这是一个入门。
回答
在Linux机器上,我使用ssh-agent和sshfs。我们需要设置sshd以接受具有密钥对的连接。然后,我们使用ssh-add将密钥添加到ssh-agent,这样就不必每次都键入密码。确保使用-t秒,这样密钥就不会永远保持加载状态。
SSH添加-t 3600 /home/user/.ssh/ssh_dsa
在那之后,
sshfs主机名:/ / PathToMountTo /
将服务器文件系统挂载到计算机上,以便我们可以访问它。
我个人编写了一个小的bash脚本,添加了我的密钥并挂载了我使用最多的服务器,因此,当我开始工作时,我只需要启动该脚本并键入密码即可。
回答
zssh(openssh上的ZMODEM包装器)完全可以满足需求。
- 安装zssh并使用它而不是openssh(我假设我们通常使用)
- 我们必须在两个系统上都安装了lrzsz软件包。
然后,要将文件zyxel.png从远程传输到本地主机:
antti@local:~$ zssh remote Press ^@ (C-Space) to enter file transfer mode, then ? for help ... antti@remote:~$ sz zyxel.png **B00000000000000 ^@ zssh > rz Receiving: zyxel.png Bytes received: 104036/ 104036 BPS:16059729 Transfer complete antti@remote:~$
上传的过程与此类似,只不过我们只切换了rz(1)和sz(1)。
Putty用户可以尝试具有类似功能的Le Putty。
回答
使用-M开关。
"Places the ssh client into 'master' mode for connection shar-ing. Multiple -M options places ssh into ``master'' mode with confirmation required before slave connections are accepted. Refer to the description of ControlMaster in ssh_config(5) for details."
我不太清楚这如何回答OP的问题,David,我们能对此做些扩展吗?
回答
这是我针对此问题的首选解决方案。创建ssh会话后,设置反向ssh隧道。通过两个bash函数可以轻松实现这一点:grabfrom()需要在本地主机上定义,而grab()应该在远程主机上定义。我们可以根据需要添加其他所有使用的ssh变量(例如-X或者-Y)。
function grabfrom() { ssh -R 2202:127.0.0.1:22 ${@}; }; function grab() { scp -P 2202 $@ [email protected]:~; };
用法:
localhost% grabfrom remoteuser@remotehost password: <remote password goes here> remotehost% grab somefile1 somefile2 *.txt password: <local password goes here>
正面:
- 它可以在OpenSSH之外的任何主机上都无需特殊软件即可工作
- 当本地主机位于NAT路由器后面时,它可以工作
- 它可以实现为一对两个单行bash函数
负面因素:
- 可能与使用远程主机上的端口的进程冲突
- 它需要localhost接受ssh连接
- 在启动会话时需要特殊的命令
- 它不会隐式处理对本地主机的身份验证
- 它不允许在本地主机上指定目标目录
- 如果我们从多个本地主机抓取到同一远程主机,则ssh不会喜欢更改密钥
未来的工作:
这仍然是个难题。显然,可以通过适当设置ssh密钥来处理身份验证问题,并且通过向grab()添加参数来允许指定远程目录更加容易。
解决其他负面问题更加困难。最好选择一个动态端口,但据我所知,没有一种优雅的方法可以将该端口传递给远程主机上的shell。据我所知,OpenSSH不允许我们在远程主机上设置任意环境变量,bash不能从命令行参数获取环境变量。即使我们可以选择一个动态端口,也无法确保没有先连接就不会在远程主机上使用它。