# 自建 DoT/DoH 服务器

通过 AdGuard Home 实现 DoH 以及 DoT,配合 CoreDNS 解决 DNS 污染

项目地址:https://github.com/AdguardTeam/AdGuardHome (opens new window)

其实有很多的工具可以实现 DoT/DoH,但是 adgh 更方便;它可以同时实现这两种功能

Last updated on 2020-10-21



# 准备(前言)

想要彻底解决 DNS 是必然要付出一些成本的

目前 1.1.1.1 在部分地区无法访问,即使 tls://8.8.8.8 也是时不时返回污染结果

所以解决 DNS 污染必须有一台海外的云服务器;若你需要在公网上提供 DNS 服务则需要两台服务器:国内、海外各一台,不然仅需海外的服务器即可

在云服务器上搭建传统 UDP DNS 而非 TLS/HTTPS 的 DNS 没有意义

开始之前需要域名以及域名的 TLS 证书,没有证书可以通过 Let's Encrypt 获取免费证书; 国内主机商提供的免费一年证书也可以

假设国内服务器域名为 example.com,海外服务器所用域名为 core.example.com

# 安装 CoreDNS

在海外的服务器使用 CoreDNS 配置 DoT 服务

# 安装 ADGH

使用官方一键安装脚本

curl -sSL https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh

# 手动安装

国内服务器安装 ADGH

发布页面 (opens new window)下载最新已发布版本

tar -xzvf AdGuardHome_linux_amd64.tar.gz
mv AdGuardHome /usr/loca/share/
cd /usr/loca/share/AdGuardHome
./AdGuardHome

程序默认监听所有网卡的 3000 端口,可在运行时添加 -p 指定新的端口

在浏览器内输入服务器 IP 和端口号即可开始安装

# 配置

点击设置 - 加密设置 - 勾选启用加密

注意

无需勾选 HTTPS 自动重定向,HTTPS 端口设置为空,稍后使用 Nginx 反向代理

填写:

  • 服务器名称 (example.com)
  • HTTPS 端口 (设置为空)
  • DNS-over-TLS 端口 (默认853即可)
  • 证书/私钥 (example.com 的证书)

点击保存配置即可

# 允许 h2c

编辑 AdGuardHome.yaml 更改 allow_unencrypted_dohtrue

# 创建守护进程

提示

使用脚本安装时此步骤跳过

新建配置文件

vi /etc/systemd/system/AdGuardHome.service

填写以下配置

[Unit]
Description=AdGuard Home: Network-level blocker
ConditionFileIsExecutable=/usr/local/share/AdGuardHome/AdGuardHome
After=syslog.target network-online.target

[Service]
StartLimitInterval=5
StartLimitBurst=10
ExecStart=/usr/local/share/AdGuardHome/AdGuardHome -c /usr/local/share/AdGuardHome/AdGuardHome.yaml -w /usr/local/share/AdGuardHome
StandardOutput=file:/var/log/AdGuardHome.out
StandardError=file:/var/log/AdGuardHome.err
Restart=always
RestartSec=10
EnvironmentFile=-/etc/sysconfig/AdGuardHome

[Install]
WantedBy=multi-user.target

完毕之后启动 AdGuardHome

# Nginx 配置

新建配置文件

vi /etc/nginx/conf.d/dns.conf 

填充以下内容

{
   listen 443 ssl http2;
   server_name example.com;

   add_header X-Frame-Options DENY;
   add_header X-Content-Type-Options nosniff;
   add_header X-XSS-Protection "1; mode=block";
   add_header Strict-Transport-Security "max-age=63072000";

   ssl_protocols TLSv1.2 TLSv1.3;
   ssl_prefer_server_ciphers on;
   ssl_ciphers EECDH+AESGCM:EDH+AESGCM;
   ssl_ecdh_curve secp384r1;
   ssl_session_timeout 10m;
   ssl_session_tickets on;
   ssl_session_cache shared:SSL:10m;
   ssl_stapling on;
   ssl_stapling_verify on;
   ssl_early_data on;
   ssl_certificate example.com.crt;
   ssl_certificate_key example.com.key;

   # 反向代理 Web 界面
   location /admin/ {
       proxy_pass http://127.0.0.1:3000/;
       proxy_redirect / /admin/;
   }

   # DoH
   # 注意: 此处端口为 web 界面的端口
   location / {
       proxy_pass http://127.0.0.1:3000/dns-query;
       proxy_http_version 1.1;
       proxy_redirect off;
       proxy_buffering off;
       proxy_set_header Host $host;
       proxy_set_header X-Real-IP $remote_addr; 
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

重启 Nginx

systemctl restart nginx

# 域名分流

使用这个工具 (opens new window)chian-domain-list (opens new window) 中的域名指定上游后并输出文件

./domain-parse -p "[/;/]tls://dns.pub;[/;/]tls://dns.pub"

编辑输出的文件将 core.example.com 添加并保存

提示

当客户端需要解析的域名配置文件不存在时使用 core.example.com 解析

为了方便更新可以使用以下脚本

#!/bin/bash
cd /usr/local/AdGuardHome
export http_proxy="http://127.0.0.1:1080"
export https_proxy=$http_proxy
./domain-parse -p "[/;/]tls://dns.pub;[/;/]tls://dns.pub"
sed -i '1 i\tls://core.example.com' domain
time=$(date "+%Y%m%d-%H%M%S")
sed -i '1 i\'#$time'' domain
systemctl restart AdGuardHome

添加到定时任务,每天凌晨3点更新一次

crontab -e

0 3 * * * /usr/local/AdGuardHome/update.sh > /dev/null

# 测试

清除浏览器缓存并输入 https://example.com/admin 跳转到 AdGuard Home Web 界面且正常登录即为正常

验证 DoT 以及 DoH 需要用到这个工具 (opens new window)

DNS-over-TLS:

./dnslookup www.google.com tls://example.com

dnslookup v1.2.0
dnslookup result:
;; opcode: QUERY, status: NOERROR, id: 36146
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;www.google.com.        IN       A

;; ANSWER SECTION:
www.google.com. 60      IN      A       199.59.148.140

DNS-over-HTTPS:

./dnslookup www.baidu.com https://example.com/dns-query

dnslookup v1.2.0
dnslookup result:
;; opcode: QUERY, status: NOERROR, id: 20965
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;www.baidu.com. IN       A

;; ANSWER SECTION:
www.baidu.com.  47      IN      CNAME   www.a.shifen.com.
www.a.shifen.com.       33      IN      A       220.181.38.149
www.a.shifen.com.       33      IN      A       220.181.38.150