一套跑在 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
65 lines
2.4 KiB
Python
65 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
"""真机冒烟:登录 → 检查统一配置 → 抽查各功能模块接口是否正常返回。"""
|
|
import json
|
|
import ssl
|
|
import urllib.error
|
|
import urllib.request
|
|
|
|
BASE = 'https://127.0.0.1:8443'
|
|
CTX = ssl._create_unverified_context()
|
|
|
|
|
|
def call(path, payload=None, token=None):
|
|
data = json.dumps(payload or {}).encode('utf-8')
|
|
req = urllib.request.Request(BASE + path, data=data, method='POST' if payload else 'GET')
|
|
req.add_header('Content-Type', 'application/json')
|
|
if token:
|
|
req.add_header('X-Token', token)
|
|
try:
|
|
with urllib.request.urlopen(req, timeout=20, context=CTX) as r:
|
|
return json.loads(r.read().decode('utf-8'))
|
|
except urllib.error.HTTPError as e:
|
|
try:
|
|
return json.loads(e.read().decode('utf-8'))
|
|
except Exception:
|
|
return {'ok': False, 'msg_cn': 'HTTP %s' % e.code}
|
|
except Exception as e:
|
|
return {'ok': False, 'msg_cn': str(e)}
|
|
|
|
|
|
r = call('/api/login', {'username': 'admin', 'password': 'admin123'})
|
|
if not r.get('ok'):
|
|
print('登录失败:%s' % r.get('msg_cn'))
|
|
raise SystemExit(1)
|
|
tok = r['data']['token']
|
|
print('登录:OK')
|
|
|
|
# 统一配置:确认各模块(含端口转发、主题)都能取到
|
|
cfg = call('/api/config', None, tok)
|
|
data = (cfg.get('data') or {})
|
|
print('配置 ok=%s,模块数=%d' % (cfg.get('ok'), len(data)))
|
|
print(' 模块:%s' % ', '.join(sorted(data)))
|
|
pf = (data.get('portfwd') or {}).get('rules') or []
|
|
print(' 端口转发规则数:%d' % len(pf))
|
|
print(' 主题配置:%s' % json.dumps(data.get('theme'), ensure_ascii=False))
|
|
|
|
# 各功能模块接口(路径取自 drouter-web.py 的真实路由表,不要凭印象写)
|
|
paths = ['sysinfo', 'metrics', 'fwlog', 'fw/log', 'wan/log', 'ddns',
|
|
'ulog', 'ulog/conf', 'ulog/daemon', 'ulog/flow',
|
|
'docker', 'acl', 'share', 'qos', 'pppoe-multi', 'ipv6', 'leases',
|
|
'nft', 'services', 'routes', 'users', 'journal',
|
|
'theme', 'themes', 'vlan', 'wol', 'dpi', 'flow',
|
|
'nat/check', 'snapshot/list', 'sysinfo']
|
|
print('\n接口冒烟:')
|
|
bad = 0
|
|
for p in paths:
|
|
rr = call('/api/' + p, None, tok)
|
|
ok_ = rr.get('ok')
|
|
if not ok_:
|
|
bad += 1
|
|
print(' %-14s %s %s' % (p, 'OK ' if ok_ else 'FAIL', str(rr.get('msg_cn'))[:44]))
|
|
|
|
print('\n结果:%d 个接口,失败 %d 个' % (len(paths), bad))
|
|
raise SystemExit(1 if bad else 0)
|