rsync,第一部分
Andrew Tridgell 的 rsync 是一个有用的文件传输工具,它本身没有加密支持,但很容易被 SSH 和 Stunnel 等加密工具“包裹”(隧道化)。rsync(像 scp 一样,基于 rcp)的区别在于它能够执行文件的差异下载和上传。
例如,如果您希望更新本地 10MB 文件的副本,而远程服务器上的较新版本仅在三个地方有所不同,总计 150KB,rsync 将自动仅下载不同的 150KB(或多或少几 KB),而不是整个文件。此功能由 Andrew Tridgell 和 Paul Mackerras 发明的 rsync 算法提供,该算法快速创建和比较两个文件的滚动校验和,从而确定要下载新文件的哪些部分并添加到/替换旧文件中的哪些部分。
由于这是一种更有效的网络使用方式,rsync 在慢速网络连接上尤其有用。但是,在复制对于事务一方或另一方完全是新文件时,它不比 rcp 具有任何性能优势。根据定义,差异复制要求存在要比较的两个文件。
总而言之,rsync 是目前最常用的智能文件传输实用程序,它既适用于加密会话,又值得花精力弄清楚如何使用。本文的其余部分重点介绍如何安全地使用 rsync。
rsync 支持长长的选项列表,其中大多数与维护软件存档、镜像和备份的特定方面相关。此处将深入介绍仅与安全性直接相关的选项,但 rsync(8) 手册页将告诉您您需要了解的有关这些其他功能的任何信息。
由于 rsync 的原始首席开发人员 Andrew Tridgell 也是 Samba 项目的主要人物之一,因此 rsync 的主页是 Samba 网站的一部分,rsync.samba.org。当然,这是关于 rsync 的所有信息的权威来源。资源页面 rsync.samba.org/resources.html 链接到一些优秀的场外 rsync 文档。
最新的 rsync 源代码可在 rsync.samba.org/ftp/rsync 获得,Debian、LinuxPPC 和 Red Hat Linux 的二进制软件包可在 rsync.samba.org/ftp/rsync/binaries 获得。rsync 已经被认为是标准的 Linux 工具,因此包含在所有流行的 Linux 发行版中;您可能无需再寻找,只需在 Linux 安装 CD-ROM 中找到适用于您系统的 rsync 软件包即可。
但是,rsync v.2.5.4 之前的 rsync 中包含的 zlib 实现存在安全漏洞。无论您的系统共享 zlib 库的版本如何,这些漏洞都适用。v2.5.4 本身也存在一个恼人的错误,有时会导致 rsync 不必要地复制整个文件。因此,我建议您运行不早于 rsync v.2.5.5 的版本。
幸运的是,从源代码编译 rsync 既快速又容易。只需解压缩并解包存档,将您的工作目录更改为源代码的顶层目录,键入 ./configure,如果此脚本完成时没有错误,则键入 make && make install。
安装 rsync 后,您可以通过多种方式使用它。第一个也是最基本的方法是使用 rcp 作为传输,这需要您连接的任何主机在 inetd.conf 中启用 shell 服务(即 in.rshd)。不要这样做!发明安全外壳的原因是“r”服务(rcp、rsh 和 rlogin)完全缺乏对强身份验证的支持,这导致它们多年来被许多成功的入侵者用作入口点。
因此,我不会描述如何将 rsync 与 rcp 用作其传输。但是,您可能希望在受信任网络上的主机之间使用此方法;如果是这样,则 rsync 和 in.rshd 各自的手册页中都有大量信息。
比 rcp 方法更好的使用 rsync 的方法是指定安全外壳作为传输。这要求远程主机正在运行 sshd,并且 rsync 命令存在于(并且在两个主机的默认路径中)。如果您尚未设置 sshd,请先设置它。
假设您有两台主机,near 和 far,并且您希望将本地文件 thegoods.tgz 复制到 far 的 /home/near.backup 目录,您认为该目录可能已经包含旧版本的 thegoods.tgz。假设您的用户名 yodeldiva 在两个系统上都存在,则事务可能如下所示
yodeldiva@near:~> rsync -vv -e ssh \ ./thegoods.tgz far:~
让我们剖析一下命令行。rsync 只有一个二进制可执行文件 rsync,它既可以用作客户端命令,也可以选择用作守护进程。在此示例中,它存在于 near 和 far 上,但它在两者上都没有作为守护进程运行;sshd 充当 far 上的监听守护进程。
上面示例中的第一个 rsync 选项是 -vv,这是几乎通用的 UNIX “非常详细”的简写。它是可选的,但具有指导意义。第二个选项是 -e,您可以使用它来指定 rsync 的默认远程复制程序 rcp 的替代方案。由于 rcp 是默认设置,并且 rcp 和 SSH 是唯一受支持的选项,因此在实践中使用 -e 来指定 SSH。
可能令人惊讶的是,-e scp 将不起作用,因为在复制任何数据之前,rsync 需要通过 SSH 传递远程 rsync 命令,以在远程文件上生成并返回滚动校验和。换句话说,rsync 需要 ssh 命令的全部功能才能完成其工作,因此如果您使用 -e 选项,请指定此命令而不是 scp。
选项之后是 rsync 的可操作参数,即本地和远程文件。这些的语法与 rcp 和 scp 非常相似。如果您立即在任一文件名前面加上冒号,rsync 会将冒号前面的字符串解释为远程主机名。如果您希望在远程系统上使用的用户名与您的本地用户名不同,您可以通过立即在主机名前面加上 @ 符号,并在其前面加上您的远程用户名来指定它。换句话说,文件名的完整 rsync 语法如下
[[username@]hostname:]/path/to/filename
必须至少有两个文件名。最右边的必须是目标文件或路径,其他必须是源文件。这两个中只有一个可以是远程的,但两者都可以是本地的(无冒号),这使您可以执行本地差异文件复制——例如,如果您需要将文件从一个本地磁盘或分区备份到另一个本地磁盘或分区,这将非常有用。
指定的源文件是 ./thegoods.tgz,这是一个普通的本地文件路径,目标是 far:~,它转换为“服务器 far 上的我的主目录”。如果您的用户名在 far 上与您的本地用户名不同,例如 yodelerwannabe 而不是 yodeldiva,请使用目标 yodelerwannabe@far:~。
将 rsync 与 SSH 结合使用是在需要和保护真实用户帐户使用的情况下安全使用 rsync 的最简单方法。但正如我在前面“[SFTP 和 SSH]”部分(本书的侧边栏)中提到的,SSH 不容易用于匿名访问。如果您想设置支持 rsync 优化的文件传输的公共文件服务器,该怎么办?
这很容易做到。创建一个简单的 /etc/rsyncd.conf 文件,并使用 --daemon 标志运行 rsync(即 rsync --daemon)。然而,魔鬼在于细节。如果您的服务器将连接到互联网或任何其他不受信任的网络,您应该非常仔细地配置 /etc/rsyncd.conf。让我们讨论一下如何配置。
rsyncd.conf 具有简单的语法;全局选项在开头列出,没有缩进。模块是特定于特定文件系统路径的选项组,由带方括号的模块名称和缩进的选项指示。
选项行各自由选项名称、等号和一个或多个值组成。如果选项是布尔值,则允许的值为 yes 或 no(不要被 rsyncd.conf(5) 手册页误导,该手册页在某些情况下引用 true 和 false)。如果选项接受多个值,则这些值应以逗号-空格分隔,例如,option1, option2。
列表 1 是 rsyncd.conf 示例文件的一部分,该文件说明了一些特别有用的安全增强选项。虽然我为此目的创建了它,但它是一个真实的配置文件,并且在语法上是完整的。让我们剖析一下它。
正如所宣传的那样,全局选项列在顶部。第一个选项集恰好也是唯一的全局选项:syslog facility、motd file、log file、pid file 和 socket options 只能用作全局设置,而不能用在模块设置中。在这些选项中,只有 syslog facility 具有直接的安全影响。与 ProFTPD 指令 SyslogFacility 类似,rsync 的 syslog facility 可用于指定如果您不希望 rsync 使用其默认值 daemon,则 rsync 应记录到哪个 syslog facility。
有关其他全局选项的详细说明,请参阅 rsyncd.conf(5) 手册页;我不会在此处介绍它们,因为它们不会直接影响系统安全,并且它们的默认设置在大多数情况下都很好。
所有其他允许的 rsyncd.conf 选项都可以用作全局选项、模块选项或两者兼而有之。如果一个选项同时出现在全局部分和模块中,则模块设置将覆盖涉及该模块的事务的全局设置。通常,全局选项替换默认值,而模块特定选项覆盖默认选项和全局选项。
第二组选项属于模块特定选项类别。
use chroot = yes:如果 use chroot 设置为 yes,则 rsync 将在任何文件传输之前将自身 chroot 到模块的路径,从而阻止或至少阻碍某些类型的滥用和攻击。这样做需要以 root 身份启动 rsync --daemon,但通过同时设置 uid 和 gid 选项,您可以最大限度地减少 rsync 使用其 root 权限的时间。默认设置为 yes。
uid = nobody:uid 选项允许您指定 rsync 在文件传输期间应使用哪个用户的权限运行,因此它会影响当 rsync 尝试代表客户端读取或写入文件时将应用哪些权限。您可以指定用户名或数字用户 ID。默认值为 -2,在许多系统上是 nobody,但在我的系统上不是,这就是为什么显式定义 uid 的原因。
gid = nobody:gid 选项允许您指定 rsync 在文件传输期间应使用哪个组的权限运行,因此它会影响(与 uid 一起)当 rsync 尝试代表客户端读取或写入文件时应用的权限。您可以指定用户名或数字用户 ID;默认值为 -2(在许多系统上是 nobody)。
max connections = 20:这限制了给定模块的并发连接数(不是所有模块的总数,即使全局设置也是如此)。如果全局指定,则此值将应用于每个不包含其自己的 max connections 设置的模块。默认值为零,这不限制并发连接数。我不建议将其设置为零,因为这会使拒绝服务 (DoS) 攻击更容易。
timeout = 600:timeout 也默认为零,在这种情况下也表示“无限制”。由于 timeout 控制 rsync 等待空闲事务再次变为活动状态的时间长度(以秒为单位),因此这也代表了 DoS 风险,也应全局设置(以及按模块设置,当给定模块由于某种原因需要不同的值时)。
read only = yes:全局定义的最后一个选项是 read-only,它指定所讨论的模块是只读的,即,不允许将任何文件或目录上传到指定的目录,只能下载。默认值为 yes。
第三组选项定义了模块 [public]。正如您所看到的,这些选项是缩进的。当 rsync 向下解析 rsyncd.conf 时,它会将模块名称下方的每个选项都视为属于该模块,直到它遇到另一个带方括号的模块名称或文件末尾。让我们一次检查一个模块 [public] 的每个选项。
[public]:这是模块的名称。此处不包含任何参数或其他修饰符:只有您希望调用的模块名称,在本例中为 public。
path = /home/public_rsync:path 选项对于每个模块都是强制性的,因为它定义了模块将允许从中读取或写入文件的目录。如果您将全局选项 use_chroot 设置为 yes,则这是 rsync 将在任何文件传输之前 chroot 到的目录。
comment = Nobody home but us tarballs:每当客户端请求可用模块列表时,都会显示此字符串。默认情况下没有注释。
hosts allow = near.echo-echo-echo.org, 10.18.3.12 和 hosts deny = *.echo-echo-echo.org, 10.16.3.0/24:如果需要,您可以使用 hosts allow 和 hosts deny 选项来定义访问控制列表 (ACL)。每个选项都接受一个逗号分隔的 FQDN 或 IP 地址列表,您希望从中显式允许或拒绝连接。默认情况下,这两个选项均未设置,这等效于“允许所有”。如果您指定 FQDN(可能包含通配符 *),rsync 将尝试反向解析所有连接客户端的 IP 地址以获取名称,然后再将其与 ACL 进行匹配。
rsync 对这些选项中每个选项的精确解释取决于另一个选项是否存在。如果仅指定 hosts allow,则任何 IP 或名称与 hosts allow 匹配的客户端都将被允许连接,而所有其他客户端将被拒绝。如果仅指定 hosts deny,则任何 IP 或名称与 hosts deny 匹配的客户端都将被拒绝,而所有其他客户端将被允许连接。
但是,如果 hosts allow 和 hosts deny 都存在,则将首先解析 hosts allow,如果客户端的 IP 或名称匹配,则事务将被传递。
如果所讨论的 IP 或名称与 hosts allow 不匹配,则将解析 hosts deny,如果客户端在那里匹配,则事务将被丢弃。
如果客户端的 IP 或名称与两者都不匹配,则将被允许。
在此示例中,两个选项都已设置。它们将被解释为如下
来自 10.18.3.12 的请求将被允许,但来自 10.16.3.1 到 10.16.3.254 范围内的任何其他 IP 的请求将被拒绝。
来自主机 near.echo-echo-echo.org 的请求将被允许,但来自 echo-echo-echo.org 域的其他所有请求将被拒绝。其他所有请求都将被允许。
ignore nonreadable = yes:客户端的 rsync 进程没有读取权限(请参阅 uid 和 gid 选项)的任何远程文件将不会与客户端的本地副本进行比较。这可能比安全性更能显着提高性能;作为访问控制的一种手段,底层文件权限更为重要。
refuse options = checksum:refuse options 选项告诉服务器端 rsync 进程忽略客户端指定的指定选项。在 rsync 的命令行选项中,只有 checksum 具有明显的安全影响。它告诉 rsync 除了其正常的滚动校验和之外,还计算 CPU 密集型 MD5 校验和,因此阻止此选项会减少某些 DoS 机会。虽然 compress 选项具有类似的风险,但您可以使用 dont compress 选项来拒绝它,而不是 refuse options 选项。
dont compress = *:您可以通过 dont compress 选项指定不应压缩的某些文件和目录。如果您希望减少在 DoS 攻击中使用压缩的机会,您还可以指定不压缩任何内容,方法是使用星号 (*),如我们的示例所示。
这个简单的示例应该让您开始提供文件以供 rsync 下载。下个月,我们将介绍如何在文件系统级别设置 rsync 模块(目录)以接受匿名上传和验证用户身份。
Mick Bauer (mick@visi.com) 是 Upstream Solutions, Inc. 的网络安全顾问,该公司位于明尼苏达州明尼阿波利斯市。他是 O'Reilly 出版的《使用 Linux 构建安全服务器》一书的作者,“网络工程波尔卡舞曲”的作曲家,以及一位自豪的(孩子们的)父亲。