背景

传统 DNS 查询以明文传输,容易被 ISP 或中间人劫持。DoH (DNS over HTTPS) 将 DNS 查询封装在 HTTPS 协议中,提供更好的隐私保护。

环境说明

本文提供两种系统的安装方法:

系统 服务管理 包管理器
Debian / Ubuntu systemd / supervisor apt
Alpine Linux OpenRC apk

安装 CoreDNS

CoreDNS 是一个灵活的 DNS 服务器,支持插件扩展。

方法一:Debian / Ubuntu

bash
# 安装必要工具
sudo apt install wget jq tar -y

# 下载最新版本
COREDNS_VERSION=$(wget -qO- -t1 -T2 "https://api.github.com/repos/coredns/coredns/releases/latest" | jq -r '.tag_name')
COREDNS_N_VERSION=${COREDNS_VERSION:1}

wget https://github.com/coredns/coredns/releases/download/${COREDNS_VERSION}/coredns_${COREDNS_N_VERSION}_linux_amd64.tgz

# 解压安装
tar zxf coredns_${COREDNS_N_VERSION}_linux_amd64.tgz
sudo mv coredns /usr/local/bin/
sudo chmod +x /usr/local/bin/coredns

方法二:Alpine Linux

bash
# 安装必要工具
apk add wget jq tar

# 下载并安装(同上)
COREDNS_VERSION=$(wget -qO- -t1 -T2 "https://api.github.com/repos/coredns/coredns/releases/latest" | jq -r '.tag_name')
COREDNS_N_VERSION=${COREDNS_VERSION:1}

wget https://github.com/coredns/coredns/releases/download/${COREDNS_VERSION}/coredns_${COREDNS_N_VERSION}_linux_amd64.tgz
tar zxf coredns_${COREDNS_N_VERSION}_linux_amd64.tgz
mv coredns /usr/local/bin/
chmod +x /usr/local/bin/coredns

配置 CoreDNS

创建配置文件目录和 Corefile:

bash
sudo mkdir -p /etc/CoreDNS
sudo mkdir -p /var/log/coredns

创建 /etc/CoreDNS/Corefile

corefile
sudo mkdir -p /etc/CoreDNS && cat << 'EOF' | sudo tee /etc/CoreDNS/Corefile > /dev/null
# 標準 DNS 服務(端口 53)
.:53 {
  bind 0.0.0.0
  forward . 1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4
  log
  errors
  cache
}

# DoH 服務(端口 8053)
https://.:8053 {
  bind 0.0.0.0
  forward . 1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4
  log
  errors
  cache
}
EOF

配置说明:

  • bind 0.0.0.0 - 监听所有网卡(容器环境需要让宿主机访问)
  • forward - 上游 DNS 服务器(Cloudflare + Google)
  • cache - 启用 DNS 缓存,减少上游查询
  • log / errors - 记录查询日志和错误

设置开机启动

Debian / Ubuntu(使用 Supervisor)

bash
# 安装 Supervisor
sudo apt install supervisor -y

# 创建服务配置
sudo tee /etc/supervisor/conf.d/coredns.conf << 'EOF'
[program:coredns]
command=/usr/local/bin/coredns -conf /etc/CoreDNS/Corefile
autostart=true
autorestart=true
startretries=3
redirect_stderr=true
stdout_logfile=/var/log/coredns/stdout.log
EOF

# 启动服务
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl status coredns

Alpine Linux(使用 OpenRC)

Alpine 默认使用 OpenRC,比 Supervisor 更轻量:

bash
# 创建 init 脚本
sudo tee /etc/init.d/coredns << 'EOF'
#!/sbin/openrc-run

name="coredns"
description="CoreDNS DNS Server"
command="/usr/local/bin/coredns"
command_args="-conf /etc/CoreDNS/Corefile"
command_background="yes"
pidfile="/run/coredns.pid"
output_log="/var/log/coredns/stdout.log"
error_log="/var/log/coredns/stderr.log"

depend() {
    need net
}
EOF

sudo chmod +x /etc/init.d/coredns

# 注册并启动服务
sudo rc-update add coredns default
sudo rc-service coredns start

# 检查状态
sudo rc-service coredns status

验证服务

测试 DNS 查询

bash
# 安装 dig 工具(如需要)
# Debian/Ubuntu: sudo apt install dnsutils
# Alpine: apk add bind-tools

dig @127.0.0.1 google.com +short
# 预期输出:IP 地址,如 142.250.71.174

检查端口监听

bash
# Alpine
netstat -tlnp | grep -E '53|8053'

# Debian/Ubuntu
ss -tlnp | grep -E '53|8053'

预期输出:

tcp  0  0  :::53     :::*  LISTEN  <pid>/coredns
tcp  0  0  :::8053   :::*  LISTEN  <pid>/coredns

Nginx 反向代理配置

在宿主机上配置 Nginx,将 DoH 流量代理到 CoreDNS 容器:

nginx
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name dns.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/dns.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/dns.yourdomain.com/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers on;

    # DoH 端点
    location /dns-query {
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # 替换为你的 CoreDNS 容器 IP
        proxy_pass http://10.10.1.106:8053;
    }
}

重载 Nginx:

bash
sudo nginx -t
sudo nginx -s reload

客户端测试

使用 dig 测试 DoH

bash
dig @dns.yourdomain.com +https google.com

浏览器配置

在支持 DoH 的浏览器中添加自定义 DNS:

  • Chrome: 设置 → 安全 → 使用安全 DNS → 自定义 → https://dns.yourdomain.com/dns-query
  • Firefox: 设置 → 常规 → 网络设置 → 启用基于 HTTPS 的 DNS → 自定义 → https://dns.yourdomain.com/dns-query

常见问题

1. 容器内服务无法从宿主机访问

确保 CoreDNS 绑定的是 0.0.0.0 而非 127.0.0.1

2. Alpine 上找不到 supervisorctl

Alpine 推荐使用 OpenRC,但也可以安装 supervisor:

bash
apk add supervisor

不过 OpenRC 更轻量且与 Alpine 集成更好。

3. DNS 查询超时

检查防火墙是否放行 53/UDP 和 8053/TCP 端口。

总结

对比项 Debian/Ubuntu Alpine Linux
服务管理 Supervisor OpenRC
内存占用 较高 极低
启动速度 较慢
配置复杂度 中等 简单

Alpine Linux 配合 OpenRC 是容器环境的理想选择,资源占用更低。


参考资料: