因为国内的 DNS 都开始限速,频繁出现 DNS 等待数分钟甚至无响应的情况,国外的 DNS 响应又比较慢,非常影响使用;刚好阿里云的服务器内网 DNS 不限速,并且网络延迟只有10ms,可以将其作为 DoH 服务器,用于提供 DNS 查询
在服务器部署 Caddy 对外提供 DoH 接口,然后将请求转发到 Blocky 服务,Blocky 服务再将 DNS 请求转发给阿里云的服务器的 DNS,间接实现 DoH 服务;经过测试,平均响应延迟在 16ms 左右,比直接使用阿里云的公网 DNS 更快更稳定

可选择的 DoH 服务有 AdGuard、Blocky、Kind、CordDNS 等,因为需要过滤广告,支持 HTTP 查询,并且需要可观测,所以选择 Blocky 作为 DoH 服务;整体的请求链路是:
客户端 -(https)-> Caddy -(http)-> Blocky -(udp)-> 阿里云内网 DNS
关于 Caddy 的使用可以参考 使用 Caddy 作为 HomeLab 内网服务的代理,HTTPS 证书使用 ZeroSSL 提供的 IP 证书,可以参考 阿里云服务器使用 Caddy 和 ZeroSSL 提供的 IP 证书为服务开启 HTTPS
部署 Blocky
- 查找服务器使用的 DNS
resolvectl status
使用 resolvectl 查看系统的 DNS 信息,100.100.2.136 和 100.100.2.138 就是默认的 DNS 服务器地址,这个地址需要作为 blocky 的上游
Global
Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub
Link 2 (eth0)
Current Scopes: DNS
Protocols: +DefaultRoute -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 100.100.2.136
DNS Servers: 100.100.2.136 100.100.2.138
- 配置 blocky
配置 blocky 的配置文件 config.yml,具体可以参考 Configuration
upstreams:
groups:
default:
- 100.100.2.138
- 100.100.2.136
timeout: 1s
# 配置广告过滤
blocking:
denylists:
ads:
- https://proxy.hellowood.dev/https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
clientGroupsBlock:
default:
- ads
# 监听端口
ports:
dns: 153 # 不使用UDP,改为其他端口
http: 4000 #用于提供 DoH/Prometheus 等
# 指标
prometheus:
enable: true
path: /metrics
# 用于解析 DoH 域名
bootstrapDns:
- upstream: tcp+udp:1.1.1.1
- upstream: tcp+udp:8.8.8.8
# 记录请求日志
queryLog:
type: csv
target: /logs
logRetentionDays: 7
fields:
- clientIP
- question
- duration
- responseAnswer
- responseReason
flushInterval: 30s
- docker-compose.yml
使用 docker compose 部署,将 4000 端口映射到宿主机,同时将配置文件和访问日志目录挂载到容器
services:
blocky:
image: ghcr.io/0xerr0r/blocky:latest
container_name: blocky
ports:
- "4000:4000"
volumes:
- ./config.yml:/app/config.yml
- ./log:/logs
restart: unless-stopped
- 访问验证
使用 DoH 访问 http://localhost:4000,查询 example.com 验证 DNS 是否生效
curl -H 'accept: application/dns-message' 'http://localhost:4000/dns-query?dns=q80BAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB' | hexdump
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 143 100 143 0 0 44409 0 --:--:-- --:--:-- --:--:-- 47666
0000000 cdab 8081 0100 0400 0000 0000 7703 7777
0000010 6507 6178 706d 656c 6303 6d6f 0000 0001
0000020 c001 000c 0005 0001 0000 000a 0322 7777
0000030 0777 7865 6d61 6c70 0665 6f63 2d6d 3476
0000040 6509 6764 7365 6975 6574 6e03 7465 c000
0000050 002d 0005 0001 0000 000a 0514 3161 3234
0000060 0432 7364 7263 6106 616b 616d c069 c04a
0000070 005b 0001 0001 0000 000a 1704 46dc c029
0000080 005b 0001 0001 0000 000a 1704 46dc 002e
000008f
配置 Caddy 代理
DoH 需要使用 HTTPS 访问,需要 Caddy 配置 HTTPS 证书,参考 阿里云服务器使用 Caddy 和 ZeroSSL 提供的 IP 证书为服务开启 HTTPS
- docker-compose.yml
services:
caddy:
image: caddy
container_name: caddy
ports:
- "10443:10443" # https
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- ./static:/var/www/html/.well-known/pki-validation # 认证文件
- ./certs:/certs # TLS 证书
extra_hosts:
- "host.docker.internal:host-gateway" # 用于容器内访问宿主机
restart: unless-stopped
- Caddyfile
{
debug
log {
output stdout
format console
}
default_sni 100.0.0.2
}
# 监听 10443 端口
https://100.0.0.2:10443 {
tls /certs/fullchain.crt /certs/private.key
# 将 dns-query 路径转发给 blocky 服务
route /dns-query* {
reverse_proxy http://host.docker.internal:4000
}
}
配置完成后启动 blocky 和 caddy 服务
查询验证
curl -H 'accept: application/dns-message' 'https://100.0.0.2:10443/dns-query?dns=q80BAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB' | hexdump
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 143 100 143 0 0 2353 0 --:--:-- --:--:-- --:--:-- 2383
0000000 cdab 8081 0100 0400 0000 0000 7703 7777
0000010 6507 6178 706d 656c 6303 6d6f 0000 0001
0000020 c001 000c 0005 0001 0000 000a 0322 7777
0000030 0777 7865 6d61 6c70 0665 6f63 2d6d 3476
0000040 6509 6764 7365 6975 6574 6e03 7465 c000
0000050 002d 0005 0001 0000 000a 0514 3161 3234
0000060 0432 7364 7263 6106 616b 616d c069 c04a
0000070 005b 0001 0001 0000 000a 1704 0530 c011
0000080 005b 0001 0001 0000 000a 1704 0530 0004
000008f
这样就可以将 https://100.0.0.2:10443/dns-query 作为 AdGuard、Clash、Dae 等工具的 DNS 服务器了:
