SCP?这就是 SSH 的便捷文件传输功能,对吗?
好吧,不完全是。这更像是黑客。或两种非法协议和非标准化协议的混搭。让我们看一下有趣的(可怕的)细节。
什么是SCP?
安全复制协议( SCP )是允许我们在两台计算机之间移动文件(和目录)的一种协议。使用起来很简单:
scp local_file.txt remote_host:/home
这会将 local_file.txt
复制到域名为 remote_host
的另一台计算机(通常是服务器)的 /home
目录中。
它的优点在于它几乎可以在任何类 Unix 系统和许多流行的 Windows 客户端上运行!这种无处不在的可用性和易用性使得 SCP 非常出名。而且构建它如何工作的 心智模型 很容易,这在故障排除时很有帮助。
但是,移动文件并不令人惊喜。SCP 的真正价值在于对计算机进行身份验证以及对传输中的数据进行加密(这就是“ S ”的含义)。
使用它时,您可能已经注意到,首先需要设置对远程计算机的 SSH 访问。SCP 身份验证提示甚至看起来与 SSH 完全相同。这是因为 SCP 在 SSH 之上运行——它使用 SSH 作为纯文本文件数据的管道。实际上,SSH完成了上述所有安全性工作,SCP 只是通过 SSH 连接,传输了一些纯文本文件( SCP just tosses some plaintext files over the SSH connection
)。
维基百科条目 有一些关于 SCP 的历史。简而言之:在旧的 BSD 系统上,曾经有一个可以在计算机之间移动文件的工具,名为 RCP 的工具 。这是在高度信任网络的时期,每个人都是彼此的朋友。然而人们意识到也许并不是网络上的每个人毕竟都是这样的好朋友。有人将 RCP 实现复制到 OpenSSH 的前身,然后仅通过 SSH 会话运行它,以保护文件免遭非友人的攻击。问题解决了!从那时起,它就一直保留在 OpenSSH 中,并且还有许多其他软件模仿它的兼容性 。
它是如何工作的?
该 SSH RFC 是相当简单的,完整。但是与通过SSH复制文件无关。SCP如何实施?
SCP 不是标准化协议。没有 RFC 或有关如何实现它的任何正式描述。OpenSSH 实现是事实上的“规范”。此实现分为两部分:“连接”建立和此后的有线协议。
建立“连接”
好的,这并不是真正的联系。这只是 STDIN/STDOUT
用SSH执行的命令,有点像Unix管道。OpenSSH有两个主要程序参与其中: sshd
和 scp
。sshd
是始终运行的服务器守护程序,接受新的SSH连接。scp
是一个伪装成客户端程序, ssh
然后发送或接收文件。
当 scp
程序运行时,它会打开一个新的 SSH 连接。在该连接上,它在服务器端执行另一个带有特殊未标记标志的 scp 程序。您可以认为 scp
它正在运行ssh exec scp [flags]
。主要标志分别是用于接收和发送的 t
(“ to”)和 f
(“ from”),其他标志是 d
(目标是目录)和 r
(递归,源是目录)。
值得注意的是,SCP 协议是单向的:一端正在发送文件,而另一端正在接收。要走另一条路,您需要单独 scp
执行。
在 scp
远端运行之后,实际的 SCP 协议命令开始通过 STDIN
和流动 STDOUT
。
有线协议
现在我们有了安全的 I/O 管道,可以有效地切换到 RCP 协议。该协议是顺序的(一次操作一次)和同步的(每个命令必须在下一个命令开始之前完成)。格式大致 [command type][arguments]\n[optional data]
(无括号或空格):
-
[command type]
始终是一个ASCII字母:- 'C' - 写入文件
- 'D' - 输入目录
- 'E' - 退出最后一个目录
- 'T' - 设置下一个文件或目录的创建/更新时间戳
-
[arguments]
是特定于命令的,例如文件/目录名称,文件大小或时间戳。'E' 命令没有参数。 -
[optional data]
当最后一个命令为“ C”(创建文件)时发送。数据大小被指定为“ C”的参数
此外,还有一些控制字节,它们不需换行即可单独发送:
-
0x00
-“确定”,表示已完成最后一条命令(如写入本地文件)。接收方在启动时也会发送此消息,以使发送方知道已准备好接收命令。 -
0x01
-“警告”,后跟要显示给用户的一行(以换行符结尾)。 -
0x02
-带有可选消息的“错误”(与警告相同),但此后连接终止。
这个带注释的示例( #
协议中符号后的所有内容)都应阐明整个过程:
SCP问题
到目前为止,SCP 听起来还不错。令人讨厌的设计和缺乏规范是不幸的,但这是一个足够简单的工具,似乎对很多人都有效。但是,现在让我们来看一些现实问题。
性能
有线协议的顺序性质以及对每个命令的强制确认会增加大量开销。例如,如果在发送过程中丢弃了单个确认数据包,则整个连接将暂停直到重新传输开始。最重要的是,不压缩而发送所有数据或询问接收器是否已经有文件小于理想。
有经验的系统管理员可以告诉您 - tar
归档文件并发送单个大存档比使用递归 scp
命令要快得多。实际上,您完全不需要 SCP 就可以做到这一点:
# Copy a local folder with 10000 files
$ find /tmp/big_folder/ -type f | wc -l
10000
# Using scp
$ time scp -r -q /tmp/big_folder/ server:/tmp/big_folder
________________________________________________________
Executed in 882.99 millis fish external
usr time 114.09 millis 0.00 micros 114.09 millis
sys time 278.46 millis 949.00 micros 277.51 millis
# Using tar over ssh
$ time sh -c "tar cf - /tmp/big_folder | ssh server 'tar xC /tmp/ -f -'"
tar: Removing leading '/' from member names
________________________________________________________
Executed in 215.68 millis fish external
usr time 93.22 millis 0.00 micros 93.22 millis
sys time 66.51 millis 897.00 micros 65.62 millis
从 882.99 毫秒到 215.68 毫秒,在这个 scp
示例中(这是最糟糕的情况),速度提高了 4 倍!
安全
SCP 在 SSH 之上运行,因此它是完全安全的,对吗?哦,我那甜美的暑假孩子,事情永远不会安全。
从 OpenSSH 8.0发行说明 :
scp协议过时,不灵活且不容易解决。我们建议改用sftp和rsync等更现代的协议进行文件传输。
如果远程方的外壳为非交互式会话打印出任何内容,则本地 scp 进程将很乐意将该输出解释为 SCP 命令。充其量,这将以难以理解的错误破坏 SCP 协议。最糟糕的是,远程 Shell 启动脚本是恶意的,会向您发送漏洞有效载荷,而不是您想要的文件。
那实现错误呢?早在 2018 年,哈里·辛顿宁(Harry Sintonen) 在流行的 SCP 实现(包括OpenSSH)中发现了 一系列漏洞 。这些范围包括从修改目录权限到覆盖任意文件(由于 ~/.ssh/authorized_keys
或,有效执行代码 ~/.bashrc
)以及注入终端转义序列以隐藏任何痕迹。这些漏洞对于任何构建联网 CLI 应用程序的人都是一个很好的教训。
SCP的替代品
好的,也许 SCP 毕竟有一些问题。我们应该如何在计算机上四处移动文件,而无需设置全新的系统或使用蜗牛邮件 USB 驱动器?
SFTP 被广泛认为是 SCP 的继承者。它仍然在SSH之上运行,以实现传输层安全性,并且不需要单独设置访问权限。它可以为您提供自定义的交互式提示,以供您浏览远程文件系统,或者可以使用一系列预写的命令编写脚本。
缺点是,您将需要学习 SFTP 提示命令,并且协议本身尚未完全标准化(有 许多 RFC 草案,但作者最终放弃了)。
Rsync 是另一个不错的选择。用法与 scp 命令完全相同-它是一种直接替代方法,还利用了 SSH 。Rsync 与性能有关-它在本地进行大量复杂的计算,以通过网络发送尽可能少的数据。从技术上讲,它执行数据同步而不是单纯的传输-如果远程和本地内容相似,则仅发送增量。
同样,它也有其自身的缺点:发送方使用大量 CPU 能力来确定要发送的内容,而接收方使用大量磁盘 IO 来按正确的顺序整理内容。与 OpenSSH 不同,Rsync 还没有预安装在大多数系统上。
如果您需要将文件发送给某人(电子邮件是不可选项),Magic Wormhole 是一个易于使用的工具。您在带外交换短而易读的代码(例如通过电话),并放入一些文件。它可以解决典型的 NAT穿越 难题,并且比交换 SSH 密钥容易得多。
问题在于您需要为每次传输交换身份验证代码,因此它仅适合一次性复制。整个系统旨在供人类使用,如果您需要在笔记本电脑和某些服务器之间传输数据,Magic Wormhole 不是正确的工具。
在较重的方面,还有用于在个人设备(包括电话和服务器)之间同步文件夹的软件。很好的两个例子是 Syncthing 和 Perkeep 。这些系统旨在始终在后台运行,并在文件之间交换差异,类似于 rsync 。
两者都需要花费一些时间来学习和配置(特别是如果您使用它们的许多功能),并且主要针对个人数据(例如照片或聊天日志)进行了优化,而不针对基础结构脚本进行了优化。与我上面提到的所有内容相比,它们还慢得多,而且更加耗费资源。
结论
SCP 是具有古怪实施方式的简单工具。它在移动文件方面做得很好,但是较新的软件在许多方面都胜过它。对于您信任的计算机之间的简单个人用例,SCP 仍然可以使用。它很熟悉,随时为您服务。
但是,如果您遇到性能问题或需要达到更高的安全标准,则上面列出的任何替代方案都比 SCP 更可取。选择最适合您的需求并迁移。
原文链接:
https://gravitational.com/blog/scp-familiar-simple-insecure-slow/
相关链接:
- https://web.archive.org/web/20170215184048/https://blogs.oracle.com/janp/entry/how_the_scp_protocol_works
- https://rsync.samba.org/how-rsync-works.html
- https://github.com/FiloSottile/agehttps://sintonen.fi/advisories/scp-client-multiple-vulnerabilities.txt
- https://github.com/gravitational/teleport/pull/2509