🌐自用无泄露MosDNS规则分享

2024-9-2|2025-1-6
Yawatasensei
Yawatasensei
type
status
date
slug
summary
tags
category
icon
password
😀
之前一篇文章介绍了OpenClash + MosDNS + Adguard Home的DNS泄露排查及修复记录。这里面最为核心的部分就是MosDNS,OpenClash和Adguard Home只负责最简单的解析工作,而MosDNS作为整个链条的中枢负责分流,类似于一个指挥中枢。所以今天将我的MosDNS配置分享出来。我的MosDNS是根据 Jasper-1024/mosdns_docker 的MosDNS V5配置进行二次修改的版本,所以这篇文章也可以说是一个二创文章,对原作者的配置进行了部分修改,并对整体的DNS处理流程进行讲解。

📝 付费内容

MosDNS介绍

一个 DNS 转发器 via IrineSistiana / mosdns
MosDNS可以算作是SmartDNS的一个替代品,两者作用在大部分场合相同。SmartDNS更侧重于缓存,而MosDNS的可玩性更高。

配置环境

我的MosDNS是运行在旁路由(旁路网关)的OpenWRT上,具体环境如下:
  • OpenWRTImmortalWrt 23.05.3 r27917-81a1f98d5b / LuCI openwrt-23.05 branch git-24.092.44091-d24c2e3
  • 内核版本5.15.162
  • 架构X86/64
  • MosDNS版本v5.3.3
以上的环境只是我个人的配置环境,理论上如果你使用MosDNS,在其支持的环境下都可以正常使用我所分享的配置文件,包括Windows、Linux的发行版本、MacOS以及Docker。

Github仓库地址

使用方法

配置文件共计3个,分别为config_custom.yaml, dns.yaml, dat_exec.yaml
各部分作用如下:
  • config_custom.yaml: 主配置文件,负责DNS序列定义以及DNS序列执行。需要依赖dns.yamldat_exec.yaml运行。
  • dns.yaml: dns定义配置文件,负责配置公共DNS服务器及远端解析DNS地址及端口。
  • dat_exec.yaml: 规则配置文件,负责定义各规则tag及规则来源文件。
下载或克隆三个yaml文件,OpenWRT放到/etc/mosdns文件夹内。如果是luci-app-mosdns,需要选择使用自定义配置文件。其他系统可以通过-c 参数指定配置文件为config_custom.yaml
默认GeoSite和GeoIP的存放位置为/var/mosdns/ ,请确保文件夹下含有geoip_cn.txtgeosite_category-ads-all.txtgeosite_geolocation-!cn.txtgeosite_gfw.txtgeosite_cn.txt以及geoip_private.txt ,OpenWRT用户可以通过luci-app-mosdnsGeoData Export功能自动下载解码生成:
notion image
 
同时,在/etc/mosdns/下需要建立rule文件夹,并新建whitelist.txtgreylist.txt文件,用于自定义白名单和污染域名名单。DDNS类域名可放到白名单whitelist.txt中。
默认监听端口为5333 ,TCP和UDP均开启,如无下游DNS服务,可修改为53端口使用。如果系统为OpenWRT,也可以直接修改dnsmasq的dns重定向到5333来使用。具体使用方法根据自己需要进行修改。修改的具体位置位于config_custom.yaml文件最底部。

MosDNS处理队列

notion image
前序列代码:
主序列代码:
合并序列:
前序列处理流程主要用于对本地域名、PTR请求、无效请求以及DNS声明等请求进行处理,不涉及到正式的域名DNS解析,不与公共DNS服务器产生数据上的交互,避免本地内部请求外泄,对解析洁癖产生安全问题的恐慌。
主序列处理流程主要用于公网的正式域名解析进行处理,根据分流规则进行直接通过公共DNS服务器进行域名解析或通过DNS转发方式将污染域名交由代理处理。
整体MosDNS的配置文件由以下部分的DNS查询片段组成:
  • query_lan
  • query_cn
  • query_gfw
  • query_nocn
  • query_fallback
在处理上通过对cngfw!cn域名的特定处理,从而避免产生DNS泄露问题。

query_lan

query_lan用于处理本地DNS请求,例如局域网内*.lan的域名解析以及PTR请求。PTR请求包括反查路由器域名、反查局域网组播域名、UPNP使用的SSDP服务对应域名以及DNS Service Discovery等。MosDNS作为DNS转发器,其本质是进行DNS的转发,并不能直接对DNS请求进行处理。在OpenWRT上,dnsmasq可以对PTR请求做出正确的回应,所以我将query_lan所使用的dns_lan配置为主路由(也是OpenWRT)的地址,由主路由的dnsmasq进行上述请求处理。在这里并不一定严格要求使用主路由使用OpenWRT系统,正常的路由器基本都可以对此进行回应。
代码片段:
主配置文件:
query_lan中,增加了cache_lan的执行选项,因为本地的DNS请求也是有DNS缓存的,通过缓存可以节省一点点时间和主路由的处理压力。
 
dns.yaml配置文件:

query_cn

query_cn是用于对已经通过Geosite和Geoip识别到为国内网站的域名,以及配置白名单的域名进行直接解析。
代码片段:
主配置文件:
首先通过ecs_cn为DNS请求附加上ecs信息,ecs相关配置在下面的dat_exec.yaml 文件中。请求所携带的IP地址可以填写你所在地运营商dns的地址,使DNS解析结果的IP地址在物理上更接近你所在的IP地址,降低访问延迟。个人不建议填写自己的公网IP地址,尽管使用的是阿里巴巴和腾讯的公共DNS服务,但依旧存在根据IP地址追踪的可能。
同时,在通过阿里和腾讯的公共DNS服务进行请求时,如果发现响应返回的是非大陆地区的IP地址,会将该请求丢弃,视为解析错误,并将该DNS请求加入到query_nocn队列进行处理。这样处理的意义在于,解析结果返回非大陆地区IP地址的一种可能为ecs没有生效,公共DNS服务器认为我们在其他的国家,另一种可能为该网站进行了服务器迁移,迁移到了国外的云服务提供商。不管是哪种结果,对于我们来说,返回的结果都不是最优的结果,无法提供足够快的访问速度,所以不如交由query_nocn去请求一个更精确的地址。
在国内(cn)的公共DNS服务器选择上,我选择了阿里巴巴的公共DNS服务和DNSPOD(腾讯)的DNS服务,我没有选择运营商的DNS服务,因为运营商的DNS服务无法提供DOH或DOT。同时在使用H3、Quic以及Pipeline的基础上,同时使用ECS,解析的结果已经足够精确,速度也足够的快,没必要为了更快一点点而选择不安全的公共DNS服务。阿里DNS作为主DNS,同时DNSPOD作为备用DNS,开启副可执行插件始终待命。
dns.yaml配置文件:
在国内(cn)的公共DNS配置上,只使用DOH和DOT,同时阿里DNS的DOH开启H3,DNSPOD目前还不支持H3;两家DNS的DOT均开启pipeline;不使用Quic DNS,晚高峰时运营商对Quic的Qos太严重。并发请求数量上维持原版的最大数量为3,从并发请求结果中选择返回最快的结果,加快DNS解析速度。
dat_exec.yaml:
 

query_gfw

query_gfw用于直接对已经确认污染域名进行DNS转发,将DNS解析请求通过上级代理进行远端解析。端口7874 为OpenClash所使用的dns监听端口,可根据自己所使用的程序进行修改。
代码片段:
主配置文件:
dns.yaml配置文件:

query_nocn

query_nocn是用于对不处于GFW List中的国外域名进行解析请求的部分。由于geosite:gfwgeosite_geolocation-!cn 的子集,所以query_nocn在主序列中位于query_gfw的下一层级,这样配置的原因在于对于已经确认被污染的域名,没有必要通过公共DNS再继续进行解析,直接交由forward_remote的代理直接进行解析速度更快,稳定性也更好一些,同时避免产生国内运营商的反诈劫持行为。
代码片段:
主配置文件:
对国外域名所附加的ECS IP地址,我通常会选择我所使用代理服务器出口附近的IP地址,这和我家里整体的网络设计有关,对于非大陆的IP地址,在没有特殊的设置情况下,均会通过代理访问,所以配置出口附近的IP地址是最好的选择,这样所解析的地址更靠近出口位置,从而获得更好的访问速度。你可以通过ipify或者其他IP地址查询网站查看自己的出口IP地址。
同时如果通过使用国外公共DNS服务器进行解析请求的结果返回的如果是大陆的IP地址,进行drop(丢弃)处理。这种情况一般表示这个域名已经被污染,即便使用请求返回的IP地址,也无法正常访问。对于部分省市的劫持反诈,也可以将反诈网站所解析的IP地址进行drop,重新使用fallback进行查询。
由于Cloudflare和Google提供的公共DNS服务在国内的延迟较高,或者无法正常使用,所以我选择了AdGuard DNS和NextDNS的dns服务,相比其他的国外无污染公共dns服务,在我这里ping下来延迟较低,且稳定性较好。你也可以根据你自己的网络情况选择自己适用的国外DNS服务。关于国外DNS服务器的选择,可以参考《国内外DNS推荐列表》这篇文章。
dns.yaml配置文件:
NextDNS在注册时候可以使用h3,同时会分配一个属于自己的dns地址,每个月的配额在300,000请求,家庭使用的话,基本上用不完。Quad9目前不支持h3,两者都支持pipeline。
在这里我配置的并发请求数(concurrent)为2,牺牲一些速度的同时,避免产生过多的upstream error错误。
dat_exec.yaml:

query_fallback

query_fallback用于对不满足上述已经执行规则的解析请求进行再次请求,默认使用dns_cn进行解析。
如果担心产生DNS泄露,fallback也可以使用国外DNS。
代码片段:
主配置文件:

DNS缓存

DNS缓存分为lan缓存(局域网域名)和wan缓存(公网域名),未开启乐观缓存,因为在下游我配置了AdGuard Home会开启乐观缓存。
代码片段:
dat_exec.yaml:

其他

关于pipelines

enable_pipeline: TCP/DoT 使用RFC 7766新的query pipelining连接复用模式。
  • 启用后可大幅提高连接利用率,减少建立连接/握手的次数,进而降低响应延时。
  • 并非所有服务器都支持。必须确定服务器支持后再启用该选项。
  • Tips: 已知Google和Cloudflare的TCP/DoT是支持该模式的。知名的公共DNS服务商大多数都支持该模式。可以使用mosdns probe pipeline {tcp|tls}://server_ip[:port] 测试命令测试服务器是否支持。比如mosdns probe pipeline tls://8.8.8.8

关于dial_addr

dial_addr: IP协议层面建立连接时使用的地址。如果host是域名,此处填入IP可免去每次建立连接时解析服务器域名。支持指定端口号。
目前MosDNS的bootstrap指定功能还处于实验性阶段,dial_addr相当于直接为DOH/DOT的dns服务器指定IP地址,省去解析的步骤。对于使用Cloudflare的DNS,也可以通过优选IP的方式进行筛选,从而选择最快的DNS接入点。

关于IPv6

国内DNS分流和远端解析默认使用IPv4/IPv6双栈模式,no_cnfallback会使用优先IPv4规则,可根据自己需要将exec: prefer_ipv4 选项删除。同时IPv4的公共DNS服务基本都支持IPv6解析,可不用单独再进行配置。
ECS暂时不支持填充IPv6地址,同时为了避免隐私泄露,以及目前大部分用户都不太习惯为IPv6配置防火墙,所以尽量不要泄露,保护好自己的IPv6地址。
如果你的网络没有IPv6,可将dns.yaml中含有IPv6地址的行删掉,避免使用IPv6地址的公共DNS服务器进行解析,也从根本上杜绝这种请求。当前维持不动也不会发生什么,只是在日志中会产生Warning

关于队列执行

如果经过上述队列执行过后依旧没有可用的DNS解析结果会发生什么?
会报错。

关于http3(H3)

为什么http3的DOH更快?
因为http3在大多数情况下,客户端和服务器之间的通信可以在第一次数据包传输时开始,不需要像TCP那样经过多次握手过程。
具体可以参见《什么是HTTP/3》这篇文章。

📎 参考文章

 
💡
有关DNS的问题,欢迎您在底部评论区留言,一起交流~
OpenWRT IPv6防火墙规则:如何放行客户端地址及端口实验性:不使用Dnsmasq绕过中国大陆IP
Loading...