惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
B
Blog
Jina AI
Jina AI
N
Netflix TechBlog - Medium
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园_首页
Hugging Face - Blog
Hugging Face - Blog
博客园 - 聂微东
美团技术团队
Google DeepMind News
Google DeepMind News
WordPress大学
WordPress大学
阮一峰的网络日志
阮一峰的网络日志
U
Unit 42
The Cloudflare Blog
V
V2EX
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
小众软件
小众软件
罗磊的独立博客
Microsoft Security Blog
Microsoft Security Blog
Apple Machine Learning Research
Apple Machine Learning Research
I
InfoQ
GbyAI
GbyAI
腾讯CDC
MongoDB | Blog
MongoDB | Blog

atpX

自建 S3 兼容对象存储服务 Garage 听风的歌 偶尔是深夜就好了 新玩具 AirPods Pro 3 公交车上的时间 从 WHOIS 到 RDAP 通过 WireGuard 访问 NFS 共享文件 自建音乐串流服务探索 我停止了探索 Fediverse 互联网背景噪音 我的数字生活降级 小城与确定性的墙 一只特立独行的猪 Fediverse 与社交 承认的勇气 mediaX - 轻量书影音记录管理工具 我的博客写作流程 网站新增 Misc 页面 擅长对线的鲍勃 再见 JavaScript 当我玩博客时我在玩什么 为什么我的博客没有友链页面 小熊猫与大熊猫 (HDR 照片测试) 是时候为网站开启 HTTP/3 支持了吗 使用 AdGuard Home 搭建自用 DoH 服务 谈谈读书与消遣 2023 年终总结 西安两日游 从 AirPods「升级」到 EarPods Docker 搭建去中心化的微博客平台 Mastodon
在 Chroot 环境下使用 Rsync 同步
ATP · 2024-05-06 · via atpX

我平时在备份或者同步服务器文件时一般会用到 rsync 工具,rsync 本身使用起来很方便,也比较可靠,但备份任务主要是通过密钥文件进行连接,不管是从 A 同步到 B 还是将 B 拉取 A,如果任一个服务器出现漏洞导致密钥泄漏,可能会导致另一个服务器买一送一。虽然一般会限制同步用户的权限,不一定会造成严重后果,但还是应该尽可能将 rsync 任务限制在更安全的环境下执行。

限制同步文件的 SSH 用户只能访问指定的文件目录似乎是个不错的解决方案。一开始想到的方法是直接使用 Docker,只映射需要同步的目录,这样可以简单粗暴的进行隔离。果然万能的 linuxserver.io 有现成的项目 docker-openssh-server 可以使用。在尝试中虽然遇到了一些问题,好在最后测试成功,也算实现了目的。但总感觉这种方式不够优雅,后了解到可以使用通过 chroot jail 的方式限制 SSH 用户在指定目录下活动,看起来非常符合需求,值得一试。

简单来说,chroot (change root) 是一种 Unix 操作,它指定一个目录作为某个进程的根目录(该目录称为 chroot jail),从而限制这个进程的权限,使其无法读取或写入该指定目录之外的文件夹和文件。

* 以下操作演示在 Debian 12 系统 root 用户下进行,实现在备份服务器(B)上通过 rsync 命令拉取生产服务器(A)上的文件,因此所有操作都在生产服务器(A)上进行,反之同理。

准备工作

新建一个专门用于 rsync 同步的用户和用户组:

groupadd rsyncuser
useradd rsyncuser -g rsyncuser -s /bin/bash -d /home/rsyncuser

设置用户目录权限,注意 chroot jail 目录的所有者必须为 root 用户,并且普通用户和组没有写入权限:

mkdir /home/rsyncuser
chown root:root /home/rsyncuser
chmod 755 /home/rsyncuser

为该用户生成 SSH 密钥,具体方法可以参考文章:修改 SSH 端口使用密钥登录并配置防火墙,如果后面需要通过 cron 任务自动同步,建议生成密钥对时不设置私钥密码,创建 /home/rsyncuser/.ssh 目录,将公钥添加到该目录下 authorized_keys 文件中。然后设置权限:

chmod 700 /home/rsyncuser/.ssh
chmod 600 /home/rsyncuser/.ssh/authorized_keys
chown -R rsyncuser:rsyncuser /home/rsyncuser/.ssh
# 或者保留 root 对 .ssh 的所有权,允许普通用户读取,两种方式各有利弊:
# chmod 755 /home/rsyncuser/.ssh
# chmod 644 /home/rsyncuser/.ssh/authorized_keys
# chown -R root:root /home/rsyncuser/.ssh

创建一个 rsyncuser 用户可以读写的目录 backup 用来同步文件:

mkdir /home/rsyncuser/backup
chmod 755 /home/rsyncuser/backup
chown rsyncuser:rsyncuser /home/rsyncuser/backup

测试 SFTP 连接(可选)

如果你只需要使用 SFTP 进行同步,可以简单的通过以下几个步骤实现,并保证了最小化权限。确认 /etc/ssh/sshd_config 中下行内容未注释:

Subsystem   sftp    /usr/lib/openssh/sftp-server

然后在文件最后添加:

Match User rsyncuser
    ChrootDirectory /home/rsyncuser
    ForceCommand internal-sftp
    AllowTcpForwarding no
    X11Forwarding no
    PasswordAuthentication no

保存后重启 SSH 进程:

systemctl restart sshd.service

此时你应该已经可以在其他服务器中通过 sftp 连接本服务器,通过下面命令测试:

sftp -i /path/to/private_key -P <port> rsyncuser@<ip>

配置 rysnc 环境

在 chroot 中运行 rsync 需要一些额外的依赖文件,相比只使用 SFTP 会麻烦一些。在 /etc/ssh/sshd_config 文件最后添加/修改为:

Match User rsyncuser
    ChrootDirectory /home/rsyncuser
    AllowTcpForwarding no
    X11Forwarding no
    PasswordAuthentication no

/bin/bash/usr/bin/rsync 的二进制文件(路径用 which rsync 查看)复制到 chroot 目录中:

mkdir /home/rsyncuser/bin && mkdir -p /home/rsyncuser/usr/bin
cp /bin/bash /home/rsyncuser/bin/
cp /usr/bin/rsync /home/rsyncuser/usr/bin/

使用 ldd 命令查看 bash 和 rsync 依赖的库:

ldd /bin/bash
# linux-vdso.so.1 (0x...)
# libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x...)
# libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x...)
# /lib64/ld-linux-x86-64.so.2 (0x...)
	
ldd /usr/bin/rsync
# linux-vdso.so.1 (0x...)
# libacl.so.1 => /lib/x86_64-linux-gnu/libacl.so.1 (0x...)
# libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x...)
# libpopt.so.0 => /lib/x86_64-linux-gnu/libpopt.so.0 (0x...)
# liblz4.so.1 => /lib/x86_64-linux-gnu/liblz4.so.1 (0x...)
# libzstd.so.1 => /lib/x86_64-linux-gnu/libzstd.so.1 (0x...)
# libxxhash.so.0 => /lib/x86_64-linux-gnu/libxxhash.so.0 (0x...)
# libcrypto.so.3 => /lib/x86_64-linux-gnu/libcrypto.so.3 (0x...)
# libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x...)
# /lib64/ld-linux-x86-64.so.2 (0x...)

其中第一个 linux-vdso* 是虚拟库,不需要考虑。根据你的情况将其他依赖库文件整理后复制到 chroot 目录中:

cd /home/rsyncuser
mkdir lib64 && mkdir -p lib/x86_64-linux-gnu
cp /lib/x86_64-linux-gnu/libtinfo.so.6 ./lib/x86_64-linux-gnu/libtinfo.so.6
cp /lib/x86_64-linux-gnu/libc.so.6 ./lib/x86_64-linux-gnu/libc.so.6
cp /lib64/ld-linux-x86-64.so.2 ./lib64/ld-linux-x86-64.so.2

cp /lib/x86_64-linux-gnu/libacl.so.1 ./lib/x86_64-linux-gnu/libacl.so.1
cp /lib/x86_64-linux-gnu/libz.so.1 ./lib/x86_64-linux-gnu/libz.so.1
cp /lib/x86_64-linux-gnu/libpopt.so.0 ./lib/x86_64-linux-gnu/libpopt.so.0
cp /lib/x86_64-linux-gnu/liblz4.so.1 ./lib/x86_64-linux-gnu/liblz4.so.1
cp /lib/x86_64-linux-gnu/libzstd.so.1 ./lib/x86_64-linux-gnu/libzstd.so.1
cp /lib/x86_64-linux-gnu/libxxhash.so.0 ./lib/x86_64-linux-gnu/libxxhash.so.0
cp /lib/x86_64-linux-gnu/libcrypto.so.3 ./lib/x86_64-linux-gnu/libcrypto.so.3

复制完成后的文件目录应该如下:

chroot-folder-tree
/home/rsyncuser 文件夹列表。

完成后,可以先进入 chroot 环境检查 rsync 是否能正常运行:

chroot /home/rsyncuser
rsync --version

然后在 backup 目录下新建一个 1.txt 文件用来测试,在其他服务器上执行 rsync 命令获取 1.txt 文件:

rsync -av -e "ssh -p <port> -i /path/to/private_key" rsyncuser@<ip>:/backup/1.txt /home/1.txt 

如果一切顺利,你的备份服务器上会出现 /home/1.txt 文件,到此就实现了在 chroot 环境下安全的使用 rsync 备份。之后只需要设置一个自动任务将需要备份的文件打包放到 /home/rsyncuser/backup 目录下,再定时同步即可。

虽然使用 chroot 相比直接使用 Docker 的方式复杂一些,但不需要额外安装 Docker,也能节省一些资源占用,总的来说更值得推荐。