docker系列 使用docker基于ADguard home搭建自己的无广告、无污染且支持DOH(DOT)的DNS服务器
本文最后更新于 101 天前,其中的信息可能已经有所发展或是发生改变,如有失效可到评论区留言。

前言

我以前也写过搭建DNS服务器的文章,是基于bind9的(参见:docker系列 搭建基于bind9的DNS服务器),但是这个更适合在自己搭建测试环境的时候使用,而平时如果我们仅仅需要一个本地dns转发器,bind9就显得太过于臃肿了。在网上搜索了一番,发现了ADguard home。本来ADguard home主打的是一个域名防护(广告过滤,黑名单过滤等),所以我最开始找DNS解决方案的时候还以为写文章的乱写,还好一阵鄙视,没想到仔细一看,这不刚好就是我想要的完美的转发器吗?还提供DOH,DOT,居然还附送了广告过滤功能~~~。同时,如果环境中刚好可以使用科学或者魔法,还能从无广告DNS升级为无广告、无污染DNS,这个可以解决不少DNS污染引发的问题,比如:emby的TMDB插件因为"api.themovdb.org"被污染导致不能刮削的问题~虽然可以通过修改本地host文件的办法来暂时解决,但是别忘了那个ip只是诸多cdn地址中的一个而已,又不是永远不变的,难道还定期解析然后修改host?(况且qnap的nas每次重启host都会恢复默认值,还要另外用启动脚本在重启完成后来修改host文件~)有了无污染DNS,这些都不是问题了。


当然,要建立无污染dns必须要科学或者魔法的环境,而有科学或者魔法环境以后想正常访问"api.themovdb.org"的方法也有很多,比如把emby所在系统直接指向科学或者魔法或者emby所在系统直接使用能够科学或者魔法的代理,所以,那个时候无污染dns也只是可选方式之一而已。

另外,DNS污染和DNS劫持是两码事,在天朝内部,所有dns都是被污染的,不存在干净的,而DOT,DOH类技术所谓的能防止DNS劫持,其实只是针对运营商而言的,所以如果你用了阿里或者腾讯的DOH,DOT,那只能说明你的运营商就没办法拦截修和改你的dns请求了(比如域名输错了却被直接被重定向到运营商的广告页面~)。


以前我的威联通上的emby是通过直接在系统层面指定http代理来解决TMDB的api被污染的问题,但是这样会导致很多和TMDB无关的外出请求也使用代理,虽然也没啥影响(科学设备有域名白名单),但是总归不爽;而直接让qnap nas的所有外出流量都通过科学或者魔法也是一样的不合适,毕竟只有emby需要使用而已,所以这些都不算是完美方案。现在,直接把dns指向无污染dns就可以了,其他外出流量都不受影响,这才是最完美的方式,强迫真患者终于能松一口气了。

当然,无污染dns仅仅能解决部分因为dns污染引发的问题,至于更高级的IP层面的限制、ASN号限制,甚至SNI限制就无能为力了,还是只能靠科学或者魔法。

部署ADguard home

在宿主机上创建需要映射到容器内部的目录

mkdir -p /docker/adguardhome/work #存放ADguard home的过滤规则文件
mkdir -p /docker/adguardhome/conf #存放ADguard home的配置文件
mkdir -p /docker/adguardhome/cert #存放ADguard home需要使用的证书文件

搭建ADguard home

搭建ADguard home的docker run格式命令如下:

docker run --name adguardhome -d --restart=always \
  -v /docker/adguardhome/work:/opt/adguardhome/work \
  -v /docker/adguardhome/conf:/opt/adguardhome/conf \
  -v /docker/adguardhome/cert:/opt/adguardhome/cert \
  -p 53:53/tcp -p 53:53/udp \ #对外提供标准dns服务的端口,如果内网有设备需要直接将dns地址指向ADguard,那么宿主机映射端口就需要使用53端口(主要是udp53,tcp53很少,不过最好也留着)
  -p 80:80/tcp -p 443:443/tcp -p 443:443/udp \ #80其实没什么用,要使用DOH或者DOQ,需要使用443端口,其中DOH使用tcp 443,DOQ使用udp 443
  -p 3000:3000/tcp \ #gui面板页面
  -p 853:853/tcp \ #DOT端口
  -p 5443:5443/tcp -p 5443:5443/udp \ #DNSCrypt server端口
  -d adguard/adguardhome

上面是完整版命令,但是实际环境中我们用不到那么多端口,顶了天就tcp/udp 53端口,tcp 443端口,tcp 3000端口,所以常规版命令如下:

docker run --name adguardhome -d --restart=always \
  -v /docker/adguardhome/work:/opt/adguardhome/work \
  -v /docker/adguardhome/conf:/opt/adguardhome/conf \
  -v /docker/adguardhome/cert:/opt/adguardhome/cert \
  -p 53:53/tcp -p 53:53/udp \
  -p 443:443/tcp \ 
  -p 3000:3000/tcp \ 
  -d adguard/adguardhome

容器运行起来以后,就可以直接使用http://宿主机ip:3000访问ADguard home了。

初始化

首次访问ADguard,在右下角语言选项里选择"简体中文",然后点击屏幕中央的"开始配置":

image.png

注意,下图中的端口都是指的容器内部的端口,其中网页管理界面的监听端口一定要改为3000,然后点击页面下方的"下一步":
image.png

设置好用户名、密码以后点击页面下方的"Next"(为啥这里又是英文~~?):
image.png

这是帮助设置的界面,初始化完成后在gui面板里也能看到,然后直接点击页面下方的"下一步":
image.png

初始化成功,直接点击"打开仪表盘":
image.png

点击"登录"即可正式进入:
image.png

配置ADguard home

DNS设置

进入"设置"-"DNS设置":

image.png

界面如下:
image.png

上图中,"上游DNS服务器"大家需要根据自己的实际环境进行修改,比如,只是国内访问,则填写国内的公共dns,比如腾讯云的119.29.29.29,阿里云的223.5.5.5等;如果是有科学或者魔法的环境并且需要搭建无污染DNS,这里就填写国外的公共dns的ip,比如谷歌的8.8.8.8,cloudflare的1.1.1.1,也可以直接填写公共的DOH地址,可以参考下方红框中的示例。
image.png

上图中这部分也是需要根据自己的实际环境修改,"后备DNS服务器"就是字面的意思,我因为"上游DNS服务器"都是用的国外的,一旦科学或者魔法中断就直接玩完了,所以在"后备DNS服务器"填了个国内的阿里云的dns以防万一。

"Bootstrap DNS服务器"并不是必须的,如果"上游DNS服务器"使用了DOH/DOT的地址,这里才有用,并且如果是使用了国内公共的DOH/DOT(例如腾讯云的),这里最好填写相应的dns地址(腾讯云的)。

设置完成后可以点击下方红框中的"测试上游"来测试上游服务器是否能正常工作,然后点击"应用"保存这部分的配置。

这部分还有其他选项,大家可以自行研究,保持默认值也不影响使用:

image.png

image.png

加密设置

进入"设置"-"加密设置":

image.png

这部分主要是设置DOT/DOH/DOQ加密需要使用的证书。


这里大家要先评估最适合自己实际环境的方式。DOH需要合法的tcp 443端口,放在国内环境就是要有tcp 443端口且能跑https,说人话就是要备案。DOQ需要使用udp 443,这个我没有实际研究,不知道云主机环境对这个有没有什限制,如果没有倒是个好选择。DOT需要用tcp 853端口,对于没有备案的云主机和有公网地址的家庭宽带来说,都是一个选择,但是这个和DOQ都有一个缺点:明眼人一看就知道你在干什么~,毕竟udp 443和tcp 853的流量太过明显,虽然不知道你干的细节,但是你在干什么却是一目了然的。我因为有个域名是备了案的,有合法使用443端口的"良民证",所以选择的DOH。而且DOH和DOT,DOQ相比有个大到天的巨大优势,我后面会介绍。


这部分启用加密并设置具体要使用哪种加密方式,我只需要DOH,所以只留下了HTTPS 443端口,大家根据自己的实际情况选择:

image.png

然后是设置证书:
image.png

具体证书的申请我以后会用另一篇文章专门来说,无外乎就是Let’s Encrypt或者腾讯云、阿里云白嫖,最方便的是ohttps(记住Let’s Encrypt和腾讯云免费申请的20个证书都是属于亚洲诚信系,共享最多20个主机名的额度,阿里没了解过,估计也是吧,具体ohttps申请部署证书的详细步骤参看文章:家庭数据中心系列 SSL证书一站式管理工具OHTTPS使用教程)。假定大家都已经有了现成的证书和私钥key,这里有2种上传方式:
1、"设置证书路径"和"设置私钥文件":
记得前面docker run命令的一条-v参数吗:
-v /docker/adguardhome/cert:/opt/adguardhome/cert
宿主机上的/docker/adguardhome/cert目录就是用来直接放置证书文件和私钥文件的,对应于容器内/opt/adguardhome/cert目录,所以只需要将xxx.crt和xxx.key直接拷贝到宿主机上的/docker/adguardhome/cert目录,然后在ADguard里的"设置证书路径"和"设置私钥文件"里分别用’/opt/adguardhome/cert/xxx.crt'及/opt/adguardhome/cert/xxx.key指定证书路径后保存即可。
2、"粘贴证书内容"和"粘贴私钥内容":
这种方式直接将证书内容和私钥内容复制粘贴到ADguard里即可,采用这种方式,证书和私钥内容是直接存放在conf目录下的AdGuardHome.yaml文件中。

以上两种方式都可以,只不过,采用"粘贴"方式,就需要定期手动更新证书内容了,而采用"设置"方式,是可以采用外部方式定期更新证书的,这个等我以后用另一篇文章来详细讲。

dns客户端设置(可选)

这部分可以添加客户端并为客户端指定特定的标识符:

image.png

image.png

这个标识符可以在前面的"DNS设置"部分调用:
image.png

可以实现只允许某客户端访问或者不允许某客户端访问。
例如,想实现只能我自己访问,那我可以添加一个客户端并指定标识符:
image.png

然后在"DNS设置"中只允许该用户访问:
image.png

然后在指定DOH地址的时候使用:https://example.org/dns-query/222-333-444-555-666作为地址,也就是说在常规的https://example.org/dns-query后面加上客户端的标识符即可。

使用DOT和DOQ也有相应的指定方式,不过需要泛域名证书,详细大家看官方说明即可:

image.png

过滤器设置

"过滤器"-"DNS黑名单":

image.png

点击上图下方的添加黑名单:
image.png

上图中有很多列表,我就选了2个CHN开头的,大家可以自行勾选,但是建议不要太多,然后点击右下方的保存即可。

"过滤器"-"DNS重写":

image.png

这里其实就是自定义域名解析:
image.png

"过滤器"-"已阻止的服务":

image.png

这里能快速阻止一些常见网络的域名解析,还能设定阻止的时间表:
image.png

具体大家就自己研究了,我对这个没有需求。

国内外DNS分流(可选)

如果是搭建的无污染dns,就会面临一个问题:使用这个dns的时候,访问国内的一些网站反而会有问题,这个时候就会涉及一个国内外DNS分流的问题。ADguard支持DNS国内外分流,但是需要一个国内域名和国内dns对应的白名单,github上的项目"mouyase/ChinaListForAdGuardHome"提供了专供ADguard home使用的白名单,部分内容如下:

image.png

白名单下载地址如下:ChinaWhiteList.txt,大家可以自行下载,定期更新。

ChinaWhiteList.txt下载下来以后,可以放在宿主机挂上挂载到容器内部的任何一个目录里,比如/docker/adguardhome/conf目录,然后用文本编辑器编辑一下相同目录下的AdGuardHome.yaml文件,在其中的upstream_dns_file选项(默认内容为空),添加如下内容:/opt/adguardhome/conf/ChinaWhiteList.txt,如下:

image.png

保存后重启容器。

对外发布ADguard home的服务

对我来说,ADguard home我有2种用法:
1、作为局域网里的无污染dns
这个主要给需要使用emby刮削的机器使用。当然,我家宽带有公网ip,53端口是可以用的,也可以暴露给互联网,但是因为是动态ip,几天就变一次,没啥意义。
2、对外提供DOH服务
这个才是最有用处的。为什么我在DOQ,DOT,DOH之中选择了DOH?因为DOH基于https,这就有个非常巨大的优势,可以使用CDN(当然,如果是国内CDN需要有备案域名)!因为我的家庭宽带出口虽然有公网IP却没有443端口,但是腾讯云的cdn可以自定义源站端口,所以可以用腾讯云CDN指向家庭宽带出口路由器的非443端口,再从路由器上经过端口映射最终指向ADguard home的443端口上,最终对外提供的是腾讯经过cdn加速的443端口,关键还能隐藏源站ip地址!

另外,对于DOT/DOQ两种技术的选择:如果是有公网地址的家庭宽带,则使用DOT;如果是云主机,则使用DOT,DOQ都行,具体大家可以自行研究,就是一个域名解析和端口映射(云主机是端口放行)的事。不过如果是DOT或者DOQ就会暴露你主机的ip地址,一定要注意安全防范。


我因为不想单独在路由器上给ADguard home开一个端口映射,还是想直接使用统一的对外发布端口,所以更复杂一点:(https到)CDN(cloudflare或者腾讯云CDN)—>(通过公网https到)家庭数据中心出口总反向代理—>(https到)ADguard home,3个位置都需要部署证书(ADguard必须是合法证书,其他2个位置随意),同时我的doh域名还通过自定义主机名的方式接入了cloudflare,也不怕爬虫和ddos,好处是大大的有。

一种简单的判断ADguard home配置的DOH是否成功的办法,就是浏览器直接访问DOH的地址,如果返回Bad Request就是成功了:

image.png

当然,这个成功不能保证是否能通过chroma的校验(比如我通过cloudflare托管的com域名):
image.png

而我另一个腾讯的cc域名的DOH却是可以通过浏览器访问以及chrome校验的:
image.png

image.png

真是不解之谜啊。

注:cloudflare通不过chrome校验的原因找到问题了,有2个注意事项:
1、cloudflare的WAF把chrome发送的查询请求当做异常请求进行质询了,需要在WAF规则里根据访问host、uri路径(/dns-query)、UA代理等条件进行跳过操作。
2、使用tunnel创建Public hostnames时,如果要直接指向ADguard的https端口,就需要配置TLS的Origin Server Name,因为ADguard只能使用合法证书(所以肯定不是cloudflare托管域名的自签证书),cloudflare通过tunnel以https协议去访问ADguard的https端口时,获取的证书包含的域名和自己托管的不匹配,就无法建立连接,所以需要使用Origin Server Name指定ADguard证书里的域名,这个真厉害,我以前就没想到这个选项有啥用,这下知道了,如图:

image.png

当然,如果不直接指向ADguard的https端口,而是再通过一个反向代理去访问就不需要这步操作。


客户端配置DOH/DOT服务器

这也是我选择DOH的原因之一,从目前客户端设置的便利性来说,DOH是最简单了,比如win11已经内置支持了:

image.png

而chrome浏览器也方便:
image.png

image.png

上图红框中可以可以填DOH,DOT,DOQ地址。

要注意,前面所述,在chrome里填入DOH、DOT、DOQ地址以后,chrome会校验该地址的合法性,如果校验不通过会显示如下报错:

image.png

而如果校验正常不会有提示,以填入腾讯云DOH为例:
image.png

所以自建的DOH等地址是否有效这里就可以看得出来(也有可能有效但是校验包被拦截)。

安卓客户端很多都是可以直接指定DOT地址,ios和macos需要使用描述文件的方式进行安装,具体描述文件的生成可以参考以下网址:https://dns.notjakob.com/tool.html

后话

这篇文章写得我好累,不少知识盲点都需要梳理,花了我很多时间,不过还算值得。我的DOH地址就不发出来了,有点犯忌讳。

博客内容均系原创,转载请注明出处!更多博客文章,可以移步至网站地图了解。博客的RSS地址为:https://blog.tangwudi.com/feed,欢迎订阅;如有需要,可以加入Telegram群一起讨论问题。

评论

  1. iPhone Safari 605.1.15
    3 月前
    2024-10-09 1:46:39

    求详细搭建教程啊 搞糊涂了都给我 我是无备案域名和腾讯云国内机 域名在cloudflare托管

    • 博主
      Macintosh Chrome 129.0.0.0
      3 月前
      2024-10-19 19:10:29

      你是对最后如何发布域名有疑惑?我是直接用家里宽带搭的,直接使用cloudflare的tunnel的方式来发布域名。除了最后一步发布域名之外,之前的流程都是文章里的了。我之间是用的腾讯的cdn加备案域名发布的,后来想了想,还是直接用cloudflare上的域名来做,都是一样的。

  2. Freddy
    Macintosh Chrome 123.0.0.0
    10 月前
    2024-4-02 21:54:17

    可以写个用npm反代的教程吗🥹

    • 博主
      Freddy
      Macintosh Chrome 122.0.0.0
      10 月前
      2024-4-02 21:58:53

      你直接在右上角的搜索框里搜索npm就出来了呀~~

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇
       

本站已禁用鼠标右键和各种快捷键,代码块内容可以直接在右上角点击复制按钮进行复制

zh_CN