看过几篇教程之后我已经知道怎么备份固件了。但是现在有一个问题,我的本意是把K2P原机带的固件备份出来,用教程上的方法进行开启telnet、备份固件等操作是否会改变固件呢?下面我们来验证这个问题。
OpenWrt的文件系统
K2P使用的是OpenWrt系统,我们先来看一下K2P的Flash Layout(图片来自恩山)
图片上的 firmware 就是我要的固件,它分成 Kernel 和 rootfs 两部分。其中 rootfs 使用SquashFS和JFFS2实现了一个可读写的文件系统,但实际上SquashFS是只读的压缩包,所有的文件修改都是记录在JFFS2,也就是rootfs_data上的。
感兴趣的话可以看看:
https://wiki.openwrt.org/doc/techref/filesystems
https://blog.csdn.net/lee244868149/article/details/57076615
路由器重置的原理
我们知道所有的文件修改都是记录在 rootfs_data 上的,系统重置实际上就是将这部分数据抹掉,我们来验证一下。
我之前下了一个网友备份的固件,地址。
打开 "/usr/lib/lua/luci/controller/admin/backuprestore.lua" 文件,查看第136~141行。
136 elseif reset_avail and luci.http.formvalue("reset") then 137 luci.template.render("backuprestore", { 138 reset_process = 1 139 }) 140 fork_exec("sleep 3; killall dropbear lighttpd miniupnpd; sleep 3; mtd -r erase rootfs_data") 141 else
mtd -r erase rootfs_data 这一句就是抹掉 rootfs_data 的数据。
通过配置文件开启telnet的原理
我们来看一下恢复配置文件是怎么实现的。
还是 "/usr/lib/lua/luci/controller/admin/backuprestore.lua" 这个文件,查看第81~136行。
81 elseif luci.http.formvalue("restore") then 82 local fs = require("luci.fs") 83 luci.http.formvalue("filename") 84 --校验配置文件 85 luci.util.exec("encryconfig decrypt /tmp/backupFile_encode /tmp/backupFile") 86 nixio.fs.unlink("/tmp/backupFile_encode") 87 local fd = io.open("/tmp/backupFile", r) 88 local restore_error_message 89 if fd ~= nil then 90 local line = fd:read() 91 fd:close() 92 if line ~= nil then 93 if not checkfwversion() then 94 nixio.fs.unlink("/tmp/backupFile") 95 restore_error_fwversion = {"restore_error"} 96 luci.template.render("backuprestore", { 97 restore_error_fwversion = restore_error_fwversion 98 }) 99 else 100 luci.util.exec("sed 1,10d /tmp/backupFile >/tmp/restore_rm_header") 101 luci.util.exec("tar -xzC/ -f /tmp/restore_rm_header") 102 nixio.fs.unlink("/tmp/restore_rm_header") 103 local cur_lan_mac = luci.util.exec("uci get network.lan.macaddr") 104 local cur_wan_mac = luci.util.exec("uci get network.wan.macaddr") 105 local flash_lan_mac = luci.util.exec("eth_mac r lan") 106 local flash_wan_mac = luci.util.exec("eth_mac r wan") 107 if cur_lan_mac ~= flash_lan_mac then 108 luci.util.exec("uci set network.lan.macaddr=%s" % flash_lan_mac) 109 end 110 if cur_wan_mac ~= flash_wan_mac then 111 luci.util.exec("uci set network.wan.macaddr=%s" % flash_wan_mac) 112 end 113 luci.util.exec("uci commit") 114 local upload = luci.http.formvalue("restore") 115 if upload and #upload > 0 then 116 luci.template.render("backuprestore", { 117 restore_avail = 1 118 }) 119 fork_exec("sleep 3; reboot") 120 end 121 end 122 else 123 restore_error_message = {"restore_error"} 124 nixio.fs.unlink("/tmp/backupFile") 125 luci.template.render("backuprestore", { 126 restore_error_message = restore_error_message 127 }) 128 end 129 else 130 nixio.fs.unlink("/tmp/backupFile") 131 restore_error_message = {"restore_error"} 132 luci.template.render("backuprestore", { 133 restore_error_message = restore_error_message 134 }) 135 end 136 elseif reset_avail and luci.http.formvalue("reset") then
第101行,tar -xzC/ -f /tmp/restore_rm_header,这条命令把配置文件解压缩到根目录下覆盖现在用的文件。
利用这个特性我们可以向系统写入我们想要的数据,比如自启动脚本。
/etc/rc.local
在 "/etc/rc.local" 脚本中加入命令开启telnet服务是一个不错的选择。
修改后的文件如下:
1 # Put your custom commands here that should be executed once 2 # the system init finished. By default this file does nothing. 3 4 case `cat /proc/cpuinfo | grep MT76` in 5 *7621*) 6 CONFIG_RALINK_MT7621=y 7 ;; 8 *7623*) 9 CONFIG_ARCH_MT7623=y 10 ;; 11 esac 12 if [ "$CONFIG_RALINK_MT7621" = "y" ]; then 13 echo 2048 > /proc/sys/vm/min_free_kbytes 14 #echo 2 > /proc/sys/vm/overcommit_memory 15 #echo 50 > /proc/sys/vm/overcommit_ratio 16 fi 17 block mount 18 19 # add nat rule manually 20 21 smp.sh wifi 22 hwnat-enable.sh 23 brctl addif br-lan ra0 24 brctl addif br-lan rax0 25 /usr/sbin/telnetd -l /bin/login.sh 26 exit 0
第25行 /usr/sbin/telnetd -l /bin/login.sh 就是开启服务的命令。注意,在这个命令中要写完整路径名。
打包配置文件
生成配置文件的代码在 "/sbin/sysupgrade" 脚本里,第131~174行。
1 do_save_conffiles() { 2 local conf_tar="${1:-$CONF_TAR}" 3 4 if [ -z "$CONF_BACKUP" ]; then 5 platform_config_prepare 6 fi 7 8 [ -z "$(rootfs_type)" ] && { 9 echo "Cannot save config while running from ramdisk." 10 ask_bool 0 "Abort" && exit 11 return 0 12 } 13 run_hooks "$CONFFILES" $sysupgrade_init_conffiles 14 ask_bool 0 "Edit config file list" && vi "$CONFFILES" 15 16 # v "Saving config files..." 17 [ "$VERBOSE" -gt 1 ] && TAR_V="v" || TAR_V="" 18 tar c${TAR_V}zf "$conf_tar" -T "$CONFFILES" 19 20 if [ -n "$CONF_BACKUP" ]; then 21 #fix project name must be first line 22 #phic_fac -g product > /tmp/backup_add_header 23 #fix project hardware info must be second line 24 #phic_fac -g hw_ver >> /tmp/backup_add_header 25 #fix project software version must be third line 26 #phic_fac -g fw_ver >> /tmp/backup_add_header 27 #we leave here 7 blank lines,so we have total 10 lines include above 3 lines at the top of /tmp/backup_2 28 echo "product=`uci get system.system.hostname`" >> /tmp/backupFile 29 echo "hw_ver=`uci get system.system.hw_ver`" >> /tmp/backupFile 30 echo "fw_ver=`uci get system.system.fw_ver`" >> /tmp/backupFile 31 for i in 4 5 6 7 8 9 10 32 do 33 echo "" >> /tmp/backupFile 34 done 35 cat $conf_tar >> /tmp/backupFile 36 encryconfig encrypt /tmp/backupFile /tmp/backupFile_encode 37 #cat /tmp/backup_add_header_encry 2>/dev/null 38 39 #rm -f "/tmp/backup_add_header" 40 #rm -f "/tmp/backup_add_header_encry" 41 rm -f "$conf_tar" 42 fi 43 rm -f "$CONFFILES" 44 }
配置文件由文件头和一个tar包组成。文件头是10行文本,这个可以在备份出的文件中截取。在tar包里放我们想写入的文件,与文件头合并成在一起。最后用openssl加密就可以了。
原文地址:https://www.cnblogs.com/LikeVirgo/p/8884716.html