最后更新于:2026年07月

自建 DoH 服务
自建 DNS over HTTPS 公共解析服务

当你使用公共 DNS(如 8.8.8.8 或 1.1.1.1)时,你的每一次域名查询都可能被记录和分析。自建 DNS over HTTPS(DoH)服务不仅能保护你的 DNS 查询隐私,还能实现自定义的域名过滤、智能分流和访问控制。

本文将带你从零搭建一个生产级的 DoH 公共解析服务,包括 doh-server 部署、AdGuard Home 集成、访问控制、证书管理以及完整的隐私审计方案。


🧭 DoH 是什么?为什么需要自建?

DNS over HTTPS 原理

传统 DNS 查询使用明文 UDP/TCP 传输,容易被窃听和篡改:

PLAINTEXT
┌──────────────────────────────────────────────────────────┐
│                    传统 DNS 查询                         │
│                                                          │
│  客户端 ──明文──► 本地 DNS ──明文──► 根服务器            │
│      │                                      │            │
│      │  ISP 可见所有查询                     │            │
│      │  可能被篡改返回结果                   │            │
│      └──────────────────────────────────────┘            │
└──────────────────────────────────────────────────────────┘

DoH 通过 HTTPS 加密传输 DNS 查询:

PLAINTEXT
┌──────────────────────────────────────────────────────────┐
│                   DNS over HTTPS 查询                    │
│                                                          │
│  客户端 ──HTTPS加密──► DoH 服务器 ──DNS──► 根服务器     │
│      │                                      │            │
│      │  ISP 只看到加密流量                   │            │
│      │  查询内容不可见                       │            │
│      │  响应完整性受 TLS 保护                │            │
│      └──────────────────────────────────────┘            │
└──────────────────────────────────────────────────────────┘

自建 DoH 的优势

对比项公共 DoH(1.1.1.1/8.8.8.8)自建 DoH
隐私保护服务商可见所有查询完全自主控制
自定义规则无法自定义可配置任意过滤规则
分流解析固定解析策略可实现国内/国外智能分流
访问控制无限制可限制访问来源
日志保留可能保留日志可配置不保留或定期清理
可用性依赖服务商完全自主可控

📦 方案选择:doh-server vs AdGuard Home

方案对比

方案功能性能部署复杂度推荐场景
doh-server纯 DoH 服务⭐⭐⭐⭐⭐⭐⭐需要高性能纯 DoH 服务
AdGuard HomeDoH + 广告过滤 + 管理界面⭐⭐⭐⭐⭐⭐⭐需要完整 DNS 管理功能
CoreDNS + DoH 插件高度可定制⭐⭐⭐⭐⭐⭐⭐⭐⭐复杂场景需要自定义插件

推荐组合

PLAINTEXT
生产环境推荐架构:

┌──────────────────────────────────────────────────────────┐
│              客户端 ──► DoH 入口 ──► AdGuard Home        │
│                          │                  │            │
│                          │                  ├── 广告过滤 │
│                          │                  ├── 自定义规则│
│                          │                  └── 智能分流 │
│                          │                             │
│                          ▼                             ▼
│                     doh-server                 上游 DNS │
│                   (高性能入口)              (国内/国外)   │
└──────────────────────────────────────────────────────────┘

🚀 实战一:doh-server 部署

环境准备

BASH
# 系统要求:Linux(推荐 Debian 12 或 Ubuntu 22.04)
# 需要域名(如 doh.example.com)
# 需要 SSL 证书(Let's Encrypt)

# 更新系统
apt update && apt upgrade -y

安装 doh-server

BASH
# 使用 go 安装
go install github.com/m13253/dns-over-https/doh-server@latest

# 或下载预编译二进制
VERSION=$(curl -s https://api.github.com/repos/m13253/dns-over-https/releases/latest | grep tag_name | cut -d '"' -f 4)
wget https://github.com/m13253/dns-over-https/releases/download/$VERSION/doh-server_${VERSION}_linux_amd64.tar.gz
tar -xzvf doh-server_${VERSION}_linux_amd64.tar.gz
cp doh-server /usr/local/bin/

# 验证安装
doh-server --help

创建配置文件

BASH
# 创建配置目录
mkdir -p /etc/doh-server
mkdir -p /var/log/doh-server

创建 /etc/doh-server/doh-server.conf

JSON
{
  "listen_address": ":443",
  "listen_address_tls": ":443",
  "upstream": [
    "119.29.29.29:53",
    "223.5.5.5:53"
  ],
  "upstream_timeout": 5,
  "tls_cert": "/etc/letsencrypt/live/doh.example.com/fullchain.pem",
  "tls_key": "/etc/letsencrypt/live/doh.example.com/privkey.pem",
  "http3": true,
  "logfile": "/var/log/doh-server/doh-server.log",
  "loglevel": "info",
  "cors": true,
  "metrics": ":9153",
  "health": ":9154"
}

配置说明

JSON
{
  "listen_address": ":443",
  // DoH HTTP 监听地址,用于反向代理或测试

  "listen_address_tls": ":443",
  // DoH HTTPS 监听地址

  "upstream": [
    "119.29.29.29:53",
    "223.5.5.5:53"
  ],
  // 上游 DNS 服务器,可以配置多个实现负载均衡

  "upstream_timeout": 5,
  // 上游查询超时时间(秒)

  "tls_cert": "/etc/letsencrypt/live/doh.example.com/fullchain.pem",
  "tls_key": "/etc/letsencrypt/live/doh.example.com/privkey.pem",
  // TLS 证书和私钥

  "http3": true,
  // 是否启用 HTTP/3(QUIC)支持

  "logfile": "/var/log/doh-server/doh-server.log",
  "loglevel": "info",
  // 日志配置

  "cors": true,
  // 是否允许跨域请求(浏览器 DoH 需要)

  "metrics": ":9153",
  // Prometheus 指标监听地址

  "health": ":9154"
  // 健康检查接口
}

获取 SSL 证书

BASH
# 安装 Certbot
apt install -y certbot python3-certbot-nginx

# 获取证书
certbot certonly --nginx -d doh.example.com

# 或使用 DNS 验证(推荐,支持泛域名)
certbot certonly --dns-cloudflare -d doh.example.com

# 验证证书
openssl x509 -in /etc/letsencrypt/live/doh.example.com/fullchain.pem -text -noout

创建 systemd 服务

BASH
cat > /etc/systemd/system/doh-server.service << 'EOF'
[Unit]
Description=DNS over HTTPS Server
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/doh-server --conf /etc/doh-server/doh-server.conf
Restart=on-failure
RestartSec=10
User=doh-server
Group=doh-server

[Install]
WantedBy=multi-user.target
EOF

# 创建专用用户
useradd -r -s /usr/sbin/nologin doh-server

# 设置文件权限
chown -R doh-server:doh-server /etc/doh-server
chown -R doh-server:doh-server /var/log/doh-server

# 启动服务
systemctl daemon-reload
systemctl enable --now doh-server
systemctl status doh-server

测试 DoH 服务

BASH
# 使用 curl 测试
curl -H "Accept: application/dns-json" \
  "https://doh.example.com/dns-query?name=google.com&type=A"

# 预期输出(JSON 格式):
{
  "Status": 0,
  "TC": false,
  "RD": true,
  "RA": true,
  "AD": false,
  "CD": false,
  "Question": [{
    "name": "google.com.",
    "type": 1
  }],
  "Answer": [{
    "name": "google.com.",
    "type": 1,
    "TTL": 300,
    "data": "142.250.185.14"
  }]
}

# 使用 dig 测试(需要安装 dnsutils)
dig @127.0.0.1 -p 443 +https google.com

🛡️ 实战二:AdGuard Home 集成

安装 AdGuard Home

BASH
# 官方脚本安装
curl -s -S -L https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh

# 或使用 Docker(推荐)
docker run -d \
  --name adguardhome \
  --restart unless-stopped \
  -v /opt/adguardhome/work:/opt/adguardhome/work \
  -v /opt/adguardhome/conf:/opt/adguardhome/conf \
  -p 53:53/tcp \
  -p 53:53/udp \
  -p 80:80/tcp \
  -p 3000:3000/tcp \
  -p 853:853/tcp \
  adguard/adguardhome:latest

配置 AdGuard Home

1. 初始化设置

访问 http://your-server-ip:3000,按照向导完成初始化:

PLAINTEXT
设置步骤:
1. 设置用户名和密码
2. 配置 DNS 监听端口(默认 53)
3. 配置上游 DNS 服务器
4. 启用加密 DNS(DoH/DoT/DoQ)

2. 配置上游 DNS

PLAINTEXT
AdGuard Home → 设置 → DNS 设置 → 上游 DNS 服务器

添加上游服务器:
- 国内:223.5.5.5、119.29.29.29、101.226.4.6
- 国外:8.8.8.8、1.1.1.1、9.9.9.9

配置自定义规则:
- 国内域名走国内 DNS
- 国外域名走国外 DNS

3. 启用加密 DNS

PLAINTEXT
设置 → DNS 设置 → 加密 DNS

启用 DoH:
- 启用 DoH 服务器
- 端口:853(标准 DoH 端口)或 443
- TLS 证书:使用 Let's Encrypt

启用 DoT:
- 启用 DoT 服务器
- 端口:853

启用 DoQ(可选):
- 启用 DoQ 服务器
- 端口:8853

4. 配置自定义过滤规则

PLAINTEXT
过滤器 → 添加过滤规则列表

常用规则列表:
- https://adguardteam.github.io/AdGuardSDNSFilter/Filters/filter.txt
- https://v.firebog.net/hosts/AdguardDNS.txt
- https://v.firebog.net/hosts/Easylist.txt
- https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts

自定义规则:
||example.com^       # 阻止 example.com
@@||example.com^     # 允许 example.com

5. 配置访问控制

PLAINTEXT
设置 → 访问控制

允许列表模式:
- 只允许指定 IP 访问
- 其他 IP 被拒绝

拒绝列表模式:
- 拒绝指定 IP 访问
- 其他 IP 允许

推荐:允许列表模式,只允许自己的网络访问

🔗 实战三:doh-server + AdGuard Home 组合

架构设计

PLAINTEXT
┌──────────────────────────────────────────────────────────┐
│                    组合架构                              │
│                                                          │
│  客户端 ──HTTPS──► doh-server(443端口)                │
│                          │                              │
│                          ▼                              │
│                    AdGuard Home(53端口)               │
│                          │                              │
│              ┌───────────┴───────────┐                  │
│              ▼                       ▼                  │
│         国内 DNS                  国外 DNS               │
│       223.5.5.5                 8.8.8.8                │
│       119.29.29.29              1.1.1.1                │
└──────────────────────────────────────────────────────────┘

配置 doh-server 转发到 AdGuard Home

修改 /etc/doh-server/doh-server.conf

JSON
{
  "listen_address": ":443",
  "listen_address_tls": ":443",
  "upstream": [
    "127.0.0.1:53"
  ],
  "upstream_timeout": 10,
  "tls_cert": "/etc/letsencrypt/live/doh.example.com/fullchain.pem",
  "tls_key": "/etc/letsencrypt/live/doh.example.com/privkey.pem",
  "http3": true,
  "logfile": "/var/log/doh-server/doh-server.log",
  "loglevel": "info",
  "cors": true,
  "metrics": ":9153",
  "health": ":9154"
}

配置 AdGuard Home 智能分流

在 AdGuard Home 的"自定义过滤规则"中添加:

PLAINTEXT
# 国内域名走国内 DNS
@@||cn^$dnsrewrite=NOERROR;A;223.5.5.5
@@||china^$dnsrewrite=NOERROR;A;119.29.29.29

# 使用上游服务器组
# 在 AdGuard Home 中配置上游服务器组

📊 监控与日志

Prometheus 监控

doh-server 内置了 Prometheus 指标:

BASH
# 查看指标
curl http://localhost:9153/metrics

# Prometheus 配置
# /etc/prometheus/prometheus.yml
scrape_configs:
  - job_name: 'doh-server'
    static_configs:
      - targets: ['localhost:9153']

  - job_name: 'adguardhome'
    static_configs:
      - targets: ['localhost:3000']

日志管理

BASH
# doh-server 日志
tail -f /var/log/doh-server/doh-server.log

# AdGuard Home 日志
tail -f /opt/adguardhome/work/logs/AdGuardHome.log

# 日志轮换配置
# /etc/logrotate.d/doh-server
/var/log/doh-server/doh-server.log {
    daily
    rotate 7
    compress
    delaycompress
    missingok
    notifempty
    create 640 doh-server doh-server
}

# 应用日志轮换
logrotate -f /etc/logrotate.d/doh-server

🔒 安全加固

1. 限制访问来源

BASH
# 使用 iptables 限制只允许特定 IP 访问 DoH 服务
iptables -A INPUT -p tcp --dport 443 -s 192.168.0.0/16 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j DROP

# 或使用 UFW
ufw allow from 192.168.0.0/16 to any port 443
ufw deny 443

2. 禁用日志保留

JSON
// doh-server 配置
{
  "logfile": "",
  "loglevel": "warn"
}

// AdGuard Home 配置
// 设置 → DNS 设置 → 日志设置
// 日志级别:警告或关闭
// 日志保留时间:不保留

3. 定期更新

BASH
# 更新 doh-server
VERSION=$(curl -s https://api.github.com/repos/m13253/dns-over-https/releases/latest | grep tag_name | cut -d '"' -f 4)
wget https://github.com/m13253/dns-over-https/releases/download/$VERSION/doh-server_${VERSION}_linux_amd64.tar.gz
tar -xzvf doh-server_${VERSION}_linux_amd64.tar.gz
cp doh-server /usr/local/bin/
systemctl restart doh-server

# 更新 AdGuard Home(Docker)
docker pull adguard/adguardhome:latest
docker stop adguardhome
docker rm adguardhome
docker run -d --name adguardhome ... adguard/adguardhome:latest

4. 使用 HTTP/3

JSON
// doh-server 配置
{
  "http3": true
}

// 客户端配置(支持 HTTP/3 的浏览器)
// Chrome: 访问 chrome://flags 启用 HTTP/3
// Firefox: about:config  network.http.http3.enabled = true

📱 客户端配置

浏览器配置

Chrome / Edge:

PLAINTEXT
设置 → 隐私和安全性 → 安全 → 高级 → 使用安全 DNS

选择:自定义
输入:https://doh.example.com/dns-query

或在 chrome://flags 中:
- Secure DNS lookups: Enabled
- DNS over HTTPS: Enabled

Firefox:

PLAINTEXT
设置 → 常规 → 网络设置 → 设置 → DNS over HTTPS

选择:自定义
输入:https://doh.example.com/dns-query

系统级配置

Windows 11:

PLAINTEXT
设置 → 网络和 Internet → Wi-Fi / 以太网 → 编辑 → IPv4 DNS

选择:手动
输入首选 DNS:1.1.1.1(或你的服务器 IP)

然后启用:使用 DNS over HTTPS

macOS:

PLAINTEXT
系统设置 → 网络 → Wi-Fi / 以太网 → 详细信息 → DNS

点击 + 添加你的服务器 IP
点击 DNS over HTTPS 下拉菜单,选择:加密

Linux(systemd-resolved):

BASH
# 编辑配置文件
cat > /etc/systemd/resolved.conf << 'EOF'
[Resolve]
DNS=127.0.0.1
DNSOverHTTPS=yes
DNSOverHTTPSFallback=no
EOF

# 重启服务
systemctl restart systemd-resolved

代理客户端配置

Clash Meta:

YAML
dns:
  enable: true
  enhanced-mode: fake-ip
  nameserver:
    - https://doh.example.com/dns-query
  fallback:
    - https://doh.example.com/dns-query
  fallback-filter:
    geoip: cn
    ipcidr:
      - 240.0.0.0/4

sing-box:

JSON
{
  "dns": {
    "servers": [
      {
        "tag": "doh",
        "type": "https",
        "server": "doh.example.com",
        "server_port": 443,
        "path": "/dns-query"
      }
    ],
    "rules": [
      {
        "outbound": "any",
        "server": "doh"
      }
    ]
  }
}

🔍 故障排查

问题 1:DoH 服务无法访问

BASH
# 检查服务状态
systemctl status doh-server

# 检查端口监听
ss -tlnp | grep 443

# 检查防火墙
ufw status
iptables -L -n | grep 443

# 测试本地访问
curl -v https://localhost/dns-query?name=google.com

# 测试远程访问
curl -v https://doh.example.com/dns-query?name=google.com

# 常见原因:
# 1. 防火墙未开放 443 端口
# 2. SSL 证书过期或配置错误
# 3. 域名解析错误
# 4. doh-server 配置错误

问题 2:DNS 查询返回错误

BASH
# 检查上游 DNS 是否可用
dig @119.29.29.29 google.com

# 检查 AdGuard Home 状态
curl http://localhost:3000/control/status

# 检查日志
tail -f /var/log/doh-server/doh-server.log

# 常见原因:
# 1. 上游 DNS 不可用
# 2. 查询超时
# 3. 域名被过滤

问题 3:浏览器无法使用 DoH

BASH
# 测试浏览器是否支持
curl -H "Accept: application/dns-json" \
  "https://doh.example.com/dns-query?name=google.com&type=A"

# 检查 CORS 设置
curl -v -H "Origin: https://example.com" \
  "https://doh.example.com/dns-query?name=google.com"

# 检查 SSL 证书
openssl s_client -connect doh.example.com:443

# 常见原因:
# 1. SSL 证书不被浏览器信任
# 2. CORS 未配置
# 3. 浏览器版本不支持 DoH

问题 4:性能问题

BASH
# 测试 DNS 查询延迟
dig @doh.example.com google.com +stats

# 检查服务器资源
top
free -h

# 检查连接数
ss -tlnp | grep 443 | wc -l

# 优化建议:
# 1. 增加上游 DNS 数量
# 2. 启用 HTTP/3
# 3. 使用 CDN 加速
# 4. 增加服务器资源

📊 性能优化

1. 启用 HTTP/3

JSON
{
  "http3": true
}

HTTP/3 使用 QUIC 协议,减少握手延迟,提高连接稳定性。

2. 配置多个上游服务器

JSON
{
  "upstream": [
    "119.29.29.29:53",
    "223.5.5.5:53",
    "101.226.4.6:53",
    "101.226.4.6:53"
  ]
}

多个上游服务器实现负载均衡和故障转移。

3. 启用缓存

在 AdGuard Home 中配置缓存:

PLAINTEXT
设置 → DNS 设置 → 缓存设置

缓存大小:10000 条
缓存时间:默认(根据 TTL)

4. 使用 CDN

将 DoH 服务部署在 Cloudflare CDN 后面:

PLAINTEXT
Cloudflare → 添加域名 → 配置 SSL/TLS → 启用 HTTPS
Cloudflare → 网络 → HTTP/3:启用
Cloudflare → 缓存 → 配置:优化 DNS 查询

📋 完整部署检查清单

PLAINTEXT
部署前准备:
□ 注册域名(如 doh.example.com)
□ 服务器配置(至少 1 核 512MB)
□ SSL 证书(Let's Encrypt)

部署步骤:
□ 安装 doh-server
□ 配置 doh-server.conf
□ 获取 SSL 证书
□ 创建 systemd 服务
□ 安装 AdGuard Home(可选)
□ 配置上游 DNS
□ 配置过滤规则
□ 配置访问控制

安全配置:
□ 限制访问来源(防火墙)
□ 禁用日志保留
□ 定期更新
□ 启用 HTTP/3

客户端配置:
□ 浏览器 DoH 配置
□ 系统级 DoH 配置
□ 代理客户端 DNS 配置

测试验证:
□ DoH 服务访问测试
□ DNS 查询测试
□ 过滤规则测试
□ 加密验证测试
□ 性能测试

结语

自建 DNS over HTTPS 服务不仅能保护你的 DNS 查询隐私,还能实现高度自定义的域名过滤和智能分流。通过 doh-server + AdGuard Home 的组合,你可以构建一个功能完整、性能卓越的私有 DNS 服务。

总结要点:

推荐架构:

PLAINTEXT
生产环境:
  doh-server(443端口)→ AdGuard Home(53端口)→ 上游 DNS

家庭使用:
  AdGuard Home(53端口 + 853端口)→ 直接供家庭设备使用

高性能需求:
  doh-server(HTTP/3)→ 多个上游 DNS → 负载均衡

记住:DNS 是互联网的入口,保护 DNS 隐私是保护网络隐私的第一步。 掌握了自建 DoH 服务,你就拥有了对网络入口的完全控制权。

愿你的 DNS 查询永远安全、快速、私密!🔒

版权声明

作者: 易邦

链接: https://blog.e8k.net/posts/doh-public-service/

许可证: 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。