Dropbear SSH 完全指南 / 07 - SCP 与 SFTP
第七章:SCP 与 SFTP
7.1 文件传输方式概述
Dropbear 提供两种文件传输方式:
| 方式 | 实现 | 特点 |
|---|---|---|
| SCP | Dropbear 内置 | 简单高效,递归复制 |
| SFTP | 需外部 sftp-server | 功能丰富,交互式操作 |
SCP vs SFTP 对比
| 对比维度 | SCP | SFTP |
|---|---|---|
| 实现方式 | Dropbear 自带 | 需要外部 sftp-server |
| 交互模式 | 仅命令行 | 交互式 + 命令行 |
| 断点续传 | ❌ | ✅ |
| 目录列表 | 有限 | 完整 |
| 文件操作 | 仅复制 | 删除、重命名、权限等 |
| 性能 | 较高 | 中等 |
| 适用场景 | 脚本自动化 | 交互式文件管理 |
7.2 Dropbear SCP
基本用法
# 上传文件到远程服务器
dbclient local-file.txt user@remote:/path/to/destination/
# 从远程服务器下载文件
dbclient user@remote:/path/to/file.txt ./local-dir/
# 递归复制目录
dbclient -r local-dir/ user@remote:/path/to/destination/
# 使用指定端口
dbclient -p 2222 file.txt user@remote:/tmp/
# 使用指定密钥
dbclient -i ~/.ssh/id_ed25519 file.txt user@remote:/tmp/
Dropbear SCP 的特点
Dropbear 的 scp 是基于 Dropbear 客户端库实现的独立工具:
# 如果编译时生成了 scp 符号链接
ls -la /usr/bin/scp
# lrwxrwxrwx 1 root root ... /usr/bin/scp -> dropbearmulti
# 或使用 dbclient 的 scp 模式
dbclient file.txt user@remote:/tmp/
SCP 命令行选项
| 选项 | 说明 |
|---|---|
-r | 递归复制目录 |
-p | 保留文件权限和时间戳 |
-v | 详细输出(调试) |
-P port | 指定端口(注意大小写) |
-i keyfile | 指定私钥 |
-l limit | 限制带宽(Kbit/s) |
SCP 实用示例
# 备份远程嵌入式设备的配置
dbclient -r root@device:/etc/config/ ./backup/config-$(date +%Y%m%d)/
# 部署固件到设备
dbclient firmware.bin root@device:/tmp/firmware.bin
dbclient root@device "sysupgrade /tmp/firmware.bin"
# 批量文件传输
for device in 192.168.1.{1..10}; do
echo "传输到 $device..."
dbclient config.txt admin@$device:/etc/config/app.conf
done
# 限制带宽(避免影响设备正常运行)
dbclient -l 1000 large-file.tar.gz root@device:/tmp/
# 限制为 1000 Kbit/s ≈ 125 KB/s
7.3 SFTP 子系统配置
Dropbear 本身不包含 SFTP 服务器实现,但可以通过配置子系统(subsystem)使用外部 SFTP 服务器。
安装 SFTP 服务器
# Debian/Ubuntu: 使用 OpenSSH 的 sftp-server
sudo apt-get install openssh-sftp-server
# 查找 sftp-server 路径
which sftp-server
# /usr/lib/openssh/sftp-server
# Alpine Linux
apk add openssh-sftp-server
# 或使用轻量级替代方案
apk add openssh-client # 包含 sftp-server
配置 Dropbear 使用 SFTP
# 方法一:编译时配置(localoptions.h)
#define DROPBEAR_SFTP_SERVER 1
#define SFTPSERVER_PATH "/usr/lib/openssh/sftp-server"
# 方法二:通过启动脚本
# 使用 -c 选项强制执行 SFTP 子系统
dropbear -c /usr/lib/openssh/sftp-server
# 注意:-c 会强制所有连接使用该命令
更好的 SFTP 集成方案
由于 Dropbear 不支持 Subsystem 指令(像 OpenSSH 那样),需要通过其他方式集成 SFTP:
# 方案一:使用 shell 脚本包装
# /usr/local/bin/sftp-shell.sh
#!/bin/sh
case "$SSH_ORIGINAL_COMMAND" in
sftp-server*)
exec /usr/lib/openssh/sftp-server
;;
*)
exec /bin/sh -l
;;
esac
# authorized_keys 中指定 command
command="/usr/local/bin/sftp-shell.sh" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA...
SFTP 客户端连接
# 使用 OpenSSH 的 sftp 客户端
sftp -o "Port=22" user@remote
# 使用 Dropbear 的 dbclient 子系统模式
dbclient -s sftp-server user@remote
# 注意:dbclient 的 SFTP 支持需要编译时启用
# 如果不可用,使用 OpenSSH 的 sftp 客户端
7.4 chroot 环境配置
chroot(Change Root)可以将 SFTP 用户限制在指定目录中,增强安全性。
创建 chroot 环境
#!/bin/bash
# setup-sftp-chroot.sh - 创建 SFTP chroot 环境
CHROOT_DIR="/sftp/jail"
SFTP_USER="sftpuser"
# 创建 chroot 目录结构
mkdir -p "$CHROOT_DIR"/{bin,lib,lib64,dev,etc,home/$SFTP_USER/upload}
mkdir -p "$CHROOT_DIR"/usr/lib
# 复制必要的库文件
# ldd /usr/lib/openssh/sftp-server 来确定依赖
for lib in $(ldd /usr/lib/openssh/sftp-server | awk '{print $3}' | grep -v '^$'); do
dir=$(dirname "$lib")
mkdir -p "$CHROOT_DIR$dir"
cp "$lib" "$CHROOT_DIR$lib"
done
# 复制 sftp-server
cp /usr/lib/openssh/sftp-server "$CHROOT_DIR/usr/lib/sftp-server"
# 创建设备文件
mknod "$CHROOT_DIR/dev/null" c 1 3 2>/dev/null || true
mknod "$CHROOT_DIR/dev/zero" c 1 5 2>/dev/null || true
mknod "$CHROOT_DIR/dev/random" c 1 8 2>/dev/null || true
mknod "$CHROOT_DIR/dev/urandom" c 1 9 2>/dev/null || true
# 设置权限
chmod 755 "$CHROOT_DIR"
chmod 755 "$CHROOT_DIR/home/$SFTP_USER"
chmod 755 "$CHROOT_DIR/home/$SFTP_USER/upload"
chown root:root "$CHROOT_DIR"
chown "$SFTP_USER":"$SFTP_USER" "$CHROOT_DIR/home/$SFTP_USER/upload"
echo "chroot 环境已创建"
Dropbear 的 chroot 支持
Dropbear 对 chroot 的支持不如 OpenSSH 完善。以下是可行的方案:
# 方案一:通过用户 shell 实现
# 将用户的 shell 设置为 chroot wrapper
usermod -s /usr/local/bin/chroot-sftp-shell "$SFTP_USER"
#!/bin/sh
# /usr/local/bin/chroot-sftp-shell - chroot SFTP shell
CHROOT_DIR="/sftp/jail"
# 检查是否是 SFTP 子系统请求
case "$SSH_ORIGINAL_COMMAND" in
sftp-server*)
exec chroot "$CHROOT_DIR" /usr/lib/sftp-server
;;
*)
echo "此账户仅允许 SFTP 访问"
exit 1
;;
esac
验证 chroot 环境
# 测试 SFTP 连接
sftp sftpuser@device
sftp> ls
sftp> pwd
sftp> cd /etc # 应该无法访问
sftp> put localfile.txt upload/
7.5 文件权限管理
SSH 文件权限要求
SSH 对文件权限有严格要求,不正确的权限会导致认证失败:
| 文件/目录 | 必需权限 | 说明 |
|---|---|---|
~/.ssh/ | 700 | 只有所有者可访问 |
~/.ssh/authorized_keys | 600 | 只有所有者可读写 |
~/.ssh/id_*(私钥) | 600 | 只有所有者可读 |
~/.ssh/id_*.pub(公钥) | 644 | 公钥可公开 |
~/.ssh/known_hosts | 644 | 可读 |
~(主目录) | 755 | 不能对组/其他可写 |
# 修复权限
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod 600 ~/.ssh/id_*
chmod 644 ~/.ssh/*.pub
chmod 644 ~/.ssh/known_hosts
嵌入式设备的权限策略
# /etc/init.d/S40permissions - 启动时修复权限
#!/bin/sh
case "$1" in
start)
# 修复 SSH 相关权限
chmod 700 /root/.ssh 2>/dev/null
chmod 600 /root/.ssh/authorized_keys 2>/dev/null
chmod 600 /etc/dropbear/*_host_key 2>/dev/null
# 确保关键目录权限正确
chmod 755 /tmp
chmod 1777 /var/tmp 2>/dev/null
;;
esac
7.6 SCP/SFTP 安全配置
限制文件传输权限
通过 authorized_keys 选项限制 SFTP 用户的权限:
# 仅允许 SFTP,禁止 shell 访问
command="/usr/lib/openssh/sftp-server",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... sftp-user
# 限制只能访问特定目录
permitopen="127.0.0.1:0",command="/usr/local/bin/restricted-sftp.sh" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... sftp-user
限制 SCP 命令
# 只允许下载,禁止上传(通过 command 包装)
# ~/.ssh/authorized_keys
command="/usr/local/bin/scp-download-only.sh" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA...
#!/bin/sh
# /usr/local/bin/scp-download-only.sh - SCP 只读访问
case "$SSH_ORIGINAL_COMMAND" in
scp\ -f\ *)
# -f 表示从服务器发送文件(下载),允许
exec $SSH_ORIGINAL_COMMAND
;;
scp\ -t\ *)
# -t 表示向服务器发送文件(上传),禁止
echo "上传权限被拒绝"
exit 1
;;
*)
echo "不支持的命令"
exit 1
;;
esac
7.7 传输性能优化
SCP 性能调优
# 选择更快的加密算法
dbclient -c aes128-ctr file.tar.gz user@remote:/tmp/
# 或
dbclient -c chacha20-poly1305@openssh.com file.tar.gz user@remote:/tmp/
# 压缩传输(适用于文本文件)
# 注意:Dropbear 不支持 -C 选项
# 替代方案:传输前压缩
tar czf - large-directory/ | dbclient user@remote "tar xzf - -C /destination/"
# 并行传输(适用于多个文件)
ls *.tar.gz | xargs -P 4 -I {} dbclient {} user@remote:/tmp/
带宽限制
# 限制 SCP 带宽,避免影响设备正常运行
# Dropbear scp: -l 选项(Kbit/s)
dbclient -l 500 large-file.tar.gz user@device:/tmp/
# 500 Kbit/s ≈ 62.5 KB/s
大文件传输策略
#!/bin/sh
# safe-transfer.sh - 安全的大文件传输脚本
SOURCE="$1"
DEST="$2"
DEVICE="$3"
USER="${4:-root}"
MAX_RETRIES=3
CHECKSUM_CMD="md5sum"
if [ -z "$SOURCE" ] || [ -z "$DEST" ] || [ -z "$DEVICE" ]; then
echo "用法: $0 <源文件> <目标路径> <设备IP> [用户名]"
exit 1
fi
# 计算本地文件校验和
LOCAL_MD5=$($CHECKSUM_CMD "$SOURCE" | awk '{print $1}')
echo "本地文件: $SOURCE (MD5: $LOCAL_MD5)"
# 传输文件
attempt=0
while [ $attempt -lt $MAX_RETRIES ]; do
attempt=$((attempt + 1))
echo "传输尝试 $attempt/$MAX_RETRIES..."
if dbclient "$SOURCE" "$USER@$DEVICE:$DEST"; then
# 验证远程校验和
REMOTE_MD5=$(dbclient "$USER@$DEVICE" "$CHECKSUM_CMD $DEST" | awk '{print $1}')
if [ "$LOCAL_MD5" = "$REMOTE_MD5" ]; then
echo "✅ 传输成功,校验和匹配: $LOCAL_MD5"
exit 0
else
echo "❌ 校验和不匹配 (本地: $LOCAL_MD5, 远程: $REMOTE_MD5)"
fi
else
echo "❌ 传输失败"
fi
done
echo "❌ 超过最大重试次数"
exit 1
7.8 业务场景:嵌入式设备固件更新
#!/bin/sh
# firmware-update.sh - 通过 SCP 更新嵌入式设备固件
DEVICE_IP="$1"
FIRMWARE="$2"
BACKUP_DIR="/tmp/device-backup/$(date +%Y%m%d_%H%M%S)"
USER="root"
if [ -z "$DEVICE_IP" ] || [ -z "$FIRMWARE" ]; then
echo "用法: $0 <设备IP> <固件文件>"
exit 1
fi
echo "=== 嵌入式设备固件更新 ==="
echo "设备: $DEVICE_IP"
echo "固件: $FIRMWARE"
echo ""
# 1. 备份当前配置
echo "[1/4] 备份当前配置..."
mkdir -p "$BACKUP_DIR"
dbclient -r "$USER@$DEVICE_IP:/etc/config/" "$BACKUP_DIR/"
echo " 配置已备份到 $BACKUP_DIR"
# 2. 传输固件
echo "[2/4] 传输固件..."
FIRMWARE_SIZE=$(du -h "$FIRMWARE" | awk '{print $1}')
echo " 固件大小: $FIRMWARE_SIZE"
dbclient "$FIRMWARE" "$USER@$DEVICE_IP:/tmp/firmware.bin"
# 3. 验证传输
echo "[3/4] 验证传输完整性..."
LOCAL_MD5=$(md5sum "$FIRMWARE" | awk '{print $1}')
REMOTE_MD5=$(dbclient "$USER@$DEVICE_IP" "md5sum /tmp/firmware.bin" | awk '{print $1}')
if [ "$LOCAL_MD5" != "$REMOTE_MD5" ]; then
echo "❌ 校验和不匹配,中止更新"
exit 1
fi
echo " 校验和匹配: $LOCAL_MD5"
# 4. 执行更新
echo "[4/4] 执行固件更新..."
read -p "确认更新? (yes/no): " confirm
if [ "$confirm" = "yes" ]; then
dbclient "$USER@$DEVICE_IP" "sysupgrade /tmp/firmware.bin"
echo "固件更新已启动,设备将重启..."
else
echo "更新已取消"
fi
7.9 本章小结
| 要点 | 说明 |
|---|---|
| SCP | Dropbear 内置,简单高效 |
| SFTP | 需要外部 sftp-server,功能丰富 |
| chroot | 限制用户在指定目录 |
| 权限 | SSH 对文件权限有严格要求 |
| 安全 | 通过 authorized_keys 选项限制传输权限 |
| 性能 | 选择合适加密算法,限制带宽避免影响设备 |
扩展阅读
上一章:端口转发 | 下一章:dropbearkey 工具 →