rsync hack反弹两个未连接服务器之间的文件


8

这是连接:

[Server1] <---> [my desktop] <---> [Server2]

服务器1和服务器2不允许直接互相交谈(不要问)。但是,我的桌面能够通过ssh访问两个服务器。

我需要将文件从server1复制到server2。

传统上,我一直在使用ssh + tar hack,例如:

ssh -q root@Server1 'tar -vzc /path/to/files ' | ssh -q root@Server2 'tar -vzx -C /'

效果很好,但我想更进一步,通过桌面在两台服务器之间使rsync工作。

现在,我知道我可以在一个终端中启动ssh端口转发隧道,然后在另一个窗口中在该隧道上进行rsync,但是我不想在第二个终端上大惊小怪,也不想创建和破坏单独的端口转发隧道。我想要的是:

  • 一个线性命令通过桌面将文件从Server1同步到Server2
  • 全部在一个命令行上,一个终端窗口
  • 我希望端口转发隧道仅在rsync命令的有效期内存在。
  • 我不想scp,我想rsync。

有人这样做有技巧吗?

编辑:这是工作命令!每个人的出色工作:1.对于rsa键路径,不能使用tildae,必须使用“ / root /”。2.这是最终的命令行:

ssh -R 2200:SERVER2:22 root@SERVER1 "rsync -e 'ssh -p 2200 -i /root/.ssh/id_rsa_ROOT_ON_SERVER2' --stats --progress -vaz /path/to/big/files root@localhost:/destination/path"

动臂炸药。


这真是太好了。需要更改的一件事是禁用主机密钥验证。您具有用于TTYless身份验证的SSH密钥,但是由于服务器之间从未相互通信,因此无法验证主机密钥。因此最好禁用它:-p或-i标志后的-o StrictHostKeyChecking = no。
阿马拉2014年

Answers:


5

如果您乐于将数据的副本保留在中间计算机上,则可以简单地编写一个脚本,该脚本使用server1作为参考来更新本地副本,然后使用本地副本作为参考来更新server2上的备份:

#!/bin/sh
rsync user@server1:/path/to/stuff /path/to/loca/copy -a --delete --compress
rsync /path/to/loca/copy user@server2:/path/to/where/stuff/should/go -a --delete --compress

使用简单的脚本意味着您只需要一个命令即可完成所有操作。如果数据很敏感(您或公司中的其他人可能不希望副本在您的笔记本电脑上浮动),那么这当然可能是安全性。如果server1对您而言是本地的,则您可以随后删除本地副本(因为下次可以通过本地LAN快速重建)。

构造隧道以便服务器可以更直接有效地相互通信,如下所示:

  1. 在服务器2上,将/ bin / sh的副本复制为/ usr / local / bin / shforkeepalive。使用符号链接而不是副本,然后不必在修补/ bin / sh的安全更新后对其进行更新。
  2. 在服务器2上,创建一个脚本,该脚本除了循环睡眠几秒钟外不执行任何操作,然后回显少量文本,然后使用sh的现在“副本”:

    #!/usr/local/bin/shforkeepalive
    while [ "1" != "0" ]; do
            echo Beep!
            sleep 5
    done
    

    echo可能不需要,因为即使SSHd配置为忽略来自ssh客户端的keep-alive数据包,会话也不会空闲足够长的时间以至于超时)

  3. 现在,您可以在笔记本电脑上编写一个脚本,该脚本在后台启动反向隧道,告诉server1使用rsync来执行复制操作,然后通过取消循环脚本来终止反向隧道(这将关闭SSH会话):

    #!/bin/sh
    ssh user@server2 -L2222:127.0.0.1:22 /usr/local/bin/keepalivesctipt &
    ssh user@server1 -R2222:127.0.0.1:2222 rsync /path/to/stuff user@127.0.0.1:/destination/path/to/update -a --delete --compress -e 'ssh -p 2222'
    ssh user@server2 killall shforkeepalive
    

工作方式:

  • 第1行:标准的“用于解释此脚本的命令”标记
  • 第2行:使用反向隧道启动SSH连接,并通过它运行keepalive脚本以使其保持打开状态。尾部的&告诉bash在后台运行此命令,因此下一行可以运行而无需等待它完成
  • 第3行:启动一个隧道,该隧道将连接到上面的隧道,以便server1可以看到server2,然后运行rsync来执行此安排的复制/更新
  • 第4行:rsync操作完成(因此第二个SSH调用返回)后,杀死keep-alive脚本,这将与第一个ssh会话一起执行。

感觉不是特别干净,但是应该可以。我尚未测试上述内容,因此您可能需要对其进行调整。通过减少对调用ssh命令上的'等转义字符的需求,可以使server1上的rsync命令成为单行脚本可能会有所帮助。

顺便说一句:您说“不要问”为什么两台服务器不能直接看到对方,但是通常有很好的理由。我的家庭服务器和保留其在线备份的服务器无法彼此登录(并且所有用户的密码和密钥都不同)-这意味着,如果这两者之一被黑客入侵,则不能用作轻松访问的途径修改其他文件,使我的在线备份更加安全(有人恶意从实时状态删除我的数据无法使用其更新备份的能力来删除所述备份,因为它没有直接接触主要备份站点的能力)。两台服务器都可以连接到其他位置的中间服务器-实时服务器设置为在清晨将其备份(通过rsync)推送到中间计算机,并且设置备份服务器(稍后再允许第一步完成)进行连接并收集更新(再次通过rsyc,然后执行快照步骤,以保持多个备份时间)。这项技术也可能在您的情况下可用,如果可以的话,我建议它是一种更清洁的处理方式。

编辑:将我的黑客与Aaron合并,以避免与/ bin / sh副本和server2上单独的keep-alive脚本混为一谈,您笔记本电脑上的此脚本应完成全部工作:

#!/bin/sh
ssh user@server2 -L2222:127.0.0.1:22 sleep 60 &
pid=$!
trap "kill $pid" EXIT 
ssh user@server1 -R2222:127.0.0.1:2222 rsync /path/to/stuff user@127.0.0.1:/destination/path/to/update -a --delete --compress -e 'ssh -p 2222'

和上面一样,rsync连接到localhost:2222,它将沿着隧道向下转发到笔记本电脑的localhost:2222,后者通过另一个隧道转发到server2的localhost:22。

编辑2:如果您不介意server1具有允许其直接通过server2进行身份验证的密钥(即使没有通道也无法看到server2),则可以使用以下方法进一步简化操作:

#!/bin/sh
ssh user@server1 -R2222:123.123.123:22 rsync /path/to/stuff user@127.0.0.1:/destination/path/to/update -a --delete --compress -e 'ssh -p 2222'

其中123.123.123.123是server2的公共地址,可以用作复制+粘贴式单行而不是脚本。


这是大量的数据(20 + gb),我更喜欢同时流进出流,而不是本地存储。我希望在不存储任何内容的情况下通过PC传输数据。您对“不要问”是正确的,这是有充分理由的,尽管是皮塔饼。
regulatre,2010年

Plesae看到了关于原始问题的新修改
法规

我认为我的上一次编辑(根据时间戳在您的评论之前发布了几秒钟,因此我们可能在同一时间键入内容)可能会为您提供所需的单线。
David Spillett

哇!有用!1.对于rsa键,不能使用tildae,必须使用“ / root /”。2.这是最终的命令行:ssh -R 2200:SERVER2:22 root@SERVER1 "rsync -e 'ssh -p 2200 -i /root/.ssh/id_rsa_ROOT_ON_SERVER2' --stats --progress -vaz /path/to/big/files root@localhost:/destination/path"
regulatre,2010年

嗨@David,感谢您的出色黑客。但是,为了使其正常工作,我需要使用两种解决方案(在第一次和第二次编辑中)在服务器1上的服务器2的密钥。我认为这很正常(是否进行端口转发,server1仍在尝试向server2进行身份验证),但是您写了If you don't mind server1 having a key ...。您能告诉我是否真的有可能避免在server1上使用server2的密钥?
ssssteffff 2012年

2

这里有一些方法可以使同步变得简单,但是需要一些设置工作。

  • 设置从server1到台式机的反向ssh隧道(对不起,我无法告诉你这个.ssh/config咒语)。使用从您的桌面到server2的连接将其链接。从server1运行rsync。

  • 在桌面上设置袜子代理(或接受CONNECT的http代理)。使用它建立从server1到server2的ssh连接。从server2运行rsync。

  • 使用统一而不是rsync。但是工作流程不同。

  • 使用sshfs从一台或两台服务器上的目录挂载目录。


1

为什么要一行?使用一个小的shell脚本:

#!/bin/bash
# Run me on server1

# Create the port forward server1 -> desktop -> server2 (i.e.
# the first forward creates a second tunnel running on the desktop)
ssh -L/-R ... desktop "ssh -L/-R ... server2 sleep 1h" &    
pid=$!

# Kill port forward process on exit and any error
trap "kill $pid" EXIT 

rsync -e ssh /path/to/files/ root@localhost:/path/to/files/on/server2

IIRC,您可以设置较低的睡眠时间;ssh只要有人使用频道,第一个不会终止。


我敢肯定,rsync的可以在两个远程服务器之间通过SSH不可操作的方式(只有局地>远程或的远程>本地) -虽然你的使用sleep,并trap是整洁比“保活杀”的方法在我的答案。
David Spillett

请查看对原始问题的修改。
法规

该死,你是对的。不允许在命令ling上指定两个主机作为参数。...嗯..
亚伦·迪古拉

好的,我已经改善了解决方案。您需要创建两个端口转发,以使server2的ssh服务在server1上可见。
亚伦·迪古拉

添加几个“;” 将其变成单线。使用脚本更容易理解这个想法。
亚伦·迪古拉
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.