OpenWrt 固件升级后 SSH 丢失问题解决方案总结报告​

影子 发布于 19 天前 26 次阅读


​问题现象​

  • 升级新固件后无法 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

​故障排除​

​常见问题​

  1. ​keep.d 文件权限问题​chmod 644 /lib/upgrade/keep.d/dropbear
  2. ​文件路径错误​# 检查实际文件位置 find / -name dropbear -type f 2>/dev/null
  3. ​备份包损坏​# 手动创建备份 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+

Good afternoon,good evening,and good night!
最后更新于 2025-10-22