问题现象
- 升级新固件后无法 SSH 登录
- 新固件不包含 dropbear 包
- WiFi 等配置正常保留(因为已在 keep.d 中)
根本原因分析
1. 新固件缺失 dropbear
# 新固件缺少以下关键文件:
/usr/sbin/dropbear # SSH 服务二进制文件
/usr/sbin/dropbearkey # SSH 密钥生成工具
/etc/dropbear/ # SSH 配置和密钥目录
2. keep.d 配置不完整
虽然 /etc/config/network在 keep.d 中得以保留(所以 WiFi 正常),但 dropbear 相关文件没有在 keep.d 中配置,导致升级后被删除。
解决方案:使用 keep.d 精确备份
1. 配置 keep.d 文件
# 创建 dropbear 专用保留配置
cat > /lib/upgrade/keep.d/dropbear << 'EOF'
# 🛡️ 保护 dropbear SSH 服务
/usr/sbin/dropbear
/usr/sbin/dropbearkey
/usr/sbin/dropbearconvert
/etc/dropbear/
/etc/dropbear/authorized_keys
/etc/dropbear/dropbear_rsa_host_key
/etc/dropbear/dropbear_dss_host_key
/etc/dropbear/dropbear_ecdsa_host_key
/etc/init.d/dropbear
/etc/config/dropbear
/root/.ssh/
EOF
2. 自动化配置脚本
将以下脚本保存为 /root/configure_upgrade_protection.sh:
#!/bin/sh
# 功能:配置OpenWRT本地源和系统文件,检查并自动修正关键配置
# 使用方法:将脚本上传至路由器后执行 sh script_name.sh
# 定义备份目录
BACKUP_DIR="/tmp/backup_$(date +%Y%m%d%H%M%S)"
mkdir -p "$BACKUP_DIR"
# 备份函数
backup_file() {
local file=$1
if [ -f "$file" ]; then
cp "$file" "$BACKUP_DIR/$(basename $file).bak"
echo "已备份: $file -> $BACKUP_DIR/$(basename $file).bak"
fi
}
# 1. 配置opkg本地源
echo "正在配置opkg本地源..."
backup_file "/etc/opkg/distfeeds.conf"
cat > /etc/opkg/distfeeds.conf <<EOF
src/gz ax1800_pro_base file:///mnt/sdb7/23.05.4/packages/arm_cortex-a15_neon-vfpv4/base
src/gz ax1800_pro_luci file:///mnt/sdb7/23.05.4/packages/arm_cortex-a15_neon-vfpv4/luci
src/gz ax1800_pro_packages file:///mnt/sdb7/23.05.4/packages/arm_cortex-a15_neon-vfpv4/packages
src/gz ax1800_pro_routing file:///mnt/sdb7/23.05.4/packages/arm_cortex-a15_neon-vfpv4/routing
src/gz ax1800_pro_telephony file:///mnt/sdb7/23.05.4/packages/arm_cortex-a15_neon-vfpv4/telephony
EOF
echo "opkg本地源配置完成"
# 2. 配置opkg.conf
echo "正在配置opkg.conf..."
backup_file "/etc/opkg.conf"
cat > /etc/opkg.conf <<EOF
#dest opt /opt
dest root /
dest ram /tmp
lists_dir ext /var/opkg-lists
option overlay_root /overlay
#option check_signature 1
arch all 1
arch noarch 10
arch ipq 20
arch aarch64_cortex-a53+crypto 30
arch aarch64_cortex-a53 40
arch arm_cortex-a15_neon-vfpv4 50
EOF
echo "opkg.conf配置完成"
# 3. 检查文件是否存在并更新保留列表
echo "正在检查关键文件..."
FILES_TO_CHECK="
/usr/sbin/dropbear
/usr/bin/scp
/etc/init.d/rc.local
/etc/init.d/done
/etc/config/dropbear
/etc/dropbear/
/etc/uci-defaults/system_check
/etc/init.d/dropbear
"
# 检查文件是否存在
for file in $FILES_TO_CHECK; do
if [ -e "$file" ]; then
echo "[存在] $file"
else
echo "[缺失] $file"
fi
done
# 更新sysupgrade.conf
for file in $FILES_TO_CHECK; do
if [ -e "$file" ] && ! grep -q "^${file}$" /etc/sysupgrade.conf 2>/dev/null; then
echo "$file" >> /etc/sysupgrade.conf
fi
done
# 更新base-files-essential
KEEP_FILE="/lib/upgrade/keep.d/base-files-essential"
for file in $FILES_TO_CHECK; do
if [ -e "$file" ] && ! grep -q "^${file}$" "$KEEP_FILE" 2>/dev/null; then
echo "$file" >> "$KEEP_FILE"
fi
done
echo "关键文件检查和保留列表更新完成"
# 4. 详细检查并自动修正相关文件内容
echo ""
echo "=== 开始详细文件检查与修正 ==="
# 检查并修正/etc/rc.local
backup_file "/etc/rc.local"
echo -n "检查/etc/rc.local中的dropbear: "
if grep -q "^/usr/sbin/dropbear" /etc/rc.local; then
echo "已存在且未被注释 - 无需修改"
elif grep -q "^#/usr/sbin/dropbear" /etc/rc.local; then
# 取消注释
sed -i 's/^#\/usr\/sbin\/dropbear/\/usr\/sbin\/dropbear/' /etc/rc.local
echo "已取消注释"
else
# 添加新行
echo "/usr/sbin/dropbear" >> /etc/rc.local
echo "已添加"
fi
# 检查并修正/etc/init.d/done
backup_file "/etc/init.d/done"
echo -n "检查/etc/init.d/done中的rc.local执行: "
if grep -q "^[[:space:]]*\[ -f /etc/rc.local \] && { sh /etc/rc.local; }" /etc/init.d/done; then
echo "已存在且未被注释 - 无需修改"
elif grep -q "^[[:space:]]*#\[ -f /etc/rc.local \] && { sh /etc/rc.local; }" /etc/init.d/done; then
# 取消注释
sed -i 's/^[[:space:]]*#\[ -f \/etc\/rc.local \] && { sh \/etc\/rc.local; }/[ -f \/etc\/rc.local ] \&\& { sh \/etc\/rc.local; }/' /etc/init.d/done
echo "已取消注释"
else
# 在start()函数中添加
if grep -q "start()" /etc/init.d/done; then
sed -i '/start()/{:a;n;/^}/!ba;i\ [ -f /etc/rc.local ] && { sh /etc/rc.local; }' /etc/init.d/done
echo "已在start()函数中添加"
else
echo "无法自动添加,请手动检查/etc/init.d/done文件结构"
fi
fi
# 检查并修正/etc/uci-defaults/system_check
backup_file "/etc/uci-defaults/system_check"
echo -n "检查/etc/uci-defaults/system_check中的dropbear设置: "
if grep -q "^#\[ \"\$(uci -q get dropbear.@dropbear\[0\].jdc_enable)\" = \"1\" \] && {" /etc/uci-defaults/system_check; then
echo "已被正确注释 - 无需修改"
elif grep -q "^\[ \"\$(uci -q get dropbear.@dropbear\[0\].jdc_enable)\" = \"1\" \] && {" /etc/uci-defaults/system_check; then
# 注释掉相关行
sed -i 's/^\[ \"$(uci -q get dropbear.@dropbear\[0\].jdc_enable)\" = \"1\" \] && {/#&/' /etc/uci-defaults/system_check
sed -i '/^#\[ \"$(uci -q get dropbear.@dropbear\[0\].jdc_enable)\" = \"1\" \] && {/,/^#}/s/^\([^#]\)/#\1/' /etc/uci-defaults/system_check
echo "已注释相关代码块"
else
echo "未找到相关行 - 无需修改"
fi
echo ""
echo "=== 最终检查结果 ==="
echo "1. /etc/rc.local: $(grep -q "^/usr/sbin/dropbear" /etc/rc.local && echo "符合要求" || echo "仍不符合要求")"
echo "2. /etc/init.d/done: $(grep -q "^[[:space:]]*\[ -f /etc/rc.local \] && { sh /etc/rc.local; }" /etc/init.d/done && echo "符合要求" || echo "仍不符合要求")"
echo "3. /etc/uci-defaults/system_check: $(grep -q "^#\[ \"\$(uci -q get dropbear.@dropbear\[0\].jdc_enable)\" = \"1\" \] && {" /etc/uci-defaults/system_check && echo "符合要求" || echo "仍不符合要求")"
echo ""
echo "=== 操作完成 ==="
echo "所有修改的文件已备份至: $BACKUP_DIR"
echo "请检查最终结果,如有问题可使用备份文件恢复"
3. 执行步骤
# 1. 创建 keep.d 配置
mkdir -p /lib/upgrade/keep.d/
cat > /lib/upgrade/keep.d/dropbear << 'EOF'
/usr/sbin/dropbear
/usr/sbin/dropbearkey
/etc/dropbear/
/etc/init.d/dropbear
/etc/config/dropbear
/root/.ssh/
EOF
# 2. 运行自动化配置脚本
chmod +x /root/configure_upgrade_protection.sh
/root/configure_upgrade_protection.sh
# 3. 验证配置
cat /lib/upgrade/keep.d/dropbear
sysupgrade -T firmware.bin | grep -i "dropbear\|ssh"
验证方法
1. 检查 keep.d 配置
# 查看配置内容
cat /lib/upgrade/keep.d/dropbear
# 检查文件是否存在
for file in $(cat /lib/upgrade/keep.d/dropbear | grep -v "^#"); do
[ -e "$file" ] && echo "✅ $file" || echo "❌ $file"
done
2. 测试升级流程
# 模拟升级(不实际执行)
sysupgrade -T firmware.bin
# 检查备份包内容
tar -tzf /tmp/sysupgrade.tgz | grep -E "dropbear|ssh"
3. 升级后验证
# 检查文件是否保留
ls -la /usr/sbin/dropbear /etc/dropbear/
# 检查服务状态
/etc/init.d/dropbear status
ps | grep dropbear
netstat -tln | grep :22
故障排除
常见问题
- keep.d 文件权限问题
chmod 644 /lib/upgrade/keep.d/dropbear - 文件路径错误
# 检查实际文件位置 find / -name dropbear -type f 2>/dev/null - 备份包损坏
# 手动创建备份 tar -czf /tmp/manual_backup.tar.gz -T /lib/upgrade/keep.d/dropbear
总结
- ✅ 根本原因:新固件不包含 dropbear,且 keep.d 配置不完整
- ✅ 解决方案:通过 keep.d 精确配置需要保留的文件
- ✅ 自动化脚本:一键检查和修正系统配置
- ✅ 验证方法:模拟升级测试确保配置生效
此方案的优势:
- 不修改核心系统文件(platform.sh)
- 符合 OpenWrt 官方升级机制
- 可预测和可验证
- 易于维护和调试
文档版本:2.0 最后更新:2024年1月 适用版本:OpenWrt 19.07+

Comments NOTHING