本文最后更新于 45 天前,其中的信息可能已经有所发展或是发生改变。
1. 安装 Unbound 递归DNS服务
关闭系统自带的systemd‑resolved避免占用53端口:
apt update
apt install -y unbound
systemctl stop systemd-resolved
systemctl disable systemd-resolved
编写unbound配置文件 /etc/unbound/unbound.conf.d/local-recursor.conf
server:
# 仅本地回环给doh‑proxy调用,不对外暴露53端口
interface: 127.0.0.1
interface: ::1
access-control: 127.0.0.0/8 allow
access-control: ::1 allow
access-control: 0.0.0.0/0 refuse
# DNSSEC 验证开启
auto-trust-anchor-file: "/var/lib/unbound/root.key"
val-log-level: 1
hide-identity: yes
hide-version: yes
# 缓存调优
msg-cache-size: 16m
rrset-cache-size: 32m
cache-max-ttl: 86400
cache-min-ttl: 60
edns-buffer-size: 1232
prefetch: yes
prefetch-key: yes
生成DNSSEC根信任锚文件:
unbound-anchor -a /var/lib/unbound/root.key
chown unbound:unbound /var/lib/unbound/root.key
校验配置语法,启动unbound:
unbound-checkconf
systemctl enable --now unbound
systemctl status unbound
测试unbound本地解析是否正常:
dig @127.0.0.1 example.com A
正常返回A记录代表递归解析工作正常。
2. 安装 doh‑proxy deb包
下载官方发布deb包并安装:
wget https://github.com/DNSCrypt/doh-server/releases/download/0.9.16/doh-proxy_0.9.16-1_amd64.deb
apt install ./doh-proxy_0.9.16-1_amd64.deb
确认版本:
doh-proxy --version
# 输出 doh-proxy 0.9.16
3. 编写 doh‑proxy TOML配置
配置文件路径固定:/etc/doh-proxy/doh-proxy.toml
# doh-proxy.toml
listen_address = "127.0.0.1:3000"
server_address = "udp:127.0.0.1:53"
max_clients = 1024
min_ttl = 10
max_ttl = 86400
err_ttl = 5
disable_keepalive = false
allow_odoh_post = true
log_level = "info"
参数说明
listen_address = "127.0.0.1:3000":仅本机回环监听,由反向代理转发请求;多机部署场景改为0.0.0.0:3000,并配置trusted_proxies信任前端代理IP。server_address = "udp:127.0.0.1:53":上游指向本机unbound,必须带udp:前缀,缺少会启动崩溃。allow_odoh_post = true:开启ODoH支持。
4. 创建 systemd 服务单元
创建文件 /etc/systemd/system/doh-proxy.service
[Unit]
Description=DoH‑Proxy 0.9.16 (DNSCrypt doh‑server)
After=network.target unbound.service
Requires=unbound.service
[Service]
Type=simple
User=nobody
Group=nogroup
ExecStart=/usr/bin/doh-proxy
Restart=on-failure
RestartSec=3
PrivateTmp=true
NoNewPrivileges=true
[Install]
WantedBy=multi-user.target
重载systemd,设置开机自启并启动服务:
systemctl daemon-reload
systemctl enable --now doh-proxy
systemctl status doh-proxy
本地裸HTTP测试doh‑proxy
curl -H "Accept: application/dns-json" 'http://127.0.0.1:3000/dns-query?name=example.com&type=A'
正常返回JSON格式DNS应答,代表 doh‑proxy ↔ unbound 链路工作正常。
5. 配置HTTPS反向代理(二选一)
doh‑proxy本身不处理TLS,必须依靠Nginx/Caddy完成443端口SSL终止。DoH访问端点:
https://你的域名/dns-query
方案A:Caddy(推荐,自动申请Let’s Encrypt证书)
Caddyfile示例
doh.example.com {
reverse_proxy 127.0.0.1:3000
}
重启caddy:
systemctl restart caddy
方案B:Nginx + Let’s Encrypt证书
server {
listen 443 ssl http2;
server_name doh.example.com;
ssl_certificate /etc/letsencrypt/live/doh.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/doh.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X‑Real‑IP $remote_addr;
proxy_set_header X‑Forwarded‑For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_read_timeout 15s;
proxy_connect_timeout 10s;
}
}
校验并重载nginx:
nginx -t
systemctl reload nginx
6. 公网完整功能测试
curl -H "Accept: application/dns-json" 'https://doh.example.com/dns-query?name=example.com&type=A'
常用排错命令
# 查看doh‑proxy运行状态
systemctl status doh-proxy
# 实时日志
journalctl -u doh-proxy -f
# 查看端口监听
ss -tulpn | grep 3000
# 前台直接运行doh‑proxy看配置解析报错
doh-proxy
# unbound日志
journalctl -u unbound -f

