想要搭建一个dns首先要注意的是不同地区的解析,由于国内网络环境非常复杂,不同运营商之间可能都有巨大的延迟,针对不同运营商、不同城市的解析是完全不一样的,所以解析的结果会对访问的速度产生很大的影响,不过有了edns后这些问题都不是问题了,edns可以将客户端的ip发送给上游然后上游知道了后响应就会更靠近客户端的ip而不是服务器的ip,那么我今天就搭建一个支持edns的dns服务器。
国内不允许没资质搭建53端口的明文dns,我也不可能搭建,自己搭得主要目的就是抗污染、防泄露、加速请求,加速请求其实是最重要的,在做到前两个的前提下,国外dns完全没有速度可言,起码3位数延迟,所以搭服务器时线路要好,国外服务器到国外dns好的可以到个位数延迟,慢的也就是30左右。
那么加密dns首先就需要一个tls证书,这个我就不解释了。
dnsproxy
先来说一种最普通的dns服务端,没有什么花里胡哨的东西,就是将请求发给上游,返回给客户端,在releases里下载自己对应系统的可执行文件(github用法:点击Assets就可以看到所有文件,如果没显示在最后点击Show all xx assets),解压缩后直接丢到/usr/bin或C:\Windows\System32,然后在ssh或cmd中执行(关掉cmd或ssh终端就会停止)
dnsproxy -l 0.0.0.0 -p 0 --https-port=443 --http3 --tls-crt=证书路径 --tls-key=私钥路径 -u quic://unfiltered.adguard-dns.com --tls-min-version=1.3 --edns --cache这就算启动成功了,-p后面的端口是明文dns端口,0就是禁用,通常是53,想要运行dot或者doq就加上--quic-port=853或--tls-port=853,有个奇怪的地方就是这两貌似没法在同一个进程里监听同一个端口的(一个tcp一个udp肯定是可以一起监听的),可能是程序本身的奇怪逻辑,也不知道看这篇文章的时候这个问题有没有弄好,现在分开运行就可以。
想要在后台运行或关掉终端依旧运行就做成服务,windows用nssm做成服务,linux可以执行以下命令创建dnsproxy.service,设置开机自启并立刻运行
cat <<EOF > /etc/systemd/system/dnsproxy.service
[Unit]
Description=dnsproxy
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/dnsproxy -l 0.0.0.0 -p 0 --https-port=443 --http3 --tls-crt=证书路径 --tls-key=私钥路径 -u quic://unfiltered.adguard-dns.com --tls-min-version=1.3 --edns --cache
WorkingDirectory=/usr/bin
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
systemctl enable dnsproxy --now搭建完后dns设置为https://域名/dns-query、tls://域名、quic://域名,需要注意的是不是所有dns都支持edns,示例中unfiltered.adguard-dns.com支持edns。
AdGuardHome
我现在就在用这个,这个项目和上面一样都是adguard团队做出来的dns服务器,不同的是这个具有更多的功能,比如统计数据、本地dns拦截、修改dns响应等功能,不是用一行参数就能直接开始用得,这个拦截相比用国外的广告拦截当上游有更快的速度,拦截过程服务器自己处理了,只需要几毫秒就能完成拦截,不再需要从上游服务器获取ip再响应,拦截规则可以每天自动更新,我当初用dnsproxy上游到adguard dns来拦截,但是后来发现了一个问题,我用得20欧元1年订阅,1个月能10m请求,而我1周会有7m请求,完全不够用,就只能搞这个了。
windows从releases里下载二进制文件(github用法:点击Assets就可以看到所有文件,如果没显示在最后点击Show all xx assets),然后放到一个喜欢的路径直接双击运行即可,linux运行官方一键脚本wget --no-verbose -O - https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh -s -- -v来安装.。
然后程序会监听所有ip的3000端口,用浏览器访问ip:3000,根据引导配置好用户名密码、dns端口、面板管理端口即可,我不建议从公网用http协议来配置,windows有rdp可以在本地用浏览器访问,linux最好弄个隧道进去,或者用web服务器反代出来用https配置,这属于安全性问题看个人是否重视。
windows的配置文件在运行目录中AdGuardHome.yaml,linux在/opt/AdGuardHome/AdGuardHome.yaml,如果是第一次部署,可以使用管理面板来修改配置,那样更轻松,如果已经部署过需要迁移/复制配置,只需要将这个文件替换就行了,替换后黑白名单需要点一下更新,windows和linux之间迁移配置需要注意证书路径要改一下,上游服务器推荐quic://unfiltered.adguard-dns.com支持edns。
dns设置里edns当然是需要开得,dnssec看自己喜好,我建议是开着,被劫持的可能已经几乎没有但是开着总没坏处,如果希望把dns服务器放在web服务器后面,edns想起作用就需要配置X-Forwarded-For请求头,我这里给一个caddy的配置,nginx网上到处都是我就不举例了,两个项目都适用
:443 {
header {
Strict-Transport-Security max-age=31536000;
}
handle /dns-query* {
reverse_proxy /dns-query* https://127.0.0.1:5443 {
transport http {
tls_insecure_skip_verify #不验证证书可信度
}
trusted_proxies 0.0.0.0/0
header_up X-Forwarded-For {remote_host}
header_up X-Real-IP {remote_host}
}
}
}想要edns就必须公网直连服务器,不要用dns over v2ray这种,这么干需要配置edns固定ip在自己的网络环境,而且只能自己用,别人用起来会很难受。
服务器在国内的上游dns配置技巧
在国内上游dns请求太慢怎么办,可以配置成这样,这是我找了一些国内规则,国内的请求也不怕泄露,发给国内支持edns的dns.alidns.com,其他请求还是发给unfiltered.adguard-dns.com,不过其实也不会多慢,dns有缓存,只有第一次请求域名的时候会花几百毫秒
https://unfiltered.adguard-dns.com/dns-query
h3://unfiltered.adguard-dns.com/dns-query
tls://unfiltered.adguard-dns.com
quic://unfiltered.adguard-dns.com
[/qq.com/tencent.com/jd.com/jdpay.com/wechat.com/smtcdns.com/qcloud.com/]tls://dns.alidns.com#tencent
[/163yun.com/163.com/netease.com/163jiasu.com/126.com/]tls://dns.alidns.com#netease
[/miyoushe.com/mihoyo.com/]tls://dns.alidns.com#mihoyo
[/bilibili.com/biliapi.net/bilivideo.net/akamaized.net/acg.tv/acgvideo.com/b23.tv/bigfun.cn/bigfunapp.cn/biliapi.com/bilibili.tv/biligame.com/biligame.net/bilivideo.cn/bilivideo.com/hdslb.com/im9.com/smtcdns.net/]tls://dns.alidns.com#bilibili
[/aliyun.com/taobao.com/alipay.com/alicdn.com/alipayobjects.com/]tls://dns.alidns.com#alibaba
[/xiaomi.com/xiaomi.net/miui.com/mi-img.com/miwifi.com/]tls://dns.alidns.com#xiaomi
[/360.com/360buyimg.com/]tls://dns.alidns.com#360
[/wmsj.cn/clngaa.com/ksyna.com/bscstorage.net/eccdnx.com/pinyuncloud.com/pinyuncloud.com/pinyuncloud.com/wmsjsteam.com/pphimalayanrt.com/steampowered.com/steamchina.com/steamcontent.com/steamusercontent.com/]tls://dns.alidns.com#steam
[/iqiyi.com/iq.com/gitv.tv/]tls://dns.alidns.com#iqiyi
[/baidu.com/baidupcs.com/xunlei.com/youku.com/xycloud.com/ykimg.com/onethingpcs.com/douyinpic.com/pinduoduo.com/letv.com/]tls://dns.alidns.com
[/cn/]tls://dns.alidns.com#cn
配合clash仅供私人使用的doh
我在clash的某个pr中看到了doh支持basic认证,其他代理我没有试过,https://用户名:密码@服务器地址/dns-query,这样的格式就可以了,还是一个caddy的配置示例
:443 {
header {
Strict-Transport-Security max-age=31536000;
}
handle /dns-query* {
reverse_proxy /dns-query* https://127.0.0.1:5443 {
transport http {
tls_insecure_skip_verify #不验证证书可信度
}
trusted_proxies 0.0.0.0/0
header_up X-Forwarded-For {remote_host}
header_up X-Real-IP {remote_host}
}
basicauth /dns-query* {
111 $2a$14$o1GceHJ0Ymw7zRdkulJjkuuY747AhoBA87E5kOTj/BorSye1CboyO #这是经过哈希处理的密码111,生成命令是caddy hash-password --plaintext 111
}
}
}
我是参考了 https://taoshu.in/dns/diy-doh.html 整的,用了一个到大陆延迟低的服务器,体验不错