Blocky v0.33.0 配置参数详解

Blocky v0.33.0 配置参数详解:27 个功能配置键总览与 16 类核心参数逐项讲解(语法/默认值/实测行为)、生产配置模板与 6 类配置 FAQ,官方参考文件取证并在 Ubuntu 22.04 实测。

BlockyBlockyDNS 服务安全2026/10/20

Blocky v0.33.0 配置参数详解

目标:逐一讲清 Blocky v0.33.0 的 config.yml 全部配置节——语法、默认值、取值范围与实测行为,并给出一套可直接落地的生产配置模板。参数语法与默认值取自官方参考配置文件与 JSON Schema(0xerr0r.github.io/blocky/latest/,查询日期 2026-10-20),标注「实测」的行为均在 Ubuntu 22.04.4 LTS 真实跑通并逐行记录回显。

一、环境信息

  • 操作系统:Ubuntu 22.04.4 LTS(x86_64),内核 6.8.0-138-generic
  • 软件版本:Blocky v0.33.0(官方二进制,blocky version 实测:Version v0.33.0 / Build time 20260630-080230)
  • 配置文件:/etc/blocky/config.yml(实验副本位于工作目录 config/config.yml,内容一致)
  • 实验监听:DNS 127.0.0.11:53(宿主 53 被占用,绑空闲回环地址,过程见《Ubuntu 22.04 安装 Blocky v0.33.0 指南》),HTTP 127.0.0.11:8130
  • 取证来源:官方参考配置 https://0xerr0r.github.io/blocky/latest/config.yml(28KB 全注释版,2026-10-20 下载)、JSON Schema https://0xerr0r.github.io/blocky/latest/config.schema.json(56KB,2026-10-20 下载)
  • 验证工具:dig(bind9-dnsutils 9.18.39)、curl、systemctl

二、前置条件

  • 已按部署篇完成 Blocky v0.33.0 安装并能 blocky validate 校验配置(Configuration is valid 回显)。
  • 理解 YAML 基础语法(列表 -、映射缩进、| 字面量块);Blocky 对同一配置键在多文件合并时重复出现会启动失败(官方文档明确:多文件是简单拼接,选项重复即报错)。
  • 修改配置的标准操作循环(每节实验都用到):改 config.yml → blocky validate → systemctl restart blocky → dig/curl 复验。

三、参数查看与修改方式

1. 官方参考文件(全参数注释版):最权威的参数字典,每个参数带内联注释与默认值说明,建议直接下载对照:

curl -sS -o /etc/blocky/config-reference.yml https://0xerr0r.github.io/blocky/latest/config.yml
wc -c /etc/blocky/config-reference.yml

实测回显(下载到工作区时的实测值):

28232 /opt/data/quzuo/tmp/blocky/reference-config.yml

2. JSON Schema 校验:schema 定义了全部顶级键与取值类型,可挂到编辑器做实时补全与校验(官方 Configuration 章节「Editor support and validation」);schema 顶级键共 38 个(含 upstreams、ports、blocking 等 27 个功能键与 port、logLevel 等旧版兼容键),2026-10-20 实查。

3. CLI 校验与运行时打印:

blocky validate --config /etc/blocky/config.yml

实测回显:

[2026-10-20 17:24:38]  INFO Validating configuration file: config.yml
[2026-10-20 17:24:38]  INFO Configuration is valid

启动时 Blocky 会把生效配置完整打印到日志(server: current configuration: 起,含 blocking 缓存条数、caching 参数、listeners 各监听地址、runtime 内存信息),这是确认「配置真的生效了」的第一手证据。实测节选:

[2026-10-20 17:18:34]  INFO server: -> blocking:
[2026-10-20 17:18:34]  INFO server:      blockType = ZEROIP
[2026-10-20 17:18:34]  INFO server:      blockTTL = 6 hours
[2026-10-20 17:18:34]  INFO server: -> caching:
[2026-10-20 17:18:34]  INFO server:      cacheTimeNegative = 30 minutes
[2026-10-20 17:18:34]  INFO server: listeners:
[2026-10-20 17:18:34]  INFO server:   DNS      = [127.0.0.11:53]
[2026-10-20 17:18:34]  INFO server:   HTTP     = [127.0.0.11:8130]

四、参数总览

Blocky v0.33.0 配置按功能分节,下表列出全部功能配置键(官方参考文件与 schema 实查,2026-10-20):

配置键作用域一句话说明默认行为
upstreams出站解析上游分组、选路策略、超时、QUIC 参数strategy=parallel_best,timeout=2s
connectIPVersion出站连接出站 IP 栈 dual/v4/v6dual
customDNS本机记录自定义 A/AAAA 记录与域名重写不启用
conditional条件转发按域名后缀指定专属上游不启用
blocking屏蔽核心黑白名单、客户端分组、拦截方式、名单加载不启用(无名单即不拦截)
caching缓存TTL 上下界、负缓存、预取、容量TTL 原样缓存,负缓存 30m
clientLookup客户端识别反向解析客户端名、自定义映射不启用
queryLog查询日志控制台/CSV/SQL/dnstap、保留期控制台输出全部字段
prometheus指标/metrics 端点关闭
statistics统计内存统计 24h 窗口与 /api/stats关闭
redis多实例Redis 同步缓存与屏蔽状态不启用
ports监听DNS/DoT/HTTP/HTTPS 监听地址端口DNS 53,HTTP/HTTPS/TLS 关闭
minTlsServeVersionTLSDoT/DoH 服务端最低 TLS 版本1.3
certFile/keyFileTLS证书路径(未配置则自签)自签证书
bootstrapDns引导解析解析上游域名/名单域名用的引导 DNS系统 /etc/resolv.conf
filtering入口过滤按查询类型丢弃(如 AAAA)不过滤
rebindingProtection安全丢弃上游应答中的私网地址关闭
rateLimit安全每客户端令牌桶限速关闭
fqdnOnly安全非 FQDN 查询返回 NXDOMAIN关闭
hostsFile本机记录/etc/hosts/URL/内联 hosts 解析不启用
ede诊断DNS 响应附加 EDE 错误码关闭
specialUseDomains安全拦截 RFC 6762 附录 G 私有 TLDenable=true
ecs隐私ECS 透传/作为客户端识别不透传
dnssec安全DNSSEC 验证(v0.31+)关闭
dns64IPv6DNS64 合成(RFC 6147)关闭
http3协议DoH over HTTP/3关闭
log日志级别/格式/时间戳/隐私脱敏info/text/开/关

💡 技术拓展:upstreams.groups 的分组键与 blocking.clientGroupsBlock 的分组键共用同一套客户端匹配体系——组键可以是 default(兜底)、客户端主机名通配(laptop*,* 匹配任意串、[0-9] 匹配数字范围)、单个 IP 或 CIDR(192.168.178.1/24)。同一键值在 upstreams 里表达「该客户端用哪些上游」,在 blocking 里表达「该客户端套哪些名单组」,两者组合即可实现「访客设备走加密上游 + 强屏蔽,办公设备走内网上游 + 弱屏蔽」的精细化策略。

五、核心参数分类详解

本章按功能节逐一展开。「实测」标注的行为均在本文环境真实执行并记录回显;默认值均来自官方参考配置内联注释。

5.1 upstreams:上游分组与选路

upstreams:
  init:
    strategy: fast          # 启动行为:blocking(默认,等名单与上游就绪)| failOnError | fast
  groups:
    default:                # 组名自定义;default 兜底
      - 223.5.5.5           # 普通 UDP/TCP,端口缺省 53
      - tcp-tls:1.12.12.12:853   # DoT
      - https://dns.alidns.com/dns-query   # DoH
      - quic:dns.adguard.com                     # DoQ,缺省端口 853
      - sdns://AAcAAAAAAAAABzguOC44Ljg           # DNS Stamp(示例:Google 8.8.8.8 明文)
  strategy: parallel_best   # parallel_best(默认)| strict | random
  timeout: 2s               # 单次上游查询超时
  quic:                     # 仅配置了 quic: 上游时相关
    maxIdleTimeout: 30s
    keepAlivePeriod: 15s
  userAgent: "custom UA"    # DoH 出站 User-Agent,默认无

逐项说明:groups 是唯一必填节(缺省启动失败实录见部署篇 FAQ);解析器格式 [net:]host[:port][/path][#commonname],net 省略即 tcp+udp;每查询从组内随机挑 2 个上游参与 parallel_best 竞速(官方注释)。init.strategy 控制启动时机——blocking 等全部上游与名单就绪才开监听(最稳),fast 立即监听后台加载(最快),failOnError 出错即退出。

实测:本文实验配置上游组 default: [223.5.5.5, 119.29.29.29],启动日志打印生效上游与策略:

[2026-10-20 17:18:34]  INFO server: -> parallel_best:
[2026-10-20 17:18:34]  INFO server:      group: default
[2026-10-20 17:18:34]  INFO server:      upstreams:
[2026-10-20 17:18:34]  INFO server:        - tcp+udp:223.5.5.5
[2026-10-20 17:18:34]  INFO server:        - tcp+udp:119.29.29.29

查询日志中 response_reason=RESOLVED (tcp+udp:223.5.5.5) 可见实际胜出的上游(实测多行使该值在两个上游间交替出现)。

5.2 ports:监听地址与端口

ports:
  dns:                      # DNS 监听(UDP+TCP 同时开)
    - 53                    # 生产推荐:等价绑 0.0.0.0:53
    - 127.0.0.11:53         # 实验实测:绑指定回环地址(实测回显见下)
  tls: 853                  # DoT 服务端,默认关闭
  http: 4000                # REST API + Prometheus + pprof
  https: 443                # DoH 服务端 + HTTP 能力(需证书或自签)
  dohPath: /dns-query       # DoH 路径,默认 /dns-query
  freeBind: false           # Linux IP_FREEBIND:允许绑定尚未配置到网卡的地址
  proxyProtocol: []         # HAProxy PROXY protocol 头解析(仅可信代理前置时开)

地址语法支持四种形态(官方注释):53、:53、127.0.0.1:53、[::1]:53,可多元素列表同时监听多个地址。

实测一(绑空闲回环地址 127.0.0.11):

[2026-10-20 17:18:34]  INFO server: UDP server is up and running on address 127.0.0.11:53
[2026-10-20 17:18:34]  INFO server: TCP server is up and running on address 127.0.0.11:53
[2026-10-20 17:18:34]  INFO server: http server is up and running on addr/port 127.0.0.11:8130

实测二(绑定被占用地址的报错,ports.dns: 127.0.0.1:53 触发):

[2026-10-20 17:21:25] ERROR server start failed: start udp listener failed: listen udp 127.0.0.1:53: bind: address already in use

💡 说明:Linux 上 lo 接口为 127.0.0.1/8,整个 127/8 网段无需额外加地址即可绑定(实测 ip addr show lo 仅显 inet 127.0.0.1/8 仍成功绑 127.0.0.11)。这对「一台服务器多 DNS 实验并存」「53 被存根占用」场景非常实用。

5.3 blocking:屏蔽核心

blocking:
  denylists:
    ads:                    # 命名名单组
      - https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts   # URL 名单
      - /etc/blocky/denylist.txt                                           # 本地文件
      - |                   # 内联名单(YAML 字面量块)
        someadsdomain.com
        *.example.com
    special:
      - https://raw.githubusercontent.com/StevenBlack/hosts/master/alternates/fakenews/hosts
  allowlists:
    ads:
      - /etc/blocky/allowlist.txt   # 同组内 allowlist 优先于 denylist
  clientGroupsBlock:
    default: [ads]          # 兜底分组
    laptop*: [ads]          # 主机名通配
    192.168.178.1/24: [special]   # CIDR
  blockType: zeroIp         # zeroIp(默认)| nxDomain | refused | 逗号分隔 IP 列表
  blockTTL: 6h              # 拦截应答 TTL,默认 6h
  loading:
    refreshPeriod: 4h       # 名单刷新周期,<=0 关闭
    concurrency: 4          # 并发加载名单数
    strategy: blocking      # 启动策略(同 upstreams.init.strategy)
    maxErrorsPerSource: 5   # 单名单允许的错误行数,超限视为名单无效
    downloads:
      timeout: 5s           # 下载超时(大名单/慢网调大)
      attempts: 3           # 下载重试次数
      cooldown: 500ms       # 重试间隔
      # cachePath: /var/cache/blocky/lists   # 可选磁盘下载缓存(断网续用旧名单)
  schedules:                # v0.33:命名时段表
    workhours:
      weekdays: [mon, tue, wed, thu, fri]
      start: "08:00"
      end: "18:00"
  listSchedules:            # 名单组绑定时段(多时段 OR 组合)
    special: [workhours]

逐项说明:名单条目支持 hosts 格式(URL/文件)与纯域名行(内联块);*.example.com 通配子域;正则条目以 / 包裹(如 /^banners?[_.-]/,官方参考文件示例)。同组同时有黑白名单时白名单胜出;若某客户端的所有组只配了白名单,进入「独占放行」模式(名单外全部拦截)。

实测一(denylist 文件名单 + zeroIp 默认拦截):

dig +time=3 +tries=1 doubleclick.net @127.0.0.11 +short

实测回显:

0.0.0.0

实测二(blockType: nxDomain 改拦截方式后重启,同一域名):

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

实测三(名单加载日志与缓存条数):

[2026-10-20 17:18:34]  INFO list_cache: import succeeded count=2 source=file:///etc/blocky/denylist.txt
[2026-10-20 17:18:34]  INFO list_cache: group import finished group=ads total_count=2
[2026-10-20 17:18:34]  INFO server:      denylist cache entries:
[2026-10-20 17:18:34]  INFO server:        ads: 2 entries

5.4 caching:响应缓存

caching:
  minTime: 5m               # 缓存下限:应答 TTL 低于此值按此值缓存;<=0 用原 TTL;默认 0
  maxTime: 30m              # 缓存上限:TTL 高于此值按此值缓存;<0 不缓存;默认 0
  maxItemsCount: 0          # 缓存条目软上限(限内存用),0 不限
  prefetching: false        # 预取高频域名(2 小时窗口内查询 >5 次的)
  prefetchExpires: 2h       # 预取统计窗口
  prefetchThreshold: 5      # 预取阈值
  prefetchMaxItemsCount: 0  # 预取域名缓存上限
  cacheTimeNegative: 30m    # 负缓存(NXDOMAIN/空应答)时长;-1 关闭

实测:配置 minTime: 5m、maxTime: 30m 后,customDNS 记录 myserver.lan(customTTL 1h)返回 TTL 3600:

myserver.lan.           3600    IN      A       192.168.178.3

💡 说明:customDNS 的应答 TTL 由 customDNS.customTTL 决定,不经 caching 上下界裁剪;caching 的 min/max 作用于上游透传应答(如 5.6 节 conditional 转发与普通递归结果)。启动日志可见生效值 minTime = 0 seconds / maxTime = 0 seconds / cacheTimeNegative = 30 minutes(未配置 caching 时的默认形态,实测)。

5.5 customDNS:自定义记录与域名重写

customDNS:
  customTTL: 1h             # 自定义记录的应答 TTL
  filterUnmappedTypes: true # true(默认):未映射类型(TXT/MX)返回空应答;false:透传上游
  rewrite:                  # 查询前重写域名
    example.com: printer.lan
  mapping:                  # 域名 → IP(逗号分隔可多值,含 IPv6)
    printer.lan: 192.168.178.3,2001:0db8:85a3:08d3:1319:8a2e:0370:7344
    myserver.lan: 192.168.178.3

实测(mapping: {myserver.lan: 192.168.178.3} + customTTL: 1h):

dig +time=3 +tries=1 myserver.lan @127.0.0.11 +short

实测回显:

192.168.178.3

完整应答中 TTL 为 3600(1h),与 customTTL 一致(实测)。

5.6 conditional:条件转发

conditional:
  fallbackUpstream: false   # false(默认):映射上游查不到就返回空;true:回落原查询到通用上游
  rewrite:                  # 查询前重写(split DNS 场景)
    example.com: fritz.box
  mapping:                  # 域名后缀 → 专属上游(逗号分隔多上游)
    fritz.box: 192.168.178.1
    qq.com: 223.5.5.5

实测(mapping: {qq.com: 223.5.5.5},查 www.qq.com 走指定上游并返回 CNAME 链,实测 +short 输出):

ins-r23tsuuf.ias.tencent-cloud.net.
ins-ysshqadg.ias.tencent-cloud.net.

查询日志 response_reason=RESOLVED (tcp+udp:223.5.5.5) 佐证走了映射上游(实测)。

5.7 hostsFile:hosts 文件解析

hostsFile:
  sources:
    - /etc/hosts            # 本机 hosts 文件
    - https://example.com/hosts   # 远程 hosts
    - |                     # 内联 hosts
      192.168.178.99 inline-test.lan
  hostsTTL: 30m             # hosts 记录 TTL,默认 1h
  filterLoopback: false     # 是否过滤 127.0.0.0/8 与 ::1 地址,默认 false
  loading:                  # 加载行为,同 blocking.loading(refreshPeriod 默认 4h)
    refreshPeriod: 24h

实测(内联 hosts 条目,TTL 1800 = hostsTTL 30m):

inline-test.lan.        1800    IN      A       192.168.178.99

5.8 queryLog 与 statistics:日志与统计

queryLog:
  type: csv-client          # 空=控制台(默认)| mysql | postgresql | timescale | sqlite | csv | csv-client | dnstap
  target: /var/lib/blocky/querylog.db   # csv=目录;sqlite=文件路径;mysql/postgresql=连接串
  logRetentionDays: 7       # >0 时自动清理超期日志;0 永久保留
  creationAttempts: 3       # 日志写入器创建重试次数
  creationCooldown: 2s      # 重试间隔
  fields:                   # 裁剪字段(缺省全量):clientIP clientName responseReason responseAnswer question duration
    - clientIP
    - duration
  flushInterval: 30s        # 批量写外部库的间隔
  # dnstap 形态(替代上述 type,不共存):type: dnstap, target: unix:/var/run/dnstap.sock 或 tcp://127.0.0.1:6000

statistics:
  enable: true              # 内存统计(24h 窗口),提供 /api/stats 与 blocky stats 命令

实测(默认控制台查询日志,info 级别逐行输出):

[2026-10-20 17:19:06]  INFO queryLog: query resolved answer=CNAME (ins-r23tsuuf.ias.tencent-cloud.net.), CNAME (ins-ysshqadg.ias.tencent-cloud.net.), A (153.3.148.154), A (122.96.96.146) client_ip=127.0.0.1 client_names=127.0.0.1 instance=ops question_name=www.qq.com. question_type=A response_code=NOERROR response_reason=RESOLVED (tcp+udp:223.5.5.5) response_type=RESOLVED
[2026-10-20 17:19:06]  INFO queryLog: query resolved answer=A (0.0.0.0) client_ip=127.0.0.1 client_names=127.0.0.1 instance=ops question_name=ads.example.com. question_type=A response_code=NOERROR response_reason=BLOCKED (ads: ads.example.com) response_type=BLOCKED

实测(statistics.enable: true 后 blocky stats --apiHost 127.0.0.11 --apiPort 8130,节选):

Summary
┌────────────────┬───────────┐
│ METRIC         │ VALUE     │
├────────────────┼───────────┤
│ Queries        │         3 │
│ Cached         │  0 (0.0%) │
│ Forwarded      │         2 │
│ Blocked        │ 1 (33.3%) │
│ Avg response   │     14 ms │
└────────────────┴───────────┘

未开启 statistics 时 stats 命令报错(实测):Error: statistics are disabled (enable 'statistics.enable' in config)。

5.9 prometheus:指标端点

prometheus:
  enable: true              # 开启 /metrics
  path: /metrics            # 路径可自定义,默认 /metrics

实测(curl 抓取指标,节选):

blocky_blocking_enabled 1
blocky_build_info{build_time="20260630-080230",version="v0.33.0"} 1
blocky_cache_entries 1
blocky_cache_hits_total 0
blocky_cache_misses_total 4
blocky_denylist_cache_entries{group="ads"} 2
blocky_query_total{client="127.0.0.1",type="A"} 6

5.10 log:日志行为

log:
  level: info               # trace | debug | info | warn | error
  format: text              # text | json
  timestamp: true           # 时间戳开关
  privacy: false            # true 时把日志中域名等敏感串脱敏为 *

实测(info/text)日志行形态见 5.8 节;privacy: true 适合日志外发场景。

5.11 入口安全四件套:filtering / rebindingProtection / rateLimit / fqdnOnly

filtering:
  queryTypes:
    - AAAA                  # 丢弃 AAAA 查询(强制 IPv4-only 网络)

rebindingProtection:
  enable: true              # 丢弃通用上游应答中的私网/回环/链路本地地址(防 DNS rebinding)
  allowedDomains:           # split-horizon 域名豁免(内网域名本就该解析私网地址)
    - intranet.example.com

rateLimit:                  # 每客户端令牌桶限速(v0.33 新增),默认关闭
  enable: false
  rate: 50                  # 持续允许的每秒查询数(桶速率)
  burst: 100                # 桶容量(突发额度),缺省为 rate×2
  ipv4Prefix: 32            # IPv4 聚合前缀(32=按单 IP,24=按 /24 共桶)
  ipv6Prefix: 64            # IPv6 聚合前缀(默认 /64)
  allowlist:                # 完全绕过限速的网段/地址
    - 10.0.0.0/8
    - 127.0.0.1

fqdnOnly:
  enable: false             # true 时非 FQDN 查询(如 workstation 裸主机名)直接 NXDOMAIN

实测(filtering AAAA 过滤生效,dig AAAA www.qq.com 返回 0 条 ANSWER):

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 27488
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;www.qq.com.                    IN      AAAA

💡 说明:官方注释特别提醒 filtering.queryTypes 含 AAAA 时不要开启 DNS64(AAAA 在进入 DNS64 前已被丢弃,合成失效)。

5.12 DNSSEC 与 DNS64

dnssec:
  validate: true            # DNSSEC 验证总开关(v0.31+),默认 false
  maxChainDepth: 10         # 信任链最大域深(防深嵌套 DoS)
  cacheExpirationHours: 1   # 验证结果缓存时长(小时)
  maxUpstreamQueries: 30    # 单次验证允许的上游查询预算
  maxNSEC3Iterations: 150   # NSEC3 最大哈希迭代(RFC 5155 §10.3)
  clockSkewToleranceSec: 3600   # 签名时间戳时钟偏移容忍(默认 1 小时)
  trustAnchors: []          # 自定义信任锚(默认用内置 IANA 根锚 KSK-2017/KSK-2024)

dns64:
  enable: false             # DNS64 合成(RFC 6147),默认 false
  prefixes:
    - 64:ff9b::/96          # 合成前缀,默认 RFC 6052 知名前缀
  # exclusionSet: [...]     # 自定义排除集(默认含 IPv4 映射段/回环/链路本地/自身前缀)

⚠️ 安全提示:v0.31.0 的 DNSSEC 实现存在安全通告 GO-2026-5745(验证绕过与验证缓存作用域污染,pkg.go.dev 版本页标注),启用 dnssec.validate 前确认版本 ≥v0.33.0(本文实测版本即 v0.33.0)。

5.13 bootstrapDns:引导解析

bootstrapDns:
  - tcp+udp:1.1.1.1                 # 引导上游(解析 DoH/DoT 域名与名单 URL 域名用)
  - https://1.1.1.1/dns-query
  - upstream: https://dns.digitale-gesellschaft.ch/dns-query
    ips:                            # 直接钉住 IP,跳过引导解析
      - 185.95.218.42
  # - resolvFile: /tmp/resolv.conf.auto   # 从 resolv.conf 文件读引导上游

未配置时实测启动日志提示:bootstrap: bootstrapDns is not configured, will use system resolver。内网无系统解析器或想加密引导查询时必须配置,否则 DoH/DoT 上游域名与名单 URL 无法解析。

5.14 clientLookup:客户端名识别

clientLookup:
  upstream: 192.168.178.1   # 反向解析用的上游(通常为路由器)
  singleNameOrder:          # 路由器返回多名字时取第几个(按序回退)
    - 2
    - 1
  clients:                  # 静态映射客户端名 → IP(反查失效时的兜底)
    laptop:
      - 192.168.178.29

识别出的客户端名会出现在查询日志 client_names= 字段,并可作为 clientGroupsBlock 分组键使用。

5.15 redis:多实例协同

redis:
  address: redismaster      # 地址:端口 或 unix socket 路径;sentinel 场景填 master 名
  username: usrname         # 可选
  password: passwd          # 支持 file:/run/secrets/xxx 从文件读
  database: 2               # 默认 0
  required: false           # true 时 Redis 连不上则拒绝启动
  connectionAttempts: 3     # 连接重试次数
  connectionCooldown: 3s    # 重试间隔
  sentinelUsername: / sentinelPassword: / sentinelAddresses:   # 哨兵模式(配置任一哨兵地址即启用)

多实例部署时通过 Redis 同步缓存与屏蔽状态,配合外部负载均衡可实现 Blocky 水平扩展。

5.16 TLS 服务端与 HTTP/3

minTlsServeVersion: 1.3    # DoT/DoH 服务端最低 TLS 版本,默认 1.3
certFile: server.crt       # 证书路径;不配置则自动生成自签证书
keyFile: server.key
http3:
  enable: false             # DoH over HTTP/3(RFC 9114)

ports.https > 0 时 DoH 服务端生效;自签证书便于内网快速启用,公网场景建议配置正式证书。

六、生产配置模板

以下模板面向 8GB 内存、SSD、50–200 客户端的办公网出口(家庭网络可删减注释项直接用;资源敏感场景把 statistics/prometheus 二选一):

upstreams:
  init:
    strategy: blocking        # 启动时等名单与上游就绪,避免「半就绪」服务窗口
  groups:
    default:
      - 223.5.5.5
      - 119.29.29.29
      - tcp-tls:1.12.12.12:853          # 混入 DoT 上游加密出站
  strategy: parallel_best
  timeout: 2s

blocking:
  denylists:
    ads:
      - https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
      - https://s3.amazonaws.com/lists.disconnect.me/simple_tracking.txt
      - /etc/blocky/denylist-custom.txt # 自定义补充名单(内网业务域名屏蔽等)
  allowlists:
    ads:
      - /etc/blocky/allowlist.txt       # 误杀放行通道
  clientGroupsBlock:
    default: [ads]
  blockType: nxDomain                   # 语义化拦截,客户端日志更干净
  blockTTL: 1m                          # 拦截记录短 TTL,放行名单变更后收敛快
  loading:
    refreshPeriod: 24h                  # 大名单每日刷一次足够
    downloads:
      timeout: 60s
      attempts: 5
    maxErrorsPerSource: 5

caching:
  minTime: 5m                           # 短 TTL 记录兜底下限,降低出站查询
  maxTime: 30m                          # 上限防「过期太久」的解析结果
  prefetching: true                     # 高频域名预取,办公网体感明显
  cacheTimeNegative: 5m

conditional:
  mapping:
    corp.local: 192.168.1.1             # 内网域转发给 AD/内网 DNS

customDNS:
  customTTL: 1h
  mapping:
    nas.corp.local: 192.168.1.10

hostsFile:
  sources:
    - /etc/hosts
  hostsTTL: 30m

queryLog:
  type: csv                             # 中小规模 CSV 最省依赖;要 SQL 分析选 sqlite/mysql
  target: /var/lib/blocky/querylog
  logRetentionDays: 14
  flushInterval: 60s

prometheus:
  enable: true

statistics:
  enable: true

rebindingProtection:
  enable: true
  allowedDomains:
    - corp.local

specialUseDomains:
  enable: true
  rfc6762-appendixG: true

ports:
  dns:
    - 53                                # 生产:绑全部地址,或写内网网卡 IP 限定范围
  http:
    - 127.0.0.1:4000                    # API 只绑本机,经反向代理或 SSH 隧道访问

log:
  level: info
  format: text

模板要点复盘:上游混排明文+加密、名单双源+自定义补充+放行通道、拦截方式 nxDomain 短 TTL、缓存上下界+预取、API 仅绑本机、查询日志 CSV 带保留期。目录准备:sudo mkdir -p /var/lib/blocky/querylog && sudo chown blocky:blocky /var/lib/blocky/querylog。

七、常见问题(FAQ)

Q1:blocky validate 通过但启动失败? validate 只做结构校验;语义缺失(如缺 upstreams.groups)要到启动才报(实测:删 upstreams 后 validate 为 valid,serve 启动报 no external DNS resolvers configured as default upstream resolvers. Please configure at least one under 'default' configuration name)。改配置后务必真实 restart 一次。

Q2:多文件配置(--config ./config/)合并失败? 官方文档明确:多文件是简单拼接,同一选项(如 upstreams)出现在多个文件会启动失败。拆分时按「一节一文件」原则,不要两处都写同一个顶级键。

Q3:外网名单拉不下来导致启动慢或失败? blocking.loading.strategy: blocking(默认)会等名单就绪才监听。慢网/名单源不稳时:调大 downloads.timeout/attempts,配置 downloads.cachePath 启用磁盘缓存(断网时可用旧名单),或改 strategy: fast 先起服务后台加载。

Q4:改了 ports.http 后 CLI 全挂? CLI 默认连 localhost:4000。对齐写法:blocky stats --apiHost 127.0.0.11 --apiPort 8130(实测通过);或保持 4000 不动。

Q5:blocked 域名有时解析成功了? 排查顺序:该客户端是否命中了其他 clientGroupsBlock 分组(分组键优先级:具体 IP/CIDR > 主机名通配 > default);是否命中了 allowlist(白名单优先);屏蔽状态是否被 blocky blocking disable 临时关闭(blocking status 可查,实测回显 blocking enabled / blocking disabled for groups: 'ads; default', for 299 seconds)。

Q6:如何确认名单真实加载了多少条? 启动日志 denylist cache entries: ads: N entries / TOTAL: N entries(实测形态见 5.3 节);运行期用 blocky stats 的 Lists 表(实测:GROUP ads DENYLIST 2 ALLOWLIST 0)或 /api/stats 的 lists 字段核对。

八、参考链接