使用Nginx+AdGuard家庭搭建的DOH服务

作者: maofun 分类: 代码 发布时间: 2025-03-07 09:22

分享一下自己在使用AdGuardHome 搭建的DOH 服务

今天看到大量的人讨论dns污染,以及海外一些doh服务被阻塞的帖子,故而分享一下我在使用AdGuardHome搭建的DOH服务的配置。

下面分享使用nginx和AdGuardHome搭建的DOH服务。
实现的效果:多个服务共享443端口,不必担心端口占用。提供doh服务进行dns解析,同时可以提供dot、doq服务进行dns解析,以及AdGuardHome的广告过滤功能。

个人用了两个月,很稳定。

图像

一些个人观点

DOH,DOT,DOQ均属于加密dns,可以在一定的编程中防止
基于HTTPS的DNS和基于TLS的DNS | 安全域名系统

个人推荐使用DOH

理由:DOT、DOQ默认使用853端口,具备一定的特征,如果使用其他端口则需要客户端支持指定端口。DOH默认使用443端口,和普通的https流量混在一起,比较难识别。

以上为个人观点,如有不同观点,欢迎各位大佬在评论区进行讨论

nginx、AdGuardHome安装和卸载(基于命令行debian12,其他系统参考官方文档)

1.nginx安装

#安装相关依赖工具
apt install -y curl gnupg2 ca-certificates lsb-release
#添加 Nginx 官方签名密钥
curl -fsSL https://nginx.org/keys/nginx_signing.key | gpg --dearmor -o /usr/share/keyrings/nginx-archive-keyring.gpg
#设置官方仓库源(后续可以使用apt命令升级nginx)
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] http://nginx.org/packages/debian $(lsb_release -cs) nginx" |  tee /etc/apt/sources.list.d/nginx.list
#更新依赖并安装nginx
apt update
apt install -y nginx 

2.nginx卸载

apt remove -y nginx
apt purge -y nginx
apt autoremove -y

#删除相关文件(如果需要)
rm -rf /etc/nginx
rm -rf /var/log/nginx
...

3.AdGuardHome安装

AdGuardHome官方开源代码仓库

#1.使用官方安装脚本(安装目录在/opt/AdGuardHome)
curl -s -S -L https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh -s -- -v

#2.手动安装(以在/{自定义目录}/AdGuardHome为安装目录为例)
cd /{自定义目录}
#到官方仓库选择自己喜欢的版本
wget https://github.com/AdguardTeam/AdGuardHome/releases/download/v0.107.57/AdGuardHome_linux_amd64.tar.gz
#解压压缩包
tar xvf AdGuardHome_linux_amd64.tar.gz
cd /{自定义目录}/AdGuardHome
./AdGuardHome -s install

4.AdGuardHome卸载

 手动安装
./{自定义目录}/AdGuardHome/AdGuardHome -s uninstall
#删除相关文件(如果需要)
rm -rf /{自定义目录}/AdGuardHome

nginx、AdGuardHome 欠缺使用 systemctl 管理服务的启动、停止、重启等操作,基础不够,自行GG

nginx配置

1.nginx Stream模块的sni分流配置文件路径:/etc/nginx/modules-enabled/stream.conf

请确保/etc/nginx/nginx.conf中的配置引用了/etc/nginx/modules-enabled/目录下的配置,

include /etc/nginx/modules-enabled/*.conf;

确认安装的nginx加载了steam模块,默认Debian仓库的nginx不包含steam模块,建议使用教程中的安装方法安装模块较为完整的nginx。

nginx -V

在输出的信息中,表示找到–with-stream参数。如果存在该参数,则启用了stream模块。

流模块的sni分流是通过证书的域名进行分流,所以需要提前准备好证书,如果开启http2多路复用则不建议使用泛域名证书!!!

stream {
    map $ssl_preread_server_name $sni_backend {
        {域名}       doh;
        www.tesla.com           proxy_reality2direct;
        apps.apple.com          proxy_reality2route;
        default web;
    }

    upstream web {
        server unix:/dev/shm/web.sock;
    }
	
    upstream doh {
        server unix:/dev/shm/doh.sock;
    }


    upstream proxy_reality2direct {
        server unix:/dev/shm/proxy_reality2direct.sock;
    }

    upstream reality2direct {
        server 127.0.0.1:3729;
    }

    upstream proxy_reality2route {
        server unix:/dev/shm/proxy_reality2route.sock;
    }

    upstream reality2route {
        server 127.0.0.1:3726;
    }

    server {
        listen 443 reuseport;
        listen [::]:443 reuseport;
        proxy_pass  $sni_backend;
		# 启用代理协议
        proxy_protocol on;
		# 启用 SSL 预读模块
        ssl_preread on;
        #  拒绝不匹配的 SNI
        # ssl_reject_handshake on;
        tcp_nodelay on;
    }
    server {
        listen unix:/dev/shm/proxy_reality2direct.sock proxy_protocol;
                
        set_real_ip_from unix:;
        # 代理到 Reality 后端
        proxy_pass reality2direct;
    }

    server {
        listen unix:/dev/shm/proxy_reality2route.sock proxy_protocol;
                
        set_real_ip_from unix:;
        # 代理到 Reality 后端
        proxy_pass reality2route;
    }

}


2.doh反代配置文件路径:/etc/nginx/sites-enabled/ad_guard_home.conf

server {
    listen unix:/dev/shm/doh.sock ssl proxy_protocol;
    http2 on;
    
    server_name {域名};

    # 如果需要启用 SSL 证书,可以启用以下配置
    ssl_certificate /etc/nginx/ssl/域名证书.cer;
    ssl_certificate_key /etc/nginx/ssl/证书密钥.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    # 静态文件目录,伪装成一个普通的网站
    root /usr/share/nginx/html;
    set_real_ip_from unix:;
    real_ip_header proxy_protocol;
    charset 'utf-8';

    location /dashboard {
        # AdGuardHome 的配置页面
        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_set_header X-Forwarded-Proto $scheme;

        # 修正 AdGuardHome 的重定向路径
        proxy_redirect / /dashboard/;

        # 避免 AdGuardHome 的重复路径前缀
        rewrite ^/dashboard(/.*)?$ $1 break;
    }

    location {path}/{自定义path} {
        proxy_buffering off;
        proxy_redirect 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;
        proxy_set_header X-Forwarded-Proto $scheme;
        # 端口
        # 这里的 Path 必须为 dns-query
        proxy_pass https://127.0.0.1:1787/dns-query; 
    }

    location {path}/common {
        proxy_buffering off;
        proxy_redirect 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;
        proxy_set_header X-Forwarded-Proto $scheme;
        # 端口
        # 这里的 Path 必须为 dns-query
        proxy_pass https://127.0.0.1:1787/dns-query; 
    } 

    location / {
        index  index.html;
    }

    location ~ /\.ht {
        deny  all;
    }
}
#测试配置是否正常
nginx -t
#重新加载nginx配置
nginx -s reload

AdGuardHome配置加密DNS的端口

图像

通过 ip:3000 或者 https://{域名}/dashboard 访问AdGuardHome后台界面。
如果访问 https://{域名} ,将会出现伪装的静态网站,默认为/usr/share/nginx/html目录,可以修改nginx配置文件,将root路径修改为自己的静态页面目录,更多玩法自行研究。

另外,通过指定路径路径进行反代,增加了隐秘性,降低被爆发的可能。添加UUID作为客户端id,并通过配置仅允许客户端访问,可以降低被扫描的可能,同时可以区分客户端访问的网站有哪些,涉及隐私。

UUID生成:

#debian系统直接执行命令
cat /proc/sys/kernel/random/uuid
#Windows系统执行打开PowerShell执行命令
New-Guid

图像

如何使用?

在chrome浏览器中,设置->隐私与安全->安全->使用安全DNS,配置https://{域名}/{path}/{自定义路径}/UUID

其他上网客户端支持自定义DOH服务器的话,可以根据自己的客户端配置格式进行修改,参考各上网工具客户端官方文档

这里我使用的是sing-box,所以贴出一个singbox的配置参考

 "dns": {
        "servers": [
            {
                "tag": "DirectDNS",
                "address": "https://223.6.6.6/dns-query",
                "strategy": "ipv4_only",
                "client_subnet": "1.0.8.0",
                "detour": "🎯 全球直连"
            },
            {
                "tag": "DIYDNS",
                "address": "https://{域名}/{path}/{自定义path}/UUID",
                "address_resolver": "DirectDNS",
                "address_strategy": "ipv4_only",
                "strategy": "ipv4_only",
                "client_subnet": "1.36.0.0",
                "detour": "🎯 全球直连"
            }
        ]
  }

注意,域名不要使用doh.xxx.xxx,太明显了!

注意,域名不要使用doh.xxx.xxx,太明显了!

注意,域名不要使用doh.xxx.xxx,太明显了!

也不要仅使用 /doh-query 或 /dns-querypath 作为,太明显了!
本文配置仅作参考请自行修改。

由于https的加密,一般的嗅探功能只能查看到你访问的域名和ip,在这种情况下,由于加入了路径路径,在一定编程中阻止主动探测,这也是为什么不建议使用/doh-query或/dns-querypath作为原因。
建议配置AdGuardHome仅允许本机访问(通过防火墙关闭AdGuardHome配置DOH的端口),只保留nginx反代的443端口作为外部入口。

编辑{安装目录}/AdGuardHome.yaml,找到下面两个配置,修改ip部分为127.0.0.1即可。否则强烈建议关闭无加密dns,被扫描到53端口很容易被判定为dns服务器。

dns:
  bind_hosts:
  - 127.0.0.1
  port: 53
http:
  address: 127.0.0.1
  port: 3000

AdGuardHome上游配置以及开启ECS

个人建议,国内使用阿里的dns作为上游,国外使用google的dns作为上游,这相当于对ECS的支持效果较好。
附上我的上游配置,打开乐观的服务器,全部在google。另外还有一个不错的dns上游https://dns11.quad9.net/dns-query,对ECS支持也不错,如果配置了多个上游,建议配置为最上游。

图像

图像

ECS重中之重,建议打开。因为我本地dns分流,国内使用阿里的DOH,海外和漏网之鱼才使用自建的DOH,而且我使用TW的落地机,所以ECS设置了根据TW的ip,请自己实际情况修改。如果你的代理客户端的dns支持ECS,那么以客户端发起dns请求时提交的ECS为基准,否则以AdGuardHome配置的ECS生效。

图像

3!2!1!上效果图

比喻修改的是个人域名、ip和UUID,请自行。查询运行时间参考,建议在延迟较低的中转机搭建DOH服务器,使用kdig每次查询都需要进行TLS握手,短暂,实际上建立TCP长连接之后(需要客户端支持,要同时nginx配置允许长连接),查询运行时间并不高。

图像

使用 kdig 测试 DoH 服务器的 ECS 支持

使用 +subnet=<subnet> 选项来指定 ECS 信息,结合 +https 指定自定义 DoH 路径。
命令格式:
kdig @{域名} +https=/{path}/{自定义path}/UUID +subnet=1.33.0.0/24 www.example.com

参数说明:
+https=/{path}/{自定义path}/UUID:指定自定义路径。
+subnet=1.33.0.0/24:指定 ECS 子网 1.33.0.0/24,这是你希望传递的客户端子网信息。
www.example.com:查询的域名

AdGuardHome服务自带dns层的广告过滤,安装时默认启用,可自行修改拦截配置。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注