Contents
前言
我以前也写过搭建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,在右下角语言选项里选择"简体中文",然后点击屏幕中央的"开始配置":
注意,下图中的端口都是指的容器内部的端口,其中网页管理界面的监听端口一定要改为3000,然后点击页面下方的"下一步":
设置好用户名、密码以后点击页面下方的"Next"(为啥这里又是英文~~?):
这是帮助设置的界面,初始化完成后在gui面板里也能看到,然后直接点击页面下方的"下一步":
初始化成功,直接点击"打开仪表盘":
点击"登录"即可正式进入:
配置ADguard home
DNS设置
进入"设置"-"DNS设置":
界面如下:
上图中,"上游DNS服务器"大家需要根据自己的实际环境进行修改,比如,只是国内访问,则填写国内的公共dns,比如腾讯云的119.29.29.29,阿里云的223.5.5.5等;如果是有科学或者魔法的环境并且需要搭建无污染DNS,这里就填写国外的公共dns的ip,比如谷歌的8.8.8.8,cloudflare的1.1.1.1,也可以直接填写公共的DOH地址,可以参考下方红框中的示例。
上图中这部分也是需要根据自己的实际环境修改,"后备DNS服务器"就是字面的意思,我因为"上游DNS服务器"都是用的国外的,一旦科学或者魔法中断就直接玩完了,所以在"后备DNS服务器"填了个国内的阿里云的dns以防万一。
"Bootstrap DNS服务器"并不是必须的,如果"上游DNS服务器"使用了DOH/DOT的地址,这里才有用,并且如果是使用了国内公共的DOH/DOT(例如腾讯云的),这里最好填写相应的dns地址(腾讯云的)。
设置完成后可以点击下方红框中的"测试上游"来测试上游服务器是否能正常工作,然后点击"应用"保存这部分的配置。
这部分还有其他选项,大家可以自行研究,保持默认值也不影响使用:
加密设置
进入"设置"-"加密设置":
这部分主要是设置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端口,大家根据自己的实际情况选择:
然后是设置证书:
具体证书的申请我以后会用另一篇文章专门来说,无外乎就是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客户端设置(可选)
这部分可以添加客户端并为客户端指定特定的标识符:
这个标识符可以在前面的"DNS设置"部分调用:
可以实现只允许某客户端访问或者不允许某客户端访问。
例如,想实现只能我自己访问,那我可以添加一个客户端并指定标识符:
然后在"DNS设置"中只允许该用户访问:
然后在指定DOH地址的时候使用:
https://example.org/dns-query/222-333-444-555-666
作为地址,也就是说在常规的https://example.org/dns-query
后面加上客户端的标识符即可。
使用DOT和DOQ也有相应的指定方式,不过需要泛域名证书,详细大家看官方说明即可:
过滤器设置
"过滤器"-"DNS黑名单":
点击上图下方的添加黑名单:
上图中有很多列表,我就选了2个CHN开头的,大家可以自行勾选,但是建议不要太多,然后点击右下方的保存即可。
"过滤器"-"DNS重写":
这里其实就是自定义域名解析:
"过滤器"-"已阻止的服务":
这里能快速阻止一些常见网络的域名解析,还能设定阻止的时间表:
具体大家就自己研究了,我对这个没有需求。
国内外DNS分流(可选)
如果是搭建的无污染dns,就会面临一个问题:使用这个dns的时候,访问国内的一些网站反而会有问题,这个时候就会涉及一个国内外DNS分流的问题。ADguard支持DNS国内外分流,但是需要一个国内域名和国内dns对应的白名单,github上的项目"mouyase/ChinaListForAdGuardHome"提供了专供ADguard home使用的白名单,部分内容如下:
白名单下载地址如下:ChinaWhiteList.txt,大家可以自行下载,定期更新。
ChinaWhiteList.txt下载下来以后,可以放在宿主机挂上挂载到容器内部的任何一个目录里,比如/docker/adguardhome/conf
目录,然后用文本编辑器编辑一下相同目录下的AdGuardHome.yaml
文件,在其中的upstream_dns_file选项(默认内容为空),添加如下内容:/opt/adguardhome/conf/ChinaWhiteList.txt
,如下:
保存后重启容器。
对外发布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就是成功了:
当然,这个成功不能保证是否能通过chroma的校验(比如我通过cloudflare托管的com域名):
而我另一个腾讯的cc域名的DOH却是可以通过浏览器访问以及chrome校验的:
真是不解之谜啊。
注: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证书里的域名,这个真厉害,我以前就没想到这个选项有啥用,这下知道了,如图:
当然,如果不直接指向ADguard的https端口,而是再通过一个反向代理去访问就不需要这步操作。
客户端配置DOH/DOT服务器
这也是我选择DOH的原因之一,从目前客户端设置的便利性来说,DOH是最简单了,比如win11已经内置支持了:
而chrome浏览器也方便:
上图红框中可以可以填DOH,DOT,DOQ地址。
要注意,前面所述,在chrome里填入DOH、DOT、DOQ地址以后,chrome会校验该地址的合法性,如果校验不通过会显示如下报错:
而如果校验正常不会有提示,以填入腾讯云DOH为例:
所以自建的DOH等地址是否有效这里就可以看得出来(也有可能有效但是校验包被拦截)。
安卓客户端很多都是可以直接指定DOT地址,ios和macos需要使用描述文件的方式进行安装,具体描述文件的生成可以参考以下网址:https://dns.notjakob.com/tool.html。
后话
这篇文章写得我好累,不少知识盲点都需要梳理,花了我很多时间,不过还算值得。我的DOH地址就不发出来了,有点犯忌讳。
求详细搭建教程啊 搞糊涂了都给我 我是无备案域名和腾讯云国内机 域名在cloudflare托管
你是对最后如何发布域名有疑惑?我是直接用家里宽带搭的,直接使用cloudflare的tunnel的方式来发布域名。除了最后一步发布域名之外,之前的流程都是文章里的了。我之间是用的腾讯的cdn加备案域名发布的,后来想了想,还是直接用cloudflare上的域名来做,都是一样的。
可以写个用npm反代的教程吗🥹
你直接在右上角的搜索框里搜索npm就出来了呀~~