我有 A 和 B Linux 服务器。我有许多用户的主目录位于 中/home
。
我想在 B 中运行 rsync 来/home
从 A 同步。我需要考虑以下几点:
- 我想使用 SSH 密钥验证进行 rsync。
- 我想使用非 sudo 用户进行 rsync。
- 用户主目录中的某些文件具有 400 权限。因此普通用户无法访问它。
- 我不希望B能够在A中拥有写权限。
实现这一目标的最佳方法是什么?
答案1
这很棘手,而且据我所知,可能没有简单的方法可以做到这一点,同时保留 Linux 文件结构中的 400 权限。
我可能会尝试使用某种覆盖/联合金融服务,创建一个备份用户并授予该用户对 UnionFS 版本的文件系统的完全访问权限,但将 UnionFS 以只读方式挂载到该用户 - 或者如果失败,则将底层文件系统以只读方式挂载,然后丢弃在文件系统上进行的任何写入,从而允许用户使用覆盖的文件系统。
我在 Ubuntu 中对此进行了原型设计,如下所示(只进行了非常轻微的测试 - 可能需要进行调整)-
以 root 身份:
apt install unionfs-fuse
mkdir /path/to/overlayfs
unionfs -o allow_other,ro,uid=1001 /path/to/mount /path/to/overlayfs
1001
与备份帐户关联的用户 ID 在哪里。ro
当然表示将文件系统挂载为只读,并allow_other
允许我们覆盖默认权限。
要使用 fstab 挂载它,语法很奇怪,行看起来像
unionfs#/path/to/mount=ro /path/to/overlayfs fuse allow_other,ro,uid=1001 0 0
(参考:https://grangerx.wordpress.com/2010/12/31/using-fuse-unionfs-with-centos-5-5-i686/)
答案2
您可以使用“强制命令”来限制通过 SSH 连接的用户可以执行的操作。这样,您就可以安全地通过 SSH 授予超级用户访问权限。您可以sshd_config
使用ForceCommand
选项,可能放在一个Match
块中。或者您可以将其直接放入 中authorized_keys
,这样您就可以创建专用的 SSH 密钥。它可能看起来像这样:
command="/var/lib/backup-operator/.ssh/allowed-commands.sh",no-port-forwarding,no-X11-forwarding,no-pty ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDcnXDtzZygrdwpxwsTe+nr7hwF6quQNkwhoROBKPagv user@client
我的脚本是这样的:
#!/bin/sh
case "$SSH_ORIGINAL_COMMAND" in
"rsync --server --sender -vlogDtpre.iLsfxCIvu . /tank/backup/mysql/")
exec rsync --server --sender -vlogDtpre.iLsfxCIvu . /tank/backup/mysql/
;;
*)
echo "Access denied."
echo "$SSH_ORIGINAL_COMMAND" > /var/lib/backup-operator/last-failed-command
exit 1
;;
esac
它很脆弱:新rsync
版本有时需要使用不同的开关更改允许的命令。
我可以轻松添加另一个块来备份不同的目录。我还可以偷偷带入sudo
(必须进行适当设置)来提升该rsync
过程。
如果您想正确同步或备份主文件夹,则不得更改其 UID、GID 或权限。无论如何,获取所有文件的唯一方法是根(或有相应的能力,但我从来没有用过它们)。
答案3
使用以下方式挂载文件系统,以便 rsync 只读systemd 运行。 看systemd.exec(5)了解详情。不过,此解决方案需要能够绑定挂载文件系统的特权用户。
#!/bin/sh
# Run rsync from SSH with read-only filesystems
# Execute this script from your authorized_keys file:
# command="/usr/local/sbin/rsnapshot-rsync",no-pty,no-port-forwarding,no-X11-forwarding...
case "$SSH_ORIGINAL_COMMAND" in
rsync\ *)
systemd-run -qGP -p PrivateDevices=true -p ProtectSystem=strict $SSH_ORIGINAL_COMMAND
;;
*)
echo "Access denied" 1>&2
exit 1
;;
esac
或者,通过运行 rsync 来删除权限--uid <USER> $SSH_ORIGINAL_COMMAND
。
我简化了上述示例。我将创建一个专用用户,例如“rsnapshot”,然后使用 sudo 执行 systemd-run 或创建文件/etc/polkit-1/rules.d/50-rsnapshot.rules如果有 polkit 可用。
polkit.addRule(function(action, subject) {
if (action.id == "org.freedesktop.systemd1.manage-units" &&
subject.user == "rsnapshot") {
return polkit.Result.YES;
}
});