Skip to content

luoye663/mosdns-controller

Repository files navigation

mosdns-controller

本项目基于 mosdns 的插件系统扩展 DNS 数据面,并提供面向局域网的 DNS 管理 Web UI,用于分流解析国内外域名。

功能概览

  • 动态白名单、黑名单、强制 local/remote 路由,规则发布不重启 DNS 监听。
  • 独立 local/remote DNS 缓存,黑名单检查位于缓存之前。
  • 查询审计、SQLite 统计、SSE 实时查询流,以及每次实际采纳响应的 upstream_tag
  • controller 不可用时,mosdns 仍使用最近成功持久化的规则快照继续解析。
  • 管理员 session、CSRF 防护、内部 Bearer Token 和非 root 容器部署。

Warning

本项目包含 AI 辅助生成或修订的代码。维护者会对代码进行人工审查,但不保证代码不存在缺陷、漏洞、兼容性问题或合规风险。

本项目按“现状”提供,不附带任何安全承诺、生产适用性承诺或完整安全审计保证。若你计划将其用于生产环境,请自行完成代码审阅、部署测试。

获取源码

mosdns/ 是 Git 子模块。首次克隆时使用 --recurse-submodules,可同时检出根仓库锁定的 mosdns 精确提交:

git clone --recurse-submodules https://github.com/luoye663/mosdns-controller.git
cd mosdns-controller

已克隆但未初始化子模块的仓库,执行:

git submodule update --init --recursive

更新根仓库并检出其锁定的 mosdns 版本:

git pull --ff-only
git submodule update --init --recursive

根仓库锁定具体的 mosdns 提交,保证构建可复现。mosdns 的日常开发分支为 managed-dns;仅在需要主动获取该分支最新代码时执行:

git submodule update --remote mosdns

该操作会更新根仓库记录的 mosdns 提交,提交根仓库变更前应完成相应测试并检查 git status

注意事项

禁用 systemd-resolved

Ubuntu / Debian 默认启用了systemd-resolved,会占用 127.0.0.53:53,停止方法:

停止并禁用:

systemctl stop systemd-resolved
systemctl disable systemd-resolved

项目截图

概况: 概况

查询日志: 查询日志

规则管理: 规则管理

上游DNS: 上游DNS

快速运行

DNS 服务会占用宿主机的 53/udp53/tcp,管理界面占用 8080/tcp;请先停止或迁移已有 DNS 服务,并确认这些端口未被占用。

方式一: 脚本安装

适用于使用 systemd 的 Linux amd64arm64 主机。安装脚本会自动识别架构,下载并校验 GitHub Releases 中的最新二进制包,然后安装并启动服务:

curl -fsSL https://raw.githubusercontent.com/luoye663/mosdns-controller/main/deploy/binary/install-release.sh | sudo bash

安装完成后访问 http://<部署主机IP>:8080 初始化管理员。需要安装指定版本时,使用 curl 下载脚本后通过 VERSION 环境变量执行,详见 二进制部署说明

方式二: Docker运行

Docker 部署包包含版本匹配的 docker-compose.yml、mosdns 配置、controller 配置和镜像版本文件。主机需要 Docker Engine、Docker Compose v2 和 openssl

curl -fLO https://github.com/luoye663/mosdns-controller/releases/latest/download/mosdns-manager-docker.tar.gz
curl -fLO https://github.com/luoye663/mosdns-controller/releases/latest/download/SHA256SUMS
sha256sum --check --ignore-missing SHA256SUMS
tar -xzf mosdns-manager-docker.tar.gz
cd mosdns-manager
umask 077
mkdir -p secrets
chmod 0700 secrets
openssl rand -hex 32 > secrets/mosdns_control_token
chmod 0444 secrets/mosdns_control_token
docker compose pull
docker compose up -d

部署包通过 .env 固定与 Release 对应的镜像版本,mosdns/config.yamlcontroller/config.yaml 可在启动前修改。服务就绪后访问 http://<部署主机IP>:8080。DNS 使用宿主机的 53/tcp53/udp,WebUI 使用 8080/tcp;这些端口必须未被其他服务占用。完整配置和升级方法见下方 Docker部署


方式三: Docker编译部署

1. 配置密钥和上游

在仓库根目录执行。共享 token 供 controller 与 mosdns 的内部 API 使用,必须保密且不能提交:

umask 077
mkdir -p deploy/secrets
chmod 0700 deploy/secrets
openssl rand -hex 32 > deploy/secrets/mosdns_control_token
# Compose 的 file secret 会保留此文件权限;两个非 root 容器均需读取它。
chmod 0444 deploy/secrets/mosdns_control_token

deploy/secrets/ 保持为 0700,token 文件可供容器内的非 root 服务读取,但普通宿主机用户不能访问该目录。不要将 token 写入 Compose 文件或提交到 Git。

mosdns 配置由 deploy/mosdns/config.yaml.tmpl 统一生成。

  1. 执行 make configs 会生成 Compose、本地和集成测试配置;
  2. make binary-package 会生成包内二进制配置。
  3. 首次启动后的上游管理通过 WebUI 完成,保存会原子热加载并清空对应缓存,无需重启 mosdns。

2. 构建并启动

docker build \
  --build-arg GOPROXY=https://goproxy.cn,direct \
  --tag luoye663/mosdns-manager:latest \
  mosdns
docker build \
  --build-arg GOPROXY=https://goproxy.cn,direct \
  --file controller/Dockerfile \
  --tag luoye663/mosdns-controller:latest \
  .
docker compose -f deploy/docker-compose.yml up -d
docker compose -f deploy/docker-compose.yml ps
docker compose -f deploy/docker-compose.yml logs --tail=100 mosdns controller

状态为 healthy 后,访问 http://<部署主机IP>:8080。仅 53/udp53/tcp8080/tcp 映射到宿主机;mosdns API 9091 和 controller ingest 8081 仅在 Compose 内部网络开放。

如果需要通过 SOCKS5 代理拉取基础镜像或下载构建依赖时,可在运行 Docker 命令的终端设置:

export ALL_PROXY=socks5://127.0.0.1:10808
docker build --build-arg GOPROXY=https://goproxy.cn,direct --tag mosdns-manager-mosdns:latest mosdns
docker build --build-arg GOPROXY=https://goproxy.cn,direct --file controller/Dockerfile --tag mosdns-manager-controller:latest .
docker compose -f deploy/docker-compose.yml up -d

停止服务但保留规则快照、缓存和 SQLite 数据:

docker compose -f deploy/docker-compose.yml down

方式四:手动编译部署

deploy/binary/ 保存原生 systemd 部署所需的模板:服务文件、配置、安装脚本与说明。

make binary-package 将它们与当前平台的 mosdns、嵌入 WebUI 的 controller 二进制一起生成至 deploy/binary/package/,同时创建可传输的 .tar.gz;生成物被 Git 忽略,不含 token、SQLite 数据、缓存或规则快照。

npm --prefix web ci
make binary-package
# 交叉编译示例:make binary-package BINARY_GOOS=linux BINARY_GOARCH=arm64
make binary-copy BINARY_HOST=root@dns-host

在目标机进入复制后的目录并安装:

sudo ./install.sh
sudo systemctl start mosdns.service mosdns-controller.service

额外一些说明

安装脚本创建最小权限服务用户、运行数据目录和共享 token,并将 mosdns.servicemosdns-controller.service 安装到 /etc/systemd/system/

远程 DoH 默认使用 Cloudflare(https://cloudflare-dns.com/dns-query);DNS 53/tcp53/udp 与 WebUI 8080/tcp 对外监听,mosdns API 9091 和 controller ingest 8081 仅监听 127.0.0.1。详细目录结构与升级说明见 deploy/binary/README.md

首次启动后,访问 http://<部署主机IP>:8080 初始化管理员,并使用 curl -fsS http://127.0.0.1:8080/health/readydig @127.0.0.1 example.com Adig @127.0.0.1 example.com A +tcp 验证服务。

升级前备份 /etc/mosdns-manager/var/lib/mosdns/var/lib/mosdns-controller;详见 升级说明恢复说明

查看二进制部署的服务日志:

# 实时跟随两个服务
sudo journalctl -fu mosdns.service -u mosdns-controller.service
# 查看本次启动后的日志
sudo journalctl -b -u mosdns.service -u mosdns-controller.service
# 仅查看近期错误
sudo journalctl -p err..alert -u mosdns.service -u mosdns-controller.service

安装后操作

创建首个管理员

首次访问 http://<部署主机IP>:8080 时,WebUI 会显示管理员初始化页面。设置用户名和至少 8 个字符的密码后会自动登录。

也可使用 CLI 初始化。命令中的密码会出现在 shell 历史记录中,生产环境应使用受控终端并在执行后清理历史记录。

docker compose -f deploy/docker-compose.yml exec controller \
  controller create-admin \
  -config /etc/mosdns-controller/config.yaml \
  -username admin \
  -password '请替换为高强度密码'

管理员只能初始化一次;完成后首次初始化接口会关闭。首次使用前,应先在 WebUI 确认系统状态和当前规则版本,再让局域网客户端使用该主机作为 DNS 服务器。


## 本地编译与测试

开发环境需要 Go `1.26.5` 或兼容版本、Node.js 22、npm 和 Docker Compose。mosdns 的 `go.mod` 基线为 Go `1.24.9`,controller 为 Go `1.25.0`。

安装 WebUI 依赖后,可执行完整的本地构建检查:

```bash
npm --prefix web ci
make test
make build
make race
make lint

常用目标:

命令 用途
make test Go 单元测试与 WebUI 类型检查
make build 编译 mosdns、controller,并构建 WebUI 静态资源
make race dynamic_rule_engine、query_audit 和 controller 的 race 检查
make lint Go vet 与 WebUI 类型检查
make web-embed 构建 WebUI 并同步到 controller 的 go:embed 静态目录
make compose-up 前台构建并启动完整 Compose 环境
make compose-down 停止 Compose 环境并保留命名卷

如需得到本机可直接执行的二进制文件:

mkdir -p bin
go -C mosdns build -o ../bin/mosdns .
go -C controller build -o ../bin/controller ./cmd/controller

本地运行完整服务(开发时)

deploy/local/ 提供不依赖 Docker 的开发配置。它只监听本机回环地址,端口为 DNS 5353、WebUI/API 18080、内部 ingest 18081、mosdns API 19091,所有本地数据均写入被 Git 忽略的 .local/。配置中的公开 DoH 仅用于开发功能验证,不应用于生产。

先执行初始化,然后在两个终端分别运行以下命令:

make local-init
make local-mosdns
make local-controller

也可使用 make local-up 同时启动两项服务。服务启动后访问 http://127.0.0.1:18080 创建首个管理员;也可以在第三个终端运行 make local-create-admin。本地 DNS 验证命令为 dig @127.0.0.1 -p 5353 example.com A

make local-clean 仅删除 .local/ 下的本机开发数据库、缓存、快照和 token,不会影响 Docker Compose 的命名卷。WebUI 的生产静态资源会在 controller/Dockerfile 构建镜像时嵌入 controller;执行 npm --prefix web run dev 后,Vite 会将 /api 请求反代到本地 controller http://127.0.0.1:18080。可通过环境变量覆盖后端地址,例如 VITE_API_PROXY_TARGET=http://127.0.0.1:8080 npm --prefix web run dev

集成环境验证

集成 Compose 会启动两个本地 CoreDNS mock upstream,并仅开放 5353/udp5353/tcp。它不需要真实远程 DoH,适合在迁移 53 前验证 DNS 路径:

umask 077
mkdir -p deploy/secrets
chmod 0700 deploy/secrets
openssl rand -hex 32 > deploy/secrets/mosdns_control_token
chmod 0444 deploy/secrets/mosdns_control_token
make configs
docker compose -f deploy/docker-compose.integration.yml --profile integration up --build

另一个不依赖 Docker 的真实 mosdns 集成测试入口:

go -C mosdns test -v ./tests/integration

更多测试范围和清理方式见 tests/integration/README.md

配置、数据与运维

  • 生产 Compose:deploy/docker-compose.yml
  • mosdns 配置模板:deploy/mosdns/config.yaml.tmpl;运行配置由 make configs 或 Release 部署包生成。
  • controller 配置模板:deploy/controller/config.yaml.tmpl;运行配置由 make configs 或 Release 部署包生成。
  • 持久化数据:Compose 命名卷 mosdns-state(快照和缓存)与 controller-state(SQLite)。
  • 密钥目录:deploy/secrets/,只保留 .gitkeep,实际 token 被 Git 忽略。
  • 运维、备份恢复、升级与故障诊断分别见 operationsrecoveryupgradetroubleshooting

版本与许可证

About

基于 mosdns 实现局域网 DNS 分流与可视化管理,用于分流解析国内外域名。

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages