hostlist
概述
hostlist 是一个 CoreDNS 插件,使用 AdGuard HostlistsRegistry 格式的规则进行 DNS 域名过滤。支持黑名单/白名单两种模式,远程规则自动同步,本地缓存。
插件在 tsig 之后执行,优先级高于测速、缓存等插件。
特性
- 支持 AdGuard 全部 DNS 过滤规则格式
- 支持 Surge 规则格式(
.domain.com)
- 支持 Clash 规则格式(
payload: 块中的 '+.domain.com')
- 黑名单模式(封锁匹配域名)和白名单模式(仅放行匹配域名)
- 远程 URL 和本地文件两种规则来源
- 定时自动同步远程规则,支持本地缓存
- 反向标签 trie 数据结构,50 万+ 域名毫秒级匹配
- 用户自定义黑白名单,不受远程更新影响
- 客户端 IP 白名单,指定 IP 绕过家长控制和安全搜索
Corefile 语法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| hostlist { url <remote-url> # 远程规则 URL(可重复) file <local-path> # 本地规则文件(可重复) whitelist_url <remote-url> # 远程白名单 URL(可重复) whitelist_file <local-path> # 本地白名单文件(可重复) allowlist <rule> # 用户白名单规则(可重复) blocklist <rule> # 用户黑名单规则(可重复) mode blacklist|whitelist # 模式,默认 blacklist block_type 0.0.0.0|nxdomain|empty # 拦截响应类型,默认 0.0.0.0 safesearch on|off # 安全搜索,默认 off parental on|off # 家长控制,默认 off bypass_ip <ip/cidr> # 客户端 IP 白名单,绕过家长控制和安全搜索(可重复) refresh <duration> # 远程同步间隔,默认 4d cache_dir <path> # 缓存目录,默认 ./hostlist/ }
|
示例配置
基础配置
1 2 3 4 5 6 7 8 9
| . { hostlist { url https://adguardteam.github.io/HostlistsRegistry/assets/filter_1.txt url https://adguardteam.github.io/HostlistsRegistry/assets/filter_21.txt file /etc/coredns/custom_blocklist.txt refresh 12h } forward . 8.8.8.8:53 }
|
支持 Surge 和 Clash 规则源
1 2 3 4 5 6 7 8 9 10 11
| . { hostlist { # Surge 格式规则源 url https://raw.githubusercontent.com/Loyalsoldier/surge-rules/release/reject.txt # Clash 格式规则源 url https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/reject.txt mode blacklist refresh 4d } forward . 8.8.8.8:53 }
|
完整配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| . { hostlist { # 黑名单来源 url https://adguardteam.github.io/HostlistsRegistry/assets/filter_1.txt url https://adguardteam.github.io/HostlistsRegistry/assets/filter_29.txt file /etc/coredns/custom_blocklist.txt
# 白名单来源(整份文件所有规则作为白名单) whitelist_url https://example.com/my_allowlist.txt whitelist_file /etc/coredns/allowlist.txt
# 用户自定义规则(不受远程更新影响) allowlist @@||www.youtube.com^ allowlist @@||m.youtube.com^ blocklist ||ads.example.com^ blocklist ||tracker.myapp.com^
# 设置 mode blacklist block_type nxdomain parental off safesearch off bypass_ip 192.168.1.100 bypass_ip 10.0.0.0/24 bypass_ip 172.16.0.0/16 refresh 12h cache_dir /var/lib/coredns/hostlist } forward . 8.8.8.8:53 log }
|
白名单模式
1 2 3 4 5 6 7
| . { hostlist { url https://adguardteam.github.io/HostlistsRegistry/assets/filter_1.txt mode whitelist } forward . 8.8.8.8:53 }
|
白名单模式下,仅放行规则列表中的域名,其他全部拦截。
家长控制 + 安全搜索 + IP 白名单
1 2 3 4 5 6 7 8 9 10
| . { hostlist { parental on safesearch on bypass_ip 192.168.1.100 bypass_ip 10.0.0.0/24 bypass_ip 172.16.0.0/16 } forward . 8.8.8.8:53 }
|
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 重写,不适用) |
注释
行为说明
黑名单模式(默认)
- 匹配
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.0
block_type nxdomain:返回 NXDOMAIN + SOA
block_type empty:返回 NOERROR,无应答记录
域名匹配
||domain^ 格式:祖先匹配,封锁 domain 及所有子域名
- hosts 格式(
127.0.0.1 domain):精确匹配,仅封锁 domain 本身
- 白名单
@@||domain^:祖先匹配,放行 domain 及所有子域名
远程同步
- 启动时立即加载所有规则
- 按
refresh 间隔定时重新下载远程规则
- 下载失败时使用本地缓存文件
- 所有错误(网络超时、文件不存在等)均跳过,不影响进程
安全搜索
safesearch on 强制搜索引擎使用安全模式,将查询重写到安全搜索域名。
1 2 3 4 5 6
| . { hostlist { safesearch on } forward . 8.8.8.8:53 }
|
支持的搜索引擎:
| 引擎 |
重写目标 |
| 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 2 3 4 5 6
| . { hostlist { parental on } forward . 8.8.8.8:53 }
|
启用后自动加载:
客户端 IP 白名单
bypass_ip 指定客户端 IP 或 CIDR 网段,这些客户端发起的 DNS 查询将绕过家长控制拦截和安全搜索重写,直接放行。
1 2 3 4 5 6 7 8 9 10
| . { hostlist { parental on safesearch on bypass_ip 192.168.1.100 # 单个 IP bypass_ip 10.0.0.0/24 # CIDR 网段 bypass_ip 2001:db8::/32 # IPv6 网段 } forward . 8.8.8.8:53 }
|
适用场景:
- 家庭网络中,家长设备不受限制,孩子设备受家长控制和安全搜索保护
- 企业内部,管理设备绕过过滤,员工设备正常过滤
- 支持 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 2
| git clone https://github.com/coredns/coredns.git coredns cd 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 2
| go generate go build -o coredns .
|
5. 验证
1 2
| ./coredns -version ./coredns -plugins | grep hostlist
|
使用 Go module 方式添加
如果需要以 module 方式引入(适用于 CoreDNS 自定义构建):
1 2 3 4
| go mod edit -require github.com/qist/hostlist@latest go mod edit -replace github.com/qist/hostlist=./plugin/hostlist go mod tidy
|
然后在 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 2 3 4 5 6 7 8 9
| GOGC=30 ./coredns -conf Corefile
export GOGC=30 ./coredns -conf Corefile
Environment=GOGC=30
|
实际效果:
- 规则数量 50 万+ 时
GOGC=100:内存约 500-600MB
GOGC=30:内存约 300-400MB
GOGC=25:内存约 250-350MB
注意: GOGC 值越低,垃圾回收越频繁,CPU 开销略高。建议在内存充足时使用 GOGC=30,在内存紧张时使用 GOGC=25。一般不推荐低于 20。