Commit Graph

11 Commits

Author SHA1 Message Date
Hermes fb3f13c3b2 fix: skip directive matches inside BIND comments
修复 _replace_or_append_option 之前没考虑注释行:
- BIND 配置文件里大量 '// ... forwarders ...' 这样的注释
- 原 regex 'forwarders\\b(?!\\-)' 在注释文本里也能匹配到 forwarders
- 导致保存时把 forwarders 块插入到了注释行的中间,破坏文件结构
- BIND parser 后续报 'unknown option 223.5.5.5'(行号指向 forwarders 块
  里的 IP,因为 forwarders 关键字所在行已被注释污染)

修法:先扫一遍文件建立 in_comment[] 布尔掩码(覆盖 // 行注释、
# 行注释、/* */ 块注释),regex 匹配后检查 match 位置是否在
注释内,若是则 skip。

测试用例包含 '// ... use them as forwarders.' 这种典型注释文本,
验证修改后的 forwarders 块正确插入到 options block 内、不破坏注释。
2026-07-24 18:17:08 +08:00
Hermes e0bb10bfab feat: listen-on and recursion toggles in upstream DNS form
Web 端 '上游 DNS 转发' 卡片新增两个字段:

1. Listen-on (IPv4) 53 端口 — textarea,每行一个 CIDR/IP/ACL 名。
   留空 = any(任意来源)。对应 BIND 指令 listen-on port 53 { ... };。
2. Recursion — yes/no 下拉,控制本 DNS 是否代客户端去外网递归。
   内网递归服务器选 yes;纯权威服务器选 no。

修了一个 regex bug:之前 _replace_or_append_option 用 \\b(?!\\-) 做
lookahead 但没用 lookbehind,导致在内容含 allow-recursion 时匹配
recursion 时也会匹配到 allow- 后面的 recursion,把 allow-recursion
破坏。改为 (?<!\\w)(?<!\\-)keyword\\b(?!\\w)(?!\\-) 双向拒绝,
确保 keyword 必须是独立单词,不能是其它带连字符 directive 的子串。

测试覆盖:
- parse listen-on (IPv4 list)
- parse recursion (yes/no/default)
- 完整 round-trip:5 个字段同时更新,allow-recursion / listen-on-v6
  等未触及的 directives 正确保留
2026-07-24 18:13:00 +08:00
Hermes 9b1679bbd0 feat: dnssec-validation toggle in upstream DNS form
Web 端 '上游 DNS 转发' 卡片新增第三个字段:DNSSEC 验证(auto/yes/no),
解决 SERVFAIL 经典坑:内网 DNS 用 auto 时会被根服务器坏 DS 记录卡住,
返回 SERVFAIL 而非答案。

实现:
- _parse_options_dnssec() 抽出当前 dnssec-validation 值
- _replace_or_append_option() 扩展支持 value-terminated directives
  ('dnssec-validation auto;' 而非 '{...}'),用负向断言避免误匹配
  'listen-on' 时把 'listen-on-v6' 也吃掉
- config_view 多传 dnssec_value/dnssec_values 给模板
- config_upstream_save 多处理 dnssec 表单字段
- 模板加 <select> 下拉,默认选中当前文件里的值

测试覆盖:brace-delimited 替换、value-terminated 替换、hyphen
lookbehind、append-when-missing、parse 各种值、完整 round-trip。
2026-07-24 18:08:41 +08:00
Hermes 1614e37386 feat: structured upstream DNS / allow-recursion editor in Web UI
新增配置管理页面 '上游 DNS 转发' 卡片,让管理员通过两个 textarea
分别维护 forwarders 和 allow-recursion,不需要手写 BIND 语法:

  - 每行一个 IP / CIDR
  - 支持 # 和 // 注释
  - 留空 = 清空该字段(forwarders 留空表示走根提示;
    allow-recursion 留空表示只有 localhost/localnets 能递归)

实现要点:

1. _parse_options_lists() 从 options 文件文本里抽出 forwarders /
   allow-recursion 列表(用大括号平衡匹配,不依赖单行格式)。
2. _replace_or_append_option() 在 options block 里精准替换已有 directive,
   自动跟随原缩进;找不到则按 4 空格缩进追加到 'options {' 之后;
   options block 本身不存在则新建一个。
3. _ensure_options_file() 自动创建缺失的 options 文件(带合理的最小
   默认值),避免 'No such file' 错误。
4. config_upstream_save() 写文件前用 named-checkconf 验证语法,
   失败则不写入;成功则备份 .bak + 写文件 + rndc reload。

附带的修复:config_view 进入页面时也调用 _ensure_options_file(),
解决了 'Web 端第一次配置 options 文件不存在' 的问题。

模板 templates/config.html 新增 '上游 DNS 转发' 卡片,放在 named.conf
主配置卡片和 named.conf.options 卡片之间,placeholder 给出常用示例
(223.5.5.5 / 114.114.114.114 / RFC1918 三段)。

回归测试(dev 环境):
- _parse_options_lists: 正确从样例 options 抽出 3 forwarders + 2 recursion
- _replace_or_append_option: 替换后缩进正确,保留其它 directives
- round-trip:表单输入 -> 写文件 -> 再解析 -> 一致
2026-07-24 17:58:56 +08:00
Hermes 903fe1704a fix: ensure zone directory exists before writing; cross-distro chown fallback
新装机器上添加域名报 500:FileNotFoundError '/etc/bind/zones/db.<x>.com'。
根因是创建 zone 时直接 open() 写文件,没先 makedirs,目录不存在
就直接抛 FileNotFoundError。

修法:
1. 写 zone 文件前 os.makedirs(BIND_ZONES_DIR, exist_ok=True),
   PermissionError 时返回用户友好提示而不是 500。
2. 把所有 chown bind:bind 改成 'chown bind:bind 2>/dev/null ||
   chown named:named 2>/dev/null',覆盖 RHEL/CentOS 上 bind 用户
   不存在的场景,避免 chown 报错污染日志。

影响范围:zone_create(创建)、record_edit/delete(修改/删除记录)、
zone_raw_edit(原始文件编辑)四处写文件路径。
2026-07-24 17:44:38 +08:00
Hermes f10ac5591e fix: detect zone name collisions with named.conf main config
创建 zone 时只检查 BIND_CONF_LOCAL 里的重复声明,遗漏了用户在
named.conf 主配置里手动声明的同名 zone —— 后果是 named reload
时直接报 'zone already exists' 错误,named 起不来。

新增 parse_all_managed_zones(),通过 named-checkconf -p 拿到 named
当前加载的所有 zone,区分 source=local(Web UI 管理的)和 source=main
(用户在 named.conf 主配置里写的)。

zone_create() 在写入新声明前检查这两个来源:
- 同名在 BIND_CONF_LOCAL:拒绝并提示
- 同名在 named.conf 主配置:拒绝并提示用户先去主配置里注释掉

回归测试在 dev 环境通过:识别 4 个 builtin zone (source=main) +
3 个 web UI zone (source=local)。
2026-07-22 17:56:41 +08:00
Hermes ab8d472b7b fix: prefer RHEL paths in BIND path detection to avoid ambiguity
之前的探测顺序优先 Debian 路径 (/etc/bind/named.conf.local),
在某些混合/历史场景下会选错:当两个 named.conf.local 都存在时
(RHEL 默认 /etc/named.conf.local + 之前手动 touch 的 /etc/bind/named.conf.local),
named 实际只读其中一个,但代码会写到另一个,导致 zone 写出来了
但 named 不加载。

调整候选顺序,把 RHEL 路径(/etc/named.conf.local、/etc/named.conf)
放在 Debian 路径前面:

  BIND_CONF_LOCAL:   /etc/named.conf.local -> /etc/bind/named.conf.local
  BIND_CONF_OPTIONS: /etc/named.conf -> /etc/bind/named.conf.options

Dev 环境(Debian)行为不变(/etc/bind/named.conf.options 和
/etc/bind/named.conf.local 实际存在,依然命中 Debian 路径)。

README '配置 BIND' 一节明确两套发行版的差异,并强调 named 主配置
必须 include 对应的 named.conf.local 文件,否则 zone 文件存在但
named 不会加载。
2026-07-22 17:47:52 +08:00
Hermes 3d417421ff feat: auto-detect BIND paths via os.path.exists fallback chain
环境变量 > 自动探测 > 内置默认值。自动探测按发行版常见路径顺序
回退(Debian/Ubuntu / RHEL/CentOS/Rocky / AlmaLinux / FreeBSD),
大多数情况下无需任何配置。

新增探测函数 _detect_bind_path() 与候选路径字典 _BIND_PATH_CANDIDATES,
覆盖以下发行版默认布局:

  BIND_CONF_DIR:     /etc/bind -> /etc -> /etc/named
  BIND_ZONES_DIR:    /etc/bind/zones -> /var/named -> /var/named/data
  BIND_CONF_LOCAL:   /etc/bind/named.conf.local -> /etc/named.conf.local
  BIND_CONF_OPTIONS: /etc/bind/named.conf.options -> /etc/named.conf
  BIND_RNDC_KEY:     /etc/bind/rndc.key -> /etc/rndc.key -> /var/named/key

环境变量仍然作为最高优先级入口,用于非标准路径或多实例场景。

README 第 5 节改名为'路径优先级',列出三层优先级与探测顺序。
2026-07-22 17:31:52 +08:00
Hermes 1b15592f4d feat: make BIND paths configurable via env vars (RHEL/CentOS support)
默认路径仍为 Debian/Ubuntu 的 /etc/bind/*。通过环境变量可在 RHEL/CentOS
(默认 /var/named + /etc/named.conf)上运行:

  BIND_CONF_DIR, BIND_ZONES_DIR, BIND_CONF_LOCAL,
  BIND_CONF_OPTIONS, BIND_RNDC_KEY, BIND_SERVICE

README 增加 RHEL/CentOS 安装步骤、systemd Environment 示例,
并提示覆盖 BIND_CONF_LOCAL 后必须在 named.conf 里 include。

Motivation: 同一项目在 CentOS 7 上 zone 文件写不到 /var/named,
Web 端新增域名后 rndc reload 找不到 zone。
2026-07-22 17:29:26 +08:00
cnbugs 3ef5926f75 add python3.6 2026-07-14 15:17:46 +08:00
AI Agent 0a18b94d84 feat: BIND DNS Web Manager - Web interface for managing BIND9 DNS server
- Flask + SQLite web app with user authentication
- Zone management: create/delete zones, edit raw zone files
- Record management: add/delete A/AAAA/CNAME/MX/TXT/NS/PTR/SRV/CAA records
- Service control: start/stop/restart/reload BIND via systemctl/rndc
- Configuration editor: edit named.conf.options/local with syntax validation
- DNS query testing: online dig tool
- Audit log: all operations logged with user/timestamp
- BIND9 backend, listening on port 53
2026-07-09 17:24:44 +08:00