diff --git a/README.md b/README.md index 0178907..aa3034d 100644 --- a/README.md +++ b/README.md @@ -70,13 +70,15 @@ dns-service/ ## BIND 配置文件 -| 文件 | 用途 | 路径 | -|------|------|------| +| 文件 | 用途 | 默认路径(Debian/Ubuntu) | +|------|------|---------------------------| | `named.conf` | 主配置 | `/etc/bind/named.conf` | | `named.conf.options` | 全局选项(监听端口、转发器、查询权限) | `/etc/bind/named.conf.options` | | `named.conf.local` | Zone 声明(由 Web UI 自动管理) | `/etc/bind/named.conf.local` | | zone files | DNS 记录文件 | `/etc/bind/zones/db.*` | +> **路径可通过环境变量覆盖**(见下方"路径配置"章节)。RHEL/CentOS/Rocky 默认 BIND 路径为 `/var/named`、`/etc/named.conf`,需要在环境变量里重新指。 + ## 安装部署 ### 1. 安装 BIND9 @@ -88,6 +90,8 @@ apt-get install -y bind9 bind9utils dnsutils ### 2. 配置 BIND +#### Debian/Ubuntu(默认路径) + ```bash # 创建 zone 文件目录 mkdir -p /etc/bind/zones @@ -124,6 +128,31 @@ systemctl enable named systemctl start named ``` +#### RHEL / CentOS 7 / Rocky Linux + +CentOS 默认 BIND 路径在 `/var/named/` 和 `/etc/named.conf`,需要: + +```bash +yum install -y bind bind-utils + +# Zone 文件目录(默认 /var/named 即可;如想用 /etc/bind/zones 也可以,但需同步修改下方环境变量) +mkdir -p /var/named +chown root:named /var/named +chmod 2770 /var/named + +# named.conf(追加 include,让 named 加载 Web UI 写入的 named.conf.local) +grep -q 'named.conf.local' /etc/named.conf || \ + echo 'include "/etc/named.conf.local";' >> /etc/named.conf + +# 给 Web UI 一个空白的入口文件 +touch /etc/named.conf.local +chown root:named /etc/named.conf.local +chmod 640 /etc/named.conf.local + +systemctl enable named +systemctl start named +``` + ### 3. 安装 Web 应用 ```bash @@ -169,6 +198,50 @@ systemctl enable dns-web systemctl start dns-web ``` +### 5. 路径配置(环境变量) + +BIND 在不同发行版的默认路径不同,下面这些环境变量可以覆盖默认值(不设置则使用 Debian/Ubuntu 默认): + +| 变量 | Debian/Ubuntu 默认 | RHEL/CentOS 推荐值 | +|------|--------------------|--------------------| +| `BIND_CONF_DIR` | `/etc/bind` | `/etc` | +| `BIND_ZONES_DIR` | `/etc/bind/zones` | `/var/named` | +| `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` | +| `BIND_SERVICE` | `named` | `named` | + +在 systemd 服务里加 `Environment=`: + +```bash +cat > /etc/systemd/system/dns-web.service << 'EOF' +[Unit] +Description=DNS Web Manager +After=network.target named.service + +[Service] +Type=notify +User=root +WorkingDirectory=/root/dns-service +Environment=BIND_CONF_DIR=/etc +Environment=BIND_ZONES_DIR=/var/named +Environment=BIND_CONF_LOCAL=/etc/named.conf.local +Environment=BIND_CONF_OPTIONS=/etc/named.conf +Environment=BIND_RNDC_KEY=/etc/rndc.key +ExecStart=/usr/local/bin/gunicorn --workers 2 --bind 0.0.0.0:5300 wsgi:app +Restart=always +RestartSec=5 + +[Install] +WantedBy=multi-user.target +EOF + +systemctl daemon-reload +systemctl restart dns-web +``` + +> 注意:覆盖 `BIND_CONF_LOCAL` 后,**必须**让 named 主配置 include 这个文件。CentOS 7 的 `/etc/named.conf` 默认不会 include,需要按上面"配置 BIND / RHEL"一节里的命令追加 `include "/etc/named.conf.local";`。 + ## 使用说明 ### 登录 diff --git a/app.py b/app.py index d31ed40..79cd33e 100644 --- a/app.py +++ b/app.py @@ -27,12 +27,16 @@ app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False db = SQLAlchemy(app) # ─── BIND paths ─── -BIND_CONF_DIR = "/etc/bind" -BIND_ZONES_DIR = "/etc/bind/zones" -BIND_CONF_LOCAL = "/etc/bind/named.conf.local" -BIND_CONF_OPTIONS = "/etc/bind/named.conf.options" -BIND_RNDC_KEY = "/etc/bind/rndc.key" -BIND_SERVICE = "named" +# Defaults are Debian/Ubuntu (bind9). Override via env on RHEL/CentOS/Rocky: +# BIND_CONF_DIR=/etc BIND_CONF_LOCAL=/etc/named.conf +# BIND_ZONES_DIR=/var/named BIND_CONF_OPTIONS=/etc/named.conf.options +# BIND_RNDC_KEY=/etc/rndc.key +BIND_CONF_DIR = os.environ.get("BIND_CONF_DIR", "/etc/bind") +BIND_ZONES_DIR = os.environ.get("BIND_ZONES_DIR", "/etc/bind/zones") +BIND_CONF_LOCAL = os.environ.get("BIND_CONF_LOCAL", "/etc/bind/named.conf.local") +BIND_CONF_OPTIONS = os.environ.get("BIND_CONF_OPTIONS", "/etc/bind/named.conf.options") +BIND_RNDC_KEY = os.environ.get("BIND_RNDC_KEY", "/etc/bind/rndc.key") +BIND_SERVICE = os.environ.get("BIND_SERVICE", "named") # ─── Record types ─── RECORD_TYPES = ["A", "AAAA", "CNAME", "MX", "TXT", "NS", "PTR", "SRV", "CAA", "SOA"] @@ -890,17 +894,17 @@ def record_delete(zone_name, idx): def service_control(action): u = current_user() if action == "start": - rc, out, err = run_cmd("systemctl start named 2>&1") + rc, out, err = run_cmd("systemctl start named") AuditLog.log(u.username, "启动BIND服务") - msg = "BIND 服务已启动" if rc == 0 else f"启动失败: {err}" + msg = "BIND 服务已启动" if rc == 0 else f"启动失败: {out} {err}" elif action == "stop": - rc, out, err = run_cmd("systemctl stop named 2>&1") + rc, out, err = run_cmd("systemctl stop named") AuditLog.log(u.username, "停止BIND服务") - msg = "BIND 服务已停止" if rc == 0 else f"停止失败: {err}" + msg = "BIND 服务已停止" if rc == 0 else f"停止失败: {out} {err}" elif action == "restart": - rc, out, err = run_cmd("systemctl restart named 2>&1") + rc, out, err = run_cmd("systemctl restart named") AuditLog.log(u.username, "重启BIND服务") - msg = "BIND 服务已重启" if rc == 0 else f"重启失败: {err}" + msg = "BIND 服务已重启" if rc == 0 else f"重启失败: {out} {err}" elif action == "reload": ok, msg = bind_reload() AuditLog.log(u.username, "重载BIND配置") @@ -934,7 +938,7 @@ def config_view(): main_content = "" # Check config - rc, out, err = run_cmd("named-checkconf 2>&1") + rc, out, err = run_cmd("named-checkconf") config_ok = rc == 0 config_msg = out + err @@ -956,11 +960,11 @@ def config_options_save(): # Write to temp and validate with open("/tmp/named_check.tmp", 'w') as f: f.write(content) - rc, out, err = run_cmd("named-checkconf /tmp/named_check.tmp 2>&1") + rc, out, err = run_cmd("named-checkconf /tmp/named_check.tmp") run_cmd("rm -f /tmp/named_check.tmp") if rc != 0: - flash(f"配置验证失败: {err}", "error") + flash(f"配置验证失败: {out} {err}", "error") return redirect(url_for("config_view")) with open(BIND_CONF_OPTIONS, 'w') as f: @@ -986,10 +990,10 @@ def config_local_save(): f.write(content) run_cmd(f"chown root:bind {BIND_CONF_LOCAL}") - rc, out, err = run_cmd("named-checkconf 2>&1") + rc, out, err = run_cmd("named-checkconf") if rc != 0: run_cmd(f"cp {backup} {BIND_CONF_LOCAL}") - flash(f"配置验证失败,已恢复: {err}", "error") + flash(f"配置验证失败,已恢复: {out} {err}", "error") return redirect(url_for("config_view")) bind_reload()