首页 > 其他分享 >使用 AdGuard Home 搭建自用 DoH 服务

使用 AdGuard Home 搭建自用 DoH 服务

时间:2024-03-13 13:11:24浏览次数:20  
标签:DoH dns IP proxy DNS Home AdGuard

众所周知,AdGuard Home 是一款很不错的自建 DNS 服务器软件,除了广告拦截之外的功能都挺好用。自己搭建也很简单,参照官方文档几行命令就能搞定。这几年我也一直在使用家里树莓派上搭建的 AdGuard Home 作为局域网 DNS 服务器,体验很不错。这里要分享的是如何通过 Docker Compose 部署 AdGuard Home 并搭建一个私有自用的 DoH 服务,以及如何使用 AdGuard Home 实现 DNS 分流解析。

搭建 AdGuard Home

国内搭建公共 DNS 服务需要申请无法申请的牌照,用国外服务器搭建也会被抢答或者阻断,53(UDP)和 853(DoT)都是重点关注对象,所以目前只推荐使用 443(DoH 或 DoQ)的方式连接。

Docker 的安装使用可以参考前面的文章:Debian 系统安装 Docker 教程

在合适的路径下(假设为 /home/adguardhome)新建一个 docker-compose.yaml 文件,我们只需要 DoH 服务,因此可以只映射容器内的 443 端口出来,3000 端口是 Web 管理页面,可以根据自己需求修改。此外,这里可以选择添加一个 Volume 用来映射域名证书文件,避免后面手动粘贴的麻烦。

免费的 SSL 证书申请可以参考前面的文章:使用 acme.sh 自动签发和更新证书

同时,当你全部配置好正常运行后会发现控制面板首页的统计数据中来源 IP 全是 Docker 的 172 内网 IP 段,这里需要在配置文件中设置 trusted_proxies 参数,指定受信任的来源 IP 地址列表,AdGuard Home 才会获取代理标头(如 X-Real-IP,X-Forwarded-For 等)中的客户端真实 IP 地址。这里也可以先设置 Docker 容器的 IP 地址段,方便后面在配置文件中添加。

综上,你的 docker-compose.yaml 文件可以写成下面这样:

version: "3"

services:
  adguardhome:
    image: adguard/adguardhome:latest
    container_name: adguardhome
    restart: unless-stopped
    ports:
      - 127.0.0.1:8443:443/tcp
      - 127.0.0.1:3000:3000/tcp
    volumes:
      - /home/adguardhome/work:/opt/adguardhome/work
      - /home/adguardhome/conf:/opt/adguardhome/conf
      - /path/to/ssl:/opt/adguardhome/cert
    networks:
      agh_net:
        ipv4_address: 172.18.1.2

networks:
  agh_net:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.18.1.0/24

使用 docker compose up 命令拉取镜像生成相关文件后再 ctrl + c 停止,修改 conf/AdGuardHome.yaml 配置文件,找到 trusted_proxies 参数,后面添加一行 172.18.1.0/24:

trusted_proxies:
  - 127.0.0.0/8
  - ::1/128
  - 172.18.1.0/24

PS:有个配置建议,可以打开 AdGuardHome.yaml 在 dns 下面增加 trusted_proxies,主要是能够获取到上游的真实请求地址,方便 ECS 的运行。

dns:
  trusted_proxies:
    - 0.0.0.0/0

然后 docker compose up -d 启动容器服务。

配置 Nginx 和 DoH 服务

在公网搭建 AdGuard Home 最怕的是主动探测和各种扫描,地址暴露后可能会变成公共 DNS 或者被各种攻击,导致你的域名或服务器被玩坏。你可以自行探索 Nginx 鉴权的方法 ,同时 AdGuard Home 本身也支持设置白名单客户端,两种方式相结合可以提高安全性,降低暴露风险。

配置 Nginx

你应该将 AdGuard Home 服务写在 443 server 块中,这里略去其它相关配置,只贴出关键 location 块:

location / {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_pass http://127.0.0.1:3000/;
}
    
location /dns-query {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_pass https://127.0.0.1:8443/dns-query;
}

这里请将 location /dns-query 路径修改为其它随机字符串,防止主动探测,同时也可以将控制面板路径修改为复杂地址。

你还可以顺便在这里限制来源 IP,只允许你常用的 IP 访问,一般可以设置为你所在地区的公网 IP 段,这种限制方式的缺点是不够灵活。最后你的 Nginx 配置可以类似这样:

location /aghome/ {
    allow 192.168.1.1;
    allow 172.16.0.0/16;
    deny all;
    proxy_cookie_path / /aghome/;
    proxy_redirect / /aghome/;
    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_pass http://127.0.0.1:3000/;
}
    
location /random-string {
    allow 192.168.1.1;
    allow 172.16.0.0/16;
    deny all;
    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_pass https://127.0.0.1:8443/dns-query;
}

重载 Nginx 后打开你的域名地址进行安装,只需将第一步中的管理页面地址(Admin Web Interface)端口修改为和上面对应的 3000,其余可以保持默认一直下一步直到完成安装。

配置 DoH 服务

登陆控制面板后台,进入 设置-加密设置 页面,☑️ 启用加密,服务器名称中输入域名,HTTPS 端口填写 443,DNS-over-TLS 端口和 DNS-over-QUIC 端口如果不需要用到留空即可。下面的证书路径填写前面 docker-compose.yaml 中对应的文件路径。

adguard-home-doh

限制 ClientID

AdGuard Home 0.105.0 及之后版本支持为部分加密查询方式设置 ClientID,你可以限制白名单内 ClientID 才能进行查询。对于 DoH 查询,只需要在地址最后加上一段字符串即可,这里以随机 UUID(7017d85e-99d3-46df-bcbc-77a0a33c9cee)举例。

为了方便查看日志,你可以先设置一个持久客户端名称,在 设置-客户端 中添加客户端:

adguard-home-clientid

设置-DNS 设置-访问设置-允许的客户端 中输入该 UUID:

adguard-home-whitelist

完成以上设置后,你可以尝试通过 https://xxx.example.org/random-string/7017d85e-99d3-46df-bcbc-77a0a33c9cee 链接进行 DNS 查询了,并且基本可以确保只有你自己才能使用。

题外话:自建 DNS 服务器在代理过程中的作用

这里说点题外话,如果你是为了搭建无污染的 DNS 在代理工具中使用,效果可能并不明显。在基于 IP 规则分流的代理过程中,DNS 的作用仅仅是在客户端发起请求的第一步中解析获得 IP 地址用来做规则匹配,即使得到的是错误的 IP,只要命中代理规则,多数代理工具依然会封装域名后发送到远程服务器上解析并建立连接,与前面客户端解析获得的 IP 没有关系,所以不会对访问造成影响。

而且这一作用也被今天主流使用的 fake-ip 所弱化,fake-ip 跳过了上面所述的第一步,命中规则的域名不会在本地进行 DNS 解析,代理工具会直接返回一个内网 IP 地址并建立映射关系,同时在远程服务器上解析并连接后通过该内网 IP 地址进行代理。fake-ip 的优势很明显,加快了响应速度,同时也不会造成 DNS 泄漏。但域名规则是写不完的,总有些规则之外的漏网之鱼(小众域名)需要一个可靠的 DNS 解析兜底。 此外 fake-ip 有一些老生常谈的小问题,我个人是不大喜欢的,仍是 redir-host 的余党。

由此,自建无污染 DNS 服务器在代理过程中的意义只是为了应对部分特殊情况以及获得更好的隐私性,顺便解决被各种「焦虑化」的 DNS 泄漏问题,对大多数人来说属于可有可无的东西。

设置 DNS 分流解析

AdGuard Home 0.107.3 及之后版本支持为指定域名设置 DNS 上游的,也可以直接使用文件列表。前面提到我还有一台树莓派在局域网内运行 AdGuard Home 服务,这时便解锁了一个新的玩法,树莓派上的 AdGuard Home 设置 DNS 分流解析。

可以实现国内域名通过 AliDNS 或 DNSPod 进行解析,其余域名通过自建的海外 DoH 服务进行解析,配合 AdGuard Home 的乐观缓存,也不会对速度造成多大影响。不过由于国内域名列表肯定是不完整的,不在列表中的域名会通过海外 DoH 解析,得到的 IP 结果是国内的还好,可以直接连接,否则会通过远程服务器连接,此时要是该域名有国内 CDN 节点就绕远了。因此比较依赖规则文件的及时更新和准确性,最后选择了使用 dnsmasq-china-list 项目。

这里写了一个 shell 脚本将 dnsmasq-china-list 发布的文件转换为 AdGuard Home 能识别的格式,如有需要可以参考修改。

#!/bin/bash
# Writen by ATP on Jan 25, 2024
# Website: https://atpx.com

# AdGuard Home 项目路径
AGH_PATH="/home/adguardhome"
# 国内 DNS 服务器,多个用空格隔开
CN_DNS="https://223.6.6.6/dns-query https://120.53.53.53/dns-query"
# 海外 DNS 服务器
GLOBAL_DNS="https://xxx.example.org/random-string/7017d85e-99d3-46df-bcbc-77a0a33c9cee"
# dnsmasq-china-list 规则文件,无法下载的话可以找 CDN 或自建反代
accelerated_domains="https://raw.githubusercontent.com/felixonmars/dnsmasq-china-list/master/accelerated-domains.china.conf"
apple_domains="https://raw.githubusercontent.com/felixonmars/dnsmasq-china-list/master/apple.china.conf"

# 下载文件并合并
wget -O "$AGH_PATH/cn-domains.conf" $accelerated_domains
wget -O "$AGH_PATH/cn-apple.conf" $apple_domains
cat "$AGH_PATH/cn-apple.conf" >> "$AGH_PATH/cn-domains.conf"

# 转换为 AdGuard Home 格式
awk -v CN_DNS="$CN_DNS" -F/ '/server=/{print "[/"$2"/]"CN_DNS}' "$AGH_PATH/cn-domains.conf" > "$AGH_PATH/cn-dns.txt"

# 添加默认海外 DNS
sed -i "1i\\$GLOBAL_DNS" "$AGH_PATH/cn-dns.txt"

# 移动文件到 AdGuard Home 目录
mv "$AGH_PATH/cn-dns.txt" "$AGH_PATH/work/data/"

# 清理临时文件
rm "$AGH_PATH/cn-domains.conf"
rm "$AGH_PATH/cn-apple.conf"

echo "规则转换完成"

# 重启 AdGuard Home
# cd $AGH_PATH
# docker compose restart

停止 AdGuard Home 后编辑目录下配置文件 conf/AdGuardHome.yaml,找到 upstream_dns_file: "" 参数,修改为:

upstream_dns_file: /opt/adguardhome/work/data/cn-dns.txt

然后启动 AdGuard Home 即可实现 DNS 分流解析。最后你可以设置一个 crontab 任务,定时执行脚本自动更新域名规则并重启 AdGuard Home,这里不再赘述。

原文
https://atpx.com/blog/adguard-home-doh-server-with-docker/
参考
https://www.xukecheng.tech/use-mosdns-and-adguardhome-to-build-your-own-dns

标签:DoH,dns,IP,proxy,DNS,Home,AdGuard
From: https://www.cnblogs.com/xututu6/p/18070399

相关文章

  • 查看 Homebrew 管理的服务的日志
    首先,使用Homebrew启动服务时你会看到一条类似如下的信息:Createdsymlink/home/ecs-user/.config/systemd/user/default.target.wants/homebrew.frps.service→/home/ecs-user/.config/systemd/user/homebrew.frps.service.==>Successfullystarted`frps`(label:homebre......
  • The First Software Engineering Homework
    这个作业属于哪个课程软件工程2024-双学位(广东工业大学)这个作业要求在哪里软件工程第一次作业这个作业的目标熟悉Markdown语法,熟悉git操作,学会写blog。其他参考文献目录1个人简历1.1自我介绍1.2当前水平2展望未来2.1阅读《构建之法》2.2未来规......
  • 使用 LVM 将多个硬盘合并,解决 /home 目录容量不足问题
    使用LVM将多个硬盘合并,解决/home目录容量不足问题误伤这又何妨于2023-11-0821:38:42发布阅读量698收藏点赞数11文章标签:5G运维版权你是否有这样一个难题,由于在安装系统时仅仅给了/home目录100G硬盘大小,但过了一段时间,发现“哎,100G不够用了,当初怎么不多分点呢。”你......
  • dday06_homework_set
    点击查看代码#列举你了解的字典中的功能(字典独有)。#keys/values/items/get/update/pop#列举你了解的集合中的功能(集合独有)。#add/update/discard/intersection/union/difference/symmetric_difference#列举你了解的可以转换为"""字符串转数字数字转字符串列表转元......
  • day05_homework_dict
    点击查看代码#请将列表中的每个元素通过"_"链接起来。#users=['李少奇','李启航','渣渣辉']#print('_'.join(users))#请将列表中的每个元素通过"_"链接起来。"""users=['李少奇','李启航',666,'渣渣辉']......
  • day03_homework_string切害与while循环
    有变量name="aleXleNb"完成如下操作:name="aleXleNb"移除name变量对应的值两边的空格,并输出处理结果print(name.strip())判断name变量是否以"al"开头,并输出结果(用切片)ifname[0:2:1]in'al':print(name[0:2:1])判断name变量是否以"Nb"结尾,并输出结果(用切......
  • day02_homework_while循环_bool值计算
    !/usr/bin/envpython--coding:utf-8--@File:day02_homework.py猜数字,设定一个理想数字比如:66,让用户输入数字,如果比66大,则显示猜测的结果大了;如果比66小,则显示猜测的结果小了;只有等于66,显示猜测结果正确,然后退出循环。实现功能1"""luck_number=66whileTrue:guass......
  • day01_homework_print与if,else语句
    1、操作系统的作用?2、列举你听过的操作系统及区别?3、列举你了解的编码及他们之间的区别?4、列举你了解的Python2和Python3的区别?5、你了解的python都有那些数据类型?6、补充代码,实现以下功能。value=_____print(value)#要求输出alex"烧饼"""value='''alex"烧饼''......
  • It's just a little homework
    Firsthomework这个作业属于哪个课程软件工程这个作业要求在哪里Firsthomwork这个作业的目标介绍自我,阅读教材初步认识软件工程课程我是谁?张荆茂,来自广东工业大学软件工程三班课程5问软件工程到底是什么?怎样将课程内容用于实践?没有学习过任何面向......
  • games101_Homework3
    摘要:在Raster部分实现数值插值,然后实现四种不同的像素着色器作业描述:作业1:修改函数rasterize_triangle(constTriangle&t)inrasterizer.cpp:在此处实现与作业2类似的插值算法,实现法向量、颜色、纹理颜色的插值。在rasterize_triangle函数中重复上次的包围盒进行点采样,......