在 Debian 下编译支持 Redis 的 Unbound

由于 unbound 的标准包里面没有带有 redis 支持,所以我们需要自己编译

对于 Debian 系统需要做如下准备

apt autopurge unbound # 卸载 Debian 的标准 unbound 包
apt install redis-server # 安装 redis 服务器
apt install build-essential libssl-dev libexpat1-dev libevent-dev libhiredis-dev # 安装编译 unbound 所需工具

然后我们开始准备下载源码包准备编译安装

wget https://nlnetlabs.nl/downloads/unbound/unbound-1.23.1.tar.gz # 下载官网最新源码包
tar -xzvf unbound-1.23.1.tar.gz
cd unbound-1.23.1
# 编译安装
./configure --prefix=/usr --sysconfdir=/etc --with-libhiredis --enable-cachedb --with-libevent
make
make install

安装之后我们还需要为服务器准备一个 unbound 用户组和 systemd service 用于单独持续运行

useradd -r -s /bin/false unbound # 创建 unbound 用户,不允许登录
vim /etc/systemd/system/unbound.service
# systemd service 文件
[Unit]
Description=Unbound DNS Resolver
Documentation=man:unbound(8)
After=network-online.target
Wants=network-online.target

[Service]
User=unbound
Group=unbound

CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
NoNewPrivileges=true

RuntimeDirectory=unbound
RuntimeDirectoryMode=0755

ExecStartPre=/usr/sbin/unbound-checkconf
ExecStart=/usr/sbin/unbound -d -c /etc/unbound/unbound.conf
ExecReload=/usr/sbin/unbound-control reload

Restart=on-failure
RestartSec=1s

ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
PrivateDevices=true

[Install]
WantedBy=multi-user.target

最后在 /etc/unbound 目录修改配置文件

server:
    # ===========================================================================
    # 网络和核心设置
    # ===========================================================================

    # 监听本地 IPv4 和 IPv6 接口
    interface: 127.0.0.1
    interface: ::1
    port: 53

    # 允许来自本机的查询
    access-control: 127.0.0.1/32 allow
    access-control: ::1/128 allow

    # 启用 IPv4, IPv6, UDP 和 TCP 查询
    do-ip4: yes
    do-ip6: yes
    do-udp: yes
    do-tcp: yes

    # 根据你的 CPU 核心数进行设置。例如,如果你的 CPU 是 4 核,就设置为 4。
    # 这能让 Unbound 并行处理更多请求。
    num-threads: 1
    pidfile: "/run/unbound/unbound.pid"
    chroot: ""

    # 建议移除 so-rcvbuf 和 so-sndbuf,让操作系统自动管理。
    # 如果你的服务器负载极高,可以取消注释并设置为 4m 或 8m。
    # so-rcvbuf: 4m
    # so-sndbuf: 4m

    # ===========================================================================
    # 性能和缓存优化
    # ===========================================================================

    # 消息缓存大小,存储 DNS 查询和应答。
    msg-cache-size: 64m
    # RRset 缓存大小,存储 DNS 记录。建议为 msg-cache-size 的两倍。
    rrset-cache-size: 128m

    # 将缓存条目分成多个板块,减少多线程锁竞争。值设为接近 num-threads 的2的幂。
    msg-cache-slabs: 1
    rrset-cache-slabs: 1
    infra-cache-slabs: 1
    key-cache-slabs: 1

    # 开启预取功能,在缓存过期前主动更新热门记录,保持缓存新鲜。
    prefetch: yes
    # 同样为 DNSSEC 密钥开启预取。
    prefetch-key: yes

    # 关键性能选项:开启后,即使记录过期也会立即从缓存返回,并在后台更新。
    # 极大地提升了用户感知的响应速度。
    serve-expired: yes
    # 设定过期记录的TTL(生存时间),防止客户端缓存过期的记录。
    serve-expired-reply-ttl: 30
    # 设定过期记录在缓存中可以被使用的最长时间。0 表示无限制。
    serve-expired-ttl: 86400

    # ===========================================================================
    # 安全和隐私增强 (这些对性能影响极小,但建议保留)
    # ===========================================================================

    # 强化 DNSSEC 数据,防止降级攻击。
    harden-glue: yes
    harden-dnssec-stripped: yes

    # 最小化查询名称,增强隐私保护。
    qname-minimisation: yes

    # 隐藏身份和版本信息。
    hide-identity: yes
    hide-version: yes
    
    # 使用随机的端口ID,增加对缓存投毒攻击的抵抗力。
    use-caps-for-id: yes
    
    # 启用最小化响应,只返回必要信息,略微减少网络流量。
    minimal-responses: yes

    # 定义私有地址,防止 DNS Rebinding 攻击。
    private-address: 10.0.0.0/8
    private-address: 172.16.0.0/12
    private-address: 192.168.0.0/16

    # 不要查询 localhost 上的权威服务器。
    do-not-query-localhost: yes
    hide-trustanchor: yes
    
    # TLS 证书包路径,用于 DNSSEC 验证。
    tls-cert-bundle: "/etc/ssl/certs/ca-certificates.crt"
    module-config: "validator cachedb iterator"
    
cachedb:
    backend: "redis"
    redis-server-host: 127.0.0.1
    redis-server-port: 6379

forward-zone:
    name: "."
    forward-tls-upstream: yes
    forward-addr: 1.1.1.1@853        # Cloudflare
    forward-addr: 1.0.0.1@853
    forward-addr: 9.9.9.9@853        # Quad9
    forward-addr: 149.112.112.112@853

最后检测 unbound 链接 redis 是否成功

systemd status unbound
# 出现 notice: Connection to Redis established (127.0.0.1 6379) 就是成功链接