如何使用 SCP 和 SFTP 通过 SSH 安全地传输文件
在本地和远程系统之间传输文件是系统管理和开发的基本要求。然而,使用标准 FTP 或 R-命令等未加密的协议会将敏感数据暴露给拦截和攻击。安全外壳(Secure Shell,简称 SSH)协议提供了两种强大、加密的文件传输方法:安全复制协议(Secure Copy Protocol,简称 SCP)和 SSH 文件传输协议(SSH File Transfer Protocol,简称 SFTP)。
本指南将详细介绍 SCP 和 SFTP 如何利用 SSH 加密来确保数据在传输过程中的完整性和保密性。我们将探讨每种协议的优势和劣势,提供实用的命令行示例,并概述安全文件管理的关键安全最佳实践。
了解基础:SSH
SCP 和 SFTP 都使用 SSH(通常运行在端口 22 上)作为底层传输层。当你使用任一协议启动传输时,SSH 会首先在客户端和服务器之间建立一个安全的、加密的隧道。所有数据,包括身份验证凭据和文件内容,都通过这个隧道传输,这使得这两种方法成为传统文件传输协议的高度安全的替代方案。
SSH 基础提供的关键功能:
- 加密: 所有数据都经过端到端加密。
- 身份验证: 支持密码身份验证和更为安全的公钥/私钥对身份验证。
- 完整性: 使用加密哈希来确保文件在传输过程中不被篡改。
安全复制协议 (SCP)
SCP 是一种基于远程复制协议(rcp)的网络协议,但加入了 SSH 的安全性。它专为简洁和速度而设计,非常适合快速、非交互式的传输,尤其是在脚本编写或自动化中。
SCP 功能和特性
- 简洁性: 使用与标准 Unix
cp命令非常相似的语法。 - 速度: 通常比 SFTP 快,因为它不需要交互式确认或会话设置,仅依赖底层的 SSH 隧道。
- 非交互性: 一旦开始,传输就会运行直到完成,无法管理会话或中断传输状态。
实用的 SCP 命令
SCP 的通用语法是 scp [options] [source] [destination]。
1. 将文件从本地复制到远程服务器
将本地文件推送到远程用户的家目录:
scp /path/to/local/file.txt user@remote_host:/home/user/destination/
2. 将文件从远程复制到本地系统
将文件从服务器拉取到你的当前目录:
scp user@remote_host:/var/log/system.log .
# 注意:‘.’ 表示当前的本地目录
3. 复制整个目录(递归)
使用 -r(递归)标志来复制目录及其所有内容:
scp -r /path/to/local/folder/ user@remote_host:/data/backups/
4. 指定非标准端口
如果你的 SSH 守护程序运行在 22 以外的端口上,请使用 -P 标志(注意是大写的 P):
scp -P 2222 local_file.zip user@remote_host:/tmp/
关于 SCP 弃用的说明: 尽管 SCP 非常有用,但它被认为是一种遗留协议。现代系统越来越推荐使用 SFTP 或 Rsync over SSH,因为 SCP 的协议设计中存在已知的漏洞,尤其是在文件名操纵方面。
SSH 文件传输协议 (SFTP)
SFTP 是 SSH 的一个子系统,它提供了更丰富、交互式的环境来进行文件管理。与 SCP 纯粹是一个复制工具不同,SFTP 是一种有状态的协议,允许进行详细的会话控制、文件列表、删除、重命名和目录创建——类似于增强的 FTP 会话,但完全安全。
SFTP 功能和特性
- 交互式会话: 传输发生在专用的、交互式的 shell 会话中。
- 健壮性: 支持在会话中查找、恢复和管理单个传输。
- 全面管理: 允许使用会话命令(
put、get、lcd、lmkdir)列出 (ls)、更改目录 (cd) 以及操作远程和本地文件。 - 安全性: 高度可靠,被认为是现代安全文件传输的标准。
实用的 SFTP 命令
1. 启动 SFTP 连接
启动到远程服务器的交互式会话:
sftp user@remote_host
如果使用特定端口:
sftp -P 2222 user@remote_host
2. SFTP 交互式命令
连接后,默认在远程环境中操作。使用命令来管理传输和目录:
| 命令 | 描述 | 示例 |
|---|---|---|
ls |
列出远程文件 | ls -l |
cd |
更改远程目录 | cd /var/www/html |
put |
上传文件(本地到远程) | put local_data.zip |
get |
下载文件(远程到本地) | get server_backup.tar.gz |
lcd |
更改本地目录 | lcd /Users/me/downloads |
lpwd |
打印本地工作目录 | lpwd |
mkdir |
创建远程目录 | mkdir new_project |
quit |
退出 SFTP 会话 | quit |
示例:在 SFTP 会话中上传和下载
$ sftp [email protected]
sftp> cd /data/backups
sftp> lcd /home/local/reports
sftp> put daily_report.csv # 上传文件
Uploading daily_report.csv to /data/backups/daily_report.csv
daily_report.csv 100% 512KB 4.3MB/s 00:00
sftp> get configuration.yaml # 下载文件
Fetching /data/backups/configuration.yaml to configuration.yaml
configuration.yaml 100% 20KB 1.1MB/s 00:00
sftp> quit
SCP 与 SFTP:选择合适的工具
虽然这两种协议都是安全的,但它们服务于不同的操作需求:
| 功能 | 安全复制协议 (SCP) | SSH 文件传输协议 (SFTP) |
|---|---|---|
| 机制 | 简单的复制协议(非交互式) | 交互式文件管理协议(有状态) |
| 使用场景 | 快速、单个文件传输;脚本/自动化。 | 复杂传输;目录管理;交互式会话。 |
| 速度 | 通常更快,因为开销较低。 | 略慢,因为需要交互式握手。 |
| 恢复 | 支持性差或不存在。 | 完全支持传输恢复和查找。 |
| 安全状态 | 遗留(存在一些协议漏洞)。 | 现代、健壮的标准。 |
何时使用 SCP: 当你需要以最快的速度进行简单的文件传输,并且是在脚本中执行命令时(偏好非交互性),请使用 SCP。
何时使用 SFTP: 几乎所有手动文件传输,需要管理多个文件、更改目录,或需要会话健壮性和现代安全功能时,请使用 SFTP。
安全文件传输的最佳实践
使用 SCP 或 SFTP 只是第一步。在 SSH 服务器上进行适当的安全配置对于保护远程环境至关重要。
1. 优先使用 SSH 密钥身份验证
基于密码的身份验证容易受到暴力破解攻击。始终使用公钥/私钥 SSH 密钥对进行文件传输身份验证。密钥的使用消除了在自动化或手动传输过程中密码泄露的风险。
生成密钥(如果需要):
ssh-keygen -t rsa -b 4096
使用特定密钥进行传输:
scp -i ~/.ssh/my_transfer_key file.txt user@remote_host:/tmp/
# 或
sftp -i ~/.ssh/my_transfer_key user@remote_host
2. 禁用 Root 登录
绝不允许使用 root 用户进行直接的文件传输。传输应始终由专用的、低权限的用户账户执行。如果需要管理权限,文件可以在传输后在远程机器上使用 sudo 移动到适当的位置。
3. 使用 ChrootDirectory 限制访问 (SFTP)
对于向外部或不受信任用户提供 SFTP 访问的系统,请在 sshd_config 文件中实施 ChrootDirectory 限制。这将 SFTP 用户锁定在特定目录中,防止他们浏览文件系统的其余部分。
/etc/ssh/sshd_config 中的示例配置片段:
Match User sftp_external_user
ForceCommand internal-sftp
ChrootDirectory /var/sftp/%u
AllowTcpForwarding no
X11Forwarding no
4. 限制权限
确保用于传输的用户账户仅具有完成其任务所需的最低权限(最小权限原则)。如果用户只需要上传文件到 /data/uploads,请确保他们不能删除 /etc/config 中的文件。
总结
SSH 为可靠的远程操作提供了必要的安全层。虽然 SCP 仍然是脚本复制中快速而简单的选项,但 SFTP 提供了更卓越的功能集、交互式控制和现代健壮性,是全面文件管理所必需的。通过利用基于密钥的身份验证和适当的服务器端配置,系统管理员可以确保他们的文件传输不仅功能完善,而且完全安全。