Initial commit: DHCP Web Manager
Flask-based web UI for managing ISC DHCP server (dhcpd). Features: - subnet / static host binding CRUD via web - listen interface configuration (INTERFACESv4) - active lease query + pool utilization stats - service status, reload/restart, syntax check - user auth + operation logs - automatic backup before each config change - safe change pipeline: write file → dhcpd -t → systemctl restart + is-active verify - error messages include journalctl tail for diagnosis
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
# DHCP Web Manager
|
||||
|
||||
一个用 Flask 写的轻量级 ISC DHCP (dhcpd) Web 管理界面,**底层直接复用系统自带的 isc-dhcp-server**,
|
||||
不引入额外 daemon。提供 Web 界面来管理 subnet / 静态 host 绑定 / 监听接口 / 查看租约 / 操作日志。
|
||||
|
||||
## 功能
|
||||
|
||||
- 🟢 子网(subnet)增删改:网段、掩码、网关、DNS、地址池、租期
|
||||
- 🟢 静态绑定(host):MAC + 固定 IP + 主机名
|
||||
- 🟢 监听接口配置(INTERFACESv4)
|
||||
- 🟢 租约查询(按 IP/MAC/主机名搜索)+ 地址池使用率
|
||||
- 🟢 服务状态 + reload / restart + 语法检查
|
||||
- 🟢 操作日志(谁在什么时间做了什么)
|
||||
- 🟢 用户名密码登录 + 改密
|
||||
- 🟢 所有变更自动:写文件 → 备份 → `dhcpd -t` 语法检查 → `systemctl reload isc-dhcp-server`
|
||||
|
||||
## 文件结构
|
||||
|
||||
```
|
||||
dhcp-service/
|
||||
├── app.py # Flask 主程序
|
||||
├── dhcp_ops.py # dhcpd.conf 读写 + leases 解析 + 服务控制
|
||||
├── requirements.txt
|
||||
├── instance/dhcp.db # SQLite(用户、日志)
|
||||
├── backups/ # dhcpd.conf 自动备份(最多保留 20 份)
|
||||
├── templates/ # Jinja2 模板
|
||||
└── static/style.css
|
||||
```
|
||||
|
||||
## 安装
|
||||
|
||||
```bash
|
||||
apt-get install -y isc-dhcp-server # 后端 DHCP 服务
|
||||
pip3 install -r requirements.txt --break-system-packages
|
||||
```
|
||||
|
||||
## 启动
|
||||
|
||||
开发模式:
|
||||
```bash
|
||||
python3 app.py # 监听 0.0.0.0:5100
|
||||
```
|
||||
|
||||
生产模式(推荐用 gunicorn):
|
||||
```bash
|
||||
gunicorn --workers 2 --bind 0.0.0.0:5100 'app:app'
|
||||
```
|
||||
|
||||
默认账号:`admin` / `admin`(首次登录后请到「改密」修改)。
|
||||
|
||||
## 关键设计
|
||||
|
||||
### 配置文件组织
|
||||
|
||||
我们改写 `/etc/dhcp/dhcpd.conf`,但**只动我们管理的区段**——通过标记:
|
||||
|
||||
```
|
||||
# 原有的通用配置(option domain-name 等)保持不变
|
||||
option domain-name "example.org";
|
||||
default-lease-time 600;
|
||||
...
|
||||
|
||||
# >>> DHCP-WEB-MANAGER BEGIN >>>
|
||||
authoritative;
|
||||
subnet 192.168.1.0 netmask 255.255.255.0 {
|
||||
option routers 192.168.1.1;
|
||||
...
|
||||
}
|
||||
host printer {
|
||||
hardware ethernet aa:bb:cc:dd:ee:01;
|
||||
fixed-address 192.168.1.50;
|
||||
}
|
||||
# <<< DHCP-WEB-MANAGER END <<<
|
||||
```
|
||||
|
||||
系统原有的 option / 注释 / 不认识的配置都不丢。备份在 `backups/dhcpd.conf.<timestamp>.bak`(最多 20 份)。
|
||||
|
||||
### 变更流程
|
||||
|
||||
所有写操作都走同一个流程(在 `app.py: apply_and_reload`):
|
||||
|
||||
1. 读现有 subnets/hosts → 追加/替换 → 生成新的 conf 文本
|
||||
2. **先备份到 backups/**
|
||||
3. 写到 `/etc/dhcp/dhcpd.conf`
|
||||
4. 跑 `dhcpd -t` 语法检查 — 失败则回滚到备份(不修改数据库)
|
||||
5. 通过则 `systemctl reload isc-dhcp-server`(不丢连接)
|
||||
|
||||
### 接口绑定
|
||||
|
||||
`/etc/default/isc-dhcp-server` 中的 `INTERFACESv4="enp0s31f6"`。
|
||||
保存接口配置会**重启**(而非 reload)服务,因为接口绑定变更不支持热加载。
|
||||
|
||||
### 租约解析
|
||||
|
||||
直接读 `/var/lib/dhcp/dhcpd.leases` 并 regex 解析 lease 块。注意 dhcpd 每次写入 leases 文件时
|
||||
会以临时名写入后 rename 替换,所以解析时可能短暂读到空内容——前端解析失败的话就是 0 条,不报错。
|
||||
|
||||
## 部署到生产
|
||||
|
||||
按本机惯例,dev 仓库在 `/root/dhcp-service/`,生产部署在 `/root/.openclaw/workspace/dhcp-service/`:
|
||||
|
||||
```bash
|
||||
# 1. 把代码复制到生产目录
|
||||
mkdir -p /root/.openclaw/workspace/dhcp-service
|
||||
cp -r /root/dhcp-service/{app.py,dhcp_ops.py,requirements.txt,templates,static} \
|
||||
/root/.openclaw/workspace/dhcp-service/
|
||||
|
||||
# 2. systemd unit (示例)
|
||||
cat > /etc/systemd/system/dhcp-web-manager.service <<EOF
|
||||
[Unit]
|
||||
Description=DHCP Web Manager (Flask)
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
WorkingDirectory=/root/.openclaw/workspace/dhcp-service
|
||||
ExecStart=/usr/bin/gunicorn --workers 2 --bind 0.0.0.0:5100 'app:app'
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
Environment=PYTHONUNBUFFERED=1
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl enable --now dhcp-web-manager
|
||||
```
|
||||
|
||||
访问 `http://<server-ip>:5100`。
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 本程序必须以 root 跑,因为需要写 `/etc/dhcp/dhcpd.conf` 和控制 systemd 服务。
|
||||
- 修改 subnet/host 走 reload(不丢现有租约),但改 INTERFACESv4 必须 restart。
|
||||
- `dhcpd -t` 语法检查失败时**不会**回滚配置,但也不会 reload——服务继续按旧配置运行,
|
||||
操作日志记录失败原因。修改者可以修正后重试。
|
||||
- 数据库 `instance/dhcp.db` 不要 commit 到 git。
|
||||
|
||||
## 备份恢复
|
||||
|
||||
所有 conf 改动前会自动备份到 `backups/`,恢复:
|
||||
|
||||
```bash
|
||||
ls backups/
|
||||
cp backups/dhcpd.conf.20260709_120000.bak /etc/dhcp/dhcpd.conf
|
||||
systemctl reload isc-dhcp-server
|
||||
```
|
||||
Reference in New Issue
Block a user