liuzhuohua
|
79f24aa264
|
fix: 部署静默回退用户设置 + radvd RDNSS 未校验等 5 处缺陷
1.0.3 为纯修复版本,五个问题全部来自真机(192.168.7.3)深度排查:
翻 journal 与统一日志的 error 记录、全盘扫描文件名控制字符、把现行配置库
里每个模块的渲染结果重新交给对应真守护进程做语法校验。
- render(radvd): RDNSS 字段原先完全不校验(同段代码里 prefix 校验网段、
DNSSL 校验域名,唯独漏了它),填 IPv4 地址会原样写进 radvd.conf 导致
radvd 起不来,界面只回一句 radvd.conf:18 error: syntax error。
现逐项按 IPv6 地址校验并给中文提示;多值支持逗号/空格并统一按空格输出
(逗号形式 radvd 本就不认);DNSSL 同样支持多域名;修正 DNSSL 生命期
误读 rdnss_life 的字段错位。
- cleanup: 自动清理的「每天 00:00」根本存不下来——前端 `Number(v) || 4`
与后端 `int(cfg.get('hour') or 4)` 都把 0 当成「没填」,叠加后保存即变
04:00 且改不回来。两处改为显式判断 None/''。执行时刻判定由「正好等于」
放宽为「不早于」,避免计划时刻恰好关机/重启导致当天彻底跳过。
- deploy.sh: 三处无条件覆写改为「只在文件不存在时初始化」——
active-theme(自定义主题每次部署被打回默认)、generated/isp-dns.conf
(PPPoE 上游 DNS 被擦、解析变空直到下次拨号)、cleanup enabled=true
(唯一会真删文件的模块被静默重新打开)。另补兜底:生效主题指向已不
存在的主题时回退 default 并打印说明。
- drouter-web: socketserver 默认 handle_error 把任何异常连整段 traceback
打进 journal,浏览器切页/关标签抛的 BrokenPipeError / ConnectionReset
属「对面先挂了」,三日攒数十条足以淹没真报错。新增 _Server 子类只静默
这几类,其余照旧抛出。
- devtools: 新增 fix-crlf-names.py 清理 CRLF 环境残留的名字带 \r 脏条目
(保守:默认只预演、仅删有同名兄弟者、目录需相对文件集合为子集、
跳过 snapshots/);sync.sh 发布预检增加「文件名不得含控制字符」。
|
2026-10-01 17:43:28 +08:00 |
|
liuzhuohua
|
7d646b5f2b
|
fix(helper): dnsmasq 预检失败时诊断出「/dev 节点缺失」
用户在 DHCP 页点「保存并应用」,弹出:
配置语法检查未通过:dnsmasq: failed to seed the random number
generator: 没有那个文件或目录
根因不是配置写错,而是目标机的 /dev 标准设备节点被误删过。
/dev 是 devtmpfs,由内核维护,但**已删除的节点内核不会重建**。
2026-09-30 一次 chroot 的 `mount --bind /dev` 变量写错,把宿主机 /dev
挂到了自己身上,随后的清理清空了整个 /dev —— 当时只补回了 /dev/null
一个节点。urandom / random / zero / full / tty / console / kmsg 以及
全部块设备(sda、sda1、sda2、zram0)和 /dev/net/tun 一直缺到今天,
直到 dnsmasq 预检要读随机数才暴露。
内核那句话里既没有 "dev" 也没有「设备」字样,用户只会以为是自己把
地址池填错了。新增 _missing_dev_nodes() 做分诊:命中该错误时返回中文
提示,指明这是系统层面的 /dev 问题、不是配置问题。
- backend/drouter-helper.py:新增 _missing_dev_nodes();_verify 的
dnsmasq 分支做错误分诊(其它语法错误仍走原路径)
- devtools/fix-dev-nodes.sh:新增。幂等地补齐被删的标准设备节点,
设备号分别取自内核 devices.txt(字符设备)、/proc/partitions
(块设备)、/sys/class/input(输入设备);已存在的一律不动
- _dev/t-verify.py:新增 15 项回归,覆盖「节点齐全不误报」「缺谁报谁」
「随机数错误被翻译」「其它错误不受影响」「合法配置通过」五条路径
- devtools/sync.sh:预检链挂上 t-verify.py
目标机 192.168.7.3 实测:
- fix-dev-nodes.sh 新建 32 个节点、0 失败;二次执行 32 跳过(幂等)
- dnsmasq --test 从「failed to seed the random number generator」
变为「syntax check OK.」(退出码 0)
- 网络基线零变化:网关仍 192.168.7.2、ip_forward=1、
5900 仍在听、网卡集合不变、dnsmasq 仍 inactive/disabled、
nft 表 0 个
|
2026-10-01 16:01:45 +08:00 |
|
liuzhuohua
|
2859705cee
|
fix(webshell): 修复终端满员自锁 + 去掉滚动条并加清屏按钮
一、修 PTY 不可用(Web 终端报「创建终端失败:out of pty devices」)
根因是目标机上 /dev/ptmx 这个符号链接丢了(devpts 里 /dev/pts/ptmx
还在,但入口没了),于是 pty.openpty() 抛出误导性的「out of pty devices」。
- 新增 ensure_ptmx():探测 -> ln -sf pts/ptmx /dev/ptmx -> mknod 兜底
- 新增 _open_pty():首次失败先自愈再重试一次,仍失败就把真实原因
(_pty_diagnose() 的结论)包进异常,不再只留一句天书
- 服务启动时也自愈一次,开机即修,不等用户踩坑
- 前端识别 PTY_FAIL 并给出可照抄的修复命令
二、修会话满员时的死锁(连到第 9 个会话整个终端服务冻死)
connect 需要「看是否满员 -> 满了就回收 -> 再看一次」,这个序列必然
在持锁时调到内部也要拿锁的 _reap_idle()。而 _lock 是普通 Lock,
同线程二次 acquire 永久阻塞 —— 不报错、不超时,直接锁死;而且锁
一直不放,其他会话的 read/write 也一起堵住,整个 Web 终端报废。
- _lock 改为 RLock
- connect 不再把 _reap_idle() 放在 with _lock 里面
- _reap_idle() 锁内只做登记摘除,close() 移到锁外:
close() 要等子进程退出(SIGHUP 后最多轮询 3 秒),持锁做同样会
把并发请求堵死
三、终端外观(按需求)
- 去掉右侧滚动条(scrollbar-width:none + ::-webkit-scrollbar),
但保留滚动能力 —— 直接关掉 overflow 会让人再也翻不了历史
- 高度改为 clamp(260px,54vh,560px) 随视口自适应;内容多了自动跟随
最新输出。刻意不做「高度随内容增长」:wsMeasure() 用 box.h 算行数,
内容撑高容器会反过来改变 PTY 行数,形成反馈环
- 标题栏加「清屏」小按钮;滚上去离开底部时另出现「↓ 最新」——
滚动条没了,总得留个回到底部的入口
- 跟随阈值收敛成唯一的 WS_TAIL_GAP:wsAutoScroll 与 wsSyncTailBtn
各写一份会出现「按钮没出现、输出也不跟着滚了」的死角
四、顺带清理
- 删掉 app.css 里整套失效的旧终端样式(.tdot/.tt/.term-in/.tk-*,
app.js 中 0 引用),它们已被新结构完全覆盖,留着只会让人改错地方
- 合并 .term-wrap / .term-body 各自重复的第二条声明
测试:
_dev/t-pty.py 扩到 37 项,含「不得自锁」的结构检查 + _reap_idle
行为验证(摘除/关闭/返回条数);_dev/t-webshell.py 加 16 项外观契约。
两者都挂进 devtools/sync.sh 预检链。
新增 devtools/preview-webshell.py:用真实 app.css + 从 viewWebShell()
抠出的 DOM 生成离线预览页,不手抄样式以免预览与线上不一致。
真机验收(192.168.7.3):
8 个会话满员后第 9 个 0.01s 干净返回 BUSY(修复前是永久卡死);
8 个会话 0.87s 全部断开、残留 0(修复前残留 8 个且后续全卡);
/dev/pts 与 pty/nr 回落到 0,无 fd 泄漏;root shell 正常执行命令。
|
2026-10-01 01:29:09 +08:00 |
|
liuzhuohua
|
3f5f31701e
|
feat(devtools): 新增截图覆盖度检查,README 标明待补页面
核对用户打包发来的 78 张截图,与仓库已入库的 78 张 md5 集合完全一致
(互相零差异),确认上一轮提交已是完整状态,本次不需改动任何图片。
本次补充的是「防漂移」能力:
1. 新增 devtools/check-shots.py —— 功能页 ↔ 截图 ↔ README 引用 三方对账
- 43 个功能页逐个报告有无截图(当前 40 有 / 3 缺)
- 映射表登记的截图 vs docs/screenshots/ 实际文件,双向查差异
- README 引用的 vs 实际存在的,双向查差异
为什么不用中文页名做子串匹配:「防火墙 IPv4」会命中「防火墙 IPv6」的
规则说明,误判是静默的假绿。宁可手工维护一张映射表。
2. sync.sh 里原来那段内联的截图清单校验,替换为调用 check-shots.py
(功能被完整覆盖,且现在多了功能页覆盖度这一维)。
3. sync.sh 的 CRLF 检查改为只扫 git 已追踪的文件。
原来用 glob('**/*.html') 会扫到未追踪的本地临时预览页
(_preview-shots.html),它既不会进仓库也不会被 deploy.sh 上传,
为它报错是纯噪音。
4. README 截图章节新增「还没截图的 3 个页面」折叠块:
新手向导 / 主题之家 / 升级与保护,附补图流程。
项目结构章节补充两个新工具。
验证:check-md-links 98 个引用 0 死链;check-shots 三方一致;
t-audit / t-packaging 全部通过。
|
2026-09-30 23:05:51 +08:00 |
|
liuzhuohua
|
a8659dfb98
|
docs(readme): 用 78 张真实界面截图替换 SVG 占位图
原文里 docs/screenshots/ 放的是 6 张同尺寸 SVG 占位图,只为让 README
在仓库刚建好时能完整渲染。现在换成 78 张真实运行截图(1272x900,
取自一台 2 核 4G 的 Debian 13 虚拟机)。
改动:
- 新增 docs/screenshots/ 78 张 jpg,按 9 个功能分组编号命名
(01-login / 02-overview… / 09-settings-4),覆盖全部 43 个功能页
- 删除 6 张 SVG 占位图与 devtools/make-placeholder-shots.py
- README「截图」章节重写:首屏放 8 张精选大图,其余 70 张按功能分
组放进 9 个 <details> 折叠块,每组内用两列表格 + 图注
- README 项目结构补充 docs/screenshots 与 devtools/shots-map.py
- dist/RELEASE_NOTES.md 同步「截图已全部为真图」
为什么文件名必须 ASCII:
GitHub Releases 资产名已被实测证明会静默剥离非 ASCII 字符
(DOCKER-使用说明.md → DOCKER-.md);且原始文件名含 &(如
AC&AP管理中心.jpg、UPnp&NAT-PMP.jpg)在 shell / CI 里都要额外转义。
devtools/shots-map.py 负责「中文名 → ASCII 名」的映射与复制,
并做完整性校验(漏拷/多余/重名都会中止)。
新增两项预检,挂进 devtools/sync.sh:
- devtools/check-md-links.py:所有 md 的本地引用逐条查存在性
- 截图清单双向校验:README 引用的 78 张与目录里的 78 个文件必须一一对应
验证:check-md-links 扫 10 个 md / 98 个本地引用,0 死链;
78 张图与源目录 md5 集合完全一致;
t-packaging / t-audit / t-deps / t-cachebust 全部通过。
|
2026-09-30 22:46:43 +08:00 |
|
liuzhuohua
|
64df3cf331
|
feat: Drouter 1.0.0 —— Debian 13 软路由管理系统
一套跑在 Debian 13 (trixie) 上的软路由管理系统,提供 43 个功能页面的
Web 管理面板:WAN 接入、PPPoE 多拨、DHCP/DNS、IPv6、防火墙、QoS 限速、
访问控制、DDNS、文件共享、Docker 管理等。
核心设计原则:不重新实现任何协议
PPPoE 交给 ppp,DHCP 交给 dnsmasq,IPv6 RA 交给 radvd,NAT 交给 nftables。
Web 面板只做三件事:渲染原生配置文件 → 语法预检 → 原子写入并 reload。
面板删掉后,系统仍是一台配置完好的 Debian 路由器。
安全默认值
· 安装后不接管网络:不改默认路由、不开 IP 转发、不启动 DHCP 服务
· 所有改网络的动作都需要用户在面板上亲手点「应用」
· 避开 5900 端口,不触碰 VNC / X 会话
· 配置写入前先做语法预检,失败则回滚
架构
· backend/ Python 3 标准库,零第三方依赖(9 个模块)
· web/ 原生 JS/CSS,无构建步骤
· 常驻 helper 通过 Unix socket 提供 75 个动作,socket 不可用时回退 subprocess
· 鉴权走 X-Token 请求头
打包
· packaging/build-deb.sh → drouter_1.0.0_all.deb(含 6 个 systemd 单元)
· scripts/make-offline-deps.sh → 236 个依赖 .deb + 本地仓库索引
· packaging/build-offline-bundle.sh → 自包含离线包,目标机零外网可装
· packaging/build-docker.sh → 容器镜像(体验用)
测试
40 套单元测试 + 3 个前端检查脚本(菜单映射 / 离线渲染 / 手机适配),
全部挂在 devtools/sync.sh 的预检链里。
许可:MIT
|
2026-09-30 19:26:24 +08:00 |
|