OpenWrt 与 Dropbear
OpenWrt 路由器使用 Dropbear 作为 SSH 服务器。Dropbear 能运行 scp,但除非另外安装,否则没有 SFTP 服务器,所以大多数 SFTP 库都会报错 “Unable to start subsystem: sftp”。node-scp 会自动回退到 SCP。
备份配置
ts
import { download } from 'node-scp';
await download('root@192.168.1.1:/etc/config', `./backup/${Date.now()}`, {
recursive: true,
password: process.env.ROUTER_PASSWORD,
});或者在 shell 中:
sh
NODE_SCP_PASSWORD=secret npx node-scp -r root@192.168.1.1:/etc/config ./backup/推送文件并应用
ts
import { connect } from 'node-scp';
await using router = await connect({
host: '192.168.1.1',
username: 'root',
password: process.env.ROUTER_PASSWORD,
});
await router.writeFile('/etc/config/wireless', wirelessConfig, { mode: 0o600 });
// 其他操作都通过 ssh2 客户端完成。
router.ssh.exec('wifi reload', (err, stream) => {
if (err) throw err;
stream.resume();
});上传固件
固件文件很大,而 OpenWrt 上的 /tmp 是内存盘,也正是 sysupgrade 期望固件所在的位置:
ts
await router.upload('./openwrt-sysupgrade.bin', '/tmp/sysupgrade.bin', {
onProgress: (p) => process.stdout.write(`\r${Math.round((p.transferred / p.total!) * 100)}%`),
});小贴士
- 远程父目录必须存在。 递归上传会创建所复制内容内部的目录,但在 SCP 下,node-scp 无法创建目标路径中缺失的父目录。请上传到已存在的目录,或者先通过
router.ssh.exec执行mkdir -p。 - 跳过 SFTP 探测:如果你清楚设备情况,可以设置
protocol: 'scp'。这样可以省去一次往返,也不会在路由器上留下一条日志。 - 用私钥代替密码。 把你的公钥放进路由器上的
/etc/dropbear/authorized_keys,然后把privateKey传给connect。 - 还是想用 SFTP? 在路由器上安装
openssh-sftp-server(opkg install openssh-sftp-server,使用 apk 的版本则是apk add openssh-sftp-server)。之后 node-scp 会自动选择 SFTP,client.fs也随之可用。 - 旧版 Dropbear 可能只提供旧的密钥交换算法。如果握手失败,可以通过 ssh2 的
algorithms选项传入这些算法。