【爬坑日记】打造自己的DNS矩阵(一)——MosDNS碎碎念
赤脚-还行
2025年05月31日 11:40
收录于文集
共20篇

在本系列文章中,我将从一般用户的理解出发,介绍相关内容。DNS是互联网古老的基础服务之一,本文不会探讨让人听着满头雾水的“域定义、根服务器、权威服务器、授权服务器”等技术概念,只从用户、团队负责人,希望实现什么功能谈起。

文章的标题中用了“矩阵”,这个看起来“装13”的词汇。无奈,毕竟我的文章主要介绍如何用开源/免费软件实现需求,在此过程中你可能遇到的问题和如何逼坑。此类软件通常不像哪些有规模的商业软件,有大而全的功能。单个软件的能力限制,满足不了我们的功能需求,只能组合使用,发挥各自的特点,而且有些软件确实在某些功能上有突出表现。

稍微了解计算机系统的人都知道,设备要上网就需要设置DNS。当访问由域名指向的网站时,就会由DNS服务器,负责将域名翻译成网络设备交换数据所需要的IP地址。对普通用户来说,都是从路由器自动配置DNS和设备IP地址,并接受网络接入服务商提供的DNS解析服务。

这种公共服务存在不少限制,不能很好应对以下场景:

1、比如打开网页,特别是开了多个网页时。满屏的广告,导致开启缓慢,页面开多了机器还卡顿。此时可以选择为浏览器安装adblock之类的软件来过滤广告。在个人电脑上安装软件,操作比较容易,但多台电脑或多个浏览器、手机、其它上网设备上,都去安装类似软件就比较麻烦了。部署AdguardHome作为内网所有终端设备统一的广告过滤服务,就是比较好的选择。它有图形管理界面和内置的统计图表。

2、内网里架设了多种内部服务器,可以用仅在内部使用的域名来访问,这比记住一大堆内网IP要方便很多。部署有图形管理界面的PowerDNS,负责内网域名分配和解析,就很合适。

3、出于各种原因,网络接入服务商提供的公共dns服务,解析某些域名的地址会被污染,导致出现目标网站不能访问的情况。此时部署mosdns,根据不同规则分别对内网、国内、国外、科学上网等域名做DNS分流解析,这能在很大程度上缓解域名污染导致的网络访问受阻问题。

以上3种服务,可以构成类似下面的服务拓扑结构:

这2种拓扑结构区别不大,仅仅是在哪个服务中做更多配置的问题,但都能实现以下目的:

  • ✅ AdGuard Home作为统一前端提供广告过滤

  • ✅ MosDNS实现精确的多级分流(本地/国内/国际/科学等)

  • ✅ PowerDNS专注内网域名解析

  • ✅ 分层架构易于扩展和维护

  • ✅ 出现问题,便于逐层排查,有助于提升性能与可靠性;

开篇介绍了不少需求场景,但本文的主角是mosdns。这个系列从mosdns开始,主要是因为Adguard和PowerDNS,都有成熟的图形界面和不少独立教程,部署时相对友好。而mosdns在部署时面临的问题琐碎和稍显复杂,会让初次接触的人一脸懵逼,难以下手。

1、mosdns到底是什么服务?它的工作逻辑是什么?

原作者的项目介绍页面(https://github.com/IrineSistiana/mosdns)和在线技术文档(https://irine-sistiana.gitbook.io/mosdns-wiki,提醒:这个网站不用科学上网,会更稳定)。就只是分享源码和功能模块的使用说明。而网上找到的其它介绍内容,基本都是在分享自己的配置文件,解释配置文件内部的逻辑关系。

对新手来说,先要明确MosDNS不直接解析域名(是做分流转发)。它依靠域名规则库的分类,针对不同类别的域名,转发给互联网上传统DNS服务器(权威、授权、递归等DNS服务器角色)完成域名和IP地址的对应解析,并对返回结果做进一步处理后(丢弃、转发等),再反馈给发起域名查询的客户端。如果客户端的域名查询,刚好命中mosdns之前的缓存记录,才会直接反馈客户端对应的结果(这种情况下,mosdns表现的像个传统dns服务器角色)。

汇总一下,MosDNS的分流本质是​​“规则匹配-->执行转发流程”的插件流水线​​,配置核心在于:

a)   ​​规则集​​(国内/国外/特殊域名列表,比如归属于google、apple、Netflix等的域名集合)

b)   ​​转发目标​​(本地缓存/国内DNS/海外DNS/加密DNS/代理服务器转发)

c)   ​​转发操作​​(都在配置文件内完成定义;forword、cache等代码模块/插件内定义具体的转发目标,由sequence代码模块/插件串联起匹配调用关系。必须先配置内容,才能在配置文件中调用某个插件或匹配规则集)

了解上述内容,才能看懂网上别人分享的配置,遇到配置中不理解的插件作用和功能,可以到项目原作者的在线技术文档查询,最终实现调整为适合自己网络结构和需求的配置。初次配置建议从基础分流入手,逐步添加缓存、广告过滤等插件。通过dig命令测试分流效果。

2、没有图形管理界面?

Mosdns项目本身没有提供图形管理界面,它是个“配置文件+命令行执行+日志反馈“的标准服务器端软件。对不习惯服务器运维的人,十分不友好了。其实,在openwrt软路由系统内,第三方开发了luci插件形式的管理界面(https://github.com/sbwml/luci-app-mosdns)。使用自定义配置文件,就可以配置自己的转发规则,调用自定义的规则集。该插件还可以定时更新域名规则库,降低了不少mosdns的应用门槛。但如果你只想用docker配置一套DNS解决方案,不想用openwrt这种软路由的其它功能。用这种方式实现mosdns的图形化管理和部署,显得不太划算,有种为吃一碟子醋,要包一顿饺子的感觉。

不过有个项目值得关注https://github.com/InabaKumori/MosDNS-Web-GUI。按照该项目的描述,是为mosdns设计了Web管理界面,但目前作者还没有释放安装文件包或独立部署的docker镜像。

3、MosDNS不同流行版配置文件不兼容问题

MosDNS的v4(最后一个版本v4.5.3)和v5(截止2025年5月的当前版v5.3.3),都是目前比较流行的版本。但它们的配置文件不兼容。新手不清楚有版本区别,拿到别人的配置参考,可能放到自己的环境内mosdns就无法正常启动(启动配置文件和它里面定义调用的规则集、插件等外部配置文件,都必须正确加载,否则启动报错)。

官方提供的docker容器,包括很多第三方打包的mosdns容器,启动后都要单独指定配置文件(没法做到开箱即用,直接体验软件功能)。这与mosdns的配置灵活性和多样性有关,大家做分流能调用的国内、国外、加密dns服务器就那么几个,但是每个人的网络结构不一定相同。比如,有些人的配置中除了国内、国外的基础分流之外,还配置了代理服务转发dns查询;有些第三方容器,封装了adguard+mosdns,而有些容器封装了smartdns作为mosdns的上游服务器,用来做dns缓存。这些配置拿过来,不一定适合自己的应用环境。下面提供v4、v5两个版本的基础配置,用它们做config.yaml配置文件的内容,只少能让mosdns正常启动。之后再参考别人的配置,逐步调整。

注意调整里面的addr:(v4版)或者listen:(v5版),适配自己的防火墙放行规则或docker容器端口映射,避免端口冲突导致启动失败。

4、MosDNS规则文件更新和服务重启问题

MosDNS的开发者,没有提供配置文件或规则文件变更后的自动重载功能,只能重启服务,才能让新配置和规则生效。虽然Mosdns提供了指令(mosdns service install/start/stop/uninstall/restart/status),将服务安装为系统服务,开机启动或执行stop/start/restart的方式管理服务。但包括官方容器在内,很多mosdns的容器都部署在高度精简的Apline linux中,导致这种方式无法使用。所以只用使用pkill mosdns干掉mosdns进程,再重新的服务。问题又来了,很多容器将mosdns作为pid 1的进程启动,pkill方式会导致重启,这与reboot容器在效果上就没有区别了。

另外,建议选择已经将crond启动为开机任务的的第三方容器(比如:https://github.com/caleee/mosdns),才能通过定时任务从网上下载不断更新的域名规则库文件,完成mosdns的规则自动更新。实际上,mosdns的规则来自于geoip.dat和geosite.dat,这两个不断更新的公共数据文件(二进制存储格式):

https://github.com/Loyalsoldier/geoip/releases/latest/download/geoip.dat;

https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat;

从有些参考配置中能看到(v4版),直接导入这2个数据库文件,由mosdns在运行时完成解析和分类匹配。为照顾低内存配置设备(软路由、开发板等),按照分类从两个数据文件中解析出独立的规则文件,再导入mosdns的方式更为普遍。

有2个工具可以完成对geoip.dat和geosite.dat的解析:

  • V2ray软件中的v2dat工具(openwrt luci版mosdns使用这种方式);

  • mosdns v4.5.3版主程序自带的v2dat指令;

如果在容器的alpine linux环境中使用V2ray的v2dat工具,需要安装libgcc支持库(apk add libgcc,安装完成后,验证是否已经存在文件/usr/lib/libgcc_s.so.1)。推荐使用第2种方式,参考下面这段脚本内容,利用v4.5.3版的mosdns内置指令,按类别批量解析geosite.dat:

注意调整脚本文件的执行权限,以及mosdns(v4.5.3版的存放位置)。

能坚持看到这里的读者,想必是动手能力比较强,喜欢折腾的极客们,如果你对mosdns感兴趣但还不是很熟悉,希望这篇文章能帮你少踩几个大坑。