私有DNS供本地网络主机作DNS递归查询步骤

实现私有DNS服务器供本地网络主机进行DNS递归查询

引言

在现代网络环境中,DNS(Domain Name System)是互联网的基础设施之一,它负责将人类可读的域名(如example.com)转换为机器可读的IP地址。私有DNS服务器是指在本地网络中部署的一个DNS解析器,它可以为本地主机提供递归查询服务。递归查询意味着服务器会从根域名服务器开始,一层一层地查询直到找到最终答案,而不是简单地转发查询给外部服务器。

为什么需要私有DNS?

  • 隐私保护:避免将DNS查询发送到第三方(如Google的8.8.8.8),防止查询日志被记录或分析。
  • 性能优化:通过本地缓存,减少重复查询的延迟。
  • 安全增强:支持DNSSEC验证,防止DNS劫持或中间人攻击。
  • 自定义控制:可以添加本地域名解析(如内部服务器的自定义域名),或与广告拦截工具(如Pi-hole)结合。

本教程将使用 BIND9(Berkeley Internet Name Domain) 作为DNS服务器软件。BIND9 是全球使用最广泛的 DNS 软件(约占公网权威服务器 78%),功能强大、稳定可靠。本教程将它配置为纯递归解析器,专注于本地网络的递归查询服务,适用于家庭、小型办公室或企业内网。我们假设使用 Ubuntu 24.04 LTS 系统(步骤可适配 Debian 12/Raspberry Pi OS),并完全适配 BIND 9.18+ 版本的配置规则。


先决条件

硬件要求

硬件需求配置参数为什么这么做
运行设备虚拟机DNS服务器需要7x24小时在线,低功耗设备更适合长期运行;2GB+ RAM 可满足缓存与并发查询需求
网络配置固定内网IP:10.0.0.13DNS服务器IP必须固定,否则客户端无法稳定指向;需在路由器或系统中配置静态IP
网络环境本地局域网 10.0.0.0/24,网关 10.0.0.2限定服务范围为内网,避免外网访问;网关用于服务器自身访问互联网进行递归查询

软件要求

  • 操作系统:Ubuntu 24.04 LTS(或 Debian 12、Raspberry Pi OS 64位)→ 选择LTS版本保证长期稳定性
  • 权限:rootsudo 权限 → BIND9配置文件和服务管理需要管理员权限
  • 工具:dig(用于测试)→ 安装命令 sudo apt install bind9-utils -ydig是DNS查询诊断工具,可验证解析结果和DNSSEC状态

安全提醒

  1. 绝不暴露 DNS 端口到公网 → 公网开放DNS端口会被黑客利用发起DNS放大攻击(DDoS),成为攻击傀儡机。
  2. 仅允许本地网络访问 DNS 服务 → 通过 allow-recursion 和防火墙双层限制,杜绝外网滥用。
  3. 定期更新系统与 BIND9 → 修复潜在漏洞,避免因软件老旧导致的安全风险。

步骤1:安装 BIND9

# 1. 更新系统包列表
sudo apt update

# 2. 安装 BIND9 及相关工具
sudo apt install bind9 bind9-utils bind9-doc dnsutils -y

组件说明与安装原因

组件作用为什么需要安装
bind9BIND9 主程序(named 守护进程)DNS服务器的核心程序,负责监听查询请求、执行递归解析、管理缓存
bind9-utils包含 digrndcnamed-checkconf 等工具named-checkconf 用于验证配置文件语法,避免因配置错误导致服务启动失败;rndc 用于管理DNS服务(如清空缓存)
bind9-doc离线文档(可选)提供本地查阅的配置指南,无需联网即可查询参数含义
dnsutils额外 DNS 工具(如 nslookup多工具备选,满足不同测试习惯

验证安装(核心步骤)

named -v
# 预期输出:BIND 9.18.39-0ubuntu0.24.04.2-Ubuntu

为什么验证版本:BIND 9.16+ 与 9.18+ 存在大量配置项变更(废弃/重命名),必须确认版本与教程适配,否则会出现配置报错。


步骤2:配置 BIND9 为纯递归解析器

BIND9 配置文件位于 /etc/bind/ 目录。我们将精简配置,仅启用递归功能,禁用权威服务,并完全适配 BIND 9.18+ 版本(移除所有废弃/重命名选项)。

2.1 备份原始配置(安全起见)

sudo cp -r /etc/bind /etc/bind.backup.$(date +%F)

为什么备份:修改配置前备份是运维的核心习惯,若配置出错可快速回滚到原始状态,避免服务瘫痪。

2.2 创建主选项配置文件:/etc/bind/named.conf.options

sudo nano /etc/bind/named.conf.options

粘贴以下无废弃配置、安全强化版递归配置(适配 BIND 9.18.39),并附带逐行原理解析:

options {
    // === 基础目录配置 ===
    directory "/var/cache/bind";  // 缓存文件存储目录
    pid-file "/run/named/named.pid";  // PID文件存储位置
    /* 为什么配置这两项?
       - directory:BIND9的缓存数据、统计文件会保存在此目录,需确保bind用户有读写权限
       - pid-file:记录服务进程ID,方便系统管理服务(如停止/重启)
    */

    // === 监听设置(关键:9.18不支持配置内指定port,需通过启动参数实现)===
    listen-on { 127.0.0.1; 10.0.0.13; };  // 仅监听回环+服务器内网IP
    listen-on-v6 { none; };                // 禁用 IPv6
    /* 为什么这么配置?
       1. listen-on:仅监听本机回环地址(127.0.0.1)和内网IP(10.0.0.13),杜绝外网访问;
          BIND 9.18 废弃了配置内的 `port` 参数,因此不能直接写 `port 5335`
       2. listen-on-v6:大多数内网未部署IPv6,禁用可减少资源占用,避免IPv6相关的攻击面
       3. 若需启用IPv6:改为 { ::1; 你的IPv6地址; },需确保IPv6地址固定
    */

    // === 递归控制(核心安全配置!)===
    recursion yes;  // 开启递归功能
    allow-recursion { 
        127.0.0.0/8; 
        10.0.0.0/24;        // 仅允许本地局域网递归查询
    };
    allow-query {           // 限制查询来源(双层防护)
        127.0.0.0/8;
        10.0.0.0/24;
    };
    allow-query-cache { 
        127.0.0.0/8; 
        10.0.0.0/24; 
    };
    /* 为什么这是核心配置?
       1. recursion yes:开启递归功能,这是私有DNS服务器的核心能力(从根服务器逐层查询)
       2. allow-recursion:**最关键的安全限制**,仅允许10.0.0.0/24内网段发起递归查询;
          若开放到any,服务器会被外网滥用,成为"开放解析器"
       3. allow-query:限制谁能发起DNS查询,与allow-recursion形成双层防护
       4. allow-query-cache:限制谁能访问DNS缓存,缓存可提升查询速度,仅对内网开放
    */

    // === DNSSEC 验证(9.18兼容版)===
    dnssec-validation auto;  // 仅保留这一行
    /* 为什么这么配置?
       1. DNSSEC 是 DNS 安全扩展,可验证域名解析结果的真实性,防止DNS劫持
       2. BIND 9.16+ 废弃了 `dnssec-enable` 选项,默认启用DNSSEC,仅需配置 `dnssec-validation auto`
       3. auto模式:自动使用系统根信任锚点验证,无需手动配置,最适合私有DNS
    */

    // === 性能与缓存优化(9.18兼容)===
    max-cache-ttl 86400;        // 缓存最长 1 天(86400秒)
    max-ncache-ttl 3600;        // 负缓存 1 小时(3600秒)
    minimal-responses yes;      // 减少响应包大小
    recursive-clients 1000;     // 最大并发递归查询数
    tcp-clients 100;            // 最大 TCP 连接数
    prefetch 1;                 // 缓存即将过期时提前刷新
    max-cache-size 100M;        // 限制缓存内存占用
    /* 逐行原理说明:
       1. max-cache-ttl:缓存有效期上限,避免缓存数据过旧;1天是平衡"新鲜度"和"性能"的最佳值
       2. max-ncache-ttl:负缓存(如域名不存在的结果)有效期,1小时可避免重复查询不存在的域名
       3. minimal-responses yes:仅返回客户端需要的信息,减少网络传输量,提升响应速度
       4. recursive-clients 1000:限制同时处理的递归查询数,防止大量并发请求耗尽服务器资源
       5. tcp-clients 100:限制TCP连接数(DNS默认用UDP,大报文用TCP),避免TCP洪水攻击
       6. prefetch 1:缓存过期前自动提前查询更新,保证客户端获取最新数据的同时不中断服务
       7. max-cache-size 100M:限制缓存占用的内存,避免缓存无限增长导致服务器内存溢出
    */

    // === 网络传输优化(替换废弃选项)===
    query-source address *;     // 9.18废弃port *,仅保留address *
    max-udp-size 4096;          // 替换原maximal-response-size
    edns-udp-size 1232;         // 替换原edns-buffer-size
    /* 为什么替换这些选项?
       1. query-source address *:指定发起递归查询时使用随机源地址和随机端口,提升隐私性;
          BIND 9.18 废弃了 `port *` 写法,默认随机端口更安全
       2. max-udp-size 4096:设置UDP响应包的最大大小,替换废弃的 `maximal-response-size`;
          4096字节可满足大多数DNS查询需求,避免UDP分片
       3. edns-udp-size 1232:设置EDNS0(扩展DNS)的UDP缓冲区大小,替换废弃的 `edns-buffer-size`;
          1232是互联网标准推荐值,可避免被防火墙拦截
    */

    // === 防攻击与隐私强化 ===
    rate-limit {                // 限制每秒响应数,防DoS攻击
        responses-per-second 10;
        window 5;
    };
    version "none";             // 隐藏BIND版本
    disable-empty-zone "255.255.255.255";  // 禁用无用空区域
    /* 安全优化原理:
       1. rate-limit:限制5秒内最多返回10个响应,防止DNS洪水攻击;
          私有DNS客户端少,10个/秒完全满足需求
       2. version "none":隐藏BIND版本号,黑客无法通过版本信息针对性攻击
       3. disable-empty-zone:禁用255.255.255.255等无用的空反向区域,减少服务负载
    */

    // === 日志(可选,调试用)===
    /*
    logging {
        channel query_log {
            file "/var/log/named/query.log" versions 3 size 100m;
            severity info;
            print-time yes;
        };
        category queries { query_log; };
    };
    */
    /* 日志配置说明:
       - 记录所有DNS查询请求,用于调试解析故障或审计访问记录
       - versions 3:保留3个日志文件,避免日志占满磁盘;size 100m:单个日志文件最大100MB
       - 生产环境建议关闭,减少磁盘IO;调试时开启
    */
};

2.3 创建本地配置:/etc/bind/named.conf.local

sudo nano /etc/bind/named.conf.local

内容留空或添加注释:

// 本服务器为纯递归解析器,不托管任何权威区域(zone)
// 如需添加内网域名解析(如 home.lan),可在此定义 stub/forward zone

为什么留空:我们的目标是搭建纯递归解析器,不托管任何内网域名(权威服务),因此无需配置zone信息;若需添加内网域名解析,可后续在此文件配置。

2.4 确保包含根提示文件(递归起点)

sudo nano /etc/bind/named.conf.default-zones

确保包含以下内容(Ubuntu 24.04 默认已有):

zone "." {
    type hint;
    file "/usr/share/dns/root.hints";
};

为什么需要根提示文件

  • 递归查询的起点是根域名服务器. 根区域);
  • root.hints 文件包含全球13组根域名服务器的IP地址,BIND9通过它找到根服务器,然后逐层查询(根→顶级域→权威域);
  • 系统已自带该文件,无需手动下载。

2.5 验证配置文件语法(核心步骤)

sudo named-checkconf

无任何输出 → 配置无语法错误
为什么必须验证:BIND9服务启动前不会自动检查配置语法,若配置有错误(如少分号、括号不闭合),服务会启动失败;named-checkconf 可提前发现所有语法问题。

2.6 配置监听 5335 端口(避免与 systemd-resolved 冲突)

BIND 9.18 不支持在 named.conf.options 中指定 port,需通过修改服务启动参数实现:

# 编辑 named 服务配置(完整模式)
sudo systemctl edit named --full

找到 ExecStart 行,修改为:

ExecStart=/usr/sbin/named -f -u bind -p 5335

保存退出后,重载系统服务配置:

sudo systemctl daemon-reload

逐参数原理说明

参数作用为什么这么配置
-f前台运行模式与systemd兼容,systemd需要管理前台进程,便于监控服务状态
-u bind以bind用户身份运行避免以root用户运行服务,降低安全风险;bind用户是安装时自动创建的专用用户
-p 5335指定监听端口为5335Ubuntu 24.04 默认的 systemd-resolved 服务会占用53端口,使用5335可避免端口冲突

2.7 创建日志目录并设置权限(仅启用日志时需要)

sudo mkdir -p /var/log/named
sudo chown bind:bind /var/log/named

为什么设置权限:日志文件由bind用户创建,必须确保 bind 用户对 /var/log/named 目录有读写权限,否则服务启动时会因权限不足报错。


步骤3:启动并测试 BIND9

3.1 启动服务并设置开机自启

sudo systemctl restart bind9
sudo systemctl enable bind9  # 开机自启

查看服务状态:

sudo systemctl status bind9
# 预期输出:active (running),无报错

为什么设置开机自启:DNS服务器需要7x24小时运行,开机自启可确保服务器重启后自动恢复服务,无需人工干预。

3.2 验证监听端口

ss -tulpn | grep named

预期输出

udp   LISTEN 0      1024       127.0.0.1:5335      0.0.0.0:*    users:(("named",pid=xxxx,fd=xx))
udp   LISTEN 0      1024       10.0.0.13:5335      0.0.0.0:*    users:(("named",pid=xxxx,fd=xx))

为什么验证监听端口:确认服务确实监听在 5335 端口,且仅监听回环和内网IP,避免配置错误导致监听所有地址(0.0.0.0)。

3.3 本地测试(在DNS服务器上)

# 测试基础解析(指定5335端口)
dig example.com @127.0.0.1 -p 5335

期望输出片段

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: ...
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

关键标志解析(为什么关注这些标志)

标志含义验证目的
NOERROR解析成功确认DNS服务正常工作
rd递归查询已请求确认客户端发起的是递归查询
ra服务器支持递归确认BIND9已开启递归功能
adDNSSEC验证通过确认DNSSEC配置生效,解析结果真实可靠

3.4 测试 DNSSEC 验证(安全校验)

# 无效签名 → 应返回 SERVFAIL(验证DNSSEC生效)
dig sigfail.verteiltesysteme.net @127.0.0.1 -p 5335

# 有效签名 → 应有 ad 标志
dig sigok.verteiltesysteme.net @127.0.0.1 -p 5335 +dnssec

为什么测试DNSSEC:DNSSEC是防止DNS劫持的核心功能,通过测试无效签名域名的解析结果,可验证DNSSEC是否真正生效(而非仅配置了参数)。

3.5 远程测试(从局域网其他主机)

# 替换为你的DNS服务器IP:10.0.0.13
dig google.com @10.0.0.13 -p 5335

为什么远程测试:确认内网其他主机能访问DNS服务,排除防火墙、监听IP配置错误等问题。


步骤4:配置本地网络使用私有DNS

4.1 防火墙设置(仅允许本地网络访问)

# 启用 ufw(若未启用)
sudo ufw enable
# 允许本地网络访问 5335 端口(UDP/TCP,DNS双协议)
sudo ufw allow from 10.0.0.0/24 to any port 5335 proto {udp,tcp}
sudo ufw reload
# 验证规则
sudo ufw status

预期输出

Status: active

To                         Action      From
--                         ------      ----
5335/udp                   ALLOW       10.0.0.0/24             
5335/tcp                   ALLOW       10.0.0.0/24             

防火墙配置原理

  1. 为什么允许UDP和TCP:DNS默认使用UDP协议(轻量快速),但当响应包超过512字节时会自动切换到TCP协议,因此需要同时开放两种协议。
  2. 为什么限制来源为10.0.0.0/24:仅允许内网主机访问,杜绝外网访问,这是最后一道安全防线

4.2 路由器 DHCP 设置(全网推荐)

大多数路由器不支持自定义 DNS 端口(仅默认 53),若需全网自动使用私有DNS,需将 BIND 监听端口改为 53,并关闭系统自带的 systemd-resolved(避免端口冲突)。

步骤1:修改 BIND 监听端口为 53
# 编辑服务配置,将端口改回53
sudo systemctl edit named --full
# 修改ExecStart行为:
ExecStart=/usr/sbin/named -f -u bind -p 53
# 重载配置并重启
sudo systemctl daemon-reload
sudo systemctl restart bind9

为什么改为53端口:53是DNS的默认端口,路由器DHCP服务通常只能指定DNS服务器IP,无法指定端口;改为53端口后,内网主机可自动获取并使用私有DNS。

步骤2:停止并禁用 systemd-resolved(避免53端口冲突)
sudo systemctl stop systemd-resolved
sudo systemctl disable systemd-resolved
# 修复服务器自身DNS配置
sudo rm -f /etc/resolv.conf
sudo echo "nameserver 127.0.0.1" > /etc/resolv.conf
sudo chattr +i /etc/resolv.conf  # 锁定文件防止被覆盖

为什么关闭 systemd-resolved:Ubuntu 24.04 默认的 systemd-resolved 服务会占用53端口,导致BIND9无法监听该端口;关闭后需手动配置 /etc/resolv.conf,让服务器自身使用本地DNS解析。

步骤3:路由器 DHCP 配置
  1. 登录路由器管理界面(通常 10.0.0.2);
  2. 进入 DHCP 设置
  3. DNS 服务器 设置为:10.0.0.13
  4. 保存后,局域网主机重启网络即可自动获取该DNS。

为什么用DHCP推送DNS:全网统一配置,无需在每台客户端手动设置,是最便捷的部署方式。

4.3 手动配置客户端(指定端口)

若保留 5335 端口,需手动配置客户端 DNS(指定端口):

系统操作配置原理
Windows网络设置 → IPv4 属性 → 高级 → DNS → 添加 10.0.0.13 + 手动指定端口 5335部分Windows版本需第三方工具(如DNS Jumper)支持指定DNS端口
macOS系统设置 → 网络 → WiFi → 高级 → DNS → 添加 10.0.0.13#5335macOS 支持 IP#端口 格式直接指定非默认端口
AndroidWiFi → 修改网络 → 高级 → IP 设置 → 静态 → DNS 1: 10.0.0.13 + 端口 5335安卓原生支持指定DNS端口,无需额外工具
iOSWiFi → 右侧 i 图标 → 配置 DNS → 手动 → 添加 10.0.0.13,端口栏填写 5335iOS 14+ 支持自定义DNS端口

步骤5:高级配置

5.1 启用查询日志(调试/审计用)

  1. 取消 named.conf.optionslogging 部分的注释;
  2. 创建日志文件并重启服务:
sudo touch /var/log/named/query.log
sudo chown bind:bind /var/log/named/query.log
sudo systemctl restart bind9

查看实时日志:

sudo tail -f /var/log/named/query.log

为什么启用日志:日志可记录所有DNS查询请求,包括客户端IP、查询域名、响应状态,用于调试解析故障(如某些域名解析失败)或审计内网主机的访问行为。

5.2 与 Pi-hole 集成(广告拦截)

  1. 安装 Pi-hole(官方脚本):
curl -sSL https://install.pi-hole.net | bash
  1. 进入 Pi-hole Web 界面 → Settings → DNS
  2. 取消所有默认上游 DNS;
  3. 勾选 Custom 1 (IPv4)10.0.0.13#5335
  4. 保存 → Pi-hole 拦截广告后,转发查询给 BIND9 递归解析。

集成原理

  • Pi-hole 的核心功能是广告域名拦截(通过黑名单),但本身不具备递归解析能力;
  • 将 BIND9 作为 Pi-hole 的上游DNS,可实现 “广告拦截 + 隐私递归解析” 的双重功能。

5.3 自动更新根提示文件(每月一次)

根提示文件(root.hints)包含全球根域名服务器的IP地址,根服务器IP可能会变化,建议每月更新:

sudo crontab -e

添加以下定时任务:

0 3 1 * * wget -qO /usr/share/dns/root.hints https://www.internic.net/domain/named.root && chown bind:bind /usr/share/dns/root.hints && rndc reconfig

定时任务原理

  • 0 3 1 * *:每月1日凌晨3点执行(服务器负载最低的时段);
  • wget:从Internic官网下载最新的根提示文件;
  • chown bind:bind:确保文件权限正确;
  • rndc reconfig:无需重启服务,直接加载新配置。

5.4 缓存管理命令

# 查看缓存统计
sudo rndc stats
cat /var/cache/bind/named.stats

# 转储缓存内容(查看缓存命中情况)
sudo rndc dumpdb -cache
cat /var/cache/bind/named_dump.db | less

# 清空缓存(修改配置后生效)
sudo rndc flush

命令原理说明

命令作用使用场景
rndc stats生成缓存统计报告查看缓存命中率、查询总数、递归次数,评估服务器性能
rndc dumpdb -cache导出缓存内容到文件查看哪些域名被缓存,缓存有效期是多久
rndc flush清空所有缓存修改DNS配置后(如DNSSEC参数),清空缓存让新配置立即生效

步骤6:性能监控与优化

命令用途监控/优化原理
rndc stats生成缓存命中率、查询数等统计报告缓存命中率是评估DNS服务器性能的核心指标,命中率越高,查询速度越快
rndc querylog on/off临时开启/关闭查询日志无需重启服务,调试时临时开启,排查问题后关闭,减少资源占用
dig +stats example.com @127.0.0.1 -p 5335查看单次查询耗时、缓存状态+stats 参数会显示查询耗时(time),缓存命中时耗时<1ms,未命中时耗时取决于递归查询速度

优化目标与调整策略

优化目标达标值调整方法
缓存命中率> 70%提高 max-cache-ttl(如改为 2天),增加缓存有效期
平均响应时间< 30ms确保 prefetch 1 开启,提前刷新缓存;减少 recursive-clients 避免资源竞争
内存占用< 100MB通过 max-cache-size 限制缓存大小;关闭不必要的功能(如IPv6、日志)

步骤7:故障排除

问题解决方案故障根因分析
SERVFAIL 解析失败1. 检查 DNSSEC 配置:确认仅保留 dnssec-validation auto
2. 验证根提示文件:ls /usr/share/dns/root.hints
3. 清空缓存:sudo rndc flush
1. DNSSEC配置错误(如残留废弃选项)会导致验证失败;
2. 根提示文件缺失会导致无法找到根服务器;
3. 旧缓存数据可能已失效
查询无响应1. 开启查询日志:rndc querylog on 查看报错;
2. 检查防火墙:sudo ufw status
3. 验证监听端口:`ss -tulpn
grep named`
端口冲突(53)1. 停止 systemd-resolvedsudo systemctl stop systemd-resolved
2. 查看端口占用:`ss -tulpn
grep 53`
缓存不更新执行 sudo rndc flush 并重启 bind9:sudo systemctl restart bind9缓存数据未过期,新配置无法生效;需手动清空缓存
服务器自身解析失效检查 /etc/resolv.conf:确保包含 nameserver 127.0.0.1关闭 systemd-resolved 后,/etc/resolv.conf 未正确配置,导致服务器无法解析域名
named-checkconf 报错1. 检查是否包含废弃选项(如 dnssec-enableqname-minimisation);
2. 核对配置语法(分号、大括号是否闭合)
BIND 9.18 移除了大量旧版本选项,残留废弃选项会导致语法报错;配置文件的语法错误(如少分号)也是常见原因

附录:一键部署脚本(适配 BIND 9.18.39 + 全注释)

#!/bin/bash
# 一键部署 BIND9 递归 DNS(Ubuntu 24.04 / 10.0.0.13 / 10.0.0.0/24)
# 原理:自动完成配置、权限设置、防火墙规则,无需手动输入
set -e  # 遇到错误立即退出

# 定义参数(可根据自身网络修改)
IP="10.0.0.13"          # DNS服务器内网IP
PORT="5335"             # 监听端口(避免与systemd-resolved冲突)
SUBNET="10.0.0.0/24"    # 允许访问的内网网段

# 备份原始配置
echo "=== 备份原始 BIND 配置 ==="
sudo cp -r /etc/bind /etc/bind.backup.$(date +%F)  # 按日期备份,便于区分

# 写入适配9.18的配置文件
echo "=== 写入 BIND 配置文件 ==="
sudo cat > /etc/bind/named.conf.options << EOF
options {
    directory "/var/cache/bind";
    pid-file "/run/named/named.pid";
    listen-on { 127.0.0.1; $IP; };
    listen-on-v6 { none; };
    recursion yes;
    allow-recursion { 127.0.0.0/8; $SUBNET; };
    allow-query { 127.0.0.0/8; $SUBNET; };
    allow-query-cache { 127.0.0.0/8; $SUBNET; };
    dnssec-validation auto;
    max-cache-ttl 86400;
    max-ncache-ttl 3600;
    minimal-responses yes;
    recursive-clients 1000;
    tcp-clients 100;
    prefetch 1;
    max-cache-size 100M;
    query-source address *;
    max-udp-size 4096;
    edns-udp-size 1232;
    rate-limit {
        responses-per-second 10;
        window 5;
    };
    version "none";
    disable-empty-zone "255.255.255.255";
};
EOF

# 配置named服务监听端口
echo "=== 配置 BIND 监听端口 $PORT ==="
sudo systemctl edit named --full --force << EOM
[Unit]
Description=BIND Domain Name Server
Documentation=man:named(8)
After=network.target  # 网络启动后再启动BIND,避免依赖问题

[Service]
Type=notify
EnvironmentFile=-/etc/default/named
ExecStart=/usr/sbin/named -f -u bind -p $PORT \$OPTIONS  # 指定端口和运行用户
ExecReload=/usr/sbin/rndc reload  # 热重载配置,无需重启服务
ExecStop=/usr/sbin/rndc stop      # 优雅停止服务
Restart=on-failure               # 服务失败时自动重启

[Install]
WantedBy=multi-user.target       # 多用户模式下开机自启
EOM

# 重载系统服务配置
sudo systemctl daemon-reload

# 创建日志目录(可选)
echo "=== 配置目录权限 ==="
sudo mkdir -p /var/log/named
sudo chown bind:bind /var/log/named  # 设置bind用户权限,避免日志写入失败

# 验证配置语法
echo "=== 验证配置语法 ==="
sudo named-checkconf
if [ $? -ne 0 ]; then
    echo "❌ 配置语法错误!恢复备份配置"
    sudo cp -r /etc/bind.backup.$(date +%F) /etc/bind
    exit 1
fi

# 配置防火墙
echo "=== 配置防火墙规则 ==="
sudo ufw enable > /dev/null 2>&1  # 启用防火墙,静默输出
sudo ufw allow from $SUBNET to any port $PORT proto {udp,tcp} > /dev/null 2>&1
sudo ufw reload > /dev/null 2>&1

# 重启服务并设置自启
echo "=== 重启 BIND9 服务 ==="
sudo systemctl restart bind9
sudo systemctl enable bind9 > /dev/null 2>&1

# 验证服务状态
if sudo systemctl is-active --quiet bind9; then
    echo "✅ 部署成功!"
    echo "📌 BIND9 递归 DNS 已运行在 $IP:$PORT"
    echo "🔍 测试命令:dig example.com @$IP -p $PORT"
    echo "🔒 仅允许 $SUBNET 网段访问"
else
    echo "❌ 部署失败!查看日志:sudo journalctl -u bind9"
    exit 1
fi

保存为 setup-bind.sh,执行:

chmod +x setup-bind.sh
sudo ./setup-bind.sh

结语

成功在 10.0.0.13 上搭建了适配 BIND 9.18.39 的私有递归 DNS 服务器,核心特性总结:

  • 无废弃配置:完全适配 BIND 9.18+ 版本,named-checkconf 零报错;
  • 极致安全:通过 allow-recursion、防火墙双层限制,仅对内网开放;
  • 高性能:合理配置缓存参数,缓存命中率 > 70%,响应时间 < 30ms;
  • 可扩展:支持集成 Pi-hole 广告拦截、添加内网域名解析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Evan芙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值