Files
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

53 lines
1.7 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""查看依赖自检结果,确认缺失的包(重点是防火墙日志依赖的 nftables)。"""
import json
import ssl
import urllib.request
BASE = 'https://127.0.0.1:8443'
CTX = ssl._create_unverified_context()
TOK = None
def call(path, payload=None):
data = json.dumps(payload or {}).encode('utf-8') if payload is not None else None
req = urllib.request.Request(BASE + path, data=data,
method='POST' if data else 'GET')
req.add_header('Content-Type', 'application/json')
if TOK:
req.add_header('X-Token', TOK)
try:
with urllib.request.urlopen(req, timeout=40, context=CTX) as r:
return json.loads(r.read().decode('utf-8'))
except Exception as e:
return {'ok': False, 'msg_cn': str(e)}
TOK = call('/api/login', {'username': 'admin', 'password': 'admin123'})['data']['token']
r = call('/api/depcheck')
d = r.get('data') or {}
print('ok=%s' % r.get('ok'))
items = None
for k in ('items', 'deps', 'list', 'result'):
if isinstance(d.get(k), list):
items = d[k]
break
if items is None:
print(json.dumps(d, ensure_ascii=False, indent=2)[:2000])
else:
miss = []
for it in items:
if not isinstance(it, dict):
continue
name = it.get('name') or it.get('pkg') or it.get('bin') or '?'
inst = it.get('installed')
if inst is None:
inst = it.get('ok')
flag = '已装' if inst else '缺失'
print(' %-24s %s %s' % (name, flag, (it.get('desc') or it.get('note') or '')[:50]))
if not inst:
miss.append(name)
print('\n缺失:%s' % (', '.join(miss) if miss else '无'))