CoreDNS 黑白名单插件hostlist
hostlist
概述
hostlist 是一个 CoreDNS 插件,使用 AdGuard HostlistsRegistry 格式的规则进行 DNS 域名过滤。支持黑名单/白名单两种模式,远程规则自动同步,本地缓存。
插件在 tsig 之后执行,优先级高于测速、缓存等插件。
特性
- 支持 AdGuard 全部 DNS 过滤规则格式
- 支持 Surge 规则格式(
.domain.com) - 支持 Clash 规则格式(
payload:块中的'+.domain.com') - 黑名单模式(封锁匹配域名)和白名单模式(仅放行匹配域名)
- 远程 URL 和本地文件两种规则来源
- 定时自动同步远程规则,支持本地缓存
- 反向标签 trie 数据结构,50 万+ 域名毫秒级匹配
- 用户自定义黑白名单,不受远程更新影响
- 客户端 IP 白名单,指定 IP 绕过家长控制和安全搜索
Corefile 语法
1 | hostlist { |
示例配置
基础配置
1 | . { |
支持 Surge 和 Clash 规则源
1 | . { |
完整配置
1 | . { |
白名单模式
1 | . { |
白名单模式下,仅放行规则列表中的域名,其他全部拦截。
家长控制 + 安全搜索 + IP 白名单
1 | . { |
bypass_ip 指定的客户端 IP 不受家长控制拦截和安全搜索重写限制,其他客户端正常过滤。
规则格式
封锁规则
| 格式 | 示例 | 说明 |
|---|---|---|
||domain^ |
||ads.example.com^ |
封锁域名及所有子域名 |
127.0.0.1 domain |
127.0.0.1 analytics.163.com |
仅封锁精确域名,不含子域名 |
/REGEX/ |
/^ads\d*\./ |
正则匹配封锁 |
||*wild*domain^ |
||*serror*.wo.com.cn^ |
通配符,自动转正则 |
.domain^ |
.bbelements.com^ |
封锁域名及子域名 |
domain |
wykop.pl |
封锁域名 |
.domain.com |
.cntv.lat |
Surge 格式,封锁域名及所有子域名(等同于 ||cntv.lat^) |
payload: 块 |
- '+.0.avmarket.rs' |
Clash 格式,+.domain 封锁域名及所有子域名(等同于 ||0.avmarket.rs^) |
白名单规则
| 格式 | 示例 | 说明 |
|---|---|---|
@@||domain^ |
@@||youtube.com^ |
放行域名及所有子域名 |
@@|domain^ |
@@|affiliate.notion.so^ |
放行(单锚点) |
@@||domain^| |
@@||sedge.nfl.com^| |
放行(末尾多余 |) |
@@/REGEX/ |
@@/^safe\./ |
正则匹配放行 |
修饰符
| 修饰符 | 行为 |
|---|---|
$important |
正常处理(剥离修饰符) |
$badfilter |
跳过(禁用其他规则,不适用) |
$dnsrewrite |
跳过(DNS 重写,不适用) |
注释
1 | ! 这是注释 |
行为说明
黑名单模式(默认)
- 匹配
url/file中的封锁规则 → 拦截 - 匹配
@@/whitelist_url/whitelist_file中的白名单规则 → 放行 - 匹配
allowlist中的用户白名单 → 放行 - 匹配
blocklist中的用户黑名单 → 拦截 - 白名单优先级最高,即使域名在黑名单中,只要匹配白名单就放行
- 其他域名 → 放行
白名单模式
- 匹配
url/file中的规则 → 放行 - 匹配
allowlist中的用户白名单 → 放行 - 其他域名 → 拦截
规则格式兼容性
插件自动识别并处理多种规则格式:
| 来源 | 格式示例 | 处理方式 |
|---|---|---|
| AdGuard | ||example.com^ | 封锁 example.com 及所有子域名 |
| Surge | .example.com | 等同于 ||example.com^ |
| Clash | - ‘+.example.com’ | 等同于 ||example.com^ |
| Hosts | 127.0.0.1 example.com | 仅封锁精确域名 example.com |
模式与规则源
mode 参数决定规则的生效方式:
- blacklist 模式:规则列表中的域名被视为黑名单,匹配则拦截
- whitelist 模式:规则列表中的域名被视为白名单,仅放行匹配的域名
此设置适用于所有规则源(AdGuard、Surge、Clash 格式)。
拦截响应
block_type 0.0.0.0(默认):返回 NOERROR + A 记录0.0.0.0block_type nxdomain:返回 NXDOMAIN + SOAblock_type empty:返回 NOERROR,无应答记录
域名匹配
||domain^格式:祖先匹配,封锁domain及所有子域名- hosts 格式(
127.0.0.1 domain):精确匹配,仅封锁domain本身 - 白名单
@@||domain^:祖先匹配,放行domain及所有子域名
远程同步
- 启动时立即加载所有规则
- 按
refresh间隔定时重新下载远程规则 - 下载失败时使用本地缓存文件
- 所有错误(网络超时、文件不存在等)均跳过,不影响进程
安全搜索
safesearch on 强制搜索引擎使用安全模式,将查询重写到安全搜索域名。
1 | . { |
支持的搜索引擎:
| 引擎 | 重写目标 |
|---|---|
| Google(190+ 国家域名) | forcesafesearch.google.com |
| Bing | strict.bing.com |
| YouTube | restrict.youtube.com |
| DuckDuckGo | safe.duckduckgo.com |
| Brave | safesearch.brave.com |
| Ecosia | strict-safe-search.ecosia.org |
| Yandex | 213.180.193.56 |
| Pixabay | safesearch.pixabay.com |
| Qwant | safeapi.qwant.com |
查询 www.google.com 时返回 CNAME forcesafesearch.google.com,客户端会自动解析到 Google 安全搜索。
家长控制
parental on 自动加载赌博和恶意软件过滤列表。
1 | . { |
启用后自动加载:
- 赌博网站
- 恶意软件
- NSFW网站
客户端 IP 白名单
bypass_ip 指定客户端 IP 或 CIDR 网段,这些客户端发起的 DNS 查询将绕过家长控制拦截和安全搜索重写,直接放行。
1 | . { |
适用场景:
- 家庭网络中,家长设备不受限制,孩子设备受家长控制和安全搜索保护
- 企业内部,管理设备绕过过滤,员工设备正常过滤
- 支持 IPv4 和 IPv6 地址,支持 CIDR 网段格式
缓存目录
远程下载的规则会保存到 cache_dir 目录(默认 ./hostlist/),文件名为 URL 的 SHA256 哈希。重启时优先读取本地缓存,后台再同步远程更新。
Prometheus 指标
| 指标 | 类型 | 说明 |
|---|---|---|
coredns_hostlist_blocked_requests_total |
Counter | 被拦截的请求数(标签:server, zone) |
coredns_hostlist_domains_loaded |
Gauge | 当前加载的封锁域名数 |
编译
1. 克隆 CoreDNS 源码
1 | git clone https://github.com/coredns/coredns.git coredns |
2. 添加 hostlist 插件
1 | git clone https://github.com/qist/hostlist.git plugin/hostlist |
3. 注册插件
1 | grep -q '^hostlist:hostlist' plugin.cfg || sed -i '/^tsig:tsig$/a hostlist:hostlist' plugin.cfg |
这会在 tsig:tsig 之后插入 hostlist:hostlist,如果已存在则跳过。
4. 生成代码并编译
1 | go generate |
5. 验证
1 | ./coredns -version |
使用 Go module 方式添加
如果需要以 module 方式引入(适用于 CoreDNS 自定义构建):
1 | # 在 CoreDNS 项目根目录 |
然后在 plugin.cfg 中使用完整包路径:
1 | hostlist:github.com/qist/hostlist |
常见问题
Q: 规则加载失败怎么办?
A: 插件会使用本地缓存,不会中断 DNS 服务。
Q: 如何验证规则是否生效?
A: 使用 dig @127.0.0.1 example.com 测试,查看日志输出。
Q: 内存占用过高?
A: 插件使用 CompactTrie 数据结构存储 50 万+ 域名规则,内存占用约 300-500MB。可以通过设置 GOGC 环境变量来优化内存占用。
GOGC 是什么?
Go 语言的垃圾回收机制默认在堆内存达到上次回收后的 2 倍时触发(GOGC=100)。降低这个值会让垃圾回收更频繁,但能保持更低的内存占用。
推荐设置:
| GOGC 值 | 内存占用 | CPU 使用 | 适用场景 |
|---|---|---|---|
100(默认) |
最高 | 最低 | 开发测试 |
30 |
中等 | 中等 | 生产环境推荐 |
25 |
较低 | 较高 | 内存紧张环境 |
20 |
最低 | 最高 | 极低内存环境 |
设置方法:
1 | # 启动时设置 |
实际效果:
- 规则数量 50 万+ 时
GOGC=100:内存约 500-600MBGOGC=30:内存约 300-400MBGOGC=25:内存约 250-350MB
注意: GOGC 值越低,垃圾回收越频繁,CPU 开销略高。建议在内存充足时使用 GOGC=30,在内存紧张时使用 GOGC=25。一般不推荐低于 20。