Files
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

156 lines
7.1 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% block title %}配置管理 - DNS{% endblock %}
{% block content %}
<div class="page-header">
<h1>BIND 配置管理</h1>
</div>
<div class="config-status {% if config_ok %}config-ok{% else %}config-err{% endif %}">
<span class="config-icon">{% if config_ok %}✅{% else %}❌{% endif %}</span>
<span>配置检查: {% if config_ok %}通过{% else %}有错误{% endif %}</span>
{% if not config_ok %}
<pre class="config-error">{{ config_msg }}</pre>
{% endif %}
</div>
<div class="card">
<div class="card-header">
<h2>named.conf (主配置)</h2>
<span class="text-muted text-sm">只读</span>
</div>
<div class="card-body">
<pre class="config-viewer">{{ main_content }}</pre>
</div>
</div>
<div class="card">
<div class="card-header">
<h2>上游 DNS 转发</h2>
<span class="text-muted text-sm">结构化字段 — 不需要手写 BIND 语法</span>
</div>
<div class="card-body">
<form method="POST" action="{{ url_for('config_upstream_save') }}">
<div class="form-group">
<label for="forwarders">
<strong>Forwarders</strong>
<span class="text-muted text-sm">每行一个上游 DNS IP(v4 / v6 都可)。留空表示使用根提示。</span>
</label>
<textarea name="forwarders" class="code-editor" rows="5" spellcheck="false"
placeholder="223.5.5.5&#10;114.114.114.114&#10;8.8.8.8">{% for ip in forwarders %}{{ ip }}
{% endfor %}</textarea>
</div>
<div class="form-group">
<label for="recursion">
<strong>Allow-recursion 网段</strong>
<span class="text-muted text-sm">允许递归查询外网的客户端 CIDR。留空表示只允许本机。</span>
</label>
<textarea name="recursion" class="code-editor" rows="5" spellcheck="false"
placeholder="127.0.0.0/8&#10;10.0.0.0/8&#10;172.16.0.0/12&#10;192.168.0.0/16">{% for net in recursion %}{{ net }}
{% endfor %}</textarea>
</div>
<div class="form-group">
<label for="dnssec">
<strong>DNSSEC 验证</strong>
<span class="text-muted text-sm">内网 DNS 通常选 <code>no</code>,避免根服务器坏 DS 记录导致 SERVFAIL。</span>
</label>
<select name="dnssec" id="dnssec" class="form-control">
{% for v in dnssec_values %}
<option value="{{ v }}" {% if v == dnssec_value %}selected{% endif %}>{{ v }}{% if v == 'auto' %}(默认,验证根 key{% elif v == 'yes' %}(强制验证){% elif v == 'no' %}(关闭验证){% endif %}</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="listen_on_v4">
<strong>Listen-on (IPv4) 53 端口</strong>
<span class="text-muted text-sm">允许哪些客户端查询本 DNS。每行一个 CIDR / IP / ACL 名。留空 = <code>any</code>(任意来源)。</span>
</label>
<textarea name="listen_on_v4" id="listen_on_v4" class="code-editor" rows="4" spellcheck="false"
placeholder="any&#10;或具体网段,如:&#10;192.168.1.0/24&#10;10.0.0.0/8">{% for net in listen_on_v4 %}{{ net }}
{% endfor %}</textarea>
</div>
<div class="form-group">
<label for="recursion_toggle">
<strong>Recursion (递归查询)</strong>
<span class="text-muted text-sm">是否允许本 DNS 代客户端去外网查询。内网递归服务器选 <code>yes</code>;纯权威服务器选 <code>no</code></span>
</label>
<select name="recursion_toggle" id="recursion_toggle" class="form-control">
<option value="yes" {% if recursion_value == 'yes' %}selected{% endif %}>yes(允许递归)</option>
<option value="no" {% if recursion_value == 'no' %}selected{% endif %}>no(仅权威应答,不递归)</option>
</select>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">💾 保存并重载</button>
<span class="text-muted text-sm" style="margin-left: 12px;">
此处改 forwarders / allow-recursion / dnssec-validation / listen-on / recursion;其它字段请用下方文本编辑器。
</span>
</div>
</form>
</div>
</div>
<div class="card">
<div class="card-header">
<h2>named.conf.options (选项配置)</h2>
</div>
<div class="card-body">
<form method="POST" action="{{ url_for('config_options_save') }}">
<div class="form-group">
<textarea name="content" class="code-editor" rows="20" spellcheck="false">{{ options_content }}</textarea>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">💾 保存并重载</button>
</div>
</form>
</div>
</div>
<div class="card">
<div class="card-header">
<h2>named.conf.local (本地区域配置)</h2>
</div>
<div class="card-body">
<form method="POST" action="{{ url_for('config_local_save') }}">
<div class="form-group">
<textarea name="content" class="code-editor" rows="20" spellcheck="false">{{ local_content }}</textarea>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">💾 保存并重载</button>
</div>
</form>
</div>
</div>
<div class="card">
<div class="card-header"><h2>配置说明</h2></div>
<div class="card-body">
<table class="table">
<thead>
<tr><th>配置文件</th><th>用途</th><th>路径</th></tr>
</thead>
<tbody>
<tr>
<td><strong>named.conf</strong></td>
<td>主配置,包含其他配置文件</td>
<td class="text-mono text-sm">/etc/bind/named.conf</td>
</tr>
<tr>
<td><strong>named.conf.options</strong></td>
<td>全局选项: 监听端口/地址、转发器、查询权限等</td>
<td class="text-mono text-sm">/etc/bind/named.conf.options</td>
</tr>
<tr>
<td><strong>named.conf.local</strong></td>
<td>区域(zone)声明 - 由 Web UI 自动管理</td>
<td class="text-mono text-sm">/etc/bind/named.conf.local</td>
</tr>
<tr>
<td><strong>zone files</strong></td>
<td>DNS 记录文件</td>
<td class="text-mono text-sm">/etc/bind/zones/db.*</td>
</tr>
</tbody>
</table>
</div>
</div>
{% endblock %}