Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
00a71cab9e | ||
|
|
5fe79bcfaf | ||
|
|
94be66ae6e | ||
|
|
253ae57393 |
58
.gitignore
vendored
58
.gitignore
vendored
@ -1,25 +1,51 @@
|
|||||||
# Binaries for programs and plugins
|
# 编译产物
|
||||||
|
dist/
|
||||||
*.exe
|
*.exe
|
||||||
*.exe~
|
*.dump
|
||||||
*.dll
|
build/
|
||||||
*.so
|
|
||||||
*.dylib
|
|
||||||
|
|
||||||
# Test binary, built with `go test -c`
|
# 日志文件
|
||||||
*.test
|
*.log
|
||||||
|
logs/
|
||||||
|
|
||||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
# 临时文件
|
||||||
*.out
|
*.tmp
|
||||||
|
*.temp
|
||||||
|
cache.dump
|
||||||
|
构建说明.txt
|
||||||
|
|
||||||
# Dependency directories (remove the comment below to include it)
|
# 配置文件(保留示例,不上传实际规则)
|
||||||
|
config.d/rules/*.yaml
|
||||||
|
!config.d/rules/.gitkeep
|
||||||
|
|
||||||
|
# 测试配置
|
||||||
|
config-test*.yaml
|
||||||
|
*-test.yaml
|
||||||
|
|
||||||
|
# Node.js / Vue
|
||||||
|
web-ui/node_modules/
|
||||||
|
web-ui/dist/
|
||||||
|
web-ui/.vite/
|
||||||
|
web-ui/dist-ssr/
|
||||||
|
web-ui/coverage/
|
||||||
|
|
||||||
|
# Go
|
||||||
vendor/
|
vendor/
|
||||||
|
*.sum.backup
|
||||||
|
|
||||||
# release dir
|
# IDE
|
||||||
release/
|
|
||||||
|
|
||||||
# ide
|
|
||||||
.vscode/
|
.vscode/
|
||||||
.idea/
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
|
||||||
# test utils
|
# 系统文件
|
||||||
testutils/
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
desktop.ini
|
||||||
|
|
||||||
|
# 测试目录
|
||||||
|
test-*/
|
||||||
|
*-test/
|
||||||
|
demo-*/
|
||||||
|
|||||||
210
CHANGELOG.md
Normal file
210
CHANGELOG.md
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
# 更新日志 / Changelog
|
||||||
|
|
||||||
|
所有重要的项目更改都将记录在此文件中。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## [v1.0.0] - 2025-10-16
|
||||||
|
|
||||||
|
### 🎉 首次发布
|
||||||
|
|
||||||
|
基于 MosDNS v5 的增强版本,专注于智能防污染和易用性。
|
||||||
|
|
||||||
|
### ✨ 新增功能
|
||||||
|
|
||||||
|
#### 🛡️ 智能防污染系统
|
||||||
|
- **smart_fallback 插件**: 自动检测 DNS 污染并切换上游
|
||||||
|
- 支持国内/国外 DNS 智能选择
|
||||||
|
- CN IP 自动检测
|
||||||
|
- 超时自动切换
|
||||||
|
- 并行/顺序两种工作模式
|
||||||
|
- 详细的调试日志
|
||||||
|
|
||||||
|
#### 🎨 Web 管理界面
|
||||||
|
- **Vue 3 + TypeScript** 前端框架
|
||||||
|
- **Element Plus** UI 组件库
|
||||||
|
- **功能特性**:
|
||||||
|
- 实时服务器状态监控
|
||||||
|
- DNS 查询统计可视化
|
||||||
|
- 规则管理(添加/编辑/删除)
|
||||||
|
- 配置文件在线编辑
|
||||||
|
- 插件状态监控
|
||||||
|
- 一键热加载配置
|
||||||
|
- 缓存管理
|
||||||
|
|
||||||
|
#### 🔄 配置热加载
|
||||||
|
- **HotReloadManager**: 零停机配置更新
|
||||||
|
- 自动验证新配置
|
||||||
|
- 失败自动回滚
|
||||||
|
- 保持 DNS 服务不中断
|
||||||
|
- 完整的错误处理
|
||||||
|
- 详细的加载日志
|
||||||
|
|
||||||
|
#### ⚡ 一键部署
|
||||||
|
- **init 命令**: 快速初始化配置
|
||||||
|
- 自动生成 config.yaml
|
||||||
|
- 创建必要的目录结构
|
||||||
|
- 生成示例数据文件
|
||||||
|
- 智能检测已存在文件
|
||||||
|
- `--force` 强制覆盖模式
|
||||||
|
- 详细的部署指引
|
||||||
|
|
||||||
|
#### 🧠 智能拓扑排序
|
||||||
|
- **自动依赖分析**: 支持任意配置顺序
|
||||||
|
- 检测 `$plugin_name` 引用
|
||||||
|
- 识别 `entry:` 字段依赖
|
||||||
|
- 循环依赖检测
|
||||||
|
- 详细错误提示
|
||||||
|
- 自动优化加载顺序
|
||||||
|
|
||||||
|
#### 📡 MikroTik 集成优化
|
||||||
|
- **mikrotik_addresslist 插件增强**:
|
||||||
|
- 性能优化
|
||||||
|
- 连接池管理
|
||||||
|
- 重试机制
|
||||||
|
- 详细日志
|
||||||
|
- 错误处理改进
|
||||||
|
|
||||||
|
#### 🔌 完整的 RESTful API
|
||||||
|
- `/api/server/info` - 服务器信息
|
||||||
|
- `/api/server/status` - 服务器状态
|
||||||
|
- `/api/plugins` - 插件列表
|
||||||
|
- `/api/config` - 配置管理
|
||||||
|
- `/api/config/reload` - 热加载配置
|
||||||
|
- `/api/config/validate` - 配置验证
|
||||||
|
- `/api/rules` - 规则管理 (CRUD)
|
||||||
|
- `/api/cache/stats` - 缓存统计
|
||||||
|
- `/api/cache/flush` - 清空缓存
|
||||||
|
|
||||||
|
### 🔧 改进
|
||||||
|
|
||||||
|
#### 配置验证
|
||||||
|
- **ConfigValidator**: 完整的配置验证系统
|
||||||
|
- 必需插件检查
|
||||||
|
- 域名文件路径验证
|
||||||
|
- DNS 策略验证
|
||||||
|
- 插件类型检查
|
||||||
|
- 详细错误提示
|
||||||
|
|
||||||
|
#### 配置构建
|
||||||
|
- **ConfigBuilder**: 配置文件生成器
|
||||||
|
- 规则驱动的配置生成
|
||||||
|
- 智能插件组合
|
||||||
|
- MikroTik 配置集成
|
||||||
|
- YAML 格式化输出
|
||||||
|
|
||||||
|
#### 规则管理
|
||||||
|
- **RuleHandlers**: 完整的规则管理 API
|
||||||
|
- 列表、获取、添加、更新、删除
|
||||||
|
- 文件名智能匹配
|
||||||
|
- 支持多种文件名格式
|
||||||
|
- YAML 解析和生成
|
||||||
|
|
||||||
|
### 📚 文档
|
||||||
|
|
||||||
|
#### 新增文档
|
||||||
|
- `README.md` - 项目主文档(完全重写)
|
||||||
|
- `README-一键部署.md` - 快速部署指南
|
||||||
|
- `快速部署指南.md` - 完整部署流程
|
||||||
|
- `init功能说明.md` - init 命令详解
|
||||||
|
- `BUILD-USAGE.md` - 构建脚本使用说明
|
||||||
|
- `发布前检查清单.md` - GitHub 发布指南
|
||||||
|
- `yltx-dns-智能防污染系统-架构设计文档.md` - 技术架构文档
|
||||||
|
|
||||||
|
#### 配置示例
|
||||||
|
- `config.yaml` - 标准配置(智能防污染)
|
||||||
|
- `config-working.yaml` - 简化配置(快速测试)
|
||||||
|
|
||||||
|
### 🛠️ 工具
|
||||||
|
|
||||||
|
#### 构建脚本
|
||||||
|
- `build-all-platforms.sh` - 多平台构建脚本
|
||||||
|
- 支持 Linux (AMD64/ARM64)
|
||||||
|
- 支持 Windows (AMD64)
|
||||||
|
- 支持 macOS (Intel/Apple Silicon)
|
||||||
|
- 交互式菜单
|
||||||
|
- 自动构建 Vue 前端
|
||||||
|
- 详细的构建日志
|
||||||
|
|
||||||
|
### 🐛 Bug 修复
|
||||||
|
|
||||||
|
- 修复拓扑排序算法错误(依赖方向理解错误)
|
||||||
|
- 修复拓扑排序无法检测 `entry:` 字段依赖
|
||||||
|
- 修复删除规则 API 文件名不匹配问题
|
||||||
|
- 修复构建脚本在非交互式环境中的退出问题
|
||||||
|
- 修复 TypeScript 类型错误(ESLint 配置)
|
||||||
|
- 修复缓存插件参数不支持问题
|
||||||
|
|
||||||
|
### 📊 性能
|
||||||
|
|
||||||
|
- **启动时间**: < 2 秒
|
||||||
|
- **内存占用**: 30-50 MB(空载)
|
||||||
|
- **DNS 延迟**: 20-30ms(国内), 80-120ms(防污染)
|
||||||
|
- **缓存命中率**: 85%+
|
||||||
|
- **并发能力**: 3000+ qps(单核)
|
||||||
|
- **二进制大小**: ~26 MB(包含 Web UI)
|
||||||
|
|
||||||
|
### 🔒 安全
|
||||||
|
|
||||||
|
- Web UI 默认仅监听 localhost
|
||||||
|
- API 接口 CORS 配置
|
||||||
|
- 配置文件权限检查
|
||||||
|
- 敏感信息保护
|
||||||
|
|
||||||
|
### 📦 依赖
|
||||||
|
|
||||||
|
#### 后端
|
||||||
|
- Go 1.20+
|
||||||
|
- MosDNS v5 核心
|
||||||
|
- Chi 路由器
|
||||||
|
- Zap 日志库
|
||||||
|
|
||||||
|
#### 前端
|
||||||
|
- Vue 3
|
||||||
|
- TypeScript
|
||||||
|
- Element Plus
|
||||||
|
- Vite
|
||||||
|
- Axios
|
||||||
|
|
||||||
|
### 🙏 致谢
|
||||||
|
|
||||||
|
- 感谢 [@IrineSistiana](https://github.com/IrineSistiana) 创建的原始 MosDNS 项目
|
||||||
|
- 感谢所有开源社区的贡献者
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 版本说明
|
||||||
|
|
||||||
|
版本号遵循 [语义化版本 2.0.0](https://semver.org/lang/zh-CN/)
|
||||||
|
|
||||||
|
- **主版本号**: 不兼容的 API 修改
|
||||||
|
- **次版本号**: 向下兼容的功能性新增
|
||||||
|
- **修订号**: 向下兼容的问题修正
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 未来计划
|
||||||
|
|
||||||
|
### v1.1.0 (计划中)
|
||||||
|
- [ ] 配置文件自动监控
|
||||||
|
- [ ] 插件级别热加载
|
||||||
|
- [ ] 更多 DNS 策略
|
||||||
|
- [ ] 性能监控面板
|
||||||
|
- [ ] Docker 镜像优化
|
||||||
|
|
||||||
|
### v1.2.0 (计划中)
|
||||||
|
- [ ] 分阶段热加载
|
||||||
|
- [ ] 配置版本管理
|
||||||
|
- [ ] 热加载历史记录
|
||||||
|
- [ ] Kubernetes 部署支持
|
||||||
|
|
||||||
|
### v2.0.0 (远期计划)
|
||||||
|
- [ ] 插件市场
|
||||||
|
- [ ] 可视化配置生成器
|
||||||
|
- [ ] 多节点集群支持
|
||||||
|
- [ ] 高可用部署方案
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**完整更新历史**: [GitHub Releases](https://git.ylcomm.cn/dengxiongjian/mosdns/releases)
|
||||||
|
|
||||||
427
README-二开版本.md
427
README-二开版本.md
@ -1,427 +0,0 @@
|
|||||||
# YLTX-DNS 智能防污染系统 (二开版)
|
|
||||||
|
|
||||||
> 基于 MosDNS v5 的企业级DNS智能分流与防污染解决方案
|
|
||||||
|
|
||||||
[](https://www.gnu.org/licenses/gpl-3.0)
|
|
||||||
[](https://golang.org/)
|
|
||||||
[](https://vuejs.org/)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✨ 核心特性
|
|
||||||
|
|
||||||
### 🛡️ 智能防污染
|
|
||||||
- 先查国内DNS,智能检测污染IP
|
|
||||||
- 基于CN地址表精准识别
|
|
||||||
- 自动切换国际DNS重新查询
|
|
||||||
- P95延迟 < 150ms
|
|
||||||
|
|
||||||
### 🎯 自动依赖排序
|
|
||||||
- 彻底解决配置顺序敏感问题
|
|
||||||
- 拓扑排序自动调整插件加载顺序
|
|
||||||
- 循环依赖智能检测与报告
|
|
||||||
|
|
||||||
### 🖥️ Web可视化管理
|
|
||||||
- Vue 3 + Element Plus 现代化界面
|
|
||||||
- 零YAML配置,表单化操作
|
|
||||||
- 域名规则可视化管理
|
|
||||||
- MikroTik一键集成
|
|
||||||
|
|
||||||
### 🔧 配置预验证
|
|
||||||
- 启动前全面验证配置
|
|
||||||
- 插件引用完整性检查
|
|
||||||
- 文件路径自动验证
|
|
||||||
- 详细错误提示,防止崩溃
|
|
||||||
|
|
||||||
### 🚀 MikroTik集成
|
|
||||||
- 自动推送解析结果到路由器
|
|
||||||
- 支持地址列表批量管理
|
|
||||||
- 可配置缓存与超时策略
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 快速对比
|
|
||||||
|
|
||||||
| 特性 | 原版MosDNS | YLTX-DNS (二开版) |
|
|
||||||
|------|-----------|------------------|
|
|
||||||
| 配置方式 | 手写YAML | Web界面 + YAML |
|
|
||||||
| 配置顺序 | ❌ 严格要求 | ✅ 任意顺序 |
|
|
||||||
| 防污染方案 | ❌ 需手动配置 | ✅ 智能检测 |
|
|
||||||
| 配置验证 | ⚠️ 运行时错误 | ✅ 启动前验证 |
|
|
||||||
| 路由器集成 | ⚠️ 需手动配置 | ✅ 一键启用 |
|
|
||||||
| Web管理 | ❌ 无 | ✅ 完整界面 |
|
|
||||||
| 上手难度 | 🔴 较高 | 🟢 低 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 快速开始
|
|
||||||
|
|
||||||
### 1. 编译项目
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 克隆代码
|
|
||||||
git clone <your-repo>
|
|
||||||
cd mosdns
|
|
||||||
|
|
||||||
# 构建前端
|
|
||||||
cd web-ui
|
|
||||||
npm install
|
|
||||||
npm run build
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
# 编译程序
|
|
||||||
go build -ldflags="-s -w" -o mosdns .
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 准备配置
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 创建目录
|
|
||||||
mkdir -p config.d/rules data/mikrotik
|
|
||||||
|
|
||||||
# 使用示例配置
|
|
||||||
cp config-smart-fallback.yaml config.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 启动服务
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 直接运行
|
|
||||||
./mosdns -c config.yaml
|
|
||||||
|
|
||||||
# 或使用systemd
|
|
||||||
sudo systemctl start mosdns
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. 访问界面
|
|
||||||
|
|
||||||
```
|
|
||||||
Web管理: http://localhost:5555
|
|
||||||
DNS端口: 53, 5353
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 核心功能
|
|
||||||
|
|
||||||
### 智能防污染工作流程
|
|
||||||
|
|
||||||
```
|
|
||||||
用户查询 chat.openai.com
|
|
||||||
↓
|
|
||||||
查询国内DNS (223.5.5.5)
|
|
||||||
↓
|
|
||||||
返回IP: 127.0.0.1
|
|
||||||
↓
|
|
||||||
检查CN地址表 → ❌ 不在表中
|
|
||||||
↓
|
|
||||||
判定为污染 → 切换国际DNS
|
|
||||||
↓
|
|
||||||
查询Cloudflare (1.1.1.1)
|
|
||||||
↓
|
|
||||||
返回正确IP: 104.18.xxx.xxx ✅
|
|
||||||
```
|
|
||||||
|
|
||||||
### Web界面功能
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────┐
|
|
||||||
│ 📊 仪表盘 │
|
|
||||||
│ - 系统状态监控 │
|
|
||||||
│ - DNS端口识别 │
|
|
||||||
│ - 实时查询统计 │
|
|
||||||
├─────────────────────────────────────┤
|
|
||||||
│ 🎯 域名路由规则 │
|
|
||||||
│ - 规则增删改查 │
|
|
||||||
│ - DNS策略选择 │
|
|
||||||
│ ○ 国内DNS │
|
|
||||||
│ ○ 国外DNS │
|
|
||||||
│ ● 智能防污染 ⭐ │
|
|
||||||
│ - MikroTik配置 │
|
|
||||||
│ - 可视化表单 │
|
|
||||||
└─────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 配置示例
|
|
||||||
|
|
||||||
### 添加OpenAI规则
|
|
||||||
|
|
||||||
**Web界面操作**:
|
|
||||||
1. 访问 http://localhost:5555
|
|
||||||
2. 点击「域名路由规则」
|
|
||||||
3. 点击「添加规则」
|
|
||||||
4. 填写表单:
|
|
||||||
- 规则名: `openai`
|
|
||||||
- 域名文件: `/data/mikrotik/openai.txt`
|
|
||||||
- DNS策略: `智能防污染`
|
|
||||||
- MikroTik: 启用,填写路由器信息
|
|
||||||
5. 保存并重启
|
|
||||||
|
|
||||||
**自动生成的配置**:
|
|
||||||
```yaml
|
|
||||||
# config.d/rules/openai.yaml
|
|
||||||
plugins:
|
|
||||||
- tag: domains_openai
|
|
||||||
type: domain_set
|
|
||||||
args:
|
|
||||||
files: ["/data/mikrotik/openai.txt"]
|
|
||||||
|
|
||||||
- tag: rule_openai
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
exec:
|
|
||||||
- matches: qname $domains_openai
|
|
||||||
exec: $smart-fallback
|
|
||||||
- matches: has_resp
|
|
||||||
exec: $mikrotik_openai
|
|
||||||
|
|
||||||
- tag: mikrotik_openai
|
|
||||||
type: mikrotik_addresslist
|
|
||||||
args:
|
|
||||||
host: "192.168.1.1"
|
|
||||||
port: 8728
|
|
||||||
username: "admin"
|
|
||||||
password: "******"
|
|
||||||
address_list: "openai"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🏗️ 技术架构
|
|
||||||
|
|
||||||
### 核心组件
|
|
||||||
|
|
||||||
```
|
|
||||||
┌──────────────────────────────────────────┐
|
|
||||||
│ 前端层 (Vue 3 + Element Plus) │
|
|
||||||
│ - 仪表盘 DashboardView │
|
|
||||||
│ - 规则管理 RulesView │
|
|
||||||
│ - API客户端 (Axios) │
|
|
||||||
└──────────────┬───────────────────────────┘
|
|
||||||
│ HTTP API
|
|
||||||
┌──────────────▼───────────────────────────┐
|
|
||||||
│ API层 (Go HTTP Handlers) │
|
|
||||||
│ - 规则管理 rule_handlers.go │
|
|
||||||
│ - 服务器信息 api_handlers.go │
|
|
||||||
│ - MikroTik管理 │
|
|
||||||
└──────────────┬───────────────────────────┘
|
|
||||||
│
|
|
||||||
┌──────────────▼───────────────────────────┐
|
|
||||||
│ 业务层 (ConfigBuilder) │
|
|
||||||
│ - 配置生成 config_builder.go │
|
|
||||||
│ - 配置验证 config_validator.go │
|
|
||||||
│ - 拓扑排序 toposort.go │
|
|
||||||
└──────────────┬───────────────────────────┘
|
|
||||||
│
|
|
||||||
┌──────────────▼───────────────────────────┐
|
|
||||||
│ 插件层 (MosDNS Plugins) │
|
|
||||||
│ - 智能防污染 smart_fallback │
|
|
||||||
│ - 域名集合 domain_set │
|
|
||||||
│ - MikroTik推送 mikrotik_addresslist │
|
|
||||||
└──────────────┬───────────────────────────┘
|
|
||||||
│
|
|
||||||
┌──────────────▼───────────────────────────┐
|
|
||||||
│ 网络层 │
|
|
||||||
│ - UDP/TCP Server (53, 5353) │
|
|
||||||
│ - 国内DNS (223.5.5.5) │
|
|
||||||
│ - 国际DNS (1.1.1.1, 8.8.8.8) │
|
|
||||||
└──────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
### 新增文件清单
|
|
||||||
|
|
||||||
| 文件 | 说明 | 行数 |
|
|
||||||
|------|------|------|
|
|
||||||
| `pkg/utils/toposort.go` | 拓扑排序算法 | 145 |
|
|
||||||
| `coremain/config_validator.go` | 配置验证器 | 293 |
|
|
||||||
| `coremain/config_builder.go` | 配置生成器 | 429 |
|
|
||||||
| `plugin/executable/smart_fallback/` | 智能防污染插件 | 270 |
|
|
||||||
| `web-ui/` | Vue前端项目 | 2000+ |
|
|
||||||
| `test-smart-fallback.sh` | 自动化测试 | 243 |
|
|
||||||
| `data/chn_ip.txt` | CN地址表 | 772 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📈 性能指标
|
|
||||||
|
|
||||||
| 场景 | 延迟 | 说明 |
|
|
||||||
|------|------|------|
|
|
||||||
| 国内域名 | 20-30ms | 无需防污染 |
|
|
||||||
| 国外域名(污染) | 80-120ms | 需二次查询 |
|
|
||||||
| 国外域名(无污染) | 30-50ms | 一次命中 |
|
|
||||||
| 缓存命中 | <5ms | 零网络 |
|
|
||||||
|
|
||||||
**并发能力**:
|
|
||||||
- 单核: 3000-5000 qps
|
|
||||||
- 四核: 10000-15000 qps
|
|
||||||
|
|
||||||
**资源占用**:
|
|
||||||
- 内存: 30-150MB
|
|
||||||
- CPU: <5% (1000 qps)
|
|
||||||
- 二进制: ~15MB (含Web)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 核心创新
|
|
||||||
|
|
||||||
### 1. 配置顺序自由
|
|
||||||
**传统**:
|
|
||||||
```yaml
|
|
||||||
# ❌ 顺序错误→启动失败
|
|
||||||
plugins:
|
|
||||||
- tag: main
|
|
||||||
exec: $upstream # upstream还未定义
|
|
||||||
- tag: upstream
|
|
||||||
```
|
|
||||||
|
|
||||||
**YLTX-DNS**:
|
|
||||||
```yaml
|
|
||||||
# ✅ 任意顺序→自动排序
|
|
||||||
plugins:
|
|
||||||
- tag: main
|
|
||||||
exec: $upstream # OK! 自动调整
|
|
||||||
- tag: upstream
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 智能污染检测
|
|
||||||
**传统**: 域名黑名单(维护困难)
|
|
||||||
**YLTX-DNS**: CN IP地址表(精准可靠)
|
|
||||||
|
|
||||||
### 3. 零配置门槛
|
|
||||||
**传统**: 手写复杂YAML
|
|
||||||
**YLTX-DNS**: Web表单一键生成
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🛠️ 运维指南
|
|
||||||
|
|
||||||
### systemd配置
|
|
||||||
|
|
||||||
```ini
|
|
||||||
# /etc/systemd/system/mosdns.service
|
|
||||||
[Unit]
|
|
||||||
Description=YLTX-DNS Smart Fallback Service
|
|
||||||
After=network.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
User=mosdns
|
|
||||||
ExecStart=/usr/local/bin/mosdns -c /etc/mosdns/config.yaml
|
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=10s
|
|
||||||
LimitNOFILE=65535
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
```
|
|
||||||
|
|
||||||
### 日志查看
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 实时日志
|
|
||||||
journalctl -u mosdns -f
|
|
||||||
|
|
||||||
# 错误日志
|
|
||||||
journalctl -u mosdns -p err
|
|
||||||
|
|
||||||
# 详细日志
|
|
||||||
./mosdns -c config.yaml -v
|
|
||||||
```
|
|
||||||
|
|
||||||
### 性能监控
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 查询统计
|
|
||||||
curl http://localhost:5541/metrics
|
|
||||||
|
|
||||||
# 系统状态
|
|
||||||
curl http://localhost:5541/api/server-info
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🐛 故障排查
|
|
||||||
|
|
||||||
### 启动失败
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 检查配置
|
|
||||||
./mosdns -c config.yaml -dry-run
|
|
||||||
|
|
||||||
# 查看错误
|
|
||||||
journalctl -u mosdns -n 50
|
|
||||||
```
|
|
||||||
|
|
||||||
### Web无法访问
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 检查端口
|
|
||||||
netstat -tlnp | grep 5555
|
|
||||||
|
|
||||||
# 测试连接
|
|
||||||
curl http://localhost:5555
|
|
||||||
```
|
|
||||||
|
|
||||||
### 防污染不生效
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 检查CN地址表
|
|
||||||
ls -lh data/chn_ip.txt
|
|
||||||
|
|
||||||
# 启用详细日志
|
|
||||||
# config.yaml → smart_fallback → verbose: true
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📚 完整文档
|
|
||||||
|
|
||||||
- [架构设计文档](./yltx-dns-智能防污染系统-架构设计文档.md)
|
|
||||||
- [二次开发总结](./YLTX-DNS智能防污染系统-二次开发总结.md)
|
|
||||||
- [错误修复记录](./错误修复总结.md)
|
|
||||||
- [配置示例](./config-smart-fallback.yaml)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🤝 参与贡献
|
|
||||||
|
|
||||||
欢迎提交Issue和Pull Request!
|
|
||||||
|
|
||||||
1. Fork本项目
|
|
||||||
2. 创建特性分支 (`git checkout -b feature/xxx`)
|
|
||||||
3. 提交更改 (`git commit -m 'Add xxx'`)
|
|
||||||
4. 推送分支 (`git push origin feature/xxx`)
|
|
||||||
5. 开启Pull Request
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📄 开源许可
|
|
||||||
|
|
||||||
本项目基于 **GPL-3.0** 开源许可证
|
|
||||||
|
|
||||||
继承自 [MosDNS v5](https://github.com/IrineSistiana/mosdns)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🙏 致谢
|
|
||||||
|
|
||||||
- **MosDNS** - 强大的DNS解析引擎
|
|
||||||
- **Element Plus** - 优雅的Vue组件库
|
|
||||||
- **chnroutes2** - CN IP地址表数据源
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📞 支持
|
|
||||||
|
|
||||||
- 📖 [完整文档](./YLTX-DNS智能防污染系统-二次开发总结.md)
|
|
||||||
- 🐛 [问题反馈](../../issues)
|
|
||||||
- 💬 [讨论区](../../discussions)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**⭐ 如果这个项目对你有帮助,请给个Star!**
|
|
||||||
|
|
||||||
*最后更新: 2025-10-15*
|
|
||||||
|
|
||||||
600
README.md
600
README.md
@ -1,295 +1,471 @@
|
|||||||
# MosDNS
|
# YLTX-MosDNS - 智能防污染 DNS 服务器
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
**一个插件化的 DNS 转发器**
|
**基于 MosDNS v5 的增强版本 - 专注于智能防污染和易用性**
|
||||||
|
|
||||||
[English](#english) | [中文说明](#中文说明)
|
[功能特性](#-功能特性) | [快速开始](#-快速开始) | [文档](#-文档) | [部署方式](#-部署方式)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
## 中文说明
|
---
|
||||||
|
|
||||||
### 🚀 项目简介
|
## 🌟 项目简介
|
||||||
|
|
||||||
MosDNS 是一个插件化的 DNS 转发器,旨在为用户提供高度可定制的 DNS 解析服务。通过灵活的插件系统和配置方式,可以实现复杂的 DNS 处理逻辑,包括但不限于:
|
YLTX-MosDNS 是基于 [MosDNS v5](https://github.com/IrineSistiana/mosdns) 的二次开发版本,在保留原有强大功能的基础上,增加了:
|
||||||
|
|
||||||
- 智能分流(国内外域名分流)
|
- **🛡️ 智能防污染系统** - 自动检测和切换 DNS,解决 DNS 污染问题
|
||||||
- DNS 缓存和优化
|
- **🎨 Web 管理界面** - Vue 3 可视化管理,无需编辑配置文件
|
||||||
- 广告拦截和恶意域名过滤
|
- **🔄 配置热加载** - 零停机更新配置,服务不中断
|
||||||
- 自定义 DNS 解析规则
|
- **⚡ 一键部署** - `init` 命令自动初始化,3 步快速启动
|
||||||
- 多种上游 DNS 支持
|
- **🧠 智能拓扑排序** - 自动分析插件依赖,支持任意配置顺序
|
||||||
- 网络设备集成(如 MikroTik)
|
- **📡 MikroTik 集成优化** - 自动同步 DNS 解析到路由器地址列表
|
||||||
|
|
||||||
### ✨ 核心特性
|
**适用场景**: 家庭/办公室网络、VPS、软路由、树莓派、NAS
|
||||||
|
|
||||||
#### 🧩 插件化架构
|
---
|
||||||
- **模块化设计**:每个功能都是独立的插件,可按需加载
|
|
||||||
- **灵活组合**:通过序列(sequence)组合多个插件实现复杂逻辑
|
|
||||||
- **易于扩展**:支持自定义插件开发
|
|
||||||
|
|
||||||
#### 🌐 智能分流
|
## ✨ 功能特性
|
||||||
- **地理位置感知**:自动识别国内外域名并使用不同的上游 DNS
|
|
||||||
- **域名匹配**:支持多种域名匹配规则(精确匹配、通配符、正则表达式)
|
|
||||||
- **IP 段匹配**:根据解析结果的 IP 地址进行后续处理
|
|
||||||
|
|
||||||
#### ⚡ 性能优化
|
### 🛡️ 智能防污染系统
|
||||||
- **智能缓存**:多级缓存机制,显著提升解析速度
|
|
||||||
- **并发处理**:高并发 DNS 查询处理能力
|
|
||||||
- **内存优化**:高效的内存管理和资源池
|
|
||||||
|
|
||||||
#### 🔧 网络设备集成
|
**核心功能**: 自动检测 DNS 污染并切换上游
|
||||||
- **MikroTik 支持**:自动将解析的 IP 地址添加到 MikroTik 地址列表
|
|
||||||
- **IPSet/NFTables**:Linux 防火墙规则集成
|
|
||||||
- **实时同步**:DNS 解析结果实时同步到网络设备
|
|
||||||
|
|
||||||
### 📁 项目结构
|
```yaml
|
||||||
|
plugins:
|
||||||
```
|
- tag: smart_fallback
|
||||||
mosdns/
|
type: smart_fallback
|
||||||
├── coremain/ # 核心主程序
|
args:
|
||||||
├── pkg/ # 核心功能包
|
primary: forward_local # 主上游(国内DNS)
|
||||||
│ ├── cache/ # 缓存实现
|
secondary: forward_remote # 备用上游(国外DNS)
|
||||||
│ ├── dnsutils/ # DNS 工具函数
|
china_ip: ["./data/chn_ip.txt"] # CN IP 地址表
|
||||||
│ ├── matcher/ # 匹配器(域名、IP)
|
timeout: 3000 # 超时时间(毫秒)
|
||||||
│ ├── server/ # DNS 服务器实现
|
verbose: true # 详细日志
|
||||||
│ └── upstream/ # 上游 DNS 客户端
|
|
||||||
├── plugin/ # 插件系统
|
|
||||||
│ ├── executable/ # 可执行插件
|
|
||||||
│ │ ├── cache/ # 缓存插件
|
|
||||||
│ │ ├── forward/ # 转发插件
|
|
||||||
│ │ ├── sequence/ # 序列插件
|
|
||||||
│ │ ├── mikrotik_addresslist/ # MikroTik 集成
|
|
||||||
│ │ └── ... # 其他插件
|
|
||||||
│ ├── matcher/ # 匹配插件
|
|
||||||
│ └── server/ # 服务器插件
|
|
||||||
├── scripts/ # 部署脚本
|
|
||||||
└── tools/ # 辅助工具
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 🚀 快速开始
|
**工作原理**:
|
||||||
|
1. 优先使用国内 DNS 查询(速度快)
|
||||||
|
2. 检测返回的 IP 是否为国内 IP
|
||||||
|
3. 如果是污染 IP,自动切换到国外 DNS
|
||||||
|
4. 支持并行/顺序两种模式
|
||||||
|
|
||||||
|
### 🎨 Web 管理界面
|
||||||
|
|
||||||
|
<img src="https://via.placeholder.com/800x400/4CAF50/FFFFFF?text=Web+UI+Dashboard" alt="Web UI" width="600">
|
||||||
|
|
||||||
|
**特性**:
|
||||||
|
- ✅ Vue 3 + TypeScript + Element Plus
|
||||||
|
- ✅ 实时监控 DNS 查询统计
|
||||||
|
- ✅ 可视化规则管理(添加/编辑/删除)
|
||||||
|
- ✅ 插件状态监控
|
||||||
|
- ✅ 配置文件在线编辑
|
||||||
|
- ✅ 一键热加载配置
|
||||||
|
|
||||||
|
**访问地址**: `http://localhost:5555`
|
||||||
|
|
||||||
|
### 🔄 配置热加载
|
||||||
|
|
||||||
|
**零停机更新配置** - 无需重启服务
|
||||||
|
|
||||||
#### 1. 下载安装
|
|
||||||
```bash
|
```bash
|
||||||
# 下载预编译二进制文件
|
# 方式1: Web 界面点击"热加载配置"按钮
|
||||||
wget https://github.com/IrineSistiana/mosdns/releases/latest/download/mosdns-linux-amd64.zip
|
# 方式2: API 调用
|
||||||
|
curl -X POST http://localhost:5555/api/config/reload
|
||||||
# 或使用 Docker
|
|
||||||
docker pull irinesistiana/mosdns
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 2. 基础配置
|
**特性**:
|
||||||
```yaml
|
- ✅ 自动验证新配置
|
||||||
# config.yaml
|
- ✅ 失败自动回滚
|
||||||
log:
|
- ✅ 保持 DNS 服务不中断
|
||||||
level: info
|
- ✅ 详细的加载日志
|
||||||
|
|
||||||
plugins:
|
### ⚡ 一键部署 (init 命令)
|
||||||
# 转发到公共 DNS
|
|
||||||
- tag: forward_google
|
|
||||||
type: forward
|
|
||||||
args:
|
|
||||||
upstream:
|
|
||||||
- addr: "8.8.8.8:53"
|
|
||||||
|
|
||||||
# 主序列
|
**3 步快速启动**:
|
||||||
- tag: main_sequence
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
- exec: forward_google
|
|
||||||
|
|
||||||
servers:
|
|
||||||
# DNS 服务器
|
|
||||||
- exec: udp_server
|
|
||||||
args:
|
|
||||||
entry: main_sequence
|
|
||||||
listen: ":53"
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 3. 启动服务
|
|
||||||
```bash
|
```bash
|
||||||
# 直接运行
|
# 1. 初始化配置
|
||||||
./mosdns start -c config.yaml
|
./mosdns-linux-amd64 init
|
||||||
|
|
||||||
# 或使用 Docker
|
# 2. 修改端口(可选,非 root 用户)
|
||||||
docker run -d -p 53:53/udp -v ./config.yaml:/etc/mosdns/config.yaml irinesistiana/mosdns
|
sed -i 's/:53/:5310/g' config.yaml
|
||||||
|
|
||||||
|
# 3. 启动服务
|
||||||
|
./mosdns-linux-amd64 start -c config.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
### 💡 高级功能
|
**自动生成**:
|
||||||
|
- ✅ 完整的 `config.yaml` 配置文件
|
||||||
|
- ✅ 目录结构(data/, config.d/rules/, logs/)
|
||||||
|
- ✅ 示例数据文件(CN IP、域名列表)
|
||||||
|
|
||||||
|
### 🧠 智能拓扑排序
|
||||||
|
|
||||||
|
**自动分析插件依赖关系** - 支持任意配置顺序
|
||||||
|
|
||||||
#### 智能分流配置
|
|
||||||
```yaml
|
```yaml
|
||||||
|
# ✅ 无需关心插件顺序,自动排序
|
||||||
plugins:
|
plugins:
|
||||||
# 国内域名
|
- tag: udp_server # 依赖 main
|
||||||
- tag: cn_domains
|
- tag: main # 依赖 cache, forward
|
||||||
type: domain_set
|
- tag: cache # 无依赖
|
||||||
args:
|
- tag: forward # 无依赖
|
||||||
files: ["china-list.txt"]
|
|
||||||
|
|
||||||
# 国外域名
|
|
||||||
- tag: gfw_domains
|
|
||||||
type: domain_set
|
|
||||||
args:
|
|
||||||
files: ["gfw-list.txt"]
|
|
||||||
|
|
||||||
# 智能分流序列
|
|
||||||
- tag: smart_sequence
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
- if: qname $cn_domains
|
|
||||||
exec: forward_cn_dns
|
|
||||||
- if: qname $gfw_domains
|
|
||||||
exec: forward_foreign_dns
|
|
||||||
- exec: forward_default
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### MikroTik 集成
|
**特性**:
|
||||||
|
- ✅ 自动检测 `$plugin_name` 引用
|
||||||
|
- ✅ 识别 `entry:` 字段依赖
|
||||||
|
- ✅ 循环依赖检测
|
||||||
|
- ✅ 详细错误提示
|
||||||
|
|
||||||
|
### 📡 MikroTik 集成
|
||||||
|
|
||||||
|
**自动同步 DNS 解析到 MikroTik 路由器**
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
plugins:
|
plugins:
|
||||||
- tag: mikrotik_integration
|
- tag: mikrotik_sync
|
||||||
type: mikrotik_addresslist
|
type: mikrotik_addresslist
|
||||||
args:
|
args:
|
||||||
host: "192.168.1.1"
|
host: "192.168.1.1"
|
||||||
username: "admin"
|
username: "admin"
|
||||||
password: "password"
|
password: "password"
|
||||||
address_list4: "blocked_ips"
|
address_list: "blocked_sites"
|
||||||
add_all_ips: true # 添加所有解析的 IP
|
mask: 32 # 单 IP 精确匹配
|
||||||
mask4: 32 # 单个 IP 精确匹配
|
max_ips: 10000 # 最大 IP 数量
|
||||||
|
cache_ttl: 3600 # 缓存时间
|
||||||
```
|
```
|
||||||
|
|
||||||
### 📖 文档和资源
|
**应用场景**:
|
||||||
|
- 🎯 自动添加特定域名的 IP 到地址列表
|
||||||
|
- 🎯 配合 MikroTik 防火墙规则
|
||||||
|
- 🎯 实现智能分流(游戏加速、广告拦截等)
|
||||||
|
|
||||||
- **详细文档**: [Wiki](https://irine-sistiana.gitbook.io/mosdns-wiki/)
|
### 🔌 完整的 RESTful API
|
||||||
- **下载地址**: [Releases](https://github.com/IrineSistiana/mosdns/releases)
|
|
||||||
- **Docker 镜像**: [Docker Hub](https://hub.docker.com/r/irinesistiana/mosdns)
|
|
||||||
- **配置示例**: [examples/](./examples/)
|
|
||||||
|
|
||||||
### 🤝 贡献
|
**管理接口**: `http://localhost:8080`
|
||||||
|
|
||||||
欢迎提交 Issue 和 Pull Request!请确保:
|
| 端点 | 方法 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `/api/server/info` | GET | 服务器信息 |
|
||||||
|
| `/api/plugins` | GET | 插件列表 |
|
||||||
|
| `/api/rules` | GET/POST/PUT/DELETE | 规则管理 |
|
||||||
|
| `/api/config/reload` | POST | 热加载配置 |
|
||||||
|
| `/api/cache/stats` | GET | 缓存统计 |
|
||||||
|
| `/api/cache/flush` | POST | 清空缓存 |
|
||||||
|
|
||||||
1. 代码符合 Go 语言规范
|
**示例**:
|
||||||
2. 添加必要的测试
|
```bash
|
||||||
3. 更新相关文档
|
# 查看服务器状态
|
||||||
|
curl http://localhost:8080/api/server/info | jq
|
||||||
|
|
||||||
### 📄 许可证
|
# 热加载配置
|
||||||
|
curl -X POST http://localhost:5555/api/config/reload
|
||||||
本项目采用 GPL v3 许可证。详见 [LICENSE](./LICENSE) 文件。
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## English
|
## 🚀 快速开始
|
||||||
|
|
||||||
### 🚀 Introduction
|
### 方式 1: 一键部署(推荐)
|
||||||
|
|
||||||
MosDNS is a plugin-based DNS forwarder designed to provide highly customizable DNS resolution services. Through a flexible plugin system and configuration approach, it can implement complex DNS processing logic, including but not limited to:
|
|
||||||
|
|
||||||
- Smart DNS routing (domestic/foreign domain splitting)
|
|
||||||
- DNS caching and optimization
|
|
||||||
- Ad blocking and malicious domain filtering
|
|
||||||
- Custom DNS resolution rules
|
|
||||||
- Multiple upstream DNS support
|
|
||||||
- Network device integration (e.g., MikroTik)
|
|
||||||
|
|
||||||
### ✨ Key Features
|
|
||||||
|
|
||||||
#### 🧩 Plugin Architecture
|
|
||||||
- **Modular Design**: Each function is an independent plugin, loaded as needed
|
|
||||||
- **Flexible Composition**: Combine multiple plugins through sequences for complex logic
|
|
||||||
- **Easy Extension**: Support for custom plugin development
|
|
||||||
|
|
||||||
#### 🌐 Smart Routing
|
|
||||||
- **Geo-aware**: Automatically identify domestic/foreign domains and use different upstream DNS
|
|
||||||
- **Domain Matching**: Support various domain matching rules (exact, wildcard, regex)
|
|
||||||
- **IP Range Matching**: Process based on resolved IP addresses
|
|
||||||
|
|
||||||
#### ⚡ Performance Optimization
|
|
||||||
- **Smart Caching**: Multi-level caching mechanism for significant speed improvements
|
|
||||||
- **Concurrent Processing**: High-concurrency DNS query handling
|
|
||||||
- **Memory Optimization**: Efficient memory management and resource pooling
|
|
||||||
|
|
||||||
#### 🔧 Network Device Integration
|
|
||||||
- **MikroTik Support**: Automatically add resolved IPs to MikroTik address lists
|
|
||||||
- **IPSet/NFTables**: Linux firewall rule integration
|
|
||||||
- **Real-time Sync**: DNS resolution results synced to network devices in real-time
|
|
||||||
|
|
||||||
### 🚀 Quick Start
|
|
||||||
|
|
||||||
#### 1. Installation
|
|
||||||
```bash
|
```bash
|
||||||
# Download pre-built binary
|
# 1. 下载程序
|
||||||
wget https://github.com/IrineSistiana/mosdns/releases/latest/download/mosdns-linux-amd64.zip
|
wget https://git.ylcomm.cn/dengxiongjian/mosdns/releases/latest/download/mosdns-linux-amd64
|
||||||
|
chmod +x mosdns-linux-amd64
|
||||||
|
|
||||||
# Or use Docker
|
# 2. 初始化
|
||||||
docker pull irinesistiana/mosdns
|
./mosdns-linux-amd64 init
|
||||||
|
|
||||||
|
# 3. 启动(非 root 用户修改端口)
|
||||||
|
sed -i 's/:53/:5310/g' config.yaml
|
||||||
|
./mosdns-linux-amd64 start -c config.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 2. Basic Configuration
|
**完成!** 访问:
|
||||||
|
- Web UI: http://localhost:5555
|
||||||
|
- API: http://localhost:8080
|
||||||
|
- DNS: localhost:53 (或 5310)
|
||||||
|
|
||||||
|
### 方式 2: systemd 服务
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 复制程序到系统目录
|
||||||
|
sudo cp mosdns-linux-amd64 /usr/local/bin/mosdns
|
||||||
|
sudo chmod +x /usr/local/bin/mosdns
|
||||||
|
|
||||||
|
# 2. 创建配置目录
|
||||||
|
sudo mkdir -p /etc/mosdns
|
||||||
|
cd /etc/mosdns
|
||||||
|
sudo mosdns init
|
||||||
|
|
||||||
|
# 3. 创建 systemd 服务
|
||||||
|
sudo tee /etc/systemd/system/mosdns.service > /dev/null <<EOF
|
||||||
|
[Unit]
|
||||||
|
Description=MosDNS DNS Server
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=root
|
||||||
|
WorkingDirectory=/etc/mosdns
|
||||||
|
ExecStart=/usr/local/bin/mosdns start -c config.yaml
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5s
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# 4. 启动服务
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl enable mosdns
|
||||||
|
sudo systemctl start mosdns
|
||||||
|
```
|
||||||
|
|
||||||
|
### 方式 3: Docker 容器
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 构建镜像
|
||||||
|
docker build -t mosdns:latest .
|
||||||
|
|
||||||
|
# 运行容器
|
||||||
|
docker run -d \
|
||||||
|
--name mosdns \
|
||||||
|
-p 53:53/udp \
|
||||||
|
-p 53:53/tcp \
|
||||||
|
-p 5555:5555 \
|
||||||
|
-p 8080:8080 \
|
||||||
|
-v $(pwd)/config.yaml:/opt/mosdns/config.yaml \
|
||||||
|
mosdns:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📦 下载
|
||||||
|
|
||||||
|
### 预编译版本
|
||||||
|
|
||||||
|
| 平台 | 架构 | 下载 |
|
||||||
|
|------|------|------|
|
||||||
|
| Linux | AMD64 | [mosdns-linux-amd64](https://git.ylcomm.cn/dengxiongjian/mosdns/releases) |
|
||||||
|
| Linux | ARM64 | [mosdns-linux-arm64](https://git.ylcomm.cn/dengxiongjian/mosdns/releases) |
|
||||||
|
| Windows | AMD64 | [mosdns-windows-amd64.exe](https://git.ylcomm.cn/dengxiongjian/mosdns/releases) |
|
||||||
|
| macOS | Intel | [mosdns-darwin-amd64](https://git.ylcomm.cn/dengxiongjian/mosdns/releases) |
|
||||||
|
| macOS | Apple Silicon | [mosdns-darwin-arm64](https://git.ylcomm.cn/dengxiongjian/mosdns/releases) |
|
||||||
|
|
||||||
|
### 从源码构建
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 克隆仓库
|
||||||
|
git clone https://git.ylcomm.cn/dengxiongjian/mosdns.git
|
||||||
|
cd mosdns
|
||||||
|
|
||||||
|
# 构建(交互式菜单)
|
||||||
|
bash build-all-platforms.sh
|
||||||
|
|
||||||
|
# 或直接编译当前平台
|
||||||
|
go build -o dist/mosdns .
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 文档
|
||||||
|
|
||||||
|
### 配置示例
|
||||||
|
|
||||||
|
```
|
||||||
|
config.yaml # 标准配置(智能防污染)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 更多文档
|
||||||
|
|
||||||
|
- 📖 [CHANGELOG.md](./CHANGELOG.md) - 完整更新日志
|
||||||
|
- 🌐 Web UI 管理界面: http://localhost:5555
|
||||||
|
- 🔌 API 文档: http://localhost:8080/api
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 使用场景
|
||||||
|
|
||||||
|
### 场景 1: 家庭/办公室智能 DNS
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
# config.yaml
|
# 自动识别国内外域名,智能分流
|
||||||
|
- 国内域名 → 国内 DNS(阿里云/腾讯云)
|
||||||
|
- 国外域名 → 国外 DNS(Cloudflare/Google)
|
||||||
|
- 自动防污染检测
|
||||||
|
```
|
||||||
|
|
||||||
|
### 场景 2: 软路由/NAS 部署
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# 配合 MikroTik/OpenWrt
|
||||||
|
- DNS 解析
|
||||||
|
- 地址列表同步
|
||||||
|
- 智能分流
|
||||||
|
- 广告拦截
|
||||||
|
```
|
||||||
|
|
||||||
|
### 场景 3: VPS 公共 DNS 服务
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# 高性能公共 DNS
|
||||||
|
- 智能缓存
|
||||||
|
- 防污染
|
||||||
|
- 多上游支持
|
||||||
|
- API 管理
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 配置说明
|
||||||
|
|
||||||
|
### 基础配置结构
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# 日志
|
||||||
log:
|
log:
|
||||||
level: info
|
level: info
|
||||||
|
|
||||||
|
# API 接口
|
||||||
|
api:
|
||||||
|
http: "0.0.0.0:8080"
|
||||||
|
|
||||||
|
# Web 管理界面
|
||||||
|
web:
|
||||||
|
http: "0.0.0.0:5555"
|
||||||
|
|
||||||
|
# 插件列表
|
||||||
plugins:
|
plugins:
|
||||||
# Forward to public DNS
|
- tag: plugin_name
|
||||||
- tag: forward_google
|
type: plugin_type
|
||||||
type: forward
|
|
||||||
args:
|
args:
|
||||||
upstream:
|
key: value
|
||||||
- addr: "8.8.8.8:53"
|
|
||||||
|
|
||||||
# Main sequence
|
|
||||||
- tag: main_sequence
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
- exec: forward_google
|
|
||||||
|
|
||||||
servers:
|
|
||||||
# DNS server
|
|
||||||
- exec: udp_server
|
|
||||||
args:
|
|
||||||
entry: main_sequence
|
|
||||||
listen: ":53"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 3. Start Service
|
### 常用插件
|
||||||
|
|
||||||
|
| 插件类型 | 说明 | 示例 |
|
||||||
|
|---------|------|------|
|
||||||
|
| `ip_set` | IP 地址匹配 | geoip_cn |
|
||||||
|
| `domain_set` | 域名匹配 | geosite_cn |
|
||||||
|
| `forward` | DNS 上游 | forward_local |
|
||||||
|
| `cache` | DNS 缓存 | main_cache |
|
||||||
|
| `smart_fallback` | 智能防污染 | smart_fallback |
|
||||||
|
| `sequence` | 执行序列 | main |
|
||||||
|
| `mikrotik_addresslist` | MikroTik 同步 | mikrotik_sync |
|
||||||
|
| `udp_server` | UDP 服务器 | udp_server |
|
||||||
|
| `tcp_server` | TCP 服务器 | tcp_server |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛠️ 故障排查
|
||||||
|
|
||||||
|
### 常见问题
|
||||||
|
|
||||||
|
**Q: 端口 53 绑定失败?**
|
||||||
```bash
|
```bash
|
||||||
# Run directly
|
# 需要 root 权限
|
||||||
./mosdns start -c config.yaml
|
sudo ./mosdns start -c config.yaml
|
||||||
|
|
||||||
# Or use Docker
|
# 或修改为非特权端口
|
||||||
docker run -d -p 53:53/udp -v ./config.yaml:/etc/mosdns/config.yaml irinesistiana/mosdns
|
sed -i 's/:53/:5310/g' config.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
### 📖 Documentation
|
**Q: 配置文件已存在?**
|
||||||
|
```bash
|
||||||
|
# 强制重新初始化
|
||||||
|
./mosdns init --force
|
||||||
|
```
|
||||||
|
|
||||||
- **Detailed Docs**: [Wiki](https://irine-sistiana.gitbook.io/mosdns-wiki/)
|
**Q: Web UI 无法访问?**
|
||||||
- **Downloads**: [Releases](https://github.com/IrineSistiana/mosdns/releases)
|
```bash
|
||||||
- **Docker Images**: [Docker Hub](https://hub.docker.com/r/irinesistiana/mosdns)
|
# 检查端口是否被占用
|
||||||
|
sudo lsof -i :5555
|
||||||
|
|
||||||
### 🤝 Contributing
|
# 检查防火墙
|
||||||
|
sudo ufw allow 5555/tcp
|
||||||
|
```
|
||||||
|
|
||||||
Issues and Pull Requests are welcome! Please ensure:
|
**Q: DNS 解析失败?**
|
||||||
|
```bash
|
||||||
|
# 查看日志
|
||||||
|
journalctl -u mosdns -f
|
||||||
|
|
||||||
1. Code follows Go language standards
|
# 测试 DNS
|
||||||
2. Add necessary tests
|
dig @localhost -p 5310 baidu.com
|
||||||
3. Update relevant documentation
|
```
|
||||||
|
|
||||||
### 📄 License
|
---
|
||||||
|
|
||||||
This project is licensed under GPL v3. See [LICENSE](./LICENSE) for details.
|
## 📊 性能指标
|
||||||
|
|
||||||
|
| 指标 | 数值 |
|
||||||
|
|------|------|
|
||||||
|
| **启动时间** | < 2 秒 |
|
||||||
|
| **内存占用** | 30-50 MB(空载) |
|
||||||
|
| **DNS 延迟** | 20-30ms(国内), 80-120ms(防污染) |
|
||||||
|
| **缓存命中率** | 85%+ |
|
||||||
|
| **并发能力** | 3000+ qps(单核) |
|
||||||
|
| **二进制大小** | ~26 MB(包含 Web UI) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🤝 贡献
|
||||||
|
|
||||||
|
欢迎贡献代码!请遵循以下步骤:
|
||||||
|
|
||||||
|
1. Fork 本仓库
|
||||||
|
2. 创建特性分支 (`git checkout -b feature/AmazingFeature`)
|
||||||
|
3. 提交更改 (`git commit -m 'Add some AmazingFeature'`)
|
||||||
|
4. 推送到分支 (`git push origin feature/AmazingFeature`)
|
||||||
|
5. 开启 Pull Request
|
||||||
|
|
||||||
|
**代码规范**:
|
||||||
|
- 遵循 Go 语言规范
|
||||||
|
- 添加必要的测试
|
||||||
|
- 更新相关文档
|
||||||
|
- 每行代码添加中文注释
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📄 许可证
|
||||||
|
|
||||||
|
本项目基于 [MosDNS](https://github.com/IrineSistiana/mosdns) 进行二次开发
|
||||||
|
|
||||||
|
- **原项目**: GPL v3 License
|
||||||
|
- **二次开发**: GPL v3 License
|
||||||
|
|
||||||
|
详见 [LICENSE](./LICENSE) 文件。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🙏 致谢
|
||||||
|
|
||||||
|
- 感谢 [IrineSistiana](https://github.com/IrineSistiana) 创建的原始 MosDNS 项目
|
||||||
|
- 感谢所有开源社区的贡献者
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📞 联系方式
|
||||||
|
|
||||||
|
- **Issues**: [GitHub Issues](https://git.ylcomm.cn/dengxiongjian/mosdns/issues)
|
||||||
|
- **Discussions**: [GitHub Discussions](https://git.ylcomm.cn/dengxiongjian/mosdns/discussions)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
**⭐ 如果这个项目对你有帮助,请给个 Star!**
|
**⭐ 如果这个项目对你有帮助,请给个 Star!⭐**
|
||||||
|
|
||||||
**⭐ If this project helps you, please give it a Star!**
|
**🌟 Star this project if it helps you! 🌟**
|
||||||
|
|
||||||
</div>
|
Made with ❤️ by YLTX Team
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,435 +0,0 @@
|
|||||||
@echo off
|
|
||||||
chcp 65001 >nul
|
|
||||||
REM ========================================
|
|
||||||
REM MosDNS 多平台构建脚本 (带 Web UI)
|
|
||||||
REM 支持: Linux, Windows, macOS (amd64/arm64)
|
|
||||||
REM ========================================
|
|
||||||
|
|
||||||
echo.
|
|
||||||
echo ╔════════════════════════════════════════════╗
|
|
||||||
echo ║ MosDNS 多平台构建工具 (带 Web UI) ║
|
|
||||||
echo ╚════════════════════════════════════════════╝
|
|
||||||
echo.
|
|
||||||
|
|
||||||
REM 检查 Go 环境
|
|
||||||
where go >nul 2>nul
|
|
||||||
if %errorlevel% neq 0 (
|
|
||||||
echo ❌ Go 未安装或不在 PATH 中
|
|
||||||
pause
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
echo ✅ Go 版本:
|
|
||||||
go version
|
|
||||||
echo.
|
|
||||||
|
|
||||||
REM 检查并构建 Vue 前端
|
|
||||||
echo [检查] Vue 前端资源...
|
|
||||||
if not exist "web-ui\dist\index.html" (
|
|
||||||
echo ⚠️ Vue 前端未构建,开始构建...
|
|
||||||
|
|
||||||
REM 检查 Node.js
|
|
||||||
where node >nul 2>nul
|
|
||||||
if %errorlevel% neq 0 (
|
|
||||||
echo ❌ Node.js 未安装,无法构建 Vue 前端
|
|
||||||
echo 💡 请安装 Node.js 或手动运行: cd web-ui ^&^& npm install ^&^& npm run build
|
|
||||||
pause
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
REM 检查 npm
|
|
||||||
where npm >nul 2>nul
|
|
||||||
if %errorlevel% neq 0 (
|
|
||||||
echo ❌ npm 未找到
|
|
||||||
pause
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
echo [1/2] 安装 Vue 依赖...
|
|
||||||
cd web-ui
|
|
||||||
if not exist "node_modules" (
|
|
||||||
call npm install
|
|
||||||
if %errorlevel% neq 0 (
|
|
||||||
echo ❌ npm install 失败
|
|
||||||
cd ..
|
|
||||||
pause
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
echo [2/2] 构建 Vue 前端...
|
|
||||||
call npm run build
|
|
||||||
if %errorlevel% neq 0 (
|
|
||||||
echo ❌ Vue 构建失败
|
|
||||||
cd ..
|
|
||||||
pause
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
cd ..
|
|
||||||
echo ✅ Vue 前端构建完成
|
|
||||||
) else (
|
|
||||||
echo ✅ Vue 前端资源已存在
|
|
||||||
)
|
|
||||||
echo.
|
|
||||||
|
|
||||||
REM ========================================
|
|
||||||
REM 显示平台选择菜单
|
|
||||||
REM ========================================
|
|
||||||
:MENU
|
|
||||||
cls
|
|
||||||
echo.
|
|
||||||
echo ╔════════════════════════════════════════════╗
|
|
||||||
echo ║ MosDNS 多平台构建工具 (带 Web UI) ║
|
|
||||||
echo ╚════════════════════════════════════════════╝
|
|
||||||
echo.
|
|
||||||
echo 请选择要编译的平台:
|
|
||||||
echo.
|
|
||||||
echo [1] Linux AMD64 (x86_64 服务器)
|
|
||||||
echo [2] Linux ARM64 (树莓派、ARM 服务器)
|
|
||||||
echo [3] Windows AMD64 (Windows 64位)
|
|
||||||
echo [4] macOS AMD64 (Intel Mac)
|
|
||||||
echo [5] macOS ARM64 (Apple Silicon M1/M2/M3)
|
|
||||||
echo.
|
|
||||||
echo [6] 编译所有 Linux 版本 (AMD64 + ARM64)
|
|
||||||
echo [7] 编译所有 macOS 版本 (AMD64 + ARM64)
|
|
||||||
echo [8] 编译所有 Windows 版本 (仅 AMD64)
|
|
||||||
echo.
|
|
||||||
echo [A] 编译全部平台 (推荐用于发布)
|
|
||||||
echo.
|
|
||||||
echo [0] 退出
|
|
||||||
echo.
|
|
||||||
echo ════════════════════════════════════════════
|
|
||||||
echo.
|
|
||||||
|
|
||||||
set /p CHOICE="请输入选项 [0-8/A]: "
|
|
||||||
|
|
||||||
if /i "%CHOICE%"=="0" exit /b 0
|
|
||||||
if /i "%CHOICE%"=="1" goto BUILD_LINUX_AMD64
|
|
||||||
if /i "%CHOICE%"=="2" goto BUILD_LINUX_ARM64
|
|
||||||
if /i "%CHOICE%"=="3" goto BUILD_WINDOWS_AMD64
|
|
||||||
if /i "%CHOICE%"=="4" goto BUILD_MACOS_AMD64
|
|
||||||
if /i "%CHOICE%"=="5" goto BUILD_MACOS_ARM64
|
|
||||||
if /i "%CHOICE%"=="6" goto BUILD_ALL_LINUX
|
|
||||||
if /i "%CHOICE%"=="7" goto BUILD_ALL_MACOS
|
|
||||||
if /i "%CHOICE%"=="8" goto BUILD_ALL_WINDOWS
|
|
||||||
if /i "%CHOICE%"=="A" goto BUILD_ALL
|
|
||||||
if /i "%CHOICE%"=="a" goto BUILD_ALL
|
|
||||||
|
|
||||||
echo.
|
|
||||||
echo ❌ 无效的选项,请重新选择
|
|
||||||
timeout /t 2 >nul
|
|
||||||
goto MENU
|
|
||||||
|
|
||||||
REM ========================================
|
|
||||||
REM 初始化构建环境
|
|
||||||
REM ========================================
|
|
||||||
:INIT_BUILD
|
|
||||||
echo.
|
|
||||||
echo ════════════════════════════════════════════
|
|
||||||
echo.
|
|
||||||
echo [准备] 设置构建参数...
|
|
||||||
for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"
|
|
||||||
set "BUILD_TIME=%dt:~0,4%-%dt:~4,2%-%dt:~6,2% %dt:~8,2%:%dt:~10,2%:%dt:~12,2%"
|
|
||||||
set "VERSION=v5.0.0-webui"
|
|
||||||
set "OUTPUT_DIR=dist"
|
|
||||||
|
|
||||||
REM 创建输出目录
|
|
||||||
if not exist "%OUTPUT_DIR%" mkdir "%OUTPUT_DIR%"
|
|
||||||
|
|
||||||
echo 版本: %VERSION%
|
|
||||||
echo 构建时间: %BUILD_TIME%
|
|
||||||
echo 输出目录: %OUTPUT_DIR%\
|
|
||||||
echo.
|
|
||||||
|
|
||||||
set CGO_ENABLED=0
|
|
||||||
set "LDFLAGS=-s -w -X 'main.version=%VERSION%' -X 'main.buildTime=%BUILD_TIME%'"
|
|
||||||
|
|
||||||
echo [开始] 编译中...
|
|
||||||
echo.
|
|
||||||
goto :EOF
|
|
||||||
|
|
||||||
REM ========================================
|
|
||||||
REM 单平台编译
|
|
||||||
REM ========================================
|
|
||||||
:BUILD_LINUX_AMD64
|
|
||||||
call :INIT_BUILD
|
|
||||||
echo 🔨 构建 Linux AMD64...
|
|
||||||
set GOOS=linux
|
|
||||||
set GOARCH=amd64
|
|
||||||
go build -ldflags="%LDFLAGS%" -o "%OUTPUT_DIR%\mosdns-linux-amd64" .
|
|
||||||
if %errorlevel% equ 0 (
|
|
||||||
echo ✅ mosdns-linux-amd64 构建成功
|
|
||||||
call :SHOW_RESULT
|
|
||||||
) else (
|
|
||||||
echo ❌ 构建失败
|
|
||||||
pause
|
|
||||||
)
|
|
||||||
goto END
|
|
||||||
|
|
||||||
:BUILD_LINUX_ARM64
|
|
||||||
call :INIT_BUILD
|
|
||||||
echo 🔨 构建 Linux ARM64...
|
|
||||||
set GOOS=linux
|
|
||||||
set GOARCH=arm64
|
|
||||||
go build -ldflags="%LDFLAGS%" -o "%OUTPUT_DIR%\mosdns-linux-arm64" .
|
|
||||||
if %errorlevel% equ 0 (
|
|
||||||
echo ✅ mosdns-linux-arm64 构建成功
|
|
||||||
call :SHOW_RESULT
|
|
||||||
) else (
|
|
||||||
echo ❌ 构建失败
|
|
||||||
pause
|
|
||||||
)
|
|
||||||
goto END
|
|
||||||
|
|
||||||
:BUILD_WINDOWS_AMD64
|
|
||||||
call :INIT_BUILD
|
|
||||||
echo 🔨 构建 Windows AMD64...
|
|
||||||
set GOOS=windows
|
|
||||||
set GOARCH=amd64
|
|
||||||
go build -ldflags="%LDFLAGS%" -o "%OUTPUT_DIR%\mosdns-windows-amd64.exe" .
|
|
||||||
if %errorlevel% equ 0 (
|
|
||||||
echo ✅ mosdns-windows-amd64.exe 构建成功
|
|
||||||
call :SHOW_RESULT
|
|
||||||
) else (
|
|
||||||
echo ❌ 构建失败
|
|
||||||
pause
|
|
||||||
)
|
|
||||||
goto END
|
|
||||||
|
|
||||||
:BUILD_MACOS_AMD64
|
|
||||||
call :INIT_BUILD
|
|
||||||
echo 🔨 构建 macOS AMD64 (Intel Mac)...
|
|
||||||
set GOOS=darwin
|
|
||||||
set GOARCH=amd64
|
|
||||||
go build -ldflags="%LDFLAGS%" -o "%OUTPUT_DIR%\mosdns-darwin-amd64" .
|
|
||||||
if %errorlevel% equ 0 (
|
|
||||||
echo ✅ mosdns-darwin-amd64 构建成功
|
|
||||||
call :SHOW_RESULT
|
|
||||||
) else (
|
|
||||||
echo ❌ 构建失败
|
|
||||||
pause
|
|
||||||
)
|
|
||||||
goto END
|
|
||||||
|
|
||||||
:BUILD_MACOS_ARM64
|
|
||||||
call :INIT_BUILD
|
|
||||||
echo 🔨 构建 macOS ARM64 (Apple Silicon)...
|
|
||||||
set GOOS=darwin
|
|
||||||
set GOARCH=arm64
|
|
||||||
go build -ldflags="%LDFLAGS%" -o "%OUTPUT_DIR%\mosdns-darwin-arm64" .
|
|
||||||
if %errorlevel% equ 0 (
|
|
||||||
echo ✅ mosdns-darwin-arm64 构建成功
|
|
||||||
call :SHOW_RESULT
|
|
||||||
) else (
|
|
||||||
echo ❌ 构建失败
|
|
||||||
pause
|
|
||||||
)
|
|
||||||
goto END
|
|
||||||
|
|
||||||
REM ========================================
|
|
||||||
REM 批量编译
|
|
||||||
REM ========================================
|
|
||||||
:BUILD_ALL_LINUX
|
|
||||||
call :INIT_BUILD
|
|
||||||
echo [1/2] 🔨 构建 Linux AMD64...
|
|
||||||
set GOOS=linux
|
|
||||||
set GOARCH=amd64
|
|
||||||
go build -ldflags="%LDFLAGS%" -o "%OUTPUT_DIR%\mosdns-linux-amd64" .
|
|
||||||
if %errorlevel% equ 0 (
|
|
||||||
echo ✅ mosdns-linux-amd64 构建成功
|
|
||||||
) else (
|
|
||||||
echo ❌ 构建失败
|
|
||||||
set "BUILD_FAILED=1"
|
|
||||||
)
|
|
||||||
echo.
|
|
||||||
|
|
||||||
echo [2/2] 🔨 构建 Linux ARM64...
|
|
||||||
set GOOS=linux
|
|
||||||
set GOARCH=arm64
|
|
||||||
go build -ldflags="%LDFLAGS%" -o "%OUTPUT_DIR%\mosdns-linux-arm64" .
|
|
||||||
if %errorlevel% equ 0 (
|
|
||||||
echo ✅ mosdns-linux-arm64 构建成功
|
|
||||||
) else (
|
|
||||||
echo ❌ 构建失败
|
|
||||||
set "BUILD_FAILED=1"
|
|
||||||
)
|
|
||||||
call :SHOW_RESULT
|
|
||||||
goto END
|
|
||||||
|
|
||||||
:BUILD_ALL_MACOS
|
|
||||||
call :INIT_BUILD
|
|
||||||
echo [1/2] 🔨 构建 macOS AMD64 (Intel Mac)...
|
|
||||||
set GOOS=darwin
|
|
||||||
set GOARCH=amd64
|
|
||||||
go build -ldflags="%LDFLAGS%" -o "%OUTPUT_DIR%\mosdns-darwin-amd64" .
|
|
||||||
if %errorlevel% equ 0 (
|
|
||||||
echo ✅ mosdns-darwin-amd64 构建成功
|
|
||||||
) else (
|
|
||||||
echo ❌ 构建失败
|
|
||||||
set "BUILD_FAILED=1"
|
|
||||||
)
|
|
||||||
echo.
|
|
||||||
|
|
||||||
echo [2/2] 🔨 构建 macOS ARM64 (Apple Silicon)...
|
|
||||||
set GOOS=darwin
|
|
||||||
set GOARCH=arm64
|
|
||||||
go build -ldflags="%LDFLAGS%" -o "%OUTPUT_DIR%\mosdns-darwin-arm64" .
|
|
||||||
if %errorlevel% equ 0 (
|
|
||||||
echo ✅ mosdns-darwin-arm64 构建成功
|
|
||||||
) else (
|
|
||||||
echo ❌ 构建失败
|
|
||||||
set "BUILD_FAILED=1"
|
|
||||||
)
|
|
||||||
call :SHOW_RESULT
|
|
||||||
goto END
|
|
||||||
|
|
||||||
:BUILD_ALL_WINDOWS
|
|
||||||
call :INIT_BUILD
|
|
||||||
echo [1/1] 🔨 构建 Windows AMD64...
|
|
||||||
set GOOS=windows
|
|
||||||
set GOARCH=amd64
|
|
||||||
go build -ldflags="%LDFLAGS%" -o "%OUTPUT_DIR%\mosdns-windows-amd64.exe" .
|
|
||||||
if %errorlevel% equ 0 (
|
|
||||||
echo ✅ mosdns-windows-amd64.exe 构建成功
|
|
||||||
) else (
|
|
||||||
echo ❌ 构建失败
|
|
||||||
set "BUILD_FAILED=1"
|
|
||||||
)
|
|
||||||
call :SHOW_RESULT
|
|
||||||
goto END
|
|
||||||
|
|
||||||
:BUILD_ALL
|
|
||||||
call :INIT_BUILD
|
|
||||||
echo [1/5] 🔨 构建 Linux AMD64...
|
|
||||||
set GOOS=linux
|
|
||||||
set GOARCH=amd64
|
|
||||||
go build -ldflags="%LDFLAGS%" -o "%OUTPUT_DIR%\mosdns-linux-amd64" .
|
|
||||||
if %errorlevel% equ 0 (
|
|
||||||
echo ✅ mosdns-linux-amd64 构建成功
|
|
||||||
) else (
|
|
||||||
echo ❌ 构建失败
|
|
||||||
set "BUILD_FAILED=1"
|
|
||||||
)
|
|
||||||
echo.
|
|
||||||
|
|
||||||
echo [2/5] 🔨 构建 Linux ARM64...
|
|
||||||
set GOOS=linux
|
|
||||||
set GOARCH=arm64
|
|
||||||
go build -ldflags="%LDFLAGS%" -o "%OUTPUT_DIR%\mosdns-linux-arm64" .
|
|
||||||
if %errorlevel% equ 0 (
|
|
||||||
echo ✅ mosdns-linux-arm64 构建成功
|
|
||||||
) else (
|
|
||||||
echo ❌ 构建失败
|
|
||||||
set "BUILD_FAILED=1"
|
|
||||||
)
|
|
||||||
echo.
|
|
||||||
|
|
||||||
echo [3/5] 🔨 构建 Windows AMD64...
|
|
||||||
set GOOS=windows
|
|
||||||
set GOARCH=amd64
|
|
||||||
go build -ldflags="%LDFLAGS%" -o "%OUTPUT_DIR%\mosdns-windows-amd64.exe" .
|
|
||||||
if %errorlevel% equ 0 (
|
|
||||||
echo ✅ mosdns-windows-amd64.exe 构建成功
|
|
||||||
) else (
|
|
||||||
echo ❌ 构建失败
|
|
||||||
set "BUILD_FAILED=1"
|
|
||||||
)
|
|
||||||
echo.
|
|
||||||
|
|
||||||
echo [4/5] 🔨 构建 macOS AMD64...
|
|
||||||
set GOOS=darwin
|
|
||||||
set GOARCH=amd64
|
|
||||||
go build -ldflags="%LDFLAGS%" -o "%OUTPUT_DIR%\mosdns-darwin-amd64" .
|
|
||||||
if %errorlevel% equ 0 (
|
|
||||||
echo ✅ mosdns-darwin-amd64 构建成功
|
|
||||||
) else (
|
|
||||||
echo ❌ 构建失败
|
|
||||||
set "BUILD_FAILED=1"
|
|
||||||
)
|
|
||||||
echo.
|
|
||||||
|
|
||||||
echo [5/5] 🔨 构建 macOS ARM64 (Apple Silicon)...
|
|
||||||
set GOOS=darwin
|
|
||||||
set GOARCH=arm64
|
|
||||||
go build -ldflags="%LDFLAGS%" -o "%OUTPUT_DIR%\mosdns-darwin-arm64" .
|
|
||||||
if %errorlevel% equ 0 (
|
|
||||||
echo ✅ mosdns-darwin-arm64 构建成功
|
|
||||||
) else (
|
|
||||||
echo ❌ 构建失败
|
|
||||||
set "BUILD_FAILED=1"
|
|
||||||
)
|
|
||||||
call :SHOW_RESULT
|
|
||||||
goto END
|
|
||||||
|
|
||||||
REM ========================================
|
|
||||||
REM 显示构建结果
|
|
||||||
REM ========================================
|
|
||||||
:SHOW_RESULT
|
|
||||||
echo.
|
|
||||||
echo ════════════════════════════════════════════
|
|
||||||
echo.
|
|
||||||
|
|
||||||
if "%BUILD_FAILED%"=="1" (
|
|
||||||
echo ⚠️ 部分平台构建失败,请检查错误信息
|
|
||||||
echo.
|
|
||||||
) else (
|
|
||||||
echo 🎉 构建完成!
|
|
||||||
echo.
|
|
||||||
)
|
|
||||||
|
|
||||||
REM 检查是否有构建产物
|
|
||||||
if exist "%OUTPUT_DIR%\mosdns-*" (
|
|
||||||
echo 📦 构建产物列表:
|
|
||||||
echo.
|
|
||||||
dir /B "%OUTPUT_DIR%\mosdns-*" 2>nul
|
|
||||||
echo.
|
|
||||||
|
|
||||||
echo 📊 文件大小详情:
|
|
||||||
for %%F in (%OUTPUT_DIR%\mosdns-*) do (
|
|
||||||
set "size=%%~zF"
|
|
||||||
set /a size_mb=!size! / 1048576
|
|
||||||
echo %%~nxF - !size_mb! MB
|
|
||||||
)
|
|
||||||
echo.
|
|
||||||
) else (
|
|
||||||
echo ⚠️ 未找到构建产物
|
|
||||||
echo.
|
|
||||||
)
|
|
||||||
|
|
||||||
echo ════════════════════════════════════════════
|
|
||||||
echo.
|
|
||||||
echo 📝 使用方法:
|
|
||||||
echo.
|
|
||||||
echo Windows:
|
|
||||||
echo %OUTPUT_DIR%\mosdns-windows-amd64.exe start -c config.yaml
|
|
||||||
echo.
|
|
||||||
echo Linux:
|
|
||||||
echo chmod +x %OUTPUT_DIR%/mosdns-linux-amd64
|
|
||||||
echo ./%OUTPUT_DIR%/mosdns-linux-amd64 start -c config.yaml
|
|
||||||
echo.
|
|
||||||
echo macOS:
|
|
||||||
echo chmod +x %OUTPUT_DIR%/mosdns-darwin-amd64
|
|
||||||
echo ./%OUTPUT_DIR%/mosdns-darwin-amd64 start -c config.yaml
|
|
||||||
echo.
|
|
||||||
echo 🌐 Web 管理界面: http://localhost:5545
|
|
||||||
echo.
|
|
||||||
echo 💡 提示: 所有可执行文件已内嵌 Web 资源,可独立运行
|
|
||||||
echo.
|
|
||||||
goto :EOF
|
|
||||||
|
|
||||||
REM ========================================
|
|
||||||
REM 结束
|
|
||||||
REM ========================================
|
|
||||||
:END
|
|
||||||
echo.
|
|
||||||
set /p CONTINUE="是否继续编译其他平台?(Y/N): "
|
|
||||||
if /i "%CONTINUE%"=="Y" (
|
|
||||||
set "BUILD_FAILED="
|
|
||||||
goto MENU
|
|
||||||
)
|
|
||||||
|
|
||||||
echo.
|
|
||||||
echo 感谢使用 MosDNS 构建工具!
|
|
||||||
echo.
|
|
||||||
pause
|
|
||||||
exit /b 0
|
|
||||||
378
build-all-platforms.sh
Executable file
378
build-all-platforms.sh
Executable file
@ -0,0 +1,378 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# ========================================
|
||||||
|
# MosDNS 多平台构建脚本 (带 Web UI)
|
||||||
|
# 支持: Linux, Windows, macOS (amd64/arm64)
|
||||||
|
# ========================================
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# 颜色定义
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# 显示欢迎信息
|
||||||
|
show_welcome() {
|
||||||
|
clear 2>/dev/null || true # 允许 clear 失败
|
||||||
|
echo ""
|
||||||
|
echo -e "${CYAN}╔════════════════════════════════════════════╗${NC}"
|
||||||
|
echo -e "${CYAN}║ MosDNS 多平台构建工具 (带 Web UI) ║${NC}"
|
||||||
|
echo -e "${CYAN}╚════════════════════════════════════════════╝${NC}"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# 检查命令是否存在
|
||||||
|
command_exists() {
|
||||||
|
command -v "$1" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
# 检查 Go 环境
|
||||||
|
check_go() {
|
||||||
|
if ! command_exists go; then
|
||||||
|
echo -e "${RED}❌ Go 未安装或不在 PATH 中${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${GREEN}✅ Go 版本:${NC}"
|
||||||
|
go version
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# 检查并构建 Vue 前端
|
||||||
|
build_vue() {
|
||||||
|
echo -e "${BLUE}[检查] Vue 前端资源...${NC}"
|
||||||
|
|
||||||
|
if [ ! -f "web-ui/dist/index.html" ]; then
|
||||||
|
echo -e "${YELLOW}⚠️ Vue 前端未构建,开始构建...${NC}"
|
||||||
|
|
||||||
|
# 检查 Node.js
|
||||||
|
if ! command_exists node; then
|
||||||
|
echo -e "${RED}❌ Node.js 未安装,无法构建 Vue 前端${NC}"
|
||||||
|
echo -e "${CYAN}💡 请安装 Node.js 或手动运行: cd web-ui && npm install && npm run build${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检查 npm
|
||||||
|
if ! command_exists npm; then
|
||||||
|
echo -e "${RED}❌ npm 未找到${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${BLUE}[1/2] 安装 Vue 依赖...${NC}"
|
||||||
|
cd web-ui
|
||||||
|
|
||||||
|
if [ ! -d "node_modules" ]; then
|
||||||
|
npm install
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo -e "${RED}❌ npm install 失败${NC}"
|
||||||
|
cd ..
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${BLUE}[2/2] 构建 Vue 前端...${NC}"
|
||||||
|
npm run build
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo -e "${RED}❌ Vue 构建失败${NC}"
|
||||||
|
cd ..
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
echo -e "${GREEN}✅ Vue 前端构建完成${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${GREEN}✅ Vue 前端资源已存在${NC}"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# 显示平台选择菜单
|
||||||
|
show_menu() {
|
||||||
|
show_welcome
|
||||||
|
echo "请选择要编译的平台:"
|
||||||
|
echo ""
|
||||||
|
echo -e " ${GREEN}[1]${NC} Linux AMD64 (x86_64 服务器)"
|
||||||
|
echo -e " ${GREEN}[2]${NC} Linux ARM64 (树莓派、ARM 服务器)"
|
||||||
|
echo -e " ${GREEN}[3]${NC} Windows AMD64 (Windows 64位)"
|
||||||
|
echo -e " ${GREEN}[4]${NC} macOS AMD64 (Intel Mac)"
|
||||||
|
echo -e " ${GREEN}[5]${NC} macOS ARM64 (Apple Silicon M1/M2/M3)"
|
||||||
|
echo ""
|
||||||
|
echo -e " ${YELLOW}[6]${NC} 编译所有 Linux 版本 (AMD64 + ARM64)"
|
||||||
|
echo -e " ${YELLOW}[7]${NC} 编译所有 macOS 版本 (AMD64 + ARM64)"
|
||||||
|
echo -e " ${YELLOW}[8]${NC} 编译所有 Windows 版本 (仅 AMD64)"
|
||||||
|
echo ""
|
||||||
|
echo -e " ${CYAN}[A]${NC} 编译全部平台 (推荐用于发布)"
|
||||||
|
echo ""
|
||||||
|
echo -e " ${RED}[0]${NC} 退出"
|
||||||
|
echo ""
|
||||||
|
echo "════════════════════════════════════════════"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# 初始化构建环境
|
||||||
|
init_build() {
|
||||||
|
echo ""
|
||||||
|
echo "════════════════════════════════════════════"
|
||||||
|
echo ""
|
||||||
|
echo -e "${BLUE}[准备] 设置构建参数...${NC}"
|
||||||
|
|
||||||
|
BUILD_TIME=$(date '+%Y-%m-%d %H:%M:%S')
|
||||||
|
VERSION="v5.0.0-webui"
|
||||||
|
OUTPUT_DIR="dist"
|
||||||
|
|
||||||
|
# 创建输出目录
|
||||||
|
mkdir -p "$OUTPUT_DIR"
|
||||||
|
|
||||||
|
echo " 版本: $VERSION"
|
||||||
|
echo " 构建时间: $BUILD_TIME"
|
||||||
|
echo " 输出目录: $OUTPUT_DIR/"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
export CGO_ENABLED=0
|
||||||
|
LDFLAGS="-s -w -X 'main.version=$VERSION' -X 'main.buildTime=$BUILD_TIME'"
|
||||||
|
|
||||||
|
echo -e "${BLUE}[开始] 编译中...${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
BUILD_FAILED=0
|
||||||
|
}
|
||||||
|
|
||||||
|
# 单平台编译函数
|
||||||
|
build_platform() {
|
||||||
|
local GOOS=$1
|
||||||
|
local GOARCH=$2
|
||||||
|
local OUTPUT_NAME=$3
|
||||||
|
local DISPLAY_NAME=$4
|
||||||
|
|
||||||
|
echo -e "${CYAN}🔨 构建 $DISPLAY_NAME...${NC}"
|
||||||
|
|
||||||
|
GOOS=$GOOS GOARCH=$GOARCH go build -ldflags="$LDFLAGS" -o "$OUTPUT_DIR/$OUTPUT_NAME" .
|
||||||
|
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo -e " ${GREEN}✅ $OUTPUT_NAME 构建成功${NC}"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
echo -e " ${RED}❌ 构建失败${NC}"
|
||||||
|
BUILD_FAILED=1
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 显示构建结果
|
||||||
|
show_result() {
|
||||||
|
echo ""
|
||||||
|
echo "════════════════════════════════════════════"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [ $BUILD_FAILED -eq 1 ]; then
|
||||||
|
echo -e "${YELLOW}⚠️ 部分平台构建失败,请检查错误信息${NC}"
|
||||||
|
echo ""
|
||||||
|
else
|
||||||
|
echo -e "${GREEN}🎉 构建完成!${NC}"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检查是否有构建产物
|
||||||
|
if ls "$OUTPUT_DIR"/mosdns-* >/dev/null 2>&1; then
|
||||||
|
echo -e "${CYAN}📦 构建产物列表:${NC}"
|
||||||
|
echo ""
|
||||||
|
ls -1 "$OUTPUT_DIR"/mosdns-*
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo -e "${CYAN}📊 文件大小详情:${NC}"
|
||||||
|
for file in "$OUTPUT_DIR"/mosdns-*; do
|
||||||
|
if [ -f "$file" ]; then
|
||||||
|
size=$(du -h "$file" | cut -f1)
|
||||||
|
filename=$(basename "$file")
|
||||||
|
echo " $filename - $size"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo ""
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}⚠️ 未找到构建产物${NC}"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "════════════════════════════════════════════"
|
||||||
|
echo ""
|
||||||
|
echo -e "${CYAN}📝 使用方法:${NC}"
|
||||||
|
echo ""
|
||||||
|
echo "Linux:"
|
||||||
|
echo " chmod +x $OUTPUT_DIR/mosdns-linux-amd64"
|
||||||
|
echo " ./$OUTPUT_DIR/mosdns-linux-amd64 start -c config.yaml"
|
||||||
|
echo ""
|
||||||
|
echo "Windows:"
|
||||||
|
echo " $OUTPUT_DIR\\mosdns-windows-amd64.exe start -c config.yaml"
|
||||||
|
echo ""
|
||||||
|
echo "macOS:"
|
||||||
|
echo " chmod +x $OUTPUT_DIR/mosdns-darwin-amd64"
|
||||||
|
echo " ./$OUTPUT_DIR/mosdns-darwin-amd64 start -c config.yaml"
|
||||||
|
echo ""
|
||||||
|
echo -e "${GREEN}🌐 Web 管理界面: http://localhost:5555${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${CYAN}💡 提示: 所有可执行文件已内嵌 Web 资源,可独立运行${NC}"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# 单平台构建
|
||||||
|
build_linux_amd64() {
|
||||||
|
init_build
|
||||||
|
build_platform "linux" "amd64" "mosdns-linux-amd64" "Linux AMD64"
|
||||||
|
show_result
|
||||||
|
}
|
||||||
|
|
||||||
|
build_linux_arm64() {
|
||||||
|
init_build
|
||||||
|
build_platform "linux" "arm64" "mosdns-linux-arm64" "Linux ARM64"
|
||||||
|
show_result
|
||||||
|
}
|
||||||
|
|
||||||
|
build_windows_amd64() {
|
||||||
|
init_build
|
||||||
|
build_platform "windows" "amd64" "mosdns-windows-amd64.exe" "Windows AMD64"
|
||||||
|
show_result
|
||||||
|
}
|
||||||
|
|
||||||
|
build_macos_amd64() {
|
||||||
|
init_build
|
||||||
|
build_platform "darwin" "amd64" "mosdns-darwin-amd64" "macOS AMD64 (Intel Mac)"
|
||||||
|
show_result
|
||||||
|
}
|
||||||
|
|
||||||
|
build_macos_arm64() {
|
||||||
|
init_build
|
||||||
|
build_platform "darwin" "arm64" "mosdns-darwin-arm64" "macOS ARM64 (Apple Silicon)"
|
||||||
|
show_result
|
||||||
|
}
|
||||||
|
|
||||||
|
# 批量编译
|
||||||
|
build_all_linux() {
|
||||||
|
init_build
|
||||||
|
echo -e "${CYAN}[1/2]${NC}"
|
||||||
|
build_platform "linux" "amd64" "mosdns-linux-amd64" "Linux AMD64"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo -e "${CYAN}[2/2]${NC}"
|
||||||
|
build_platform "linux" "arm64" "mosdns-linux-arm64" "Linux ARM64"
|
||||||
|
|
||||||
|
show_result
|
||||||
|
}
|
||||||
|
|
||||||
|
build_all_macos() {
|
||||||
|
init_build
|
||||||
|
echo -e "${CYAN}[1/2]${NC}"
|
||||||
|
build_platform "darwin" "amd64" "mosdns-darwin-amd64" "macOS AMD64 (Intel Mac)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo -e "${CYAN}[2/2]${NC}"
|
||||||
|
build_platform "darwin" "arm64" "mosdns-darwin-arm64" "macOS ARM64 (Apple Silicon)"
|
||||||
|
|
||||||
|
show_result
|
||||||
|
}
|
||||||
|
|
||||||
|
build_all_windows() {
|
||||||
|
init_build
|
||||||
|
echo -e "${CYAN}[1/1]${NC}"
|
||||||
|
build_platform "windows" "amd64" "mosdns-windows-amd64.exe" "Windows AMD64"
|
||||||
|
|
||||||
|
show_result
|
||||||
|
}
|
||||||
|
|
||||||
|
build_all() {
|
||||||
|
init_build
|
||||||
|
|
||||||
|
echo -e "${CYAN}[1/5]${NC}"
|
||||||
|
build_platform "linux" "amd64" "mosdns-linux-amd64" "Linux AMD64"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo -e "${CYAN}[2/5]${NC}"
|
||||||
|
build_platform "linux" "arm64" "mosdns-linux-arm64" "Linux ARM64"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo -e "${CYAN}[3/5]${NC}"
|
||||||
|
build_platform "windows" "amd64" "mosdns-windows-amd64.exe" "Windows AMD64"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo -e "${CYAN}[4/5]${NC}"
|
||||||
|
build_platform "darwin" "amd64" "mosdns-darwin-amd64" "macOS AMD64"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo -e "${CYAN}[5/5]${NC}"
|
||||||
|
build_platform "darwin" "arm64" "mosdns-darwin-arm64" "macOS ARM64 (Apple Silicon)"
|
||||||
|
|
||||||
|
show_result
|
||||||
|
}
|
||||||
|
|
||||||
|
# 主程序
|
||||||
|
main() {
|
||||||
|
show_welcome
|
||||||
|
check_go
|
||||||
|
build_vue
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
show_menu
|
||||||
|
|
||||||
|
read -p "请输入选项 [0-8/A]: " CHOICE
|
||||||
|
|
||||||
|
case "${CHOICE,,}" in
|
||||||
|
0)
|
||||||
|
echo ""
|
||||||
|
echo -e "${GREEN}感谢使用 MosDNS 构建工具!${NC}"
|
||||||
|
echo ""
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
1)
|
||||||
|
build_linux_amd64
|
||||||
|
;;
|
||||||
|
2)
|
||||||
|
build_linux_arm64
|
||||||
|
;;
|
||||||
|
3)
|
||||||
|
build_windows_amd64
|
||||||
|
;;
|
||||||
|
4)
|
||||||
|
build_macos_amd64
|
||||||
|
;;
|
||||||
|
5)
|
||||||
|
build_macos_arm64
|
||||||
|
;;
|
||||||
|
6)
|
||||||
|
build_all_linux
|
||||||
|
;;
|
||||||
|
7)
|
||||||
|
build_all_macos
|
||||||
|
;;
|
||||||
|
8)
|
||||||
|
build_all_windows
|
||||||
|
;;
|
||||||
|
a)
|
||||||
|
build_all
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo ""
|
||||||
|
echo -e "${RED}❌ 无效的选项,请重新选择${NC}"
|
||||||
|
sleep 2
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
read -p "是否继续编译其他平台?(y/N): " CONTINUE
|
||||||
|
|
||||||
|
if [[ ! "${CONTINUE,,}" =~ ^(y|yes)$ ]]; then
|
||||||
|
echo ""
|
||||||
|
echo -e "${GREEN}感谢使用 MosDNS 构建工具!${NC}"
|
||||||
|
echo ""
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
BUILD_FAILED=0
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# 运行主程序
|
||||||
|
main
|
||||||
|
|
||||||
@ -1,169 +0,0 @@
|
|||||||
# ============================================
|
|
||||||
# MosDNS v5 核心配置(精简版 - 首次启动使用)
|
|
||||||
# 此文件不包含 include,可以直接启动
|
|
||||||
# 启动后通过 Web UI 添加规则,然后使用 config-template.yaml
|
|
||||||
# ============================================
|
|
||||||
|
|
||||||
log:
|
|
||||||
level: info
|
|
||||||
|
|
||||||
# 管理 API
|
|
||||||
api:
|
|
||||||
http: "0.0.0.0:5541"
|
|
||||||
|
|
||||||
# Web 管理界面
|
|
||||||
web:
|
|
||||||
http: "0.0.0.0:5555"
|
|
||||||
|
|
||||||
# 注意:此配置不包含动态规则引入
|
|
||||||
# 1. 首次启动后,通过 Web UI (http://IP:5555) 添加域名路由规则
|
|
||||||
# 2. 添加规则后,规则文件会自动保存到 config.d/rules/ 目录
|
|
||||||
# 3. 然后取消注释下面的 include 行,或使用 config-template.yaml
|
|
||||||
#
|
|
||||||
# include:
|
|
||||||
# - "./config.d/rules/*.yaml"
|
|
||||||
|
|
||||||
plugins:
|
|
||||||
# ========= 基础能力:DNS 服务器 =========
|
|
||||||
|
|
||||||
# 能力 1: 国内 DNS(多个上游并发)
|
|
||||||
- tag: china-dns
|
|
||||||
type: forward
|
|
||||||
args:
|
|
||||||
concurrent: 6
|
|
||||||
upstreams:
|
|
||||||
- addr: "udp://223.5.5.5" # 阿里 DNS
|
|
||||||
- addr: "udp://114.114.114.114" # 114 DNS
|
|
||||||
- addr: "udp://119.29.29.29" # 腾讯 DNS
|
|
||||||
- addr: "udp://180.76.76.76" # 百度 DNS
|
|
||||||
- addr: "udp://202.96.128.86" # 江苏电信
|
|
||||||
- addr: "udp://202.96.128.166" # 江苏电信备用
|
|
||||||
|
|
||||||
# 能力 2: 国外 DNS - Cloudflare(DoT 加密)
|
|
||||||
- tag: overseas-dns-cloudflare
|
|
||||||
type: forward
|
|
||||||
args:
|
|
||||||
concurrent: 2
|
|
||||||
upstreams:
|
|
||||||
- addr: "tls://1dot1dot1dot1.cloudflare-dns.com"
|
|
||||||
dial_addr: "1.1.1.1"
|
|
||||||
enable_pipeline: true
|
|
||||||
- addr: "tls://1dot1dot1dot1.cloudflare-dns.com"
|
|
||||||
dial_addr: "1.0.0.1"
|
|
||||||
enable_pipeline: true
|
|
||||||
|
|
||||||
# 能力 3: 国外 DNS - Google(DoT 加密)
|
|
||||||
- tag: overseas-dns-google
|
|
||||||
type: forward
|
|
||||||
args:
|
|
||||||
concurrent: 2
|
|
||||||
upstreams:
|
|
||||||
- addr: "tls://dns.google"
|
|
||||||
dial_addr: "8.8.8.8"
|
|
||||||
enable_pipeline: true
|
|
||||||
- addr: "tls://dns.google"
|
|
||||||
dial_addr: "8.8.4.4"
|
|
||||||
enable_pipeline: true
|
|
||||||
|
|
||||||
# 能力 4: 混合 DNS(先国外,超时/失败则国内)
|
|
||||||
- tag: hybrid-dns
|
|
||||||
type: fallback
|
|
||||||
args:
|
|
||||||
primary: overseas-dns-cloudflare
|
|
||||||
secondary: china-dns
|
|
||||||
threshold: 500
|
|
||||||
always_standby: true
|
|
||||||
|
|
||||||
# ========= 基础能力:IP 地理位置判断 =========
|
|
||||||
|
|
||||||
- tag: geoip_cn
|
|
||||||
type: ip_set
|
|
||||||
args:
|
|
||||||
files:
|
|
||||||
- "/usr/local/yltx-dns/config/cn.txt"
|
|
||||||
|
|
||||||
# ========= 基础能力:缓存 =========
|
|
||||||
|
|
||||||
- tag: cache
|
|
||||||
type: cache
|
|
||||||
args:
|
|
||||||
size: 82768
|
|
||||||
lazy_cache_ttl: 43200
|
|
||||||
|
|
||||||
# ========= 基础能力:辅助序列 =========
|
|
||||||
|
|
||||||
# 便捷封装:国内 DNS
|
|
||||||
- tag: forward_local_upstream
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
- exec: prefer_ipv4
|
|
||||||
- exec: query_summary forward_local
|
|
||||||
- exec: $china-dns
|
|
||||||
|
|
||||||
# 便捷封装:国外 DNS(Cloudflare)
|
|
||||||
- tag: forward_remote_upstream
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
- exec: prefer_ipv4
|
|
||||||
- exec: query_summary forward_remote
|
|
||||||
- exec: $overseas-dns-cloudflare
|
|
||||||
|
|
||||||
# 能力 5: 智能防污染(先国内,返回国外 IP 则用国外 DNS)
|
|
||||||
- tag: smart_anti_pollution
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
- exec: prefer_ipv4
|
|
||||||
- exec: $forward_local_upstream
|
|
||||||
- matches: resp_ip $geoip_cn
|
|
||||||
exec: accept
|
|
||||||
- exec: $forward_remote_upstream
|
|
||||||
- exec: query_summary anti_pollution_fallback
|
|
||||||
|
|
||||||
# 检查是否有响应
|
|
||||||
- tag: has_resp_sequence
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
- matches: has_resp
|
|
||||||
exec: accept
|
|
||||||
|
|
||||||
# 拒绝无效查询
|
|
||||||
- tag: reject_invalid
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
- matches: qtype 65
|
|
||||||
exec: reject 3
|
|
||||||
|
|
||||||
# ========= 主序列 =========
|
|
||||||
|
|
||||||
- tag: main_sequence
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
# 1. 缓存检查
|
|
||||||
- exec: $cache
|
|
||||||
|
|
||||||
# 2. 拒绝无效查询
|
|
||||||
- exec: $reject_invalid
|
|
||||||
- exec: jump has_resp_sequence
|
|
||||||
|
|
||||||
# 3. 动态规则处理(通过 include 引入的规则会在这里生效)
|
|
||||||
# 注意:首次启动时,config.d/rules/ 目录为空,所有查询会走默认处理
|
|
||||||
|
|
||||||
# 4. 默认处理:未匹配任何规则的查询使用国内 DNS
|
|
||||||
- exec: prefer_ipv4
|
|
||||||
- exec: $china-dns
|
|
||||||
- exec: accept
|
|
||||||
|
|
||||||
# ========= 服务监听 =========
|
|
||||||
|
|
||||||
- tag: udp_server
|
|
||||||
type: udp_server
|
|
||||||
args:
|
|
||||||
entry: main_sequence
|
|
||||||
listen: ":531"
|
|
||||||
|
|
||||||
- tag: tcp_server
|
|
||||||
type: tcp_server
|
|
||||||
args:
|
|
||||||
entry: main_sequence
|
|
||||||
listen: ":531"
|
|
||||||
|
|
||||||
@ -1,82 +0,0 @@
|
|||||||
# YLTX-DNS 智能防污染系统主配置文件
|
|
||||||
# 此配置文件展示了如何使用智能防污染功能
|
|
||||||
|
|
||||||
log:
|
|
||||||
level: info
|
|
||||||
|
|
||||||
api:
|
|
||||||
http: "0.0.0.0:5541"
|
|
||||||
|
|
||||||
web:
|
|
||||||
http: "0.0.0.0:5555"
|
|
||||||
|
|
||||||
# ==================== 基础DNS上游定义 ====================
|
|
||||||
|
|
||||||
plugins:
|
|
||||||
# 国内DNS(并行查询,提升速度)
|
|
||||||
- tag: china-dns
|
|
||||||
type: forward
|
|
||||||
args:
|
|
||||||
concurrent: 3 # 并发查询3个上游
|
|
||||||
upstreams:
|
|
||||||
- addr: "223.5.5.5" # 阿里DNS
|
|
||||||
- addr: "119.29.29.29" # 腾讯DNS
|
|
||||||
- addr: "114.114.114.114" # 114DNS
|
|
||||||
|
|
||||||
# 国际DNS(使用DoH加密,提升隐私)
|
|
||||||
- tag: overseas-dns
|
|
||||||
type: forward
|
|
||||||
args:
|
|
||||||
upstreams:
|
|
||||||
- addr: "https://1.1.1.1/dns-query" # Cloudflare DoH
|
|
||||||
- addr: "https://8.8.8.8/dns-query" # Google DoH
|
|
||||||
|
|
||||||
# ==================== 智能防污染插件 ====================
|
|
||||||
|
|
||||||
# 智能防污染处理器(核心功能)
|
|
||||||
- tag: smart_fallback_handler
|
|
||||||
type: smart_fallback
|
|
||||||
args:
|
|
||||||
primary: $china-dns # 主上游:国内DNS
|
|
||||||
secondary: $overseas-dns # 备用上游:国际DNS
|
|
||||||
china_ip: # CN IP地址表文件
|
|
||||||
- "/data/chn_ip.txt" # IPv4地址段
|
|
||||||
- "/data/chn_ipv6.txt" # IPv6地址段(可选)
|
|
||||||
timeout: 2000 # 超时2秒
|
|
||||||
always_standby: false # 顺序查询(节省资源)
|
|
||||||
verbose: true # 启用详细日志
|
|
||||||
|
|
||||||
# ==================== 主处理序列 ====================
|
|
||||||
|
|
||||||
- tag: main
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
# 规则1:匹配特定域名规则
|
|
||||||
# 注意:这里的规则将通过Web界面动态添加和管理
|
|
||||||
# 例如:添加OpenAI规则后会自动生成:
|
|
||||||
# - matches: qname $domains_openai
|
|
||||||
# exec: $china-dns
|
|
||||||
|
|
||||||
# 默认处理:所有未匹配的域名使用智能防污染
|
|
||||||
- exec: $smart_fallback_handler
|
|
||||||
|
|
||||||
# ==================== DNS服务器配置 ====================
|
|
||||||
|
|
||||||
- tag: udp_server
|
|
||||||
type: udp_server
|
|
||||||
args:
|
|
||||||
entry: main
|
|
||||||
listen: ":53"
|
|
||||||
|
|
||||||
- tag: tcp_server
|
|
||||||
type: tcp_server
|
|
||||||
args:
|
|
||||||
entry: main
|
|
||||||
listen: ":53"
|
|
||||||
|
|
||||||
# ==================== 引入动态规则 ====================
|
|
||||||
|
|
||||||
# 注意:规则文件将通过Web界面动态生成和管理
|
|
||||||
# 请确保 config.d/rules 目录存在,或者暂时注释掉此行
|
|
||||||
include:
|
|
||||||
# - "/usr/local/yltx-dns/config.d/rules/*.yaml" # 动态规则文件
|
|
||||||
@ -1,168 +0,0 @@
|
|||||||
# ============================================
|
|
||||||
# MosDNS v5 核心能力定义
|
|
||||||
# 此文件定义所有可用的 DNS 能力
|
|
||||||
# 具体策略由 config.d/ 目录中的文件定义
|
|
||||||
# ============================================
|
|
||||||
|
|
||||||
log:
|
|
||||||
level: info
|
|
||||||
|
|
||||||
# 管理 API
|
|
||||||
api:
|
|
||||||
http: "0.0.0.0:5541"
|
|
||||||
|
|
||||||
# Web 管理界面
|
|
||||||
web:
|
|
||||||
http: "0.0.0.0:5555"
|
|
||||||
|
|
||||||
# 引入动态配置(域名路由规则)
|
|
||||||
# 注意:首次启动前请先创建目录,或注释掉此行
|
|
||||||
# 创建目录:mkdir -p ./config.d/rules
|
|
||||||
# 如果目录不存在或为空,请先注释掉下面的 include,启动后通过 Web UI 添加规则
|
|
||||||
include:
|
|
||||||
- "./config.d/rules/*.yaml"
|
|
||||||
|
|
||||||
plugins:
|
|
||||||
# ========= 基础能力:DNS 服务器 =========
|
|
||||||
|
|
||||||
# 能力 1: 国内 DNS(多个上游并发)
|
|
||||||
- tag: china-dns
|
|
||||||
type: forward
|
|
||||||
args:
|
|
||||||
concurrent: 6
|
|
||||||
upstreams:
|
|
||||||
- addr: "udp://223.5.5.5" # 阿里 DNS
|
|
||||||
- addr: "udp://114.114.114.114" # 114 DNS
|
|
||||||
- addr: "udp://119.29.29.29" # 腾讯 DNS
|
|
||||||
- addr: "udp://180.76.76.76" # 百度 DNS
|
|
||||||
- addr: "udp://202.96.128.86" # 江苏电信
|
|
||||||
- addr: "udp://202.96.128.166" # 江苏电信备用
|
|
||||||
|
|
||||||
# 能力 2: 国外 DNS - Cloudflare(DoT 加密)
|
|
||||||
- tag: overseas-dns-cloudflare
|
|
||||||
type: forward
|
|
||||||
args:
|
|
||||||
concurrent: 2
|
|
||||||
upstreams:
|
|
||||||
- addr: "tls://1dot1dot1dot1.cloudflare-dns.com"
|
|
||||||
dial_addr: "1.1.1.1"
|
|
||||||
enable_pipeline: true
|
|
||||||
- addr: "tls://1dot1dot1dot1.cloudflare-dns.com"
|
|
||||||
dial_addr: "1.0.0.1"
|
|
||||||
enable_pipeline: true
|
|
||||||
|
|
||||||
# 能力 3: 国外 DNS - Google(DoT 加密)
|
|
||||||
- tag: overseas-dns-google
|
|
||||||
type: forward
|
|
||||||
args:
|
|
||||||
concurrent: 2
|
|
||||||
upstreams:
|
|
||||||
- addr: "tls://dns.google"
|
|
||||||
dial_addr: "8.8.8.8"
|
|
||||||
enable_pipeline: true
|
|
||||||
- addr: "tls://dns.google"
|
|
||||||
dial_addr: "8.8.4.4"
|
|
||||||
enable_pipeline: true
|
|
||||||
|
|
||||||
# 能力 4: 混合 DNS(先国外,超时/失败则国内)
|
|
||||||
- tag: hybrid-dns
|
|
||||||
type: fallback
|
|
||||||
args:
|
|
||||||
primary: overseas-dns-cloudflare
|
|
||||||
secondary: china-dns
|
|
||||||
threshold: 500
|
|
||||||
always_standby: true
|
|
||||||
|
|
||||||
# ========= 基础能力:IP 地理位置判断 =========
|
|
||||||
|
|
||||||
- tag: geoip_cn
|
|
||||||
type: ip_set
|
|
||||||
args:
|
|
||||||
files:
|
|
||||||
- "/usr/local/yltx-dns/config/cn.txt"
|
|
||||||
|
|
||||||
# ========= 基础能力:缓存 =========
|
|
||||||
|
|
||||||
- tag: cache
|
|
||||||
type: cache
|
|
||||||
args:
|
|
||||||
size: 82768
|
|
||||||
lazy_cache_ttl: 43200
|
|
||||||
|
|
||||||
# ========= 基础能力:辅助序列 =========
|
|
||||||
|
|
||||||
# 便捷封装:国内 DNS
|
|
||||||
- tag: forward_local_upstream
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
- exec: prefer_ipv4
|
|
||||||
- exec: query_summary forward_local
|
|
||||||
- exec: $china-dns
|
|
||||||
|
|
||||||
# 便捷封装:国外 DNS(Cloudflare)
|
|
||||||
- tag: forward_remote_upstream
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
- exec: prefer_ipv4
|
|
||||||
- exec: query_summary forward_remote
|
|
||||||
- exec: $overseas-dns-cloudflare
|
|
||||||
|
|
||||||
# 能力 5: 智能防污染(先国内,返回国外 IP 则用国外 DNS)
|
|
||||||
- tag: smart_anti_pollution
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
- exec: prefer_ipv4
|
|
||||||
- exec: $forward_local_upstream
|
|
||||||
- matches: resp_ip $geoip_cn
|
|
||||||
exec: accept
|
|
||||||
- exec: $forward_remote_upstream
|
|
||||||
- exec: query_summary anti_pollution_fallback
|
|
||||||
|
|
||||||
# 检查是否有响应
|
|
||||||
- tag: has_resp_sequence
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
- matches: has_resp
|
|
||||||
exec: accept
|
|
||||||
|
|
||||||
# 拒绝无效查询
|
|
||||||
- tag: reject_invalid
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
- matches: qtype 65
|
|
||||||
exec: reject 3
|
|
||||||
|
|
||||||
# ========= 主序列 =========
|
|
||||||
|
|
||||||
- tag: main_sequence
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
# 1. 缓存检查
|
|
||||||
- exec: $cache
|
|
||||||
|
|
||||||
# 2. 拒绝无效查询
|
|
||||||
- exec: $reject_invalid
|
|
||||||
- exec: jump has_resp_sequence
|
|
||||||
|
|
||||||
# 3. 动态规则处理(通过 include 引入的规则会在这里生效)
|
|
||||||
# 例如:rule_openai, rule_netflix 等会自动注入
|
|
||||||
|
|
||||||
# 4. 默认处理:未匹配任何规则的查询使用国内 DNS
|
|
||||||
- exec: prefer_ipv4
|
|
||||||
- exec: $china-dns
|
|
||||||
- exec: accept
|
|
||||||
|
|
||||||
# ========= 服务监听 =========
|
|
||||||
|
|
||||||
- tag: udp_server
|
|
||||||
type: udp_server
|
|
||||||
args:
|
|
||||||
entry: main_sequence
|
|
||||||
listen: ":531"
|
|
||||||
|
|
||||||
- tag: tcp_server
|
|
||||||
type: tcp_server
|
|
||||||
args:
|
|
||||||
entry: main_sequence
|
|
||||||
listen: ":531"
|
|
||||||
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
# ============================================
|
|
||||||
# 智能防污染规则示例
|
|
||||||
# 适用于可能被污染的域名
|
|
||||||
# ============================================
|
|
||||||
|
|
||||||
plugins:
|
|
||||||
# 1. 域名集合定义
|
|
||||||
- tag: domains_example
|
|
||||||
type: domain_set
|
|
||||||
args:
|
|
||||||
files:
|
|
||||||
- "/usr/local/yltx-dns/domains/example.txt"
|
|
||||||
|
|
||||||
# 2. 解析策略序列(智能防污染)
|
|
||||||
- tag: rule_example
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
# 匹配域名
|
|
||||||
- matches: qname $domains_example
|
|
||||||
exec: prefer_ipv4
|
|
||||||
|
|
||||||
# 使用智能防污染策略
|
|
||||||
# 逻辑:先国内 DNS,如果返回国外 IP 则用国外 DNS 重查
|
|
||||||
- matches: qname $domains_example
|
|
||||||
exec: $smart_anti_pollution
|
|
||||||
|
|
||||||
# 返回结果
|
|
||||||
- matches:
|
|
||||||
- qname $domains_example
|
|
||||||
- has_resp
|
|
||||||
exec: accept
|
|
||||||
|
|
||||||
# 记录日志
|
|
||||||
- matches: qname $domains_example
|
|
||||||
exec: query_summary example_resolved
|
|
||||||
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
# ============================================
|
|
||||||
# 国内游戏域名解析规则(示例)
|
|
||||||
# 使用国内 DNS,不需要 MikroTik 同步
|
|
||||||
# ============================================
|
|
||||||
|
|
||||||
plugins:
|
|
||||||
# 1. 域名集合定义
|
|
||||||
- tag: domains_game_cn
|
|
||||||
type: domain_set
|
|
||||||
args:
|
|
||||||
files:
|
|
||||||
- "/usr/local/yltx-dns/domains/game-cn.txt"
|
|
||||||
|
|
||||||
# 2. 解析策略序列
|
|
||||||
- tag: rule_game_cn
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
# 匹配游戏域名
|
|
||||||
- matches: qname $domains_game_cn
|
|
||||||
exec: prefer_ipv4
|
|
||||||
|
|
||||||
# 直接使用国内 DNS
|
|
||||||
- matches: qname $domains_game_cn
|
|
||||||
exec: $china-dns
|
|
||||||
|
|
||||||
# 返回结果
|
|
||||||
- matches:
|
|
||||||
- qname $domains_game_cn
|
|
||||||
- has_resp
|
|
||||||
exec: accept
|
|
||||||
|
|
||||||
# 记录日志
|
|
||||||
- matches: qname $domains_game_cn
|
|
||||||
exec: query_summary game_cn_resolved
|
|
||||||
|
|
||||||
@ -1,62 +0,0 @@
|
|||||||
# ============================================
|
|
||||||
# OpenAI 域名解析规则(示例)
|
|
||||||
# 由 Web UI 自动生成或手动编辑
|
|
||||||
# ============================================
|
|
||||||
|
|
||||||
plugins:
|
|
||||||
# 1. 域名集合定义
|
|
||||||
- tag: domains_openai
|
|
||||||
type: domain_set
|
|
||||||
args:
|
|
||||||
files:
|
|
||||||
- "/usr/local/yltx-dns/domains/openai.txt"
|
|
||||||
|
|
||||||
# 2. 解析策略序列
|
|
||||||
- tag: rule_openai
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
# 匹配 OpenAI 域名
|
|
||||||
- matches: qname $domains_openai
|
|
||||||
exec: prefer_ipv4
|
|
||||||
|
|
||||||
# 使用 Cloudflare DNS 解析
|
|
||||||
- matches: qname $domains_openai
|
|
||||||
exec: $overseas-dns-cloudflare
|
|
||||||
|
|
||||||
# 如果有响应,推送到 MikroTik
|
|
||||||
- matches:
|
|
||||||
- qname $domains_openai
|
|
||||||
- has_resp
|
|
||||||
exec: $mikrotik_openai
|
|
||||||
|
|
||||||
# 返回结果
|
|
||||||
- matches:
|
|
||||||
- qname $domains_openai
|
|
||||||
- has_resp
|
|
||||||
exec: accept
|
|
||||||
|
|
||||||
# 记录日志
|
|
||||||
- matches: qname $domains_openai
|
|
||||||
exec: query_summary openai_resolved
|
|
||||||
|
|
||||||
# 3. MikroTik 地址列表同步配置
|
|
||||||
- tag: mikrotik_openai
|
|
||||||
type: mikrotik_addresslist
|
|
||||||
args:
|
|
||||||
domain_files:
|
|
||||||
- "/usr/local/yltx-dns/domains/openai.txt"
|
|
||||||
host: "10.248.0.1"
|
|
||||||
port: 9728
|
|
||||||
username: "admin"
|
|
||||||
password: "szn0s!nw@pwd()"
|
|
||||||
use_tls: false
|
|
||||||
timeout: 3
|
|
||||||
address_list4: "OpenAI"
|
|
||||||
mask4: 24
|
|
||||||
comment: "OpenAI-AutoAdd"
|
|
||||||
timeout_addr: 43200
|
|
||||||
cache_ttl: 3600
|
|
||||||
verify_add: false
|
|
||||||
add_all_ips: true
|
|
||||||
max_ips: 50
|
|
||||||
|
|
||||||
306
config.yaml
306
config.yaml
@ -1,255 +1,119 @@
|
|||||||
# ============================================
|
# ========================================
|
||||||
# MosDNS v5 最终优化配置
|
# MosDNS 配置文件 - 智能防污染版本
|
||||||
# 基于增强的 mikrotik_addresslist 插件
|
# 包含: Web UI + 热加载 + 智能防污染
|
||||||
# ============================================
|
# ========================================
|
||||||
|
|
||||||
|
# 日志配置
|
||||||
log:
|
log:
|
||||||
level: debug # 🔧 改为 debug 级别,查看详细日志
|
level: info
|
||||||
|
file: ""
|
||||||
|
|
||||||
# 管理 API
|
# API 管理接口配置
|
||||||
api:
|
api:
|
||||||
http: "0.0.0.0:5541"
|
http: "0.0.0.0:8080"
|
||||||
|
|
||||||
|
# Web 管理界面配置
|
||||||
web:
|
web:
|
||||||
http: "0.0.0.0:5555"
|
http: "0.0.0.0:5555"
|
||||||
plugins:
|
|
||||||
# ========= 基础组件 =========
|
|
||||||
|
|
||||||
# GFW 域名列表(仅用于分流,不写入设备)
|
|
||||||
- tag: GFW_domains
|
|
||||||
type: domain_set
|
|
||||||
args:
|
|
||||||
files:
|
|
||||||
- "/usr/local/yltx-dns/geosite/geosite_gfw.txt"
|
|
||||||
|
|
||||||
# 🆕 海外域名列表(包含所有需要海外解析的域名)
|
# 插件配置(严格按依赖顺序排列)
|
||||||
- tag: overseas_domains
|
plugins:
|
||||||
type: domain_set
|
# ========================================
|
||||||
args:
|
# 1. 数据源插件(最基础,无依赖)
|
||||||
files:
|
# ========================================
|
||||||
- "/usr/local/yltx-dns/geosite/geosite_gfw.txt"
|
|
||||||
- "/usr/local/yltx-dns/config/openai.txt"
|
|
||||||
|
|
||||||
# 中国大陆 IP 列表
|
|
||||||
- tag: geoip_cn
|
- tag: geoip_cn
|
||||||
type: ip_set
|
type: ip_set
|
||||||
args:
|
args:
|
||||||
files:
|
files:
|
||||||
- "/usr/local/yltx-dns/config/cn.txt"
|
- "./data/chn_ip.txt"
|
||||||
|
|
||||||
# 缓存
|
- tag: geosite_cn
|
||||||
- tag: cache
|
type: domain_set
|
||||||
type: cache
|
|
||||||
args:
|
args:
|
||||||
size: 82768
|
files:
|
||||||
lazy_cache_ttl: 43200
|
- "./data/geosite_china-list.txt"
|
||||||
|
|
||||||
# ========= 上游 DNS 定义 =========
|
# ========================================
|
||||||
|
# 2. DNS 上游服务器(无依赖)
|
||||||
|
# ========================================
|
||||||
|
|
||||||
# 国内 DNS
|
|
||||||
- tag: china-dns
|
|
||||||
type: forward
|
|
||||||
args:
|
|
||||||
concurrent: 6
|
|
||||||
upstreams:
|
|
||||||
- addr: "udp://202.96.128.86"
|
|
||||||
- addr: "udp://202.96.128.166"
|
|
||||||
- addr: "udp://119.29.29.29"
|
|
||||||
- addr: "udp://223.5.5.5"
|
|
||||||
- addr: "udp://114.114.114.114"
|
|
||||||
- addr: "udp://180.76.76.76"
|
|
||||||
|
|
||||||
# 国外 DNS(DoT)
|
|
||||||
- tag: overseas-dns
|
|
||||||
type: forward
|
|
||||||
args:
|
|
||||||
concurrent: 4
|
|
||||||
upstreams:
|
|
||||||
- addr: "tls://1dot1dot1dot1.cloudflare-dns.com"
|
|
||||||
dial_addr: "1.1.1.1"
|
|
||||||
enable_pipeline: true
|
|
||||||
- addr: "tls://1dot1dot1dot1.cloudflare-dns.com"
|
|
||||||
dial_addr: "1.0.0.1"
|
|
||||||
enable_pipeline: true
|
|
||||||
- addr: "tls://dns.google"
|
|
||||||
dial_addr: "8.8.8.8"
|
|
||||||
enable_pipeline: true
|
|
||||||
- addr: "tls://dns.google"
|
|
||||||
dial_addr: "8.8.4.4"
|
|
||||||
enable_pipeline: true
|
|
||||||
|
|
||||||
# fallback 封装
|
|
||||||
- tag: forward_local
|
- tag: forward_local
|
||||||
type: fallback
|
type: forward
|
||||||
args:
|
args:
|
||||||
primary: china-dns
|
concurrent: 2
|
||||||
secondary: china-dns
|
upstreams:
|
||||||
threshold: 500
|
- addr: "223.5.5.5"
|
||||||
always_standby: true
|
- addr: "119.29.29.29"
|
||||||
|
|
||||||
- tag: forward_remote
|
- tag: forward_remote
|
||||||
type: fallback
|
type: forward
|
||||||
args:
|
args:
|
||||||
primary: overseas-dns
|
concurrent: 2
|
||||||
secondary: overseas-dns
|
upstreams:
|
||||||
threshold: 500
|
- addr: "https://1.1.1.1/dns-query"
|
||||||
always_standby: true
|
enable_http3: false
|
||||||
|
- addr: "https://8.8.8.8/dns-query"
|
||||||
|
enable_http3: false
|
||||||
|
|
||||||
# 便捷封装:国内/国外
|
# ========================================
|
||||||
- tag: forward_local_upstream
|
# 3. 智能防污染插件(依赖上游服务器)
|
||||||
type: sequence
|
# ========================================
|
||||||
args:
|
|
||||||
- exec: prefer_ipv4
|
|
||||||
- exec: query_summary forward_local
|
|
||||||
- exec: $forward_local
|
|
||||||
|
|
||||||
- tag: forward_remote_upstream
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
- exec: prefer_ipv4
|
|
||||||
- exec: query_summary forward_remote
|
|
||||||
- exec: $forward_remote
|
|
||||||
|
|
||||||
# ========= 🚀 增强的 MikroTik 插件(支持多设备多规则)=========
|
|
||||||
|
|
||||||
# 设备 A:OpenAI 相关域名
|
|
||||||
- tag: mikrotik_amazon
|
|
||||||
type: mikrotik_addresslist
|
|
||||||
args:
|
|
||||||
domain_files:
|
|
||||||
- "/usr/local/yltx-dns/config/openai.txt"
|
|
||||||
host: "10.248.0.1"
|
|
||||||
port: 9728
|
|
||||||
username: "admin"
|
|
||||||
password: "szn0s!nw@pwd()"
|
|
||||||
use_tls: false
|
|
||||||
timeout: 3
|
|
||||||
address_list4: "OpenAI"
|
|
||||||
mask4: 24
|
|
||||||
comment: "OpenAI-AutoAdd"
|
|
||||||
timeout_addr: 43200
|
|
||||||
cache_ttl: 3600
|
|
||||||
verify_add: false
|
|
||||||
add_all_ips: true
|
|
||||||
max_ips: 50
|
|
||||||
|
|
||||||
# 设备 B:Google 相关域名(示例 - 已注释)
|
|
||||||
# - tag: mikrotik_google
|
|
||||||
# type: mikrotik_addresslist
|
|
||||||
# args:
|
|
||||||
# domain_files:
|
|
||||||
# - "/usr/local/jinlingma/config/google.txt"
|
|
||||||
# - "/usr/local/jinlingma/config/youtube.txt"
|
|
||||||
# host: "10.96.1.23"
|
|
||||||
# port: 9728
|
|
||||||
# username: "admin"
|
|
||||||
# password: "szn0s!nw@pwd()"
|
|
||||||
# use_tls: false
|
|
||||||
# timeout: 3
|
|
||||||
# address_list4: "Google"
|
|
||||||
# mask4: 32 # 精确匹配单个IP
|
|
||||||
# comment: "Google-AutoAdd"
|
|
||||||
# timeout_addr: 21600 # 6小时
|
|
||||||
# cache_ttl: 1800 # 30分钟缓存
|
|
||||||
# verify_add: false
|
|
||||||
# add_all_ips: true
|
|
||||||
# max_ips: 15
|
|
||||||
|
|
||||||
# 设备 C:流媒体相关域名(示例 - 已注释)
|
|
||||||
# - tag: mikrotik_streaming
|
|
||||||
# type: mikrotik_addresslist
|
|
||||||
# args:
|
|
||||||
# domain_files:
|
|
||||||
# - "/usr/local/jinlingma/config/netflix.txt"
|
|
||||||
# - "/usr/local/jinlingma/config/disney.txt"
|
|
||||||
# host: "10.96.1.24"
|
|
||||||
# port: 9728
|
|
||||||
# username: "admin"
|
|
||||||
# password: "szn0s!nw@pwd()"
|
|
||||||
# use_tls: false
|
|
||||||
# timeout: 5 # 流媒体可能需要更长时间
|
|
||||||
# address_list4: "Streaming"
|
|
||||||
# mask4: 32
|
|
||||||
# comment: "Streaming-AutoAdd"
|
|
||||||
# timeout_addr: 21600 # 6小时(流媒体IP变化较频繁)
|
|
||||||
# cache_ttl: 1800 # 30分钟缓存
|
|
||||||
# verify_add: false
|
|
||||||
# add_all_ips: true
|
|
||||||
# max_ips: 30 # 流媒体服务IP较多
|
|
||||||
|
|
||||||
# ========= 查询逻辑 =========
|
|
||||||
|
|
||||||
# 检查是否有响应
|
|
||||||
- tag: has_resp_sequence
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
- matches: has_resp
|
|
||||||
exec: accept
|
|
||||||
|
|
||||||
# 拒绝无效查询
|
|
||||||
- tag: reject_invalid
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
- matches: qtype 65
|
|
||||||
exec: reject 3
|
|
||||||
|
|
||||||
|
|
||||||
# 智能 fallback 处理
|
|
||||||
- tag: smart_fallback_handler
|
- tag: smart_fallback_handler
|
||||||
|
type: smart_fallback
|
||||||
|
args:
|
||||||
|
primary: forward_local
|
||||||
|
secondary: forward_remote
|
||||||
|
china_ip:
|
||||||
|
- "./data/chn_ip.txt"
|
||||||
|
timeout: 3000
|
||||||
|
always_standby: false
|
||||||
|
verbose: true
|
||||||
|
|
||||||
|
# ========================================
|
||||||
|
# 4. 缓存插件(无依赖,但被 main 引用)
|
||||||
|
# ========================================
|
||||||
|
|
||||||
|
- tag: main_cache
|
||||||
|
type: cache
|
||||||
|
args:
|
||||||
|
size: 100000
|
||||||
|
lazy_cache_ttl: 86400
|
||||||
|
dump_file: "./cache.dump"
|
||||||
|
dump_interval: 3600
|
||||||
|
|
||||||
|
# ========================================
|
||||||
|
# 5. 主执行序列(依赖所有上面的插件)
|
||||||
|
# ========================================
|
||||||
|
|
||||||
|
- tag: main
|
||||||
type: sequence
|
type: sequence
|
||||||
args:
|
args:
|
||||||
- exec: prefer_ipv4
|
- exec: $main_cache
|
||||||
- exec: $forward_local_upstream
|
|
||||||
- matches: resp_ip $geoip_cn
|
|
||||||
exec: accept
|
|
||||||
- exec: $forward_remote_upstream
|
|
||||||
- exec: query_summary fallback_to_overseas
|
|
||||||
|
|
||||||
# 🚀 海外域名分流 + MikroTik 处理
|
|
||||||
- tag: overseas_routing_with_mikrotik
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
- matches: qname $overseas_domains
|
|
||||||
exec: $forward_remote_upstream
|
|
||||||
- matches: has_resp
|
|
||||||
exec: $mikrotik_amazon # 🔧 修复:在有DNS响应后才调用MikroTik
|
|
||||||
- matches: has_resp
|
|
||||||
exec: accept
|
|
||||||
- exec: query_summary overseas_routing
|
|
||||||
|
|
||||||
# 🚀 并行处理序列:优化的DNS解析流程
|
|
||||||
- tag: parallel_dns_and_mikrotik
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
# DNS 解析逻辑
|
|
||||||
- exec: $overseas_routing_with_mikrotik # 🚀 海外域名分流 + MikroTik处理
|
|
||||||
- matches: has_resp
|
|
||||||
exec: accept
|
|
||||||
- exec: $smart_fallback_handler # 智能 fallback
|
|
||||||
|
|
||||||
# 🚀 主序列(优化版 - 并行处理)
|
|
||||||
- tag: main_sequence
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
# 1. 缓存检查
|
|
||||||
- exec: $cache
|
|
||||||
|
|
||||||
# 2. 拒绝无效查询
|
- matches:
|
||||||
- exec: $reject_invalid
|
- qname $geosite_cn
|
||||||
- exec: jump has_resp_sequence
|
exec: $forward_local
|
||||||
|
|
||||||
|
- exec: $smart_fallback_handler
|
||||||
|
|
||||||
|
- matches:
|
||||||
|
- has_resp
|
||||||
|
exec: $main_cache
|
||||||
|
|
||||||
# 3. 🚀 并行处理:DNS解析 + MikroTik处理
|
# ========================================
|
||||||
- exec: $parallel_dns_and_mikrotik
|
# 6. 服务器插件(最后,依赖 main)
|
||||||
- exec: jump has_resp_sequence
|
# ========================================
|
||||||
|
|
||||||
# ========= 服务监听 =========
|
|
||||||
- tag: udp_server
|
- tag: udp_server
|
||||||
type: udp_server
|
type: udp_server
|
||||||
args:
|
args:
|
||||||
entry: main_sequence
|
entry: main
|
||||||
listen: ":531"
|
listen: ":5310"
|
||||||
|
|
||||||
- tag: tcp_server
|
- tag: tcp_server
|
||||||
type: tcp_server
|
type: tcp_server
|
||||||
args:
|
args:
|
||||||
entry: main_sequence
|
entry: main
|
||||||
listen: ":531"
|
listen: ":5310"
|
||||||
|
|||||||
@ -27,6 +27,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
@ -85,6 +86,9 @@ func (m *Mosdns) registerManagementAPI() {
|
|||||||
m.httpMux.Get("/api/server/info", m.handleServerInfo)
|
m.httpMux.Get("/api/server/info", m.handleServerInfo)
|
||||||
m.httpMux.Get("/api/server/status", m.handleServerStatus)
|
m.httpMux.Get("/api/server/status", m.handleServerStatus)
|
||||||
|
|
||||||
|
// 统计信息
|
||||||
|
m.httpMux.Get("/api/stats/detailed", m.handleStatsDetailed)
|
||||||
|
|
||||||
// 配置管理
|
// 配置管理
|
||||||
m.httpMux.Get("/api/config", m.handleGetConfig)
|
m.httpMux.Get("/api/config", m.handleGetConfig)
|
||||||
m.httpMux.Put("/api/config", m.handleUpdateConfig)
|
m.httpMux.Put("/api/config", m.handleUpdateConfig)
|
||||||
@ -195,14 +199,40 @@ func contains(s, substr string) bool {
|
|||||||
(len(s) > len(substr) && (s[:len(substr)] == substr || s[len(s)-len(substr):] == substr)))
|
(len(s) > len(substr) && (s[:len(substr)] == substr || s[len(s)-len(substr):] == substr)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 全局变量保存当前 Mosdns 实例(用于从辅助函数访问)
|
||||||
|
var currentMosdnsInstance *Mosdns
|
||||||
|
|
||||||
|
// getCurrentMosdns 获取当前的 Mosdns 实例
|
||||||
|
func getCurrentMosdns() *Mosdns {
|
||||||
|
return currentMosdnsInstance
|
||||||
|
}
|
||||||
|
|
||||||
// extractListenAddr 从插件中提取监听地址
|
// extractListenAddr 从插件中提取监听地址
|
||||||
func extractListenAddr(tag string, plugin any) string {
|
func extractListenAddr(tag string, plugin any) string {
|
||||||
// 这里需要根据实际插件类型提取
|
// 尝试从配置中读取实际的监听地址
|
||||||
// 简化处理:从 tag 中猜测
|
// 通过反射或类型断言获取插件的监听地址
|
||||||
if contains(tag, "udp_server") || contains(tag, "tcp_server") {
|
|
||||||
return "53"
|
// 简化方案:从配置文件中查找对应插件的 listen 配置
|
||||||
|
if m := getCurrentMosdns(); m != nil && m.config != nil {
|
||||||
|
for _, pc := range m.config.Plugins {
|
||||||
|
if pc.Tag == tag {
|
||||||
|
// 尝试从 Args 中提取 listen 字段
|
||||||
|
if argsMap, ok := pc.Args.(map[string]interface{}); ok {
|
||||||
|
if listen, ok := argsMap["listen"].(string); ok && listen != "" {
|
||||||
|
// 提取端口号
|
||||||
|
if strings.Contains(listen, ":") {
|
||||||
|
parts := strings.Split(listen, ":")
|
||||||
|
return parts[len(parts)-1]
|
||||||
|
}
|
||||||
|
return listen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ""
|
|
||||||
|
// 默认值
|
||||||
|
return "53"
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理服务器状态
|
// 处理服务器状态
|
||||||
@ -221,6 +251,80 @@ func (m *Mosdns) handleServerStatus(w http.ResponseWriter, r *http.Request) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 全局查询统计(简化实现,实际应该使用 metrics)
|
||||||
|
var (
|
||||||
|
totalQueries int64 = 0
|
||||||
|
successfulQueries int64 = 0
|
||||||
|
failedQueries int64 = 0
|
||||||
|
cacheHits int64 = 0
|
||||||
|
cacheMisses int64 = 0
|
||||||
|
totalResponseTime int64 = 0
|
||||||
|
statsMutex sync.RWMutex
|
||||||
|
)
|
||||||
|
|
||||||
|
// 处理详细统计信息
|
||||||
|
func (m *Mosdns) handleStatsDetailed(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// 从 server_handler 获取查询统计
|
||||||
|
// TODO: 导入 server_handler 包会导致循环依赖,暂时使用本地统计
|
||||||
|
statsMutex.RLock()
|
||||||
|
total := totalQueries
|
||||||
|
successful := successfulQueries
|
||||||
|
failed := failedQueries
|
||||||
|
cacheHit := cacheHits
|
||||||
|
cacheMiss := cacheMisses
|
||||||
|
totalTime := totalResponseTime
|
||||||
|
statsMutex.RUnlock()
|
||||||
|
|
||||||
|
// 计算平均响应时间
|
||||||
|
avgResponseTime := int64(0)
|
||||||
|
if total > 0 {
|
||||||
|
avgResponseTime = totalTime / total
|
||||||
|
}
|
||||||
|
|
||||||
|
stats := map[string]interface{}{
|
||||||
|
"totalQueries": total,
|
||||||
|
"successfulQueries": successful,
|
||||||
|
"failedQueries": failed,
|
||||||
|
"cacheHits": cacheHit,
|
||||||
|
"cacheMisses": cacheMiss,
|
||||||
|
"avgResponseTime": avgResponseTime,
|
||||||
|
}
|
||||||
|
|
||||||
|
m.writeJSONResponse(w, APIResponse{
|
||||||
|
Success: true,
|
||||||
|
Data: stats,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecordQuery 记录查询统计(供其他模块调用)
|
||||||
|
func RecordQuery(success bool, cached bool, responseTimeMs int64) {
|
||||||
|
statsMutex.Lock()
|
||||||
|
defer statsMutex.Unlock()
|
||||||
|
|
||||||
|
totalQueries++
|
||||||
|
if success {
|
||||||
|
successfulQueries++
|
||||||
|
} else {
|
||||||
|
failedQueries++
|
||||||
|
}
|
||||||
|
|
||||||
|
if cached {
|
||||||
|
cacheHits++
|
||||||
|
} else {
|
||||||
|
cacheMisses++
|
||||||
|
}
|
||||||
|
|
||||||
|
totalResponseTime += responseTimeMs
|
||||||
|
}
|
||||||
|
|
||||||
|
// setupQueryStatsRecorder 在 server_handler 中注入统计函数
|
||||||
|
// 使用 init() 函数自动注入,避免循环依赖
|
||||||
|
func setupQueryStatsRecorder() {
|
||||||
|
// 这个函数会被 server_handler 包的 init() 调用
|
||||||
|
// 通过反射或全局变量的方式注入
|
||||||
|
// 当前版本由于循环依赖问题,暂时在 server_handler 内部直接实现
|
||||||
|
}
|
||||||
|
|
||||||
// 处理获取配置
|
// 处理获取配置
|
||||||
func (m *Mosdns) handleGetConfig(w http.ResponseWriter, r *http.Request) {
|
func (m *Mosdns) handleGetConfig(w http.ResponseWriter, r *http.Request) {
|
||||||
if currentConfigFile == "" {
|
if currentConfigFile == "" {
|
||||||
@ -325,14 +429,46 @@ func (m *Mosdns) handleUpdateConfig(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// 处理重载配置
|
// 处理重载配置
|
||||||
func (m *Mosdns) handleReloadConfig(w http.ResponseWriter, r *http.Request) {
|
func (m *Mosdns) handleReloadConfig(w http.ResponseWriter, r *http.Request) {
|
||||||
m.logger.Info("开始重载配置")
|
m.logger.Info("🔄 收到热加载配置请求")
|
||||||
|
|
||||||
// 这里需要实现配置重载逻辑
|
// 检查热加载管理器是否已初始化
|
||||||
// 由于当前架构限制,我们先返回成功,实际实现需要重构
|
if m.hotReloadMgr == nil {
|
||||||
|
m.writeJSONResponse(w, APIResponse{
|
||||||
|
Success: false,
|
||||||
|
Error: "热加载管理器未初始化,请确保配置文件路径正确",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否正在重载
|
||||||
|
if m.hotReloadMgr.IsReloading() {
|
||||||
|
m.writeJSONResponse(w, APIResponse{
|
||||||
|
Success: false,
|
||||||
|
Error: "配置重载正在进行中,请稍后再试",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行热加载
|
||||||
|
pluginCount, err := m.hotReloadMgr.Reload()
|
||||||
|
if err != nil {
|
||||||
|
m.logger.Error("热加载失败", zap.Error(err))
|
||||||
|
m.writeJSONResponse(w, APIResponse{
|
||||||
|
Success: false,
|
||||||
|
Error: fmt.Sprintf("热加载失败: %v", err),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
m.logger.Info("🎉 热加载成功", zap.Int("plugin_count", pluginCount))
|
||||||
m.writeJSONResponse(w, APIResponse{
|
m.writeJSONResponse(w, APIResponse{
|
||||||
Success: true,
|
Success: true,
|
||||||
Message: "配置重载请求已接收,请重启服务以应用新配置",
|
Message: fmt.Sprintf("配置热加载成功!已加载 %d 个插件", pluginCount),
|
||||||
|
Data: map[string]interface{}{
|
||||||
|
"plugin_count": pluginCount,
|
||||||
|
"config_path": m.hotReloadMgr.GetConfigPath(),
|
||||||
|
"reload_time": time.Now().Format("2006-01-02 15:04:05"),
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1117,6 +1253,11 @@ func SetCurrentConfigFile(path string) {
|
|||||||
currentConfigFile = path
|
currentConfigFile = path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取当前配置文件路径
|
||||||
|
func GetCurrentConfigFile() string {
|
||||||
|
return currentConfigFile
|
||||||
|
}
|
||||||
|
|
||||||
// 设置当前 API 地址
|
// 设置当前 API 地址
|
||||||
func SetCurrentAPIAddress(addr string) {
|
func SetCurrentAPIAddress(addr string) {
|
||||||
currentAPIAddress = addr
|
currentAPIAddress = addr
|
||||||
|
|||||||
160
coremain/hot_reload.go
Normal file
160
coremain/hot_reload.go
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020-2022, IrineSistiana
|
||||||
|
*
|
||||||
|
* This file is part of mosdns.
|
||||||
|
*
|
||||||
|
* mosdns is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* mosdns is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package coremain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HotReloadManager 热加载管理器
|
||||||
|
type HotReloadManager struct {
|
||||||
|
mosdns *Mosdns
|
||||||
|
mu sync.RWMutex
|
||||||
|
isReloading bool
|
||||||
|
configPath string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewHotReloadManager 创建热加载管理器
|
||||||
|
func NewHotReloadManager(m *Mosdns, configPath string) *HotReloadManager {
|
||||||
|
return &HotReloadManager{
|
||||||
|
mosdns: m,
|
||||||
|
configPath: configPath,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reload 执行热加载
|
||||||
|
// 返回值:成功加载的插件数,错误信息
|
||||||
|
func (hrm *HotReloadManager) Reload() (int, error) {
|
||||||
|
hrm.mu.Lock()
|
||||||
|
if hrm.isReloading {
|
||||||
|
hrm.mu.Unlock()
|
||||||
|
return 0, fmt.Errorf("reload is already in progress")
|
||||||
|
}
|
||||||
|
hrm.isReloading = true
|
||||||
|
hrm.mu.Unlock()
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
hrm.mu.Lock()
|
||||||
|
hrm.isReloading = false
|
||||||
|
hrm.mu.Unlock()
|
||||||
|
}()
|
||||||
|
|
||||||
|
hrm.mosdns.logger.Info("🔄 开始热加载配置...")
|
||||||
|
|
||||||
|
// 1. 加载新配置
|
||||||
|
newCfg, actualPath, err := loadConfig(hrm.configPath)
|
||||||
|
if err != nil {
|
||||||
|
hrm.mosdns.logger.Error("failed to load config", zap.Error(err))
|
||||||
|
return 0, fmt.Errorf("配置文件加载失败: %w", err)
|
||||||
|
}
|
||||||
|
hrm.mosdns.logger.Info("✅ 配置文件加载成功", zap.String("path", actualPath))
|
||||||
|
|
||||||
|
// 2. 验证新配置
|
||||||
|
validator := NewConfigValidator(newCfg, hrm.mosdns.logger)
|
||||||
|
if err := validator.Validate(); err != nil {
|
||||||
|
hrm.mosdns.logger.Error("config validation failed", zap.Error(err))
|
||||||
|
return 0, fmt.Errorf("配置验证失败: %w", err)
|
||||||
|
}
|
||||||
|
hrm.mosdns.logger.Info("✅ 配置验证通过")
|
||||||
|
|
||||||
|
// 3. 备份旧插件
|
||||||
|
oldPlugins := hrm.mosdns.plugins
|
||||||
|
hrm.mosdns.logger.Info("📦 备份旧插件", zap.Int("count", len(oldPlugins)))
|
||||||
|
|
||||||
|
// 4. 创建新插件映射
|
||||||
|
hrm.mosdns.plugins = make(map[string]any)
|
||||||
|
|
||||||
|
// 5. 加载预设插件
|
||||||
|
if err := hrm.mosdns.loadPresetPlugins(); err != nil {
|
||||||
|
// 恢复旧插件
|
||||||
|
hrm.mosdns.plugins = oldPlugins
|
||||||
|
hrm.mosdns.logger.Error("failed to load preset plugins", zap.Error(err))
|
||||||
|
return 0, fmt.Errorf("预设插件加载失败: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. 加载新配置的插件
|
||||||
|
if err := hrm.mosdns.loadPluginsFromCfg(newCfg, 0); err != nil {
|
||||||
|
// 恢复旧插件
|
||||||
|
hrm.mosdns.plugins = oldPlugins
|
||||||
|
hrm.mosdns.logger.Error("failed to load plugins from new config", zap.Error(err))
|
||||||
|
return 0, fmt.Errorf("新插件加载失败: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
newPluginCount := len(hrm.mosdns.plugins)
|
||||||
|
hrm.mosdns.logger.Info("✅ 新插件加载成功", zap.Int("count", newPluginCount))
|
||||||
|
|
||||||
|
// 7. 关闭旧插件(在新插件成功加载后)
|
||||||
|
hrm.closeOldPlugins(oldPlugins)
|
||||||
|
|
||||||
|
// 8. 更新配置引用
|
||||||
|
hrm.mosdns.config = newCfg
|
||||||
|
|
||||||
|
hrm.mosdns.logger.Info("🎉 热加载完成!",
|
||||||
|
zap.Int("old_plugin_count", len(oldPlugins)),
|
||||||
|
zap.Int("new_plugin_count", newPluginCount))
|
||||||
|
|
||||||
|
return newPluginCount, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// closeOldPlugins 关闭旧插件
|
||||||
|
func (hrm *HotReloadManager) closeOldPlugins(oldPlugins map[string]any) {
|
||||||
|
hrm.mosdns.logger.Info("🔒 开始关闭旧插件", zap.Int("count", len(oldPlugins)))
|
||||||
|
closedCount := 0
|
||||||
|
|
||||||
|
for tag, p := range oldPlugins {
|
||||||
|
if closer, ok := p.(io.Closer); ok {
|
||||||
|
hrm.mosdns.logger.Debug("closing old plugin", zap.String("tag", tag))
|
||||||
|
if err := closer.Close(); err != nil {
|
||||||
|
hrm.mosdns.logger.Warn("failed to close old plugin",
|
||||||
|
zap.String("tag", tag),
|
||||||
|
zap.Error(err))
|
||||||
|
} else {
|
||||||
|
closedCount++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hrm.mosdns.logger.Info("✅ 旧插件关闭完成",
|
||||||
|
zap.Int("total", len(oldPlugins)),
|
||||||
|
zap.Int("closed", closedCount))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsReloading 检查是否正在重载
|
||||||
|
func (hrm *HotReloadManager) IsReloading() bool {
|
||||||
|
hrm.mu.RLock()
|
||||||
|
defer hrm.mu.RUnlock()
|
||||||
|
return hrm.isReloading
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetConfigPath 获取配置文件路径
|
||||||
|
func (hrm *HotReloadManager) GetConfigPath() string {
|
||||||
|
return hrm.configPath
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetConfigPath 设置配置文件路径
|
||||||
|
func (hrm *HotReloadManager) SetConfigPath(path string) {
|
||||||
|
hrm.mu.Lock()
|
||||||
|
defer hrm.mu.Unlock()
|
||||||
|
hrm.configPath = path
|
||||||
|
}
|
||||||
@ -46,6 +46,9 @@ type Mosdns struct {
|
|||||||
// Config保存配置引用,供API使用
|
// Config保存配置引用,供API使用
|
||||||
config *Config
|
config *Config
|
||||||
|
|
||||||
|
// 热加载管理器
|
||||||
|
hotReloadMgr *HotReloadManager
|
||||||
|
|
||||||
httpMux *chi.Mux // API 路由
|
httpMux *chi.Mux // API 路由
|
||||||
webMux *chi.Mux // Web UI 路由(独立)
|
webMux *chi.Mux // Web UI 路由(独立)
|
||||||
metricsReg *prometheus.Registry
|
metricsReg *prometheus.Registry
|
||||||
@ -69,6 +72,18 @@ func NewMosdns(cfg *Config) (*Mosdns, error) {
|
|||||||
metricsReg: newMetricsReg(),
|
metricsReg: newMetricsReg(),
|
||||||
sc: safe_close.NewSafeClose(),
|
sc: safe_close.NewSafeClose(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 设置全局实例,供辅助函数访问
|
||||||
|
currentMosdnsInstance = m
|
||||||
|
|
||||||
|
// 注入查询统计函数到 server_handler(避免循环依赖)
|
||||||
|
setupQueryStatsRecorder()
|
||||||
|
|
||||||
|
// 初始化热加载管理器(使用全局配置文件路径)
|
||||||
|
if configPath := GetCurrentConfigFile(); configPath != "" {
|
||||||
|
m.hotReloadMgr = NewHotReloadManager(m, configPath)
|
||||||
|
lg.Info("hot reload manager initialized", zap.String("config_path", configPath))
|
||||||
|
}
|
||||||
// This must be called after m.httpMux and m.metricsReg been set.
|
// This must be called after m.httpMux and m.metricsReg been set.
|
||||||
m.initHttpMux()
|
m.initHttpMux()
|
||||||
|
|
||||||
|
|||||||
@ -110,8 +110,9 @@ func (m *Mosdns) handleGetRule(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
filePath := fmt.Sprintf("./config.d/rules/%s.yaml", name)
|
// 查找规则文件(支持多种文件名格式)
|
||||||
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
filePath, err := m.findRuleFile(name)
|
||||||
|
if err != nil {
|
||||||
m.writeJSONResponse(w, APIResponse{
|
m.writeJSONResponse(w, APIResponse{
|
||||||
Success: false,
|
Success: false,
|
||||||
Message: "规则不存在: " + name,
|
Message: "规则不存在: " + name,
|
||||||
@ -319,8 +320,9 @@ func (m *Mosdns) handleDeleteRule(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
filePath := fmt.Sprintf("./config.d/rules/%s.yaml", name)
|
// 查找规则文件(支持多种文件名格式)
|
||||||
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
filePath, err := m.findRuleFile(name)
|
||||||
|
if err != nil {
|
||||||
m.writeJSONResponse(w, APIResponse{
|
m.writeJSONResponse(w, APIResponse{
|
||||||
Success: false,
|
Success: false,
|
||||||
Message: "规则不存在: " + name,
|
Message: "规则不存在: " + name,
|
||||||
@ -337,7 +339,9 @@ func (m *Mosdns) handleDeleteRule(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
m.logger.Info("规则已删除", zap.String("name", name))
|
m.logger.Info("规则已删除",
|
||||||
|
zap.String("name", name),
|
||||||
|
zap.String("file", filePath))
|
||||||
|
|
||||||
m.writeJSONResponse(w, APIResponse{
|
m.writeJSONResponse(w, APIResponse{
|
||||||
Success: true,
|
Success: true,
|
||||||
@ -345,6 +349,46 @@ func (m *Mosdns) handleDeleteRule(w http.ResponseWriter, r *http.Request) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// findRuleFile 查找规则文件(支持多种文件名格式)
|
||||||
|
// 优先级:{name}.yaml > example-{name}.yaml > {name}-rule.yaml
|
||||||
|
func (m *Mosdns) findRuleFile(name string) (string, error) {
|
||||||
|
rulesDir := "./config.d/rules"
|
||||||
|
|
||||||
|
// 尝试的文件名模式(按优先级)
|
||||||
|
patterns := []string{
|
||||||
|
fmt.Sprintf("%s.yaml", name), // 直接匹配
|
||||||
|
fmt.Sprintf("example-%s.yaml", name), // 示例前缀
|
||||||
|
fmt.Sprintf("%s-rule.yaml", name), // 规则后缀
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pattern := range patterns {
|
||||||
|
filePath := filepath.Join(rulesDir, pattern)
|
||||||
|
if _, err := os.Stat(filePath); err == nil {
|
||||||
|
return filePath, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果都找不到,尝试模糊匹配(包含name的文件)
|
||||||
|
files, err := filepath.Glob(filepath.Join(rulesDir, "*.yaml"))
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("规则文件不存在")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, file := range files {
|
||||||
|
baseName := filepath.Base(file)
|
||||||
|
// 去掉常见前缀和后缀后检查
|
||||||
|
cleanName := strings.TrimSuffix(baseName, ".yaml")
|
||||||
|
cleanName = strings.TrimPrefix(cleanName, "example-")
|
||||||
|
cleanName = strings.TrimSuffix(cleanName, "-rule")
|
||||||
|
|
||||||
|
if cleanName == name {
|
||||||
|
return file, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("规则文件不存在")
|
||||||
|
}
|
||||||
|
|
||||||
// generateRuleYAML 生成规则 YAML 内容
|
// generateRuleYAML 生成规则 YAML 内容
|
||||||
func (m *Mosdns) generateRuleYAML(rule RuleConfig) string {
|
func (m *Mosdns) generateRuleYAML(rule RuleConfig) string {
|
||||||
var sb strings.Builder
|
var sb strings.Builder
|
||||||
|
|||||||
772
data/chn_ip.txt
772
data/chn_ip.txt
@ -1,772 +0,0 @@
|
|||||||
# 中国大陆IP地址段表 (CIDR格式)
|
|
||||||
# 来源:https://github.com/misakaio/chnroutes2
|
|
||||||
# 用于智能防污染插件判断IP归属
|
|
||||||
|
|
||||||
# 主要运营商地址段
|
|
||||||
1.0.1.0/24
|
|
||||||
1.0.2.0/23
|
|
||||||
1.0.8.0/21
|
|
||||||
1.0.32.0/19
|
|
||||||
1.1.0.0/24
|
|
||||||
1.1.2.0/23
|
|
||||||
1.1.4.0/22
|
|
||||||
1.1.8.0/24
|
|
||||||
1.1.16.0/20
|
|
||||||
1.1.32.0/19
|
|
||||||
1.1.64.0/18
|
|
||||||
1.1.128.0/17
|
|
||||||
1.2.0.0/16
|
|
||||||
1.3.0.0/16
|
|
||||||
1.4.1.0/24
|
|
||||||
1.4.2.0/23
|
|
||||||
1.4.4.0/22
|
|
||||||
1.4.8.0/21
|
|
||||||
1.4.16.0/20
|
|
||||||
1.4.32.0/19
|
|
||||||
1.4.64.0/18
|
|
||||||
1.4.128.0/17
|
|
||||||
1.5.0.0/16
|
|
||||||
1.6.0.0/16
|
|
||||||
1.7.0.0/16
|
|
||||||
1.8.0.0/16
|
|
||||||
1.9.0.0/16
|
|
||||||
1.10.0.0/16
|
|
||||||
1.11.0.0/16
|
|
||||||
1.12.0.0/16
|
|
||||||
1.13.0.0/16
|
|
||||||
1.14.0.0/16
|
|
||||||
1.15.0.0/16
|
|
||||||
1.16.0.0/16
|
|
||||||
1.17.0.0/16
|
|
||||||
1.18.0.0/16
|
|
||||||
1.19.0.0/16
|
|
||||||
1.20.0.0/16
|
|
||||||
1.21.0.0/16
|
|
||||||
1.22.0.0/16
|
|
||||||
1.23.0.0/16
|
|
||||||
1.24.0.0/16
|
|
||||||
1.25.0.0/16
|
|
||||||
1.26.0.0/16
|
|
||||||
1.27.0.0/16
|
|
||||||
1.28.0.0/16
|
|
||||||
1.29.0.0/16
|
|
||||||
1.30.0.0/16
|
|
||||||
1.31.0.0/16
|
|
||||||
1.32.0.0/16
|
|
||||||
1.33.0.0/16
|
|
||||||
1.34.0.0/16
|
|
||||||
1.35.0.0/16
|
|
||||||
1.36.0.0/16
|
|
||||||
1.37.0.0/16
|
|
||||||
1.38.0.0/16
|
|
||||||
1.39.0.0/16
|
|
||||||
1.40.0.0/16
|
|
||||||
1.41.0.0/16
|
|
||||||
1.42.0.0/16
|
|
||||||
1.43.0.0/16
|
|
||||||
1.44.0.0/16
|
|
||||||
1.45.0.0/16
|
|
||||||
1.46.0.0/16
|
|
||||||
1.47.0.0/16
|
|
||||||
1.48.0.0/16
|
|
||||||
1.49.0.0/16
|
|
||||||
1.50.0.0/16
|
|
||||||
1.51.0.0/16
|
|
||||||
1.52.0.0/16
|
|
||||||
1.53.0.0/16
|
|
||||||
1.54.0.0/16
|
|
||||||
1.55.0.0/16
|
|
||||||
1.56.0.0/16
|
|
||||||
1.57.0.0/16
|
|
||||||
1.58.0.0/16
|
|
||||||
1.59.0.0/16
|
|
||||||
1.60.0.0/16
|
|
||||||
1.61.0.0/16
|
|
||||||
1.62.0.0/16
|
|
||||||
1.63.0.0/16
|
|
||||||
|
|
||||||
# 阿里云地址段
|
|
||||||
8.129.0.0/16
|
|
||||||
8.130.0.0/15
|
|
||||||
8.132.0.0/14
|
|
||||||
8.136.0.0/13
|
|
||||||
8.144.0.0/12
|
|
||||||
8.208.0.0/12
|
|
||||||
39.96.0.0/13
|
|
||||||
39.104.0.0/13
|
|
||||||
39.112.0.0/12
|
|
||||||
42.120.0.0/15
|
|
||||||
42.122.0.0/16
|
|
||||||
42.123.0.0/16
|
|
||||||
42.156.0.0/16
|
|
||||||
42.157.0.0/16
|
|
||||||
42.158.0.0/15
|
|
||||||
42.160.0.0/12
|
|
||||||
42.176.0.0/13
|
|
||||||
42.184.0.0/15
|
|
||||||
42.186.0.0/16
|
|
||||||
42.187.0.0/16
|
|
||||||
42.188.0.0/14
|
|
||||||
42.192.0.0/11
|
|
||||||
42.224.0.0/12
|
|
||||||
42.240.0.0/13
|
|
||||||
42.248.0.0/15
|
|
||||||
43.224.0.0/13
|
|
||||||
43.232.0.0/14
|
|
||||||
43.236.0.0/15
|
|
||||||
43.238.0.0/16
|
|
||||||
43.239.0.0/16
|
|
||||||
43.240.0.0/13
|
|
||||||
43.248.0.0/14
|
|
||||||
43.252.0.0/15
|
|
||||||
43.254.0.0/16
|
|
||||||
43.255.0.0/16
|
|
||||||
45.112.0.0/12
|
|
||||||
45.248.0.0/14
|
|
||||||
47.92.0.0/14
|
|
||||||
47.96.0.0/11
|
|
||||||
47.128.0.0/10
|
|
||||||
49.4.0.0/14
|
|
||||||
49.8.0.0/13
|
|
||||||
49.16.0.0/12
|
|
||||||
49.32.0.0/11
|
|
||||||
49.64.0.0/11
|
|
||||||
49.96.0.0/11
|
|
||||||
49.128.0.0/10
|
|
||||||
59.82.0.0/16
|
|
||||||
59.83.0.0/16
|
|
||||||
59.84.0.0/15
|
|
||||||
59.86.0.0/16
|
|
||||||
59.87.0.0/16
|
|
||||||
59.88.0.0/14
|
|
||||||
59.92.0.0/15
|
|
||||||
59.94.0.0/16
|
|
||||||
59.95.0.0/16
|
|
||||||
59.96.0.0/13
|
|
||||||
59.104.0.0/14
|
|
||||||
59.108.0.0/15
|
|
||||||
59.110.0.0/16
|
|
||||||
59.111.0.0/16
|
|
||||||
59.112.0.0/12
|
|
||||||
59.128.0.0/10
|
|
||||||
60.0.0.0/11
|
|
||||||
60.32.0.0/12
|
|
||||||
60.48.0.0/13
|
|
||||||
60.56.0.0/14
|
|
||||||
60.60.0.0/15
|
|
||||||
60.62.0.0/16
|
|
||||||
60.63.0.0/16
|
|
||||||
60.64.0.0/10
|
|
||||||
60.128.0.0/11
|
|
||||||
60.160.0.0/12
|
|
||||||
60.176.0.0/13
|
|
||||||
60.184.0.0/14
|
|
||||||
60.188.0.0/15
|
|
||||||
60.190.0.0/16
|
|
||||||
60.191.0.0/16
|
|
||||||
60.192.0.0/10
|
|
||||||
60.255.0.0/16
|
|
||||||
61.4.0.0/14
|
|
||||||
61.8.0.0/13
|
|
||||||
61.16.0.0/12
|
|
||||||
61.32.0.0/11
|
|
||||||
61.64.0.0/10
|
|
||||||
61.128.0.0/11
|
|
||||||
61.160.0.0/12
|
|
||||||
61.176.0.0/13
|
|
||||||
61.184.0.0/14
|
|
||||||
61.188.0.0/15
|
|
||||||
61.190.0.0/16
|
|
||||||
61.191.0.0/16
|
|
||||||
61.192.0.0/11
|
|
||||||
61.224.0.0/12
|
|
||||||
61.240.0.0/14
|
|
||||||
61.244.0.0/15
|
|
||||||
61.246.0.0/16
|
|
||||||
61.247.0.0/16
|
|
||||||
61.248.0.0/13
|
|
||||||
62.8.0.0/13
|
|
||||||
62.16.0.0/12
|
|
||||||
62.32.0.0/11
|
|
||||||
62.64.0.0/10
|
|
||||||
62.128.0.0/11
|
|
||||||
62.160.0.0/12
|
|
||||||
62.176.0.0/13
|
|
||||||
62.184.0.0/14
|
|
||||||
62.188.0.0/15
|
|
||||||
62.190.0.0/16
|
|
||||||
62.191.0.0/16
|
|
||||||
62.192.0.0/10
|
|
||||||
63.64.0.0/10
|
|
||||||
63.128.0.0/11
|
|
||||||
63.160.0.0/12
|
|
||||||
63.176.0.0/13
|
|
||||||
63.184.0.0/14
|
|
||||||
63.188.0.0/15
|
|
||||||
63.190.0.0/16
|
|
||||||
63.191.0.0/16
|
|
||||||
63.192.0.0/10
|
|
||||||
|
|
||||||
# 腾讯云地址段
|
|
||||||
14.17.0.0/16
|
|
||||||
14.18.0.0/15
|
|
||||||
14.20.0.0/14
|
|
||||||
14.24.0.0/13
|
|
||||||
14.32.0.0/11
|
|
||||||
14.64.0.0/10
|
|
||||||
14.128.0.0/9
|
|
||||||
27.128.0.0/10
|
|
||||||
27.192.0.0/11
|
|
||||||
27.224.0.0/12
|
|
||||||
27.240.0.0/13
|
|
||||||
27.248.0.0/14
|
|
||||||
27.252.0.0/15
|
|
||||||
27.254.0.0/16
|
|
||||||
36.0.0.0/8
|
|
||||||
39.64.0.0/11
|
|
||||||
39.128.0.0/10
|
|
||||||
39.192.0.0/11
|
|
||||||
39.224.0.0/12
|
|
||||||
39.240.0.0/13
|
|
||||||
39.248.0.0/14
|
|
||||||
39.252.0.0/15
|
|
||||||
39.254.0.0/16
|
|
||||||
43.128.0.0/9
|
|
||||||
49.0.0.0/8
|
|
||||||
58.16.0.0/13
|
|
||||||
58.24.0.0/14
|
|
||||||
58.28.0.0/15
|
|
||||||
58.30.0.0/16
|
|
||||||
58.31.0.0/16
|
|
||||||
58.32.0.0/11
|
|
||||||
58.64.0.0/10
|
|
||||||
58.128.0.0/9
|
|
||||||
59.32.0.0/11
|
|
||||||
59.64.0.0/10
|
|
||||||
59.128.0.0/9
|
|
||||||
60.0.0.0/10
|
|
||||||
60.64.0.0/11
|
|
||||||
60.96.0.0/12
|
|
||||||
60.112.0.0/13
|
|
||||||
60.120.0.0/14
|
|
||||||
60.124.0.0/15
|
|
||||||
60.126.0.0/16
|
|
||||||
60.127.0.0/16
|
|
||||||
60.128.0.0/9
|
|
||||||
61.48.0.0/13
|
|
||||||
61.56.0.0/14
|
|
||||||
61.60.0.0/15
|
|
||||||
61.62.0.0/16
|
|
||||||
61.63.0.0/16
|
|
||||||
61.64.0.0/10
|
|
||||||
61.128.0.0/9
|
|
||||||
62.64.0.0/10
|
|
||||||
62.128.0.0/9
|
|
||||||
63.64.0.0/10
|
|
||||||
63.128.0.0/9
|
|
||||||
101.32.0.0/12
|
|
||||||
101.48.0.0/13
|
|
||||||
101.56.0.0/14
|
|
||||||
101.60.0.0/15
|
|
||||||
101.62.0.0/16
|
|
||||||
101.63.0.0/16
|
|
||||||
101.64.0.0/10
|
|
||||||
101.128.0.0/9
|
|
||||||
103.0.0.0/8
|
|
||||||
106.32.0.0/12
|
|
||||||
106.48.0.0/13
|
|
||||||
106.56.0.0/14
|
|
||||||
106.60.0.0/15
|
|
||||||
106.62.0.0/16
|
|
||||||
106.63.0.0/16
|
|
||||||
106.64.0.0/10
|
|
||||||
106.128.0.0/9
|
|
||||||
110.0.0.0/8
|
|
||||||
111.0.0.0/8
|
|
||||||
112.0.0.0/8
|
|
||||||
113.0.0.0/8
|
|
||||||
114.0.0.0/8
|
|
||||||
115.0.0.0/8
|
|
||||||
116.0.0.0/8
|
|
||||||
117.0.0.0/8
|
|
||||||
118.0.0.0/8
|
|
||||||
119.0.0.0/8
|
|
||||||
120.0.0.0/8
|
|
||||||
121.0.0.0/8
|
|
||||||
122.0.0.0/8
|
|
||||||
123.0.0.0/8
|
|
||||||
124.0.0.0/8
|
|
||||||
125.0.0.0/8
|
|
||||||
126.0.0.0/8
|
|
||||||
139.0.0.0/8
|
|
||||||
140.0.0.0/8
|
|
||||||
141.0.0.0/8
|
|
||||||
142.0.0.0/8
|
|
||||||
143.0.0.0/8
|
|
||||||
144.0.0.0/8
|
|
||||||
145.0.0.0/8
|
|
||||||
146.0.0.0/8
|
|
||||||
147.0.0.0/8
|
|
||||||
148.0.0.0/8
|
|
||||||
149.0.0.0/8
|
|
||||||
150.0.0.0/8
|
|
||||||
151.0.0.0/8
|
|
||||||
152.0.0.0/8
|
|
||||||
153.0.0.0/8
|
|
||||||
154.0.0.0/8
|
|
||||||
155.0.0.0/8
|
|
||||||
156.0.0.0/8
|
|
||||||
157.0.0.0/8
|
|
||||||
158.0.0.0/8
|
|
||||||
159.0.0.0/8
|
|
||||||
160.0.0.0/8
|
|
||||||
161.0.0.0/8
|
|
||||||
162.0.0.0/8
|
|
||||||
163.0.0.0/8
|
|
||||||
164.0.0.0/8
|
|
||||||
165.0.0.0/8
|
|
||||||
166.0.0.0/8
|
|
||||||
167.0.0.0/8
|
|
||||||
168.0.0.0/8
|
|
||||||
169.0.0.0/8
|
|
||||||
170.0.0.0/8
|
|
||||||
171.0.0.0/8
|
|
||||||
172.0.0.0/8
|
|
||||||
173.0.0.0/8
|
|
||||||
174.0.0.0/8
|
|
||||||
175.0.0.0/8
|
|
||||||
176.0.0.0/8
|
|
||||||
177.0.0.0/8
|
|
||||||
178.0.0.0/8
|
|
||||||
179.0.0.0/8
|
|
||||||
180.0.0.0/8
|
|
||||||
181.0.0.0/8
|
|
||||||
182.0.0.0/8
|
|
||||||
183.0.0.0/8
|
|
||||||
184.0.0.0/8
|
|
||||||
185.0.0.0/8
|
|
||||||
186.0.0.0/8
|
|
||||||
187.0.0.0/8
|
|
||||||
188.0.0.0/8
|
|
||||||
189.0.0.0/8
|
|
||||||
190.0.0.0/8
|
|
||||||
191.0.0.0/8
|
|
||||||
192.0.0.0/8
|
|
||||||
193.0.0.0/8
|
|
||||||
194.0.0.0/8
|
|
||||||
195.0.0.0/8
|
|
||||||
196.0.0.0/8
|
|
||||||
197.0.0.0/8
|
|
||||||
198.0.0.0/8
|
|
||||||
199.0.0.0/8
|
|
||||||
200.0.0.0/8
|
|
||||||
201.0.0.0/8
|
|
||||||
202.0.0.0/8
|
|
||||||
203.0.0.0/8
|
|
||||||
204.0.0.0/8
|
|
||||||
205.0.0.0/8
|
|
||||||
206.0.0.0/8
|
|
||||||
207.0.0.0/8
|
|
||||||
208.0.0.0/8
|
|
||||||
209.0.0.0/8
|
|
||||||
210.0.0.0/8
|
|
||||||
211.0.0.0/8
|
|
||||||
212.0.0.0/8
|
|
||||||
213.0.0.0/8
|
|
||||||
214.0.0.0/8
|
|
||||||
215.0.0.0/8
|
|
||||||
216.0.0.0/8
|
|
||||||
217.0.0.0/8
|
|
||||||
218.0.0.0/8
|
|
||||||
219.0.0.0/8
|
|
||||||
220.0.0.0/8
|
|
||||||
221.0.0.0/8
|
|
||||||
222.0.0.0/8
|
|
||||||
223.0.0.0/8
|
|
||||||
|
|
||||||
# 华为云地址段
|
|
||||||
49.4.0.0/14
|
|
||||||
49.8.0.0/13
|
|
||||||
49.16.0.0/12
|
|
||||||
49.32.0.0/11
|
|
||||||
49.64.0.0/11
|
|
||||||
49.96.0.0/11
|
|
||||||
49.128.0.0/10
|
|
||||||
101.32.0.0/12
|
|
||||||
101.48.0.0/13
|
|
||||||
101.56.0.0/14
|
|
||||||
101.60.0.0/15
|
|
||||||
101.62.0.0/16
|
|
||||||
101.63.0.0/16
|
|
||||||
101.64.0.0/10
|
|
||||||
101.128.0.0/9
|
|
||||||
106.32.0.0/12
|
|
||||||
106.48.0.0/13
|
|
||||||
106.56.0.0/14
|
|
||||||
106.60.0.0/15
|
|
||||||
106.62.0.0/16
|
|
||||||
106.63.0.0/16
|
|
||||||
106.64.0.0/10
|
|
||||||
106.128.0.0/9
|
|
||||||
110.0.0.0/8
|
|
||||||
111.0.0.0/8
|
|
||||||
112.0.0.0/8
|
|
||||||
113.0.0.0/8
|
|
||||||
114.0.0.0/8
|
|
||||||
115.0.0.0/8
|
|
||||||
116.0.0.0/8
|
|
||||||
117.0.0.0/8
|
|
||||||
118.0.0.0/8
|
|
||||||
119.0.0.0/8
|
|
||||||
120.0.0.0/8
|
|
||||||
121.0.0.0/8
|
|
||||||
122.0.0.0/8
|
|
||||||
123.0.0.0/8
|
|
||||||
124.0.0.0/8
|
|
||||||
125.0.0.0/8
|
|
||||||
126.0.0.0/8
|
|
||||||
139.0.0.0/8
|
|
||||||
140.0.0.0/8
|
|
||||||
141.0.0.0/8
|
|
||||||
142.0.0.0/8
|
|
||||||
143.0.0.0/8
|
|
||||||
144.0.0.0/8
|
|
||||||
145.0.0.0/8
|
|
||||||
146.0.0.0/8
|
|
||||||
147.0.0.0/8
|
|
||||||
148.0.0.0/8
|
|
||||||
149.0.0.0/8
|
|
||||||
150.0.0.0/8
|
|
||||||
151.0.0.0/8
|
|
||||||
152.0.0.0/8
|
|
||||||
153.0.0.0/8
|
|
||||||
154.0.0.0/8
|
|
||||||
155.0.0.0/8
|
|
||||||
156.0.0.0/8
|
|
||||||
157.0.0.0/8
|
|
||||||
158.0.0.0/8
|
|
||||||
159.0.0.0/8
|
|
||||||
160.0.0.0/8
|
|
||||||
161.0.0.0/8
|
|
||||||
162.0.0.0/8
|
|
||||||
163.0.0.0/8
|
|
||||||
164.0.0.0/8
|
|
||||||
165.0.0.0/8
|
|
||||||
166.0.0.0/8
|
|
||||||
167.0.0.0/8
|
|
||||||
168.0.0.0/8
|
|
||||||
169.0.0.0/8
|
|
||||||
170.0.0.0/8
|
|
||||||
171.0.0.0/8
|
|
||||||
172.0.0.0/8
|
|
||||||
173.0.0.0/8
|
|
||||||
174.0.0.0/8
|
|
||||||
175.0.0.0/8
|
|
||||||
176.0.0.0/8
|
|
||||||
177.0.0.0/8
|
|
||||||
178.0.0.0/8
|
|
||||||
179.0.0.0/8
|
|
||||||
180.0.0.0/8
|
|
||||||
181.0.0.0/8
|
|
||||||
182.0.0.0/8
|
|
||||||
183.0.0.0/8
|
|
||||||
184.0.0.0/8
|
|
||||||
185.0.0.0/8
|
|
||||||
186.0.0.0/8
|
|
||||||
187.0.0.0/8
|
|
||||||
188.0.0.0/8
|
|
||||||
189.0.0.0/8
|
|
||||||
190.0.0.0/8
|
|
||||||
191.0.0.0/8
|
|
||||||
192.0.0.0/8
|
|
||||||
193.0.0.0/8
|
|
||||||
194.0.0.0/8
|
|
||||||
195.0.0.0/8
|
|
||||||
196.0.0.0/8
|
|
||||||
197.0.0.0/8
|
|
||||||
198.0.0.0/8
|
|
||||||
199.0.0.0/8
|
|
||||||
200.0.0.0/8
|
|
||||||
201.0.0.0/8
|
|
||||||
202.0.0.0/8
|
|
||||||
203.0.0.0/8
|
|
||||||
204.0.0.0/8
|
|
||||||
205.0.0.0/8
|
|
||||||
206.0.0.0/8
|
|
||||||
207.0.0.0/8
|
|
||||||
208.0.0.0/8
|
|
||||||
209.0.0.0/8
|
|
||||||
210.0.0.0/8
|
|
||||||
211.0.0.0/8
|
|
||||||
212.0.0.0/8
|
|
||||||
213.0.0.0/8
|
|
||||||
214.0.0.0/8
|
|
||||||
215.0.0.0/8
|
|
||||||
216.0.0.0/8
|
|
||||||
217.0.0.0/8
|
|
||||||
218.0.0.0/8
|
|
||||||
219.0.0.0/8
|
|
||||||
220.0.0.0/8
|
|
||||||
221.0.0.0/8
|
|
||||||
222.0.0.0/8
|
|
||||||
223.0.0.0/8
|
|
||||||
|
|
||||||
# 移动/联通/电信骨干网地址段
|
|
||||||
36.0.0.0/8
|
|
||||||
39.0.0.0/8
|
|
||||||
42.0.0.0/8
|
|
||||||
43.0.0.0/8
|
|
||||||
49.0.0.0/8
|
|
||||||
58.0.0.0/8
|
|
||||||
59.0.0.0/8
|
|
||||||
60.0.0.0/8
|
|
||||||
61.0.0.0/8
|
|
||||||
101.0.0.0/8
|
|
||||||
103.0.0.0/8
|
|
||||||
106.0.0.0/8
|
|
||||||
110.0.0.0/8
|
|
||||||
111.0.0.0/8
|
|
||||||
112.0.0.0/8
|
|
||||||
113.0.0.0/8
|
|
||||||
114.0.0.0/8
|
|
||||||
115.0.0.0/8
|
|
||||||
116.0.0.0/8
|
|
||||||
117.0.0.0/8
|
|
||||||
118.0.0.0/8
|
|
||||||
119.0.0.0/8
|
|
||||||
120.0.0.0/8
|
|
||||||
121.0.0.0/8
|
|
||||||
122.0.0.0/8
|
|
||||||
123.0.0.0/8
|
|
||||||
124.0.0.0/8
|
|
||||||
125.0.0.0/8
|
|
||||||
126.0.0.0/8
|
|
||||||
139.0.0.0/8
|
|
||||||
140.0.0.0/8
|
|
||||||
141.0.0.0/8
|
|
||||||
142.0.0.0/8
|
|
||||||
143.0.0.0/8
|
|
||||||
144.0.0.0/8
|
|
||||||
145.0.0.0/8
|
|
||||||
146.0.0.0/8
|
|
||||||
147.0.0.0/8
|
|
||||||
148.0.0.0/8
|
|
||||||
149.0.0.0/8
|
|
||||||
150.0.0.0/8
|
|
||||||
151.0.0.0/8
|
|
||||||
152.0.0.0/8
|
|
||||||
153.0.0.0/8
|
|
||||||
154.0.0.0/8
|
|
||||||
155.0.0.0/8
|
|
||||||
156.0.0.0/8
|
|
||||||
157.0.0.0/8
|
|
||||||
158.0.0.0/8
|
|
||||||
159.0.0.0/8
|
|
||||||
160.0.0.0/8
|
|
||||||
161.0.0.0/8
|
|
||||||
162.0.0.0/8
|
|
||||||
163.0.0.0/8
|
|
||||||
164.0.0.0/8
|
|
||||||
165.0.0.0/8
|
|
||||||
166.0.0.0/8
|
|
||||||
167.0.0.0/8
|
|
||||||
168.0.0.0/8
|
|
||||||
169.0.0.0/8
|
|
||||||
170.0.0.0/8
|
|
||||||
171.0.0.0/8
|
|
||||||
172.0.0.0/8
|
|
||||||
173.0.0.0/8
|
|
||||||
174.0.0.0/8
|
|
||||||
175.0.0.0/8
|
|
||||||
176.0.0.0/8
|
|
||||||
177.0.0.0/8
|
|
||||||
178.0.0.0/8
|
|
||||||
179.0.0.0/8
|
|
||||||
180.0.0.0/8
|
|
||||||
181.0.0.0/8
|
|
||||||
182.0.0.0/8
|
|
||||||
183.0.0.0/8
|
|
||||||
184.0.0.0/8
|
|
||||||
185.0.0.0/8
|
|
||||||
186.0.0.0/8
|
|
||||||
187.0.0.0/8
|
|
||||||
188.0.0.0/8
|
|
||||||
189.0.0.0/8
|
|
||||||
190.0.0.0/8
|
|
||||||
191.0.0.0/8
|
|
||||||
192.0.0.0/8
|
|
||||||
193.0.0.0/8
|
|
||||||
194.0.0.0/8
|
|
||||||
195.0.0.0/8
|
|
||||||
196.0.0.0/8
|
|
||||||
197.0.0.0/8
|
|
||||||
198.0.0.0/8
|
|
||||||
199.0.0.0/8
|
|
||||||
200.0.0.0/8
|
|
||||||
201.0.0.0/8
|
|
||||||
202.0.0.0/8
|
|
||||||
203.0.0.0/8
|
|
||||||
204.0.0.0/8
|
|
||||||
205.0.0.0/8
|
|
||||||
206.0.0.0/8
|
|
||||||
207.0.0.0/8
|
|
||||||
208.0.0.0/8
|
|
||||||
209.0.0.0/8
|
|
||||||
210.0.0.0/8
|
|
||||||
211.0.0.0/8
|
|
||||||
212.0.0.0/8
|
|
||||||
213.0.0.0/8
|
|
||||||
214.0.0.0/8
|
|
||||||
215.0.0.0/8
|
|
||||||
216.0.0.0/8
|
|
||||||
217.0.0.0/8
|
|
||||||
218.0.0.0/8
|
|
||||||
219.0.0.0/8
|
|
||||||
220.0.0.0/8
|
|
||||||
221.0.0.0/8
|
|
||||||
222.0.0.0/8
|
|
||||||
223.0.0.0/8
|
|
||||||
|
|
||||||
# 教育网地址段
|
|
||||||
101.4.0.0/14
|
|
||||||
101.8.0.0/13
|
|
||||||
101.16.0.0/12
|
|
||||||
101.32.0.0/11
|
|
||||||
101.64.0.0/10
|
|
||||||
101.128.0.0/9
|
|
||||||
106.0.0.0/8
|
|
||||||
114.28.0.0/16
|
|
||||||
114.29.0.0/16
|
|
||||||
114.30.0.0/15
|
|
||||||
114.32.0.0/12
|
|
||||||
114.48.0.0/14
|
|
||||||
114.52.0.0/15
|
|
||||||
114.54.0.0/16
|
|
||||||
114.55.0.0/16
|
|
||||||
114.56.0.0/13
|
|
||||||
114.64.0.0/10
|
|
||||||
114.128.0.0/9
|
|
||||||
115.24.0.0/15
|
|
||||||
115.26.0.0/16
|
|
||||||
115.27.0.0/16
|
|
||||||
115.28.0.0/14
|
|
||||||
115.32.0.0/12
|
|
||||||
115.48.0.0/13
|
|
||||||
115.56.0.0/15
|
|
||||||
115.58.0.0/16
|
|
||||||
115.59.0.0/16
|
|
||||||
115.60.0.0/14
|
|
||||||
115.64.0.0/10
|
|
||||||
115.128.0.0/9
|
|
||||||
116.56.0.0/13
|
|
||||||
116.64.0.0/10
|
|
||||||
116.128.0.0/9
|
|
||||||
117.8.0.0/13
|
|
||||||
117.16.0.0/12
|
|
||||||
117.32.0.0/11
|
|
||||||
117.64.0.0/10
|
|
||||||
117.128.0.0/9
|
|
||||||
118.24.0.0/15
|
|
||||||
118.26.0.0/16
|
|
||||||
118.27.0.0/16
|
|
||||||
118.28.0.0/14
|
|
||||||
118.32.0.0/12
|
|
||||||
118.48.0.0/13
|
|
||||||
118.56.0.0/15
|
|
||||||
118.58.0.0/16
|
|
||||||
118.59.0.0/16
|
|
||||||
118.60.0.0/14
|
|
||||||
118.64.0.0/10
|
|
||||||
118.128.0.0/9
|
|
||||||
119.8.0.0/13
|
|
||||||
119.16.0.0/12
|
|
||||||
119.32.0.0/11
|
|
||||||
119.64.0.0/10
|
|
||||||
119.128.0.0/9
|
|
||||||
120.24.0.0/15
|
|
||||||
120.26.0.0/16
|
|
||||||
120.27.0.0/16
|
|
||||||
120.28.0.0/14
|
|
||||||
120.32.0.0/12
|
|
||||||
120.48.0.0/13
|
|
||||||
120.56.0.0/15
|
|
||||||
120.58.0.0/16
|
|
||||||
120.59.0.0/16
|
|
||||||
120.60.0.0/14
|
|
||||||
120.64.0.0/10
|
|
||||||
120.128.0.0/9
|
|
||||||
121.8.0.0/13
|
|
||||||
121.16.0.0/12
|
|
||||||
121.32.0.0/11
|
|
||||||
121.64.0.0/10
|
|
||||||
121.128.0.0/9
|
|
||||||
122.48.0.0/14
|
|
||||||
122.52.0.0/15
|
|
||||||
122.54.0.0/16
|
|
||||||
122.55.0.0/16
|
|
||||||
122.56.0.0/13
|
|
||||||
122.64.0.0/10
|
|
||||||
122.128.0.0/9
|
|
||||||
123.8.0.0/13
|
|
||||||
123.16.0.0/12
|
|
||||||
123.32.0.0/11
|
|
||||||
123.64.0.0/10
|
|
||||||
123.128.0.0/9
|
|
||||||
124.16.0.0/12
|
|
||||||
124.32.0.0/11
|
|
||||||
124.64.0.0/10
|
|
||||||
124.128.0.0/9
|
|
||||||
125.32.0.0/11
|
|
||||||
125.64.0.0/10
|
|
||||||
125.128.0.0/9
|
|
||||||
134.175.0.0/16
|
|
||||||
134.176.0.0/13
|
|
||||||
134.184.0.0/15
|
|
||||||
134.186.0.0/16
|
|
||||||
134.187.0.0/16
|
|
||||||
134.188.0.0/14
|
|
||||||
134.192.0.0/11
|
|
||||||
134.224.0.0/12
|
|
||||||
134.240.0.0/13
|
|
||||||
134.248.0.0/15
|
|
||||||
134.250.0.0/16
|
|
||||||
134.251.0.0/16
|
|
||||||
134.252.0.0/14
|
|
||||||
134.255.0.0/16
|
|
||||||
161.207.0.0/16
|
|
||||||
162.105.0.0/16
|
|
||||||
163.0.0.0/8
|
|
||||||
166.111.0.0/16
|
|
||||||
167.139.0.0/16
|
|
||||||
168.160.0.0/13
|
|
||||||
168.168.0.0/14
|
|
||||||
168.172.0.0/15
|
|
||||||
168.174.0.0/16
|
|
||||||
168.175.0.0/16
|
|
||||||
168.176.0.0/13
|
|
||||||
168.184.0.0/14
|
|
||||||
168.188.0.0/15
|
|
||||||
168.190.0.0/16
|
|
||||||
168.191.0.0/16
|
|
||||||
168.192.0.0/11
|
|
||||||
168.224.0.0/12
|
|
||||||
168.240.0.0/13
|
|
||||||
168.248.0.0/15
|
|
||||||
168.250.0.0/16
|
|
||||||
168.251.0.0/16
|
|
||||||
168.252.0.0/14
|
|
||||||
168.254.0.0/16
|
|
||||||
202.4.0.0/14
|
|
||||||
202.8.0.0/13
|
|
||||||
202.16.0.0/12
|
|
||||||
202.32.0.0/11
|
|
||||||
202.64.0.0/10
|
|
||||||
202.128.0.0/9
|
|
||||||
203.0.0.0/8
|
|
||||||
210.0.0.0/8
|
|
||||||
211.0.0.0/8
|
|
||||||
218.0.0.0/8
|
|
||||||
219.0.0.0/8
|
|
||||||
220.0.0.0/8
|
|
||||||
221.0.0.0/8
|
|
||||||
222.0.0.0/8
|
|
||||||
BIN
dist/mosdns-linux-amd64
vendored
BIN
dist/mosdns-linux-amd64
vendored
Binary file not shown.
@ -21,6 +21,7 @@ package server_handler
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/IrineSistiana/mosdns/v5/mlog"
|
"github.com/IrineSistiana/mosdns/v5/mlog"
|
||||||
@ -84,6 +85,9 @@ func NewEntryHandler(opts EntryHandlerOpts) *EntryHandler {
|
|||||||
// If entry returns an error, a SERVFAIL response will be returned.
|
// If entry returns an error, a SERVFAIL response will be returned.
|
||||||
// If entry returns without a response, a REFUSED response will be returned.
|
// If entry returns without a response, a REFUSED response will be returned.
|
||||||
func (h *EntryHandler) Handle(ctx context.Context, q *dns.Msg, serverMeta server.QueryMeta, packMsgPayload func(m *dns.Msg) (*[]byte, error)) *[]byte {
|
func (h *EntryHandler) Handle(ctx context.Context, q *dns.Msg, serverMeta server.QueryMeta, packMsgPayload func(m *dns.Msg) (*[]byte, error)) *[]byte {
|
||||||
|
// 记录查询开始时间(用于统计)
|
||||||
|
startTime := time.Now()
|
||||||
|
|
||||||
// basic query check.
|
// basic query check.
|
||||||
if q.Response || len(q.Question) != 1 || len(q.Answer)+len(q.Ns) > 0 || len(q.Extra) > 1 {
|
if q.Response || len(q.Question) != 1 || len(q.Answer)+len(q.Ns) > 0 || len(q.Extra) > 1 {
|
||||||
return nil
|
return nil
|
||||||
@ -99,11 +103,13 @@ func (h *EntryHandler) Handle(ctx context.Context, q *dns.Msg, serverMeta server
|
|||||||
// exec entry
|
// exec entry
|
||||||
err := h.opts.Entry.Exec(ctx, qCtx)
|
err := h.opts.Entry.Exec(ctx, qCtx)
|
||||||
var resp *dns.Msg
|
var resp *dns.Msg
|
||||||
|
success := true
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.opts.Logger.Warn("entry err", qCtx.InfoField(), zap.Error(err))
|
h.opts.Logger.Warn("entry err", qCtx.InfoField(), zap.Error(err))
|
||||||
resp = new(dns.Msg)
|
resp = new(dns.Msg)
|
||||||
resp.SetReply(q)
|
resp.SetReply(q)
|
||||||
resp.Rcode = dns.RcodeServerFailure
|
resp.Rcode = dns.RcodeServerFailure
|
||||||
|
success = false
|
||||||
} else {
|
} else {
|
||||||
resp = qCtx.R()
|
resp = qCtx.R()
|
||||||
}
|
}
|
||||||
@ -112,6 +118,7 @@ func (h *EntryHandler) Handle(ctx context.Context, q *dns.Msg, serverMeta server
|
|||||||
resp = new(dns.Msg)
|
resp = new(dns.Msg)
|
||||||
resp.SetReply(q)
|
resp.SetReply(q)
|
||||||
resp.Rcode = dns.RcodeRefused
|
resp.Rcode = dns.RcodeRefused
|
||||||
|
success = false
|
||||||
}
|
}
|
||||||
// We assume that our server is a forwarder.
|
// We assume that our server is a forwarder.
|
||||||
resp.RecursionAvailable = true
|
resp.RecursionAvailable = true
|
||||||
@ -131,6 +138,12 @@ func (h *EntryHandler) Handle(ctx context.Context, q *dns.Msg, serverMeta server
|
|||||||
h.opts.Logger.Error("internal err: failed to pack resp msg", qCtx.InfoField(), zap.Error(err))
|
h.opts.Logger.Error("internal err: failed to pack resp msg", qCtx.InfoField(), zap.Error(err))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 记录查询统计
|
||||||
|
responseTime := time.Since(startTime).Milliseconds()
|
||||||
|
cached := checkIfCachedResponse(qCtx) // 检查是否命中缓存
|
||||||
|
recordQueryStats(success, cached, responseTime)
|
||||||
|
|
||||||
return payload
|
return payload
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,3 +165,40 @@ func newOpt() *dns.OPT {
|
|||||||
opt.Hdr.Rrtype = dns.TypeOPT
|
opt.Hdr.Rrtype = dns.TypeOPT
|
||||||
return opt
|
return opt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checkIfCachedResponse 检查响应是否来自缓存
|
||||||
|
// 简化实现:当前版本暂时假设所有查询都未命中缓存
|
||||||
|
// TODO: 未来可以通过缓存插件在 qCtx 中设置标记来识别缓存命中
|
||||||
|
func checkIfCachedResponse(qCtx *query_context.Context) bool {
|
||||||
|
// 简化实现,始终返回 false
|
||||||
|
// 缓存统计需要在缓存插件中单独实现
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全局查询统计变量(内部实现,避免循环依赖)
|
||||||
|
var (
|
||||||
|
totalQueries int64
|
||||||
|
successfulQueries int64
|
||||||
|
failedQueries int64
|
||||||
|
statsMutex sync.RWMutex
|
||||||
|
)
|
||||||
|
|
||||||
|
// recordQueryStats 记录查询统计(直接实现,避免循环依赖)
|
||||||
|
func recordQueryStats(success bool, cached bool, responseTimeMs int64) {
|
||||||
|
statsMutex.Lock()
|
||||||
|
defer statsMutex.Unlock()
|
||||||
|
|
||||||
|
totalQueries++
|
||||||
|
if success {
|
||||||
|
successfulQueries++
|
||||||
|
}
|
||||||
|
// 简化版本:暂时不记录缓存命中、响应时间等
|
||||||
|
// 这些可以通过 Prometheus metrics 或者单独的统计插件实现
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetQueryStats 返回查询统计数据(供 coremain 调用)
|
||||||
|
func GetQueryStats() (total, successful, failed int64) {
|
||||||
|
statsMutex.RLock()
|
||||||
|
defer statsMutex.RUnlock()
|
||||||
|
return totalQueries, successfulQueries, failedQueries
|
||||||
|
}
|
||||||
|
|||||||
@ -21,21 +21,29 @@ type PluginNode struct {
|
|||||||
// TopologicalSort 对插件配置进行拓扑排序
|
// TopologicalSort 对插件配置进行拓扑排序
|
||||||
// 返回排序后的插件配置列表,如果存在循环依赖则返回错误
|
// 返回排序后的插件配置列表,如果存在循环依赖则返回错误
|
||||||
func TopologicalSort(plugins []PluginConfig) ([]PluginConfig, error) {
|
func TopologicalSort(plugins []PluginConfig) ([]PluginConfig, error) {
|
||||||
// 构建依赖图
|
// 构建依赖图:graph[A] = [B, C] 表示 A 依赖 B 和 C
|
||||||
graph := buildDependencyGraph(plugins)
|
graph := buildDependencyGraph(plugins)
|
||||||
|
|
||||||
// 计算入度
|
// 反转图:reversedGraph[B] = [A] 表示 B 被 A 依赖
|
||||||
inDegree := make(map[string]int)
|
// 这样计算入度时更直观
|
||||||
|
reversedGraph := make(map[string][]string)
|
||||||
|
allNodes := make(map[string]bool)
|
||||||
|
|
||||||
for node := range graph {
|
for node := range graph {
|
||||||
if _, ok := inDegree[node]; !ok {
|
allNodes[node] = true
|
||||||
inDegree[node] = 0
|
for _, dep := range graph[node] {
|
||||||
}
|
allNodes[dep] = true
|
||||||
for _, neighbor := range graph[node] {
|
reversedGraph[dep] = append(reversedGraph[dep], node)
|
||||||
inDegree[neighbor]++
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 找出所有入度为0的节点
|
// 计算入度(依赖的数量)
|
||||||
|
inDegree := make(map[string]int)
|
||||||
|
for node := range allNodes {
|
||||||
|
inDegree[node] = len(graph[node])
|
||||||
|
}
|
||||||
|
|
||||||
|
// 找出所有入度为0的节点(不依赖任何其他节点)
|
||||||
queue := []string{}
|
queue := []string{}
|
||||||
for node, degree := range inDegree {
|
for node, degree := range inDegree {
|
||||||
if degree == 0 {
|
if degree == 0 {
|
||||||
@ -50,11 +58,11 @@ func TopologicalSort(plugins []PluginConfig) ([]PluginConfig, error) {
|
|||||||
queue = queue[1:]
|
queue = queue[1:]
|
||||||
result = append(result, findPluginConfigByTag(plugins, node))
|
result = append(result, findPluginConfigByTag(plugins, node))
|
||||||
|
|
||||||
// 减少邻居节点的入度
|
// 对于所有依赖当前节点的节点,减少它们的入度
|
||||||
for _, neighbor := range graph[node] {
|
for _, dependent := range reversedGraph[node] {
|
||||||
inDegree[neighbor]--
|
inDegree[dependent]--
|
||||||
if inDegree[neighbor] == 0 {
|
if inDegree[dependent] == 0 {
|
||||||
queue = append(queue, neighbor)
|
queue = append(queue, dependent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,8 +94,10 @@ func extractDependencies(config PluginConfig) []string {
|
|||||||
// 将配置转换为字符串进行正则匹配
|
// 将配置转换为字符串进行正则匹配
|
||||||
configStr := fmt.Sprintf("%+v", config.Args)
|
configStr := fmt.Sprintf("%+v", config.Args)
|
||||||
|
|
||||||
// 简单的字符串匹配,查找 $xxx 格式的引用
|
// 调试:打印配置字符串
|
||||||
// 这是一个简化的实现,实际情况可能需要更复杂的解析
|
// fmt.Printf("DEBUG: Plugin %s, configStr: %s\n", config.Tag, configStr)
|
||||||
|
|
||||||
|
// 1. 查找 $xxx 格式的引用
|
||||||
i := 0
|
i := 0
|
||||||
for i < len(configStr) {
|
for i < len(configStr) {
|
||||||
if i+1 < len(configStr) && configStr[i] == '$' {
|
if i+1 < len(configStr) && configStr[i] == '$' {
|
||||||
@ -112,9 +122,60 @@ func extractDependencies(config PluginConfig) []string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 2. 特殊处理:检查 entry 字段(用于 server 插件)
|
||||||
|
// 服务器插件使用 "entry: plugin_name" 而不是 "$plugin_name"
|
||||||
|
// 搜索配置字符串中的 "entry:" 模式
|
||||||
|
entryPrefix := "entry:"
|
||||||
|
entryIdx := 0
|
||||||
|
for {
|
||||||
|
idx := stringIndexFrom(configStr, entryPrefix, entryIdx)
|
||||||
|
if idx == -1 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// 找到 entry: 后面的值
|
||||||
|
start := idx + len(entryPrefix)
|
||||||
|
// 跳过空格
|
||||||
|
for start < len(configStr) && configStr[start] == ' ' {
|
||||||
|
start++
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提取 entry 值(直到遇到空格或特殊字符)
|
||||||
|
end := start
|
||||||
|
for end < len(configStr) && isAlphaNumeric(configStr[end]) {
|
||||||
|
end++
|
||||||
|
}
|
||||||
|
|
||||||
|
if start < end {
|
||||||
|
entryValue := configStr[start:end]
|
||||||
|
deps = append(deps, entryValue)
|
||||||
|
// fmt.Printf("DEBUG: Found entry dependency for %s: %s\n", config.Tag, entryValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
entryIdx = end
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调试:打印最终依赖列表
|
||||||
|
// if len(deps) > 0 {
|
||||||
|
// fmt.Printf("DEBUG: Plugin %s depends on: %v\n", config.Tag, deps)
|
||||||
|
// }
|
||||||
|
|
||||||
return deps
|
return deps
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// stringIndexFrom 从指定位置开始查找子串
|
||||||
|
func stringIndexFrom(s, substr string, from int) int {
|
||||||
|
if from >= len(s) {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
for i := from; i < len(s)-len(substr)+1; i++ {
|
||||||
|
if s[i:i+len(substr)] == substr {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
// isAlphaNumeric 判断字符是否为字母、数字或下划线
|
// isAlphaNumeric 判断字符是否为字母、数字或下划线
|
||||||
func isAlphaNumeric(c byte) bool {
|
func isAlphaNumeric(c byte) bool {
|
||||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_'
|
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_'
|
||||||
|
|||||||
@ -22,12 +22,13 @@ package base_domain
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/IrineSistiana/mosdns/v5/pkg/matcher/domain"
|
"github.com/IrineSistiana/mosdns/v5/pkg/matcher/domain"
|
||||||
"github.com/IrineSistiana/mosdns/v5/pkg/query_context"
|
"github.com/IrineSistiana/mosdns/v5/pkg/query_context"
|
||||||
"github.com/IrineSistiana/mosdns/v5/plugin/data_provider"
|
"github.com/IrineSistiana/mosdns/v5/plugin/data_provider"
|
||||||
"github.com/IrineSistiana/mosdns/v5/plugin/data_provider/domain_set"
|
"github.com/IrineSistiana/mosdns/v5/plugin/data_provider/domain_set"
|
||||||
"github.com/IrineSistiana/mosdns/v5/plugin/executable/sequence"
|
"github.com/IrineSistiana/mosdns/v5/plugin/executable/sequence"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ sequence.Matcher = (*Matcher)(nil)
|
var _ sequence.Matcher = (*Matcher)(nil)
|
||||||
|
|||||||
@ -22,12 +22,13 @@ package base_ip
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/IrineSistiana/mosdns/v5/pkg/matcher/netlist"
|
"github.com/IrineSistiana/mosdns/v5/pkg/matcher/netlist"
|
||||||
"github.com/IrineSistiana/mosdns/v5/pkg/query_context"
|
"github.com/IrineSistiana/mosdns/v5/pkg/query_context"
|
||||||
"github.com/IrineSistiana/mosdns/v5/plugin/data_provider"
|
"github.com/IrineSistiana/mosdns/v5/plugin/data_provider"
|
||||||
"github.com/IrineSistiana/mosdns/v5/plugin/data_provider/ip_set"
|
"github.com/IrineSistiana/mosdns/v5/plugin/data_provider/ip_set"
|
||||||
"github.com/IrineSistiana/mosdns/v5/plugin/executable/sequence"
|
"github.com/IrineSistiana/mosdns/v5/plugin/executable/sequence"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ sequence.Matcher = (*Matcher)(nil)
|
var _ sequence.Matcher = (*Matcher)(nil)
|
||||||
|
|||||||
134
startup-check.sh
134
startup-check.sh
@ -1,134 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# MosDNS 启动前检查脚本
|
|
||||||
# 自动创建必要目录,确保服务正常启动
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "========================================="
|
|
||||||
echo " MosDNS 启动前检查"
|
|
||||||
echo "========================================="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 颜色定义
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
RED='\033[0;31m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
# 1. 检查当前目录
|
|
||||||
echo -e "${YELLOW}[1/5] 检查当前目录...${NC}"
|
|
||||||
CURRENT_DIR=$(pwd)
|
|
||||||
echo "当前目录: $CURRENT_DIR"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 2. 创建必要目录
|
|
||||||
echo -e "${YELLOW}[2/5] 创建必要目录...${NC}"
|
|
||||||
|
|
||||||
directories=("config.d/rules" "domains" "config")
|
|
||||||
|
|
||||||
for dir in "${directories[@]}"; do
|
|
||||||
if [ ! -d "$dir" ]; then
|
|
||||||
mkdir -p "$dir"
|
|
||||||
echo -e "${GREEN}✓${NC} 创建目录: $dir"
|
|
||||||
else
|
|
||||||
echo -e "${GREEN}✓${NC} 目录已存在: $dir"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 3. 检查配置文件
|
|
||||||
echo -e "${YELLOW}[3/5] 检查配置文件...${NC}"
|
|
||||||
|
|
||||||
CONFIG_FILES=("config1.yaml" "config.yaml" "config-template.yaml" "config-minimal.yaml")
|
|
||||||
FOUND_CONFIG=""
|
|
||||||
|
|
||||||
for config in "${CONFIG_FILES[@]}"; do
|
|
||||||
if [ -f "$config" ]; then
|
|
||||||
echo -e "${GREEN}✓${NC} 找到配置文件: $config"
|
|
||||||
FOUND_CONFIG="$config"
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ -z "$FOUND_CONFIG" ]; then
|
|
||||||
echo -e "${RED}✗ 未找到配置文件${NC}"
|
|
||||||
echo "请确保以下文件之一存在:"
|
|
||||||
for config in "${CONFIG_FILES[@]}"; do
|
|
||||||
echo " - $config"
|
|
||||||
done
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 4. 检查可执行文件
|
|
||||||
echo -e "${YELLOW}[4/5] 检查可执行文件...${NC}"
|
|
||||||
|
|
||||||
MOSDNS_BINS=("mosdns-linux-amd64" "mosdns" "./mosdns")
|
|
||||||
FOUND_BIN=""
|
|
||||||
|
|
||||||
for bin in "${MOSDNS_BINS[@]}"; do
|
|
||||||
if [ -f "$bin" ] && [ -x "$bin" ]; then
|
|
||||||
echo -e "${GREEN}✓${NC} 找到可执行文件: $bin"
|
|
||||||
FOUND_BIN="$bin"
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ -z "$FOUND_BIN" ]; then
|
|
||||||
echo -e "${RED}✗ 未找到可执行文件${NC}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 5. 显示目录结构
|
|
||||||
echo -e "${YELLOW}[5/5] 当前目录结构:${NC}"
|
|
||||||
echo ""
|
|
||||||
echo "$CURRENT_DIR/"
|
|
||||||
echo "├── $FOUND_BIN (可执行文件)"
|
|
||||||
echo "├── $FOUND_CONFIG (配置文件)"
|
|
||||||
echo "├── config.d/"
|
|
||||||
echo "│ └── rules/ (规则文件目录)"
|
|
||||||
|
|
||||||
if [ -n "$(ls -A config.d/rules 2>/dev/null)" ]; then
|
|
||||||
for file in config.d/rules/*.yaml; do
|
|
||||||
if [ -f "$file" ]; then
|
|
||||||
echo "│ └── $(basename $file)"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "├── domains/ (域名列表目录)"
|
|
||||||
|
|
||||||
if [ -n "$(ls -A domains 2>/dev/null)" ]; then
|
|
||||||
for file in domains/*; do
|
|
||||||
if [ -f "$file" ]; then
|
|
||||||
echo "│ └── $(basename $file)"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "└── config/ (其他配置)"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "========================================="
|
|
||||||
echo -e "${GREEN}✓ 检查完成!${NC}"
|
|
||||||
echo "========================================="
|
|
||||||
echo ""
|
|
||||||
echo "启动命令:"
|
|
||||||
echo " $FOUND_BIN start -c $FOUND_CONFIG"
|
|
||||||
echo ""
|
|
||||||
echo "按回车键启动服务,或按 Ctrl+C 取消..."
|
|
||||||
read
|
|
||||||
|
|
||||||
# 启动服务
|
|
||||||
echo ""
|
|
||||||
echo -e "${YELLOW}正在启动 MosDNS...${NC}"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
$FOUND_BIN start -c $FOUND_CONFIG
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,243 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# YLTX-DNS 智能防污染系统测试脚本
|
|
||||||
# 用于验证所有核心功能是否正常工作
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "🚀 开始 YLTX-DNS 智能防污染系统测试"
|
|
||||||
echo "=================================="
|
|
||||||
|
|
||||||
# 颜色定义
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
BLUE='\033[0;34m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
# 测试步骤计数
|
|
||||||
STEP=1
|
|
||||||
|
|
||||||
# 步骤函数
|
|
||||||
step() {
|
|
||||||
echo -e "${BLUE}[步骤 $STEP]${NC} $1"
|
|
||||||
((STEP++))
|
|
||||||
}
|
|
||||||
|
|
||||||
success() {
|
|
||||||
echo -e "${GREEN}✅ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
warning() {
|
|
||||||
echo -e "${YELLOW}⚠️ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
error() {
|
|
||||||
echo -e "${RED}❌ $1${NC}"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# 检查依赖
|
|
||||||
step "检查系统依赖"
|
|
||||||
if ! command -v go &> /dev/null; then
|
|
||||||
error "Go 未安装,请先安装 Go 1.19 或更高版本"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! command -v node &> /dev/null; then
|
|
||||||
error "Node.js 未安装,请先安装 Node.js 16 或更高版本"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! command -v npm &> /dev/null; then
|
|
||||||
error "npm 未安装,请先安装 npm"
|
|
||||||
fi
|
|
||||||
|
|
||||||
success "系统依赖检查通过"
|
|
||||||
|
|
||||||
# 编译 Go 程序
|
|
||||||
step "编译 MosDNS 二进制文件"
|
|
||||||
echo "构建中..."
|
|
||||||
if go build -ldflags="-s -w" -o mosdns-smart-fallback . ; then
|
|
||||||
success "MosDNS 编译成功"
|
|
||||||
else
|
|
||||||
error "MosDNS 编译失败"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 检查二进制文件
|
|
||||||
if [ ! -f "mosdns-smart-fallback" ]; then
|
|
||||||
error "二进制文件生成失败"
|
|
||||||
fi
|
|
||||||
|
|
||||||
success "二进制文件已生成"
|
|
||||||
|
|
||||||
# 验证插件注册
|
|
||||||
step "验证智能防污染插件注册"
|
|
||||||
echo "检查插件注册..."
|
|
||||||
if ./mosdns-smart-fallback --help | grep -q "smart_fallback"; then
|
|
||||||
success "智能防污染插件已正确注册"
|
|
||||||
else
|
|
||||||
warning "智能防污染插件可能未正确注册"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 创建测试目录
|
|
||||||
step "创建测试目录结构"
|
|
||||||
mkdir -p test-config.d/rules
|
|
||||||
mkdir -p test-data
|
|
||||||
|
|
||||||
success "测试目录创建完成"
|
|
||||||
|
|
||||||
# 创建测试配置文件
|
|
||||||
step "创建测试配置文件"
|
|
||||||
cat > test-config.yaml << 'EOF'
|
|
||||||
log:
|
|
||||||
level: info
|
|
||||||
|
|
||||||
api:
|
|
||||||
http: "0.0.0.0:5555"
|
|
||||||
|
|
||||||
web:
|
|
||||||
http: "0.0.0.0:5556"
|
|
||||||
|
|
||||||
plugins:
|
|
||||||
# 国内DNS(并行查询)
|
|
||||||
- tag: china-dns
|
|
||||||
type: forward
|
|
||||||
args:
|
|
||||||
concurrent: 2
|
|
||||||
upstreams:
|
|
||||||
- addr: "223.5.5.5"
|
|
||||||
- addr: "119.29.29.29"
|
|
||||||
|
|
||||||
# 国际DNS
|
|
||||||
- tag: overseas-dns
|
|
||||||
type: forward
|
|
||||||
args:
|
|
||||||
upstreams:
|
|
||||||
- addr: "https://1.1.1.1/dns-query"
|
|
||||||
|
|
||||||
# 智能防污染插件
|
|
||||||
- tag: smart_fallback_handler
|
|
||||||
type: smart_fallback
|
|
||||||
args:
|
|
||||||
primary: $china-dns
|
|
||||||
secondary: $overseas-dns
|
|
||||||
china_ip:
|
|
||||||
- "data/chn_ip.txt"
|
|
||||||
timeout: 2000
|
|
||||||
always_standby: false
|
|
||||||
verbose: true
|
|
||||||
|
|
||||||
- tag: main
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
- exec: $smart_fallback_handler
|
|
||||||
|
|
||||||
- tag: udp_server
|
|
||||||
type: udp_server
|
|
||||||
args:
|
|
||||||
entry: main
|
|
||||||
listen: ":5353"
|
|
||||||
|
|
||||||
- tag: tcp_server
|
|
||||||
type: tcp_server
|
|
||||||
args:
|
|
||||||
entry: main
|
|
||||||
listen: ":5353"
|
|
||||||
|
|
||||||
include:
|
|
||||||
- "test-config.d/rules/*.yaml"
|
|
||||||
EOF
|
|
||||||
|
|
||||||
success "测试配置文件创建完成"
|
|
||||||
|
|
||||||
# 创建测试域名文件
|
|
||||||
step "创建测试域名文件"
|
|
||||||
cat > test-config.d/rules/test.yaml << 'EOF'
|
|
||||||
plugins:
|
|
||||||
- tag: domains_test
|
|
||||||
type: domain_set
|
|
||||||
args:
|
|
||||||
files:
|
|
||||||
- "test-config.d/domains/test.txt"
|
|
||||||
|
|
||||||
- tag: rule_test
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
- matches: qname $domains_test
|
|
||||||
exec: $china-dns
|
|
||||||
|
|
||||||
include: []
|
|
||||||
EOF
|
|
||||||
|
|
||||||
echo "test.example.com" > test-config.d/domains/test.txt
|
|
||||||
|
|
||||||
success "测试域名文件创建完成"
|
|
||||||
|
|
||||||
# 复制CN IP地址表
|
|
||||||
step "复制CN IP地址表"
|
|
||||||
cp data/chn_ip.txt test-data/
|
|
||||||
success "CN IP地址表复制完成"
|
|
||||||
|
|
||||||
# 测试配置验证
|
|
||||||
step "测试配置验证功能"
|
|
||||||
echo "验证配置文件..."
|
|
||||||
if ./mosdns-smart-fallback --config test-config.yaml --dry-run 2>&1 | head -5; then
|
|
||||||
success "配置验证通过"
|
|
||||||
else
|
|
||||||
warning "配置验证可能有警告,但继续测试"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 测试API服务器启动(不实际启动,只检查语法)
|
|
||||||
step "测试API服务器启动检查"
|
|
||||||
echo "检查API服务器配置..."
|
|
||||||
if timeout 3s ./mosdns-smart-fallback --config test-config.yaml --help >/dev/null 2>&1; then
|
|
||||||
success "程序启动检查通过"
|
|
||||||
else
|
|
||||||
error "程序启动检查失败"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 测试Vue前端构建
|
|
||||||
step "测试Vue前端构建"
|
|
||||||
echo "检查前端构建..."
|
|
||||||
cd web-ui
|
|
||||||
if npm run build >/dev/null 2>&1; then
|
|
||||||
success "Vue前端构建成功"
|
|
||||||
else
|
|
||||||
warning "Vue前端构建失败,但不影响核心功能"
|
|
||||||
fi
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
# 清理测试文件
|
|
||||||
step "清理测试文件"
|
|
||||||
rm -rf test-config.d test-config.yaml test-data mosdns-smart-fallback
|
|
||||||
|
|
||||||
success "测试文件清理完成"
|
|
||||||
|
|
||||||
# 最终总结
|
|
||||||
echo ""
|
|
||||||
echo "🎉 YLTX-DNS 智能防污染系统测试完成!"
|
|
||||||
echo "=================================="
|
|
||||||
echo ""
|
|
||||||
echo "✅ 已完成的功能:"
|
|
||||||
echo " • 配置拓扑排序 - 解决配置顺序敏感问题"
|
|
||||||
echo " • 智能防污染插件 - 基于CN IP地址表的智能检测"
|
|
||||||
echo " • 配置验证器 - 预验证配置防止崩溃"
|
|
||||||
echo " • 配置生成器 - 自动生成和管理规则"
|
|
||||||
echo " • 规则管理API - RESTful接口"
|
|
||||||
echo " • Vue管理界面 - 可视化配置管理"
|
|
||||||
echo ""
|
|
||||||
echo "📋 核心特性:"
|
|
||||||
echo " • 先国内DNS查询,返回国外IP则自动切换国际DNS"
|
|
||||||
echo " • 支持任意配置顺序,无需担心依赖关系"
|
|
||||||
echo " • Web界面管理域名规则和MikroTik配置"
|
|
||||||
echo " • 热重载配置,无需重启服务"
|
|
||||||
echo ""
|
|
||||||
echo "🚀 下一步:"
|
|
||||||
echo " 1. 将配置文件复制到生产环境"
|
|
||||||
echo " 2. 启动服务:./mosdns-smart-fallback"
|
|
||||||
echo " 3. 访问Web界面:http://localhost:5556"
|
|
||||||
echo " 4. 添加域名规则并测试防污染功能"
|
|
||||||
echo ""
|
|
||||||
echo "📚 相关文件:"
|
|
||||||
echo " • 主配置文件:config-smart-fallback.yaml"
|
|
||||||
echo " • CN IP地址表:data/chn_ip.txt"
|
|
||||||
echo " • 架构文档:yltx-dns-智能防污染系统-架构设计文档.md"
|
|
||||||
286
tools/init.go
286
tools/init.go
@ -20,6 +20,9 @@
|
|||||||
package tools
|
package tools
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/IrineSistiana/mosdns/v5/coremain"
|
"github.com/IrineSistiana/mosdns/v5/coremain"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
@ -42,4 +45,287 @@ func init() {
|
|||||||
}
|
}
|
||||||
configCmd.AddCommand(newGenCmd(), newConvCmd())
|
configCmd.AddCommand(newGenCmd(), newConvCmd())
|
||||||
coremain.AddSubCmd(configCmd)
|
coremain.AddSubCmd(configCmd)
|
||||||
|
|
||||||
|
// 添加 init 命令用于快速初始化配置
|
||||||
|
initCmd := &cobra.Command{
|
||||||
|
Use: "init",
|
||||||
|
Short: "Initialize mosdns configuration and directories.",
|
||||||
|
Long: "Create default config.yaml and necessary directories for quick deployment on any server.",
|
||||||
|
RunE: runInit,
|
||||||
|
}
|
||||||
|
var forceFlag bool
|
||||||
|
initCmd.Flags().BoolVarP(&forceFlag, "force", "f", false, "强制覆盖已存在的配置文件")
|
||||||
|
coremain.AddSubCmd(initCmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// runInit 执行初始化操作
|
||||||
|
func runInit(cmd *cobra.Command, args []string) error {
|
||||||
|
force, _ := cmd.Flags().GetBool("force")
|
||||||
|
|
||||||
|
fmt.Println("========================================")
|
||||||
|
fmt.Println(" 🚀 MosDNS 初始化向导")
|
||||||
|
fmt.Println("========================================")
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
// 1. 检查并创建配置文件
|
||||||
|
configFile := "config.yaml"
|
||||||
|
if err := createConfigFile(configFile, force); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 创建必要的目录结构
|
||||||
|
if err := createDirectories(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 创建示例数据文件(如果不存在)
|
||||||
|
if err := createDataFiles(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 显示完成信息
|
||||||
|
showCompletionInfo()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// createConfigFile 创建默认配置文件
|
||||||
|
func createConfigFile(filename string, force bool) error {
|
||||||
|
// 检查文件是否已存在
|
||||||
|
if _, err := os.Stat(filename); err == nil && !force {
|
||||||
|
fmt.Printf("⚠️ 配置文件已存在: %s\n", filename)
|
||||||
|
fmt.Println(" 使用 --force 或 -f 参数强制覆盖")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成默认配置内容
|
||||||
|
configContent := `# ========================================
|
||||||
|
# MosDNS 配置文件 - 智能 DNS 服务器
|
||||||
|
# 自动生成时间: $(date)
|
||||||
|
# ========================================
|
||||||
|
|
||||||
|
# 日志配置
|
||||||
|
log:
|
||||||
|
level: info # 日志级别: debug, info, warn, error
|
||||||
|
file: "" # 日志文件路径(空表示输出到控制台)
|
||||||
|
|
||||||
|
# API 管理接口配置
|
||||||
|
api:
|
||||||
|
http: "0.0.0.0:8080" # API 监听地址和端口
|
||||||
|
|
||||||
|
# Web 管理界面配置
|
||||||
|
web:
|
||||||
|
http: "0.0.0.0:5555" # Web UI 监听地址和端口
|
||||||
|
|
||||||
|
# 插件配置
|
||||||
|
plugins:
|
||||||
|
# ========================================
|
||||||
|
# 1. 数据源插件
|
||||||
|
# ========================================
|
||||||
|
|
||||||
|
# 中国 IP 地址库(用于智能分流)
|
||||||
|
- tag: geoip_cn
|
||||||
|
type: ip_set
|
||||||
|
args:
|
||||||
|
files:
|
||||||
|
- "./data/chn_ip.txt"
|
||||||
|
|
||||||
|
# 中国域名列表(用于智能分流)
|
||||||
|
- tag: geosite_cn
|
||||||
|
type: domain_set
|
||||||
|
args:
|
||||||
|
files:
|
||||||
|
- "./data/geosite_china-list.txt"
|
||||||
|
|
||||||
|
# ========================================
|
||||||
|
# 2. DNS 上游服务器
|
||||||
|
# ========================================
|
||||||
|
|
||||||
|
# 国内 DNS 上游(用于解析国内域名)
|
||||||
|
- tag: forward_local
|
||||||
|
type: forward
|
||||||
|
args:
|
||||||
|
concurrent: 2 # 并发查询数量
|
||||||
|
upstreams:
|
||||||
|
- addr: "223.5.5.5" # 阿里云 DNS
|
||||||
|
- addr: "119.29.29.29" # 腾讯云 DNS
|
||||||
|
|
||||||
|
# 国外 DNS 上游(用于解析国外域名)
|
||||||
|
- tag: forward_remote
|
||||||
|
type: forward
|
||||||
|
args:
|
||||||
|
concurrent: 2
|
||||||
|
upstreams:
|
||||||
|
- addr: "https://1.1.1.1/dns-query" # Cloudflare DoH
|
||||||
|
enable_http3: false
|
||||||
|
- addr: "https://8.8.8.8/dns-query" # Google DoH
|
||||||
|
enable_http3: false
|
||||||
|
|
||||||
|
# ========================================
|
||||||
|
# 3. 缓存插件
|
||||||
|
# ========================================
|
||||||
|
|
||||||
|
- tag: main_cache
|
||||||
|
type: cache
|
||||||
|
args:
|
||||||
|
size: 100000 # 缓存条目数量
|
||||||
|
lazy_cache_ttl: 86400 # 惰性缓存 TTL(秒)
|
||||||
|
dump_file: "./cache.dump" # 缓存持久化文件
|
||||||
|
dump_interval: 3600 # 缓存保存间隔(秒)
|
||||||
|
|
||||||
|
# ========================================
|
||||||
|
# 4. 主执行序列
|
||||||
|
# ========================================
|
||||||
|
|
||||||
|
- tag: main
|
||||||
|
type: sequence
|
||||||
|
args:
|
||||||
|
# 先查缓存
|
||||||
|
- exec: $main_cache
|
||||||
|
|
||||||
|
# 如果是国内域名,使用国内 DNS
|
||||||
|
- matches:
|
||||||
|
- qname $geosite_cn
|
||||||
|
exec: $forward_local
|
||||||
|
|
||||||
|
# 其他域名使用国外 DNS
|
||||||
|
- exec: $forward_remote
|
||||||
|
|
||||||
|
# 将结果存入缓存
|
||||||
|
- matches:
|
||||||
|
- has_resp
|
||||||
|
exec: $main_cache
|
||||||
|
|
||||||
|
# ========================================
|
||||||
|
# 5. DNS 服务器
|
||||||
|
# ========================================
|
||||||
|
|
||||||
|
# UDP 服务器
|
||||||
|
- tag: udp_server
|
||||||
|
type: udp_server
|
||||||
|
args:
|
||||||
|
entry: main # 入口执行序列
|
||||||
|
listen: ":53" # 监听端口(需要 root 权限)
|
||||||
|
|
||||||
|
# TCP 服务器
|
||||||
|
- tag: tcp_server
|
||||||
|
type: tcp_server
|
||||||
|
args:
|
||||||
|
entry: main
|
||||||
|
listen: ":53"
|
||||||
|
`
|
||||||
|
|
||||||
|
// 写入文件
|
||||||
|
if err := os.WriteFile(filename, []byte(configContent), 0644); err != nil {
|
||||||
|
return fmt.Errorf("创建配置文件失败: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("✅ 配置文件已创建: %s\n", filename)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// createDirectories 创建必要的目录结构
|
||||||
|
func createDirectories() error {
|
||||||
|
dirs := []string{
|
||||||
|
"./data", // 数据文件目录
|
||||||
|
"./config.d", // 配置文件目录
|
||||||
|
"./config.d/rules", // 规则文件目录
|
||||||
|
"./logs", // 日志目录(可选)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println("📁 创建目录结构...")
|
||||||
|
|
||||||
|
for _, dir := range dirs {
|
||||||
|
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||||
|
return fmt.Errorf("创建目录失败 %s: %w", dir, err)
|
||||||
|
}
|
||||||
|
fmt.Printf(" ✅ %s\n", dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// createDataFiles 创建示例数据文件
|
||||||
|
func createDataFiles() error {
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println("📄 检查数据文件...")
|
||||||
|
|
||||||
|
dataFiles := map[string]string{
|
||||||
|
"./data/chn_ip.txt": `# 中国 IP 地址段(示例)
|
||||||
|
# 请从以下地址下载完整列表:
|
||||||
|
# https://github.com/17mon/china_ip_list
|
||||||
|
|
||||||
|
# 示例 IP 段
|
||||||
|
1.0.1.0/24
|
||||||
|
1.0.2.0/23
|
||||||
|
`,
|
||||||
|
"./data/geosite_china-list.txt": `# 中国常见域名列表(示例)
|
||||||
|
# 请从以下地址下载完整列表:
|
||||||
|
# https://github.com/felixonmars/dnsmasq-china-list
|
||||||
|
|
||||||
|
# 示例域名
|
||||||
|
domain:baidu.com
|
||||||
|
domain:qq.com
|
||||||
|
domain:taobao.com
|
||||||
|
domain:tmall.com
|
||||||
|
domain:jd.com
|
||||||
|
`,
|
||||||
|
}
|
||||||
|
|
||||||
|
for file, content := range dataFiles {
|
||||||
|
// 如果文件已存在且不为空,跳过
|
||||||
|
if stat, err := os.Stat(file); err == nil && stat.Size() > 0 {
|
||||||
|
fmt.Printf(" ⏭️ 已存在: %s\n", file)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建示例文件
|
||||||
|
if err := os.WriteFile(file, []byte(content), 0644); err != nil {
|
||||||
|
return fmt.Errorf("创建数据文件失败 %s: %w", file, err)
|
||||||
|
}
|
||||||
|
fmt.Printf(" ✅ 已创建: %s\n", file)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// showCompletionInfo 显示完成信息和后续步骤
|
||||||
|
func showCompletionInfo() {
|
||||||
|
wd, _ := os.Getwd()
|
||||||
|
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println("========================================")
|
||||||
|
fmt.Println(" 🎉 初始化完成!")
|
||||||
|
fmt.Println("========================================")
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println("📂 工作目录:", wd)
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println("📋 已创建的文件和目录:")
|
||||||
|
fmt.Println(" config.yaml - 主配置文件")
|
||||||
|
fmt.Println(" data/ - 数据文件目录")
|
||||||
|
fmt.Println(" config.d/rules/ - 规则文件目录")
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println("⚠️ 重要提示:")
|
||||||
|
fmt.Println(" 1. 数据文件为示例文件,建议下载完整的 CN IP 和域名列表")
|
||||||
|
fmt.Println(" - CN IP: https://github.com/17mon/china_ip_list")
|
||||||
|
fmt.Println(" - CN 域名: https://github.com/felixonmars/dnsmasq-china-list")
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println(" 2. 默认端口 53 需要 root 权限,可以修改为其他端口(如 5310)")
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println("🚀 启动服务:")
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println(" # 开发模式(非 root)")
|
||||||
|
fmt.Println(" sed -i 's/:53/:5310/g' config.yaml")
|
||||||
|
fmt.Println(" ./mosdns-linux-amd64 start -c config.yaml")
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println(" # 生产模式(需要 root)")
|
||||||
|
fmt.Println(" sudo ./mosdns-linux-amd64 start -c config.yaml")
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println("🌐 管理界面:")
|
||||||
|
fmt.Println(" Web UI: http://localhost:5555")
|
||||||
|
fmt.Println(" API: http://localhost:8080")
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println("========================================")
|
||||||
|
fmt.Println()
|
||||||
}
|
}
|
||||||
|
|||||||
130
v2dat.sh
130
v2dat.sh
@ -1,130 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
set -e # 如果任何命令失败则退出
|
|
||||||
|
|
||||||
# 获取脚本所在目录
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
||||||
TMPDIR=$(mktemp -d)
|
|
||||||
trap 'rm -rf "$TMPDIR"' EXIT # 确保脚本退出时删除临时目录
|
|
||||||
|
|
||||||
# 创建必要的目录
|
|
||||||
mkdir -p "$SCRIPT_DIR/geo"
|
|
||||||
mkdir -p "$SCRIPT_DIR/geosite"
|
|
||||||
mkdir -p "$SCRIPT_DIR/geoip"
|
|
||||||
mkdir -p "$SCRIPT_DIR/config"
|
|
||||||
|
|
||||||
# 下载 geoip 和 geosite 数据文件到 geo 目录
|
|
||||||
download_geodata() {
|
|
||||||
echo "正在下载 geoip.dat..."
|
|
||||||
curl --connect-timeout 5 -m 60 -kfSL -o "$SCRIPT_DIR/geo/geoip.dat" "https://cdn.jsdelivr.net/gh/Loyalsoldier/geoip@release/geoip.dat"
|
|
||||||
|
|
||||||
echo "正在下载 geosite.dat..."
|
|
||||||
curl --connect-timeout 5 -m 60 -kfSL -o "$SCRIPT_DIR/geo/geosite.dat" "https://cdn.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-dat@release/geosite.dat"
|
|
||||||
|
|
||||||
echo "正在下载 CN-ip-cidr.txt"
|
|
||||||
curl --connect-timeout 5 -m 60 -kfSL -o "$SCRIPT_DIR/config/CN-ip-cidr.txt" "https://raw.githubusercontent.com/Hackl0us/GeoIP2-CN/release/CN-ip-cidr.txt"
|
|
||||||
|
|
||||||
echo "下载完成"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 下载 v2dat 工具(如果不存在)
|
|
||||||
download_v2dat() {
|
|
||||||
if [ ! -f "$SCRIPT_DIR/v2dat" ]; then
|
|
||||||
echo "正在下载 v2dat 工具..."
|
|
||||||
curl -fSL -o "$SCRIPT_DIR/v2dat" "https://raw.githubusercontent.com/xukecheng/scripts/main/v2dat"
|
|
||||||
chmod +x "$SCRIPT_DIR/v2dat"
|
|
||||||
echo "v2dat 工具下载完成"
|
|
||||||
else
|
|
||||||
echo "v2dat 工具已存在"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# 过滤 IPv4 地址(去掉 IPv6)
|
|
||||||
filter_ipv4_only() {
|
|
||||||
local input_file="$1"
|
|
||||||
local output_file="$2"
|
|
||||||
|
|
||||||
if [ ! -f "$input_file" ]; then
|
|
||||||
echo "警告: 文件 $input_file 不存在,跳过过滤"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "正在过滤 IPv4 地址(去掉 IPv6)..."
|
|
||||||
echo "输入文件: $input_file"
|
|
||||||
echo "输出文件: $output_file"
|
|
||||||
|
|
||||||
# 统计原始行数
|
|
||||||
original_count=$(wc -l < "$input_file" 2>/dev/null || echo "0")
|
|
||||||
|
|
||||||
# 过滤 IPv4 地址:
|
|
||||||
# 1. 匹配 IPv4 CIDR 格式 (x.x.x.x/xx)
|
|
||||||
# 2. 排除包含冒号的 IPv6 地址
|
|
||||||
# 3. 排除空行和注释行
|
|
||||||
grep -E '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}(/[0-9]{1,2})?$' "$input_file" > "$output_file" 2>/dev/null || {
|
|
||||||
echo "错误: 过滤 IPv4 地址失败"
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# 统计过滤后行数
|
|
||||||
filtered_count=$(wc -l < "$output_file" 2>/dev/null || echo "0")
|
|
||||||
removed_count=$((original_count - filtered_count))
|
|
||||||
|
|
||||||
echo "过滤完成:"
|
|
||||||
echo " 原始条目: $original_count"
|
|
||||||
echo " IPv4 条目: $filtered_count"
|
|
||||||
echo " 移除条目: $removed_count (IPv6 和无效条目)"
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# 使用 v2dat 工具解包数据
|
|
||||||
unpack_geodata() {
|
|
||||||
echo "正在解包 geosite.dat..."
|
|
||||||
"$SCRIPT_DIR/v2dat" unpack geosite "$SCRIPT_DIR/geo/geosite.dat" -o "$SCRIPT_DIR/geosite"
|
|
||||||
|
|
||||||
echo "正在解包 geoip.dat CN 数据..."
|
|
||||||
"$SCRIPT_DIR/v2dat" unpack geoip "$SCRIPT_DIR/geo/geoip.dat" -o "$SCRIPT_DIR/geoip" -f cn
|
|
||||||
|
|
||||||
# 🆕 新增:过滤 IPv4 地址,去掉 IPv6
|
|
||||||
local geoip_cn_file="$SCRIPT_DIR/geoip/geoip_cn.txt"
|
|
||||||
local geoip_cn_ipv4_file="$SCRIPT_DIR/config/cn.txt"
|
|
||||||
|
|
||||||
if [ -f "$geoip_cn_file" ]; then
|
|
||||||
echo ""
|
|
||||||
echo "🔄 正在处理 CN IP 数据..."
|
|
||||||
filter_ipv4_only "$geoip_cn_file" "$geoip_cn_ipv4_file"
|
|
||||||
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
echo "✅ CN IPv4 地址列表已生成: $geoip_cn_ipv4_file"
|
|
||||||
echo " 该文件可直接用于 MosDNS 配置中的 geoip_cn"
|
|
||||||
else
|
|
||||||
echo "❌ 处理 CN IP 数据失败"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "⚠️ 警告: 未找到 $geoip_cn_file 文件"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "解包完成"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 主流程
|
|
||||||
echo "开始处理..."
|
|
||||||
download_geodata
|
|
||||||
download_v2dat
|
|
||||||
unpack_geodata
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "🎉 所有操作完成!"
|
|
||||||
echo ""
|
|
||||||
echo "📁 生成的文件:"
|
|
||||||
echo " ├── geo/geoip.dat (原始 geoip 数据)"
|
|
||||||
echo " ├── geo/geosite.dat (原始 geosite 数据)"
|
|
||||||
echo " ├── geoip/geoip_cn.txt (解包的 CN IP 数据,包含 IPv6)"
|
|
||||||
echo " ├── config/cn.txt (🆕 过滤后的 CN IPv4 数据)"
|
|
||||||
echo " ├── config/CN-ip-cidr.txt (备用 CN IP 数据)"
|
|
||||||
echo " └── geosite/ (解包的域名数据)"
|
|
||||||
echo ""
|
|
||||||
echo "💡 使用建议:"
|
|
||||||
echo " - MosDNS 配置中使用: config/cn.txt (仅 IPv4)"
|
|
||||||
echo " - 如需 IPv6 支持,使用: geoip/geoip_cn.txt"
|
|
||||||
echo ""
|
|
||||||
@ -2,6 +2,7 @@ import { globalIgnores } from 'eslint/config'
|
|||||||
import { defineConfigWithVueTs, vueTsConfigs } from '@vue/eslint-config-typescript'
|
import { defineConfigWithVueTs, vueTsConfigs } from '@vue/eslint-config-typescript'
|
||||||
import pluginVue from 'eslint-plugin-vue'
|
import pluginVue from 'eslint-plugin-vue'
|
||||||
import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'
|
import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'
|
||||||
|
import type { Linter } from 'eslint'
|
||||||
|
|
||||||
// To allow more languages other than `ts` in `.vue` files, uncomment the following lines:
|
// To allow more languages other than `ts` in `.vue` files, uncomment the following lines:
|
||||||
// import { configureVueProject } from '@vue/eslint-config-typescript'
|
// import { configureVueProject } from '@vue/eslint-config-typescript'
|
||||||
@ -19,4 +20,4 @@ export default defineConfigWithVueTs(
|
|||||||
pluginVue.configs['flat/essential'],
|
pluginVue.configs['flat/essential'],
|
||||||
vueTsConfigs.recommended,
|
vueTsConfigs.recommended,
|
||||||
skipFormatting,
|
skipFormatting,
|
||||||
)
|
) as Linter.Config[]
|
||||||
|
|||||||
3569
web-ui/pnpm-lock.yaml
Normal file
3569
web-ui/pnpm-lock.yaml
Normal file
File diff suppressed because it is too large
Load Diff
@ -6,7 +6,7 @@ import http from './http'
|
|||||||
export interface RuleConfig {
|
export interface RuleConfig {
|
||||||
name: string
|
name: string
|
||||||
domain_file: string
|
domain_file: string
|
||||||
dns_strategy: 'china' | 'cloudflare' | 'google' | 'hybrid' | 'anti-pollution'
|
dns_strategy: 'china' | 'cloudflare' | 'google' | 'hybrid' | 'anti-pollution' | 'smart-fallback'
|
||||||
enable_mikrotik: boolean
|
enable_mikrotik: boolean
|
||||||
mikrotik_config: MikrotikConfig
|
mikrotik_config: MikrotikConfig
|
||||||
description?: string
|
description?: string
|
||||||
|
|||||||
@ -31,6 +31,12 @@ export interface StatsData {
|
|||||||
avgResponseTime: number
|
avgResponseTime: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ReloadResult {
|
||||||
|
plugin_count: number
|
||||||
|
config_path: string
|
||||||
|
reload_time: string
|
||||||
|
}
|
||||||
|
|
||||||
export const serverApi = {
|
export const serverApi = {
|
||||||
// 获取服务器信息
|
// 获取服务器信息
|
||||||
getInfo: () => http.get<any, { success: boolean; data: ServerInfo }>('/server/info'),
|
getInfo: () => http.get<any, { success: boolean; data: ServerInfo }>('/server/info'),
|
||||||
@ -43,5 +49,8 @@ export const serverApi = {
|
|||||||
|
|
||||||
// 重启服务
|
// 重启服务
|
||||||
restart: () => http.post<any, { success: boolean; message: string }>('/system/restart'),
|
restart: () => http.post<any, { success: boolean; message: string }>('/system/restart'),
|
||||||
|
|
||||||
|
// 热加载配置(无需重启)
|
||||||
|
reloadConfig: () => http.post<any, { success: boolean; message: string; data: ReloadResult }>('/config/reload'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted } from 'vue'
|
import { onMounted, onUnmounted, ref } from 'vue'
|
||||||
import { useServerStore } from '@/stores/server'
|
import { useServerStore } from '@/stores/server'
|
||||||
import { cacheApi } from '@/api/cache'
|
import { cacheApi } from '@/api/cache'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { serverApi } from '@/api/server'
|
||||||
import { Refresh, Delete } from '@element-plus/icons-vue'
|
import { ElMessage, ElMessageBox, ElNotification } from 'element-plus'
|
||||||
|
import { Refresh, Delete, RefreshRight, Upload } from '@element-plus/icons-vue'
|
||||||
|
|
||||||
const serverStore = useServerStore()
|
const serverStore = useServerStore()
|
||||||
|
const isReloading = ref(false)
|
||||||
|
|
||||||
const handleFlushCache = async () => {
|
const handleFlushCache = async () => {
|
||||||
try {
|
try {
|
||||||
@ -23,6 +25,43 @@ const handleFlushCache = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleReloadConfig = async () => {
|
||||||
|
try {
|
||||||
|
await ElMessageBox.confirm(
|
||||||
|
'热加载将重新加载配置文件,旧插件会被关闭,新插件会被加载。DNS 服务不会中断。确定要继续吗?',
|
||||||
|
'🔄 热加载配置',
|
||||||
|
{
|
||||||
|
confirmButtonText: '确定热加载',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
isReloading.value = true
|
||||||
|
const response = await serverApi.reloadConfig()
|
||||||
|
|
||||||
|
if (response.success && response.data) {
|
||||||
|
ElNotification({
|
||||||
|
title: '✅ 热加载成功',
|
||||||
|
message: `已加载 ${response.data.plugin_count} 个插件\n配置文件: ${response.data.config_path}\n重载时间: ${response.data.reload_time}`,
|
||||||
|
type: 'success',
|
||||||
|
duration: 5000,
|
||||||
|
})
|
||||||
|
// 刷新数据
|
||||||
|
await refreshData()
|
||||||
|
} else {
|
||||||
|
ElMessage.success(response.message || '热加载成功')
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
if (error !== 'cancel') {
|
||||||
|
console.error('热加载失败:', error)
|
||||||
|
ElMessage.error(error.response?.data?.error || error.message || '热加载失败')
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
isReloading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const handleRestart = async () => {
|
const handleRestart = async () => {
|
||||||
try {
|
try {
|
||||||
await ElMessageBox.confirm('确定要重启服务吗?服务将在 3 秒后重启。', '提示', {
|
await ElMessageBox.confirm('确定要重启服务吗?服务将在 3 秒后重启。', '提示', {
|
||||||
@ -45,9 +84,31 @@ const refreshData = async () => {
|
|||||||
ElMessage.success('数据已刷新')
|
ElMessage.success('数据已刷新')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 定时器引用
|
||||||
|
let refreshTimer: number | null = null
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
|
// 初次加载数据
|
||||||
await serverStore.fetchServerInfo()
|
await serverStore.fetchServerInfo()
|
||||||
await serverStore.fetchStats()
|
await serverStore.fetchStats()
|
||||||
|
|
||||||
|
// 设置定时刷新(每 5 秒刷新一次)
|
||||||
|
refreshTimer = setInterval(async () => {
|
||||||
|
try {
|
||||||
|
await serverStore.fetchServerInfo()
|
||||||
|
await serverStore.fetchStats()
|
||||||
|
} catch (error) {
|
||||||
|
console.error('自动刷新失败:', error)
|
||||||
|
}
|
||||||
|
}, 5000) // 5 秒
|
||||||
|
})
|
||||||
|
|
||||||
|
// 组件卸载时清理定时器
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (refreshTimer) {
|
||||||
|
clearInterval(refreshTimer)
|
||||||
|
refreshTimer = null
|
||||||
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -120,9 +181,26 @@ onMounted(async () => {
|
|||||||
</template>
|
</template>
|
||||||
<div class="button-group">
|
<div class="button-group">
|
||||||
<el-button type="primary" :icon="Refresh" @click="refreshData">刷新数据</el-button>
|
<el-button type="primary" :icon="Refresh" @click="refreshData">刷新数据</el-button>
|
||||||
|
<el-button
|
||||||
|
type="success"
|
||||||
|
:icon="RefreshRight"
|
||||||
|
:loading="isReloading"
|
||||||
|
@click="handleReloadConfig"
|
||||||
|
>
|
||||||
|
{{ isReloading ? '热加载中...' : '🔄 热加载配置' }}
|
||||||
|
</el-button>
|
||||||
<el-button type="warning" :icon="Delete" @click="handleFlushCache">清空缓存</el-button>
|
<el-button type="warning" :icon="Delete" @click="handleFlushCache">清空缓存</el-button>
|
||||||
<el-button type="danger" @click="handleRestart">重启服务</el-button>
|
<el-button type="danger" @click="handleRestart">重启服务</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="tip-info">
|
||||||
|
<el-alert
|
||||||
|
title="💡 提示:热加载可以在不重启服务的情况下重新加载配置,DNS服务不会中断"
|
||||||
|
type="info"
|
||||||
|
:closable="false"
|
||||||
|
show-icon
|
||||||
|
style="margin-top: 15px;"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|||||||
@ -1,628 +0,0 @@
|
|||||||
# YLTX-DNS 智能防污染系统架构设计文档
|
|
||||||
|
|
||||||
## 📋 目录
|
|
||||||
|
|
||||||
- [1. 项目概述](#1-项目概述)
|
|
||||||
- [2. 需求分析](#2-需求分析)
|
|
||||||
- [3. 系统架构设计](#3-系统架构设计)
|
|
||||||
- [4. 技术方案详述](#4-技术方案详述)
|
|
||||||
- [5. 开发计划](#5-开发计划)
|
|
||||||
- [6. 风险评估与应对](#6-风险评估与应对)
|
|
||||||
- [7. 质量保障](#7-质量保障)
|
|
||||||
- [8. 部署与运维](#8-部署与运维)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 1. 项目概述
|
|
||||||
|
|
||||||
### 1.1 项目背景
|
|
||||||
|
|
||||||
传统DNS解析存在污染问题,特别是在访问国际服务时容易受到干扰。本项目旨在基于成熟的MosDNS引擎,开发一套智能防污染DNS系统,实现:
|
|
||||||
|
|
||||||
- **智能污染检测**:自动识别DNS污染行为
|
|
||||||
- **动态策略切换**:根据域名特征和IP归属智能选择解析策略
|
|
||||||
- **可视化管理**:提供直观的Web界面进行配置管理
|
|
||||||
- **自动化运维**:支持配置热重载和实时监控
|
|
||||||
|
|
||||||
### 1.2 项目目标
|
|
||||||
|
|
||||||
#### 🎯 核心目标
|
|
||||||
- **零配置崩溃**:解决MosDNS配置顺序敏感导致的崩溃问题
|
|
||||||
- **智能防污染**:实现基于CN IP地址表的智能污染检测和自动切换
|
|
||||||
- **可视化管理**:提供完整的Web界面进行域名规则管理
|
|
||||||
- **热重载配置**:无需重启服务即可生效配置变更
|
|
||||||
|
|
||||||
#### 📊 性能指标
|
|
||||||
- **响应时间**:< 200ms(国内DNS),< 500ms(国际DNS)
|
|
||||||
- **准确率**:> 95%(污染检测准确率)
|
|
||||||
- **可用性**:> 99.9%(服务可用性)
|
|
||||||
- **并发数**:> 1000 QPS
|
|
||||||
|
|
||||||
### 1.3 项目范围
|
|
||||||
|
|
||||||
#### ✅ 包含功能
|
|
||||||
- 基于MosDNS的二次开发改造
|
|
||||||
- 智能防污染插件开发
|
|
||||||
- 配置智能加载和验证系统
|
|
||||||
- Web管理界面开发
|
|
||||||
- 域名规则管理API
|
|
||||||
- CN IP地址表集成
|
|
||||||
- MikroTik推送集成
|
|
||||||
|
|
||||||
#### ❌ 不包含功能
|
|
||||||
- 完全自主DNS协议栈开发
|
|
||||||
- 硬件加速优化
|
|
||||||
- 多地域部署方案
|
|
||||||
- 商业化SaaS版本
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 2. 需求分析
|
|
||||||
|
|
||||||
### 2.1 用户痛点
|
|
||||||
|
|
||||||
1. **配置复杂**:MosDNS配置语法复杂,顺序敏感,容易出错
|
|
||||||
2. **污染检测困难**:传统防污染方案依赖人工判断或简单黑名单
|
|
||||||
3. **管理不便**:缺乏直观的配置管理界面
|
|
||||||
4. **运维成本高**:配置变更需要重启服务,可用性差
|
|
||||||
|
|
||||||
### 2.2 功能需求
|
|
||||||
|
|
||||||
#### 核心功能需求
|
|
||||||
|
|
||||||
| 功能模块 | 优先级 | 描述 |
|
|
||||||
|---------|--------|------|
|
|
||||||
| 智能防污染 | P0 | 先国内DNS查询,返回国外IP则自动切换国际DNS |
|
|
||||||
| 配置智能加载 | P0 | 自动分析依赖关系,解决配置顺序问题 |
|
|
||||||
| 可视化规则管理 | P1 | Web界面管理域名路由规则 |
|
|
||||||
| CN IP地址表集成 | P1 | 自动判断IP归属,实现精准污染检测 |
|
|
||||||
| MikroTik推送 | P2 | 支持RouterOS地址列表自动更新 |
|
|
||||||
| 热重载配置 | P2 | 无需重启即可生效配置变更 |
|
|
||||||
|
|
||||||
#### 非功能需求
|
|
||||||
|
|
||||||
| 需求类型 | 具体要求 |
|
|
||||||
|---------|---------|
|
|
||||||
| 性能 | 响应时间<200ms,QPS>1000 |
|
|
||||||
| 可靠性 | 服务可用性>99.9%,自动故障恢复 |
|
|
||||||
| 可扩展性 | 支持插件化扩展,支持多DNS策略 |
|
|
||||||
| 安全性 | 支持HTTPS管理接口,支持API认证 |
|
|
||||||
| 可维护性 | 模块化设计,详细日志记录 |
|
|
||||||
|
|
||||||
### 2.3 用户场景
|
|
||||||
|
|
||||||
#### 场景1:日常上网防护
|
|
||||||
```
|
|
||||||
用户访问各种网站,系统自动:
|
|
||||||
- 国内网站 → 国内DNS加速解析
|
|
||||||
- 国际网站 → 自动检测污染并切换国际DNS
|
|
||||||
- 未知网站 → 智能判断并选择最优解析策略
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 场景2:管理员配置管理
|
|
||||||
```
|
|
||||||
管理员通过Web界面:
|
|
||||||
- 添加域名规则(支持域名文件导入)
|
|
||||||
- 配置DNS策略(国内/国际/智能防污染)
|
|
||||||
- 设置MikroTik推送参数
|
|
||||||
- 查看实时统计和日志
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 场景3:故障排查
|
|
||||||
```
|
|
||||||
系统出现异常时:
|
|
||||||
- 详细错误日志便于定位问题
|
|
||||||
- 实时监控指标帮助诊断
|
|
||||||
- 配置验证防止人为错误
|
|
||||||
- 热重载快速恢复服务
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 3. 系统架构设计
|
|
||||||
|
|
||||||
### 3.1 总体架构
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────────────────────────────┐
|
|
||||||
│ 用户层 │
|
|
||||||
├─────────────────────────────────────────────────────────────────┤
|
|
||||||
│ 🌐 Web浏览器 → Vue前端 → RESTful API → 业务逻辑层 │
|
|
||||||
├─────────────────────────────────────────────────────────────────┤
|
|
||||||
│ 服务层 │
|
|
||||||
├─────────────────────────────────────────────────────────────────┤
|
|
||||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
|
||||||
│ │ Web管理界面 │ │ 配置生成器 │ │ 智能验证器 │ │ 规则引擎 │ │
|
|
||||||
│ │ Vue3 + TS │ │ Go API │ │ 依赖分析 │ │ 策略路由 │ │
|
|
||||||
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │
|
|
||||||
├─────────────────────────────────────────────────────────────────┤
|
|
||||||
│ 核心层 │
|
|
||||||
├─────────────────────────────────────────────────────────────────┤
|
|
||||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
|
||||||
│ │ MosDNS引擎 │ │ 防污染插件 │ │ 缓存系统 │ │ 上游管理 │ │
|
|
||||||
│ │ DNS协议栈 │ │ SmartFallback│ │ LRU Cache │ │ 连接池 │ │
|
|
||||||
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │
|
|
||||||
├─────────────────────────────────────────────────────────────────┤
|
|
||||||
│ 数据层 │
|
|
||||||
├─────────────────────────────────────────────────────────────────┤
|
|
||||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
|
||||||
│ │ 域名文件 │ │ CN IP表 │ │ 配置存储 │ │ 日志存储 │ │
|
|
||||||
│ │ .txt格式 │ │ CIDR格式 │ │ YAML文件 │ │ 文件系统 │ │
|
|
||||||
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │
|
|
||||||
└─────────────────────────────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3.2 模块划分
|
|
||||||
|
|
||||||
#### 前端模块 (Vue3 + TypeScript)
|
|
||||||
- **RulesView.vue**:域名规则管理界面
|
|
||||||
- **DashboardView.vue**:系统状态监控面板
|
|
||||||
- **ConfigView.vue**:配置管理界面
|
|
||||||
- **api/**:HTTP客户端和服务接口
|
|
||||||
|
|
||||||
#### 后端模块 (Go)
|
|
||||||
- **coremain/**:核心业务逻辑
|
|
||||||
- `config.go`:配置加载和智能排序
|
|
||||||
- `config_validator.go`:配置验证器
|
|
||||||
- `config_builder.go`:配置生成器
|
|
||||||
- `api_handlers.go`:Web API接口
|
|
||||||
- **plugin/executable/smart_fallback/**:智能防污染插件
|
|
||||||
- **pkg/**:通用工具包
|
|
||||||
|
|
||||||
#### 数据存储
|
|
||||||
- **域名文件**:`/data/mikrotik/*.txt`
|
|
||||||
- **CN IP表**:`/data/chn_ip.txt`
|
|
||||||
- **配置文件**:`config.yaml` + `config.d/rules/*.yaml`
|
|
||||||
- **日志文件**:`/var/log/mosdns.log`
|
|
||||||
|
|
||||||
### 3.3 数据流设计
|
|
||||||
|
|
||||||
#### 配置管理流程
|
|
||||||
```
|
|
||||||
1. 用户在Web界面添加规则
|
|
||||||
2. 前端发送POST请求到 /api/rules
|
|
||||||
3. API调用配置生成器生成YAML
|
|
||||||
4. 验证器检查配置合法性
|
|
||||||
5. 保存到 config.d/rules/ 目录
|
|
||||||
6. 用户点击重载,热重载配置
|
|
||||||
7. MosDNS重新加载配置,无需重启
|
|
||||||
```
|
|
||||||
|
|
||||||
#### DNS查询流程
|
|
||||||
```
|
|
||||||
1. 客户端发起DNS查询
|
|
||||||
2. MosDNS主序列接收请求
|
|
||||||
3. 根据域名匹配对应规则
|
|
||||||
4. 执行对应DNS策略
|
|
||||||
├─ 国内DNS → 直接转发到国内上游
|
|
||||||
├─ 国际DNS → 转发到国际上游
|
|
||||||
└─ 智能防污染 → 执行SmartFallback逻辑
|
|
||||||
5. 返回解析结果
|
|
||||||
6. 可选:推送IP到MikroTik
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 4. 技术方案详述
|
|
||||||
|
|
||||||
### 4.1 核心技术方案
|
|
||||||
|
|
||||||
#### 4.1.1 配置智能加载系统
|
|
||||||
|
|
||||||
**问题解决**:MosDNS配置顺序敏感导致崩溃
|
|
||||||
|
|
||||||
**技术方案**:
|
|
||||||
```go
|
|
||||||
// 核心算法:拓扑排序
|
|
||||||
func (c *Config) loadPlugins() error {
|
|
||||||
// 1. 构建依赖图
|
|
||||||
graph := buildDependencyGraph(c.Plugins)
|
|
||||||
|
|
||||||
// 2. 拓扑排序
|
|
||||||
sorted := topologicalSort(graph)
|
|
||||||
|
|
||||||
// 3. 按正确顺序加载
|
|
||||||
for _, plugin := range sorted {
|
|
||||||
c.loadPlugin(plugin)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**依赖图构建**:
|
|
||||||
```go
|
|
||||||
// 分析 $plugin_name 引用关系
|
|
||||||
func buildDependencyGraph(plugins []PluginConfig) map[string][]string {
|
|
||||||
graph := make(map[string][]string)
|
|
||||||
for _, p := range plugins {
|
|
||||||
graph[p.Tag] = extractDependencies(p.Args)
|
|
||||||
}
|
|
||||||
return graph
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 4.1.2 智能防污染插件
|
|
||||||
|
|
||||||
**核心算法**:
|
|
||||||
```go
|
|
||||||
func (s *SmartFallback) Exec(ctx context.Context, qCtx *QueryContext) error {
|
|
||||||
// 1. 先查询国内DNS
|
|
||||||
err := s.primary.Exec(ctx, qCtx)
|
|
||||||
|
|
||||||
// 2. 检查返回IP是否在CN地址表
|
|
||||||
if s.isResponseFromChina(qCtx.Response()) {
|
|
||||||
return nil // 是CN IP,直接返回
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. 非CN IP,重新查询国际DNS
|
|
||||||
return s.secondary.Exec(ctx, qCtx)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**CN IP检测**:
|
|
||||||
```go
|
|
||||||
func (s *SmartFallback) isResponseFromChina(resp *dns.Msg) bool {
|
|
||||||
for _, ans := range resp.Answer {
|
|
||||||
if a, ok := ans.(*dns.A); ok {
|
|
||||||
ip := netip.AddrFrom4([4]byte(a.A))
|
|
||||||
// 检查是否在CN地址表
|
|
||||||
if matched, _ := s.chinaIPList.Match(ip); !matched {
|
|
||||||
return false // 国外IP
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true // 全部为CN IP
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 4.1.3 配置生成器
|
|
||||||
|
|
||||||
**规则定义**:
|
|
||||||
```go
|
|
||||||
type DomainRule struct {
|
|
||||||
Name string // 规则名称
|
|
||||||
DomainFile string // 域名文件路径
|
|
||||||
DNSStrategy string // DNS策略:china-dns/overseas-dns/smart-fallback
|
|
||||||
EnableMikroTik bool // 是否启用MikroTik推送
|
|
||||||
MikroTikConfig MikroTikConfig // MikroTik配置
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**自动生成配置**:
|
|
||||||
```go
|
|
||||||
func (b *ConfigBuilder) AddDomainRule(rule DomainRule) error {
|
|
||||||
// 1. 创建domain_set插件
|
|
||||||
domainSet := PluginConfig{
|
|
||||||
Tag: "domains_" + rule.Name,
|
|
||||||
Type: "domain_set",
|
|
||||||
Args: map[string]interface{}{
|
|
||||||
"files": []string{rule.DomainFile},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 创建sequence插件
|
|
||||||
sequence := PluginConfig{
|
|
||||||
Tag: "rule_" + rule.Name,
|
|
||||||
Type: "sequence",
|
|
||||||
Args: map[string]interface{}{
|
|
||||||
"exec": []map[string]interface{}{
|
|
||||||
{
|
|
||||||
"matches": "qname $" + domainSet.Tag,
|
|
||||||
"exec": "$" + rule.DNSStrategy,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. 添加到主序列
|
|
||||||
b.addToMainSequence(sequence.Tag)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4.2 前端技术方案
|
|
||||||
|
|
||||||
#### 4.2.1 界面设计原则
|
|
||||||
|
|
||||||
- **用户友好**:向导式配置,减少技术门槛
|
|
||||||
- **实时反馈**:即时验证和错误提示
|
|
||||||
- **状态可视**:实时显示系统运行状态
|
|
||||||
- **响应式设计**:支持桌面和移动端访问
|
|
||||||
|
|
||||||
#### 4.2.2 核心界面组件
|
|
||||||
|
|
||||||
**规则管理表单**:
|
|
||||||
```vue
|
|
||||||
<template>
|
|
||||||
<!-- 基础信息卡片 -->
|
|
||||||
<el-card class="form-section">
|
|
||||||
<template #header>基础信息</template>
|
|
||||||
<el-form-item label="规则名称" prop="name">
|
|
||||||
<el-input v-model="form.name" placeholder="请输入规则名称" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-card>
|
|
||||||
|
|
||||||
<!-- DNS策略卡片 -->
|
|
||||||
<el-card class="form-section">
|
|
||||||
<template #header>DNS解析策略</template>
|
|
||||||
<el-radio-group v-model="form.dnsStrategy">
|
|
||||||
<el-radio value="china-dns">🇨🇳 国内DNS</el-radio>
|
|
||||||
<el-radio value="overseas-dns">🌐 国外DNS</el-radio>
|
|
||||||
<el-radio value="smart-fallback">🛡️ 智能防污染</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-card>
|
|
||||||
|
|
||||||
<!-- MikroTik配置卡片 -->
|
|
||||||
<el-card class="form-section">
|
|
||||||
<template #header>
|
|
||||||
RouterOS推送配置
|
|
||||||
<el-switch v-model="form.enableMikrotik" />
|
|
||||||
</template>
|
|
||||||
<div v-if="form.enableMikrotik">
|
|
||||||
<!-- MikroTik参数表单 -->
|
|
||||||
</div>
|
|
||||||
</el-card>
|
|
||||||
</template>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4.3 数据存储方案
|
|
||||||
|
|
||||||
#### 4.3.1 域名文件格式
|
|
||||||
```
|
|
||||||
# /data/mikrotik/openai.txt
|
|
||||||
openai.com
|
|
||||||
api.openai.com
|
|
||||||
chat.openai.com
|
|
||||||
*.openai.com
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 4.3.2 CN IP地址表格式
|
|
||||||
```
|
|
||||||
# /data/chn_ip.txt (CIDR格式)
|
|
||||||
1.0.1.0/24
|
|
||||||
1.0.2.0/23
|
|
||||||
1.1.0.0/24
|
|
||||||
# ... 更多地址段
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 4.3.3 配置文件结构
|
|
||||||
```
|
|
||||||
config.yaml # 主配置文件
|
|
||||||
config.d/
|
|
||||||
└── rules/
|
|
||||||
├── openai.yaml # OpenAI规则
|
|
||||||
├── netflix.yaml # Netflix规则
|
|
||||||
└── game-cn.yaml # 国内游戏规则
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 5. 开发计划
|
|
||||||
|
|
||||||
### 5.1 总体时间线
|
|
||||||
|
|
||||||
```
|
|
||||||
第1-7天:核心功能开发
|
|
||||||
第8-14天:管理层开发
|
|
||||||
第15-21天:前端开发与集成
|
|
||||||
第22-28天:测试与优化
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5.2 详细开发计划
|
|
||||||
|
|
||||||
#### 第一阶段:核心功能改造(1周)
|
|
||||||
|
|
||||||
| 任务 | 负责人 | 时间 | 交付物 |
|
|
||||||
|-----|--------|------|--------|
|
|
||||||
| 配置拓扑排序实现 | 后端开发 | 2天 | `coremain/config.go` |
|
|
||||||
| 智能防污染插件开发 | 后端开发 | 3天 | `plugin/executable/smart_fallback/` |
|
|
||||||
| 配置验证器开发 | 后端开发 | 2天 | `coremain/config_validator.go` |
|
|
||||||
|
|
||||||
**里程碑**:核心DNS功能正常工作,配置顺序不敏感
|
|
||||||
|
|
||||||
#### 第二阶段:管理层开发(1周)
|
|
||||||
|
|
||||||
| 任务 | 负责人 | 时间 | 交付物 |
|
|
||||||
|-----|--------|------|--------|
|
|
||||||
| 配置生成器开发 | 后端开发 | 3天 | `coremain/config_builder.go` |
|
|
||||||
| 规则管理API开发 | 后端开发 | 2天 | API接口文档 |
|
|
||||||
| 基础Web界面集成 | 前端开发 | 2天 | 基本CRUD界面 |
|
|
||||||
|
|
||||||
**里程碑**:可通过Web界面管理域名规则
|
|
||||||
|
|
||||||
#### 第三阶段:前端开发与集成(1周)
|
|
||||||
|
|
||||||
| 任务 | 负责人 | 时间 | 交付物 |
|
|
||||||
|-----|--------|------|--------|
|
|
||||||
| Vue界面优化 | 前端开发 | 3天 | 完整管理界面 |
|
|
||||||
| 实时状态显示 | 前端开发 | 2天 | 监控面板 |
|
|
||||||
| 用户体验完善 | 前端开发 | 2天 | 交互优化 |
|
|
||||||
|
|
||||||
**里程碑**:完整的管理界面,支持所有功能
|
|
||||||
|
|
||||||
#### 第四阶段:测试与优化(1周)
|
|
||||||
|
|
||||||
| 任务 | 负责人 | 时间 | 交付物 |
|
|
||||||
|-----|--------|------|--------|
|
|
||||||
| 功能测试 | 测试工程师 | 2天 | 测试报告 |
|
|
||||||
| 性能测试 | 测试工程师 | 2天 | 性能报告 |
|
|
||||||
| 用户体验测试 | 产品经理 | 1天 | UX反馈 |
|
|
||||||
| 部署测试 | 运维工程师 | 2天 | 部署指南 |
|
|
||||||
|
|
||||||
**里程碑**:系统稳定可用,性能达标
|
|
||||||
|
|
||||||
### 5.3 人力资源配置
|
|
||||||
|
|
||||||
| 角色 | 人数 | 职责 |
|
|
||||||
|-----|------|------|
|
|
||||||
| 后端开发工程师 | 1 | Go核心功能开发 |
|
|
||||||
| 前端开发工程师 | 1 | Vue界面开发 |
|
|
||||||
| 测试工程师 | 1 | 功能和性能测试 |
|
|
||||||
| 产品经理 | 1 | 需求分析和用户体验 |
|
|
||||||
| 运维工程师 | 1 | 部署和运维支持 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 6. 风险评估与应对
|
|
||||||
|
|
||||||
### 6.1 技术风险
|
|
||||||
|
|
||||||
#### 高风险
|
|
||||||
- **配置兼容性**:二次开发可能破坏现有配置
|
|
||||||
- **应对**:保留原有API,向后兼容,提供迁移指南
|
|
||||||
|
|
||||||
- **性能回归**:新功能可能影响DNS解析性能
|
|
||||||
- **应对**:性能基准测试,建立性能监控体系
|
|
||||||
|
|
||||||
#### 中风险
|
|
||||||
- **CN IP表准确性**:IP地址表可能过期或不准确
|
|
||||||
- **应对**:提供自动更新机制,多数据源验证
|
|
||||||
|
|
||||||
- **MikroTik集成稳定性**:RouterOS API可能不稳定
|
|
||||||
- **应对**:添加重试机制,异步处理,避免阻塞DNS响应
|
|
||||||
|
|
||||||
#### 低风险
|
|
||||||
- **前端兼容性**:不同浏览器可能表现不一致
|
|
||||||
- **应对**:使用主流UI框架,确保跨浏览器兼容
|
|
||||||
|
|
||||||
### 6.2 项目风险
|
|
||||||
|
|
||||||
#### 高风险
|
|
||||||
- **时间延误**:核心功能开发可能超出预期
|
|
||||||
- **应对**:采用敏捷开发,定期review,及时调整计划
|
|
||||||
|
|
||||||
- **需求变更**:用户需求可能在开发过程中变化
|
|
||||||
- **应对**:建立变更控制流程,优先级管理
|
|
||||||
|
|
||||||
#### 中风险
|
|
||||||
- **人员变动**:核心开发人员可能变动
|
|
||||||
- **应对**:知识共享,建立文档体系,交叉培训
|
|
||||||
|
|
||||||
- **技术选型错误**:技术方案可能不符合实际需求
|
|
||||||
- **应对**:快速原型验证,建立技术评审机制
|
|
||||||
|
|
||||||
### 6.3 应对策略
|
|
||||||
|
|
||||||
#### 风险监控
|
|
||||||
- 建立风险登记册,定期评估风险状态
|
|
||||||
- 设置风险阈值,超过阈值立即采取行动
|
|
||||||
- 定期向项目组汇报风险状态
|
|
||||||
|
|
||||||
#### 应急预案
|
|
||||||
- 核心功能失败:回退到原版MosDNS
|
|
||||||
- 性能问题:优化算法或降低功能复杂度
|
|
||||||
- 时间延误:压缩测试时间或减少非核心功能
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 7. 质量保障
|
|
||||||
|
|
||||||
### 7.1 测试策略
|
|
||||||
|
|
||||||
#### 单元测试
|
|
||||||
- 每个核心函数和模块都需要单元测试
|
|
||||||
- 测试覆盖率 > 80%
|
|
||||||
- 边界条件和异常情况必须覆盖
|
|
||||||
|
|
||||||
#### 集成测试
|
|
||||||
- 测试完整的功能流程
|
|
||||||
- 测试配置生成和加载过程
|
|
||||||
- 测试防污染逻辑的准确性
|
|
||||||
|
|
||||||
#### 性能测试
|
|
||||||
- 基准性能测试(响应时间、吞吐量)
|
|
||||||
- 负载测试(高并发场景)
|
|
||||||
- 稳定性测试(长时间运行)
|
|
||||||
|
|
||||||
#### 用户验收测试
|
|
||||||
- 实际使用场景测试
|
|
||||||
- 用户体验评估
|
|
||||||
- 功能完整性验证
|
|
||||||
|
|
||||||
### 7.2 代码质量
|
|
||||||
|
|
||||||
#### 编码规范
|
|
||||||
- 遵循Go官方编码规范
|
|
||||||
- 使用 golint、gofmt 等工具检查
|
|
||||||
- 统一的错误处理模式
|
|
||||||
|
|
||||||
#### 文档要求
|
|
||||||
- 每个函数和模块必须有注释
|
|
||||||
- 复杂算法需要详细说明
|
|
||||||
- 配置文件格式需要文档说明
|
|
||||||
|
|
||||||
#### 版本控制
|
|
||||||
- 使用Git进行版本管理
|
|
||||||
- 建立分支管理策略(master/develop/feature)
|
|
||||||
- 代码审查流程(PR审查)
|
|
||||||
|
|
||||||
### 7.3 质量指标
|
|
||||||
|
|
||||||
| 指标类型 | 具体指标 | 目标值 |
|
|
||||||
|---------|---------|--------|
|
|
||||||
| 功能性 | 功能覆盖率 | 100% |
|
|
||||||
| 性能 | 平均响应时间 | < 200ms |
|
|
||||||
| 可靠性 | 服务可用性 | > 99.9% |
|
|
||||||
| 可维护性 | 技术债务比 | < 5% |
|
|
||||||
| 安全性 | 安全漏洞数 | 0 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 8. 部署与运维
|
|
||||||
|
|
||||||
### 8.1 部署方案
|
|
||||||
|
|
||||||
#### 开发环境
|
|
||||||
- 本地开发:Go 1.19+,Node.js 16+
|
|
||||||
- 代码管理:Git + GitHub
|
|
||||||
- CI/CD:GitHub Actions
|
|
||||||
|
|
||||||
#### 测试环境
|
|
||||||
- Docker容器部署
|
|
||||||
- 自动化测试流水线
|
|
||||||
- 性能监控集成
|
|
||||||
|
|
||||||
#### 生产环境
|
|
||||||
- 二进制文件部署(推荐)
|
|
||||||
- Docker容器部署(备选)
|
|
||||||
- Systemd服务管理
|
|
||||||
|
|
||||||
### 8.2 运维方案
|
|
||||||
|
|
||||||
#### 监控体系
|
|
||||||
- 应用指标监控(响应时间、错误率、QPS)
|
|
||||||
- 系统资源监控(CPU、内存、磁盘、网络)
|
|
||||||
- 日志聚合和分析
|
|
||||||
|
|
||||||
#### 运维工具
|
|
||||||
- 配置管理:Ansible或脚本自动化
|
|
||||||
- 日志管理:ELK Stack或Loki
|
|
||||||
- 监控告警:Prometheus + Grafana
|
|
||||||
|
|
||||||
#### 备份策略
|
|
||||||
- 配置文件自动备份
|
|
||||||
- 日志文件定期归档
|
|
||||||
- 域名文件和IP表备份
|
|
||||||
|
|
||||||
### 8.3 升级策略
|
|
||||||
|
|
||||||
#### 小版本升级
|
|
||||||
- 配置热重载,无需停机
|
|
||||||
- 新功能逐步上线,灰度发布
|
|
||||||
|
|
||||||
#### 大版本升级
|
|
||||||
- 蓝绿部署或滚动升级
|
|
||||||
- 升级前数据备份和兼容性检查
|
|
||||||
- 升级后全面验证和监控
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📞 联系方式
|
|
||||||
|
|
||||||
- 项目负责人:yltx
|
|
||||||
- 技术支持:相关技术群组
|
|
||||||
- 文档维护:GitHub Wiki
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*本文档最后更新时间:2025年10月15日*
|
|
||||||
411
功能实现清单.md
411
功能实现清单.md
@ -1,411 +0,0 @@
|
|||||||
# YLTX-DNS 功能实现清单
|
|
||||||
|
|
||||||
> 二次开发完整功能一览表
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✅ 已实现功能
|
|
||||||
|
|
||||||
### 🔧 核心引擎层
|
|
||||||
|
|
||||||
#### 1. 配置拓扑排序系统 ✅
|
|
||||||
- [x] Kahn算法实现
|
|
||||||
- [x] 依赖关系自动提取 (`$plugin_name` 正则匹配)
|
|
||||||
- [x] 循环依赖检测
|
|
||||||
- [x] 详细错误提示
|
|
||||||
- [x] 自动顺序调整
|
|
||||||
- **文件**: `pkg/utils/toposort.go` (145行)
|
|
||||||
- **测试**: ✅ 通过
|
|
||||||
|
|
||||||
#### 2. 配置预验证器 ✅
|
|
||||||
- [x] 基本结构验证
|
|
||||||
- [x] 插件引用完整性检查
|
|
||||||
- [x] 必需插件检查 (main等)
|
|
||||||
- [x] 文件路径验证 (domain_set, ip_set)
|
|
||||||
- [x] 配置冲突检测 (重复标签, 端口冲突)
|
|
||||||
- [x] 循环依赖验证
|
|
||||||
- [x] 警告与错误分级
|
|
||||||
- **文件**: `coremain/config_validator.go` (293行)
|
|
||||||
- **测试**: ✅ 通过
|
|
||||||
|
|
||||||
#### 3. 智能防污染插件 ✅
|
|
||||||
- [x] 顺序查询模式 (节省资源)
|
|
||||||
- [x] 并行查询模式 (低延迟)
|
|
||||||
- [x] CN IP地址表匹配
|
|
||||||
- [x] 自动DNS切换
|
|
||||||
- [x] IPv4/IPv6支持
|
|
||||||
- [x] 详细日志输出
|
|
||||||
- [x] 超时控制
|
|
||||||
- **文件**: `plugin/executable/smart_fallback/smart_fallback.go` (270行)
|
|
||||||
- **性能**: P95 < 150ms
|
|
||||||
- **测试**: ✅ 通过
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 🏗️ 业务逻辑层
|
|
||||||
|
|
||||||
#### 4. 配置生成器 (ConfigBuilder) ✅
|
|
||||||
- [x] 域名规则增删改查
|
|
||||||
- [x] 自动生成YAML配置
|
|
||||||
- [x] domain_set 插件自动创建
|
|
||||||
- [x] sequence 插件自动创建
|
|
||||||
- [x] mikrotik_addresslist 插件自动创建
|
|
||||||
- [x] include 列表自动管理
|
|
||||||
- [x] YAML格式化 (2空格缩进)
|
|
||||||
- [x] 智能默认值填充
|
|
||||||
- **文件**: `coremain/config_builder.go` (429行)
|
|
||||||
- **API**: AddDomainRule, UpdateDomainRule, DeleteDomainRule, ListRules, GetRule
|
|
||||||
- **测试**: ✅ 通过
|
|
||||||
|
|
||||||
#### 5. 规则管理API ✅
|
|
||||||
- [x] GET /api/rules - 列出所有规则
|
|
||||||
- [x] GET /api/rules/{name} - 获取规则详情
|
|
||||||
- [x] POST /api/rules - 添加新规则
|
|
||||||
- [x] PUT /api/rules/{name} - 更新规则
|
|
||||||
- [x] DELETE /api/rules/{name} - 删除规则
|
|
||||||
- [x] 参数验证
|
|
||||||
- [x] 错误处理
|
|
||||||
- [x] CORS支持
|
|
||||||
- **文件**: `coremain/rule_handlers.go` (639行)
|
|
||||||
- **测试**: ✅ 通过
|
|
||||||
|
|
||||||
#### 6. 服务器信息API ✅
|
|
||||||
- [x] GET /api/server-info - 系统状态
|
|
||||||
- [x] GET /api/stats - 查询统计
|
|
||||||
- [x] DNS端口识别
|
|
||||||
- [x] 运行时间统计
|
|
||||||
- [x] 插件数量统计
|
|
||||||
- **文件**: `coremain/api_handlers.go` (已修改)
|
|
||||||
- **测试**: ✅ 通过
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 🖥️ 前端界面层
|
|
||||||
|
|
||||||
#### 7. Vue 3 Web管理界面 ✅
|
|
||||||
|
|
||||||
##### 7.1 仪表盘 ✅
|
|
||||||
- [x] 系统状态卡片
|
|
||||||
- [x] 运行时间显示
|
|
||||||
- [x] 插件数量显示
|
|
||||||
- [x] DNS端口识别
|
|
||||||
- [x] 实时统计
|
|
||||||
- [x] 查询总数
|
|
||||||
- [x] 缓存命中率
|
|
||||||
- [x] 平均延迟
|
|
||||||
- [x] 响应式布局
|
|
||||||
- [x] 自动刷新
|
|
||||||
- **文件**: `web-ui/src/views/DashboardView.vue`
|
|
||||||
- **测试**: ✅ 通过
|
|
||||||
|
|
||||||
##### 7.2 域名规则管理 ✅
|
|
||||||
- [x] 规则列表展示
|
|
||||||
- [x] 表格展示
|
|
||||||
- [x] 排序支持
|
|
||||||
- [x] 搜索功能
|
|
||||||
- [x] 添加规则对话框
|
|
||||||
- [x] 表单验证
|
|
||||||
- [x] DNS策略选择
|
|
||||||
- [x] 国内DNS
|
|
||||||
- [x] 国外DNS
|
|
||||||
- [x] 智能防污染
|
|
||||||
- [x] MikroTik配置
|
|
||||||
- [x] 路由器连接信息
|
|
||||||
- [x] 地址列表配置
|
|
||||||
- [x] 高级参数
|
|
||||||
- [x] 启用/禁用开关
|
|
||||||
- [x] 编辑规则
|
|
||||||
- [x] 删除规则 (二次确认)
|
|
||||||
- [x] 实时状态更新
|
|
||||||
- **文件**: `web-ui/src/views/RulesView.vue`
|
|
||||||
- **测试**: ✅ 通过
|
|
||||||
|
|
||||||
##### 7.3 应用布局 ✅
|
|
||||||
- [x] 顶部导航栏
|
|
||||||
- [x] 侧边菜单
|
|
||||||
- [x] 响应式设计
|
|
||||||
- [x] 全屏自适应
|
|
||||||
- [x] Element Plus主题
|
|
||||||
- **文件**: `web-ui/src/App.vue`
|
|
||||||
- **测试**: ✅ 通过
|
|
||||||
|
|
||||||
#### 8. 状态管理 (Pinia) ✅
|
|
||||||
- [x] 规则状态管理
|
|
||||||
- [x] 异步操作处理
|
|
||||||
- [x] 错误状态管理
|
|
||||||
- **文件**: `web-ui/src/stores/rules.ts`
|
|
||||||
- **测试**: ✅ 通过
|
|
||||||
|
|
||||||
#### 9. API客户端 ✅
|
|
||||||
- [x] Axios配置
|
|
||||||
- [x] 拦截器
|
|
||||||
- [x] 错误处理
|
|
||||||
- [x] 规则API封装
|
|
||||||
- [x] 服务器API封装
|
|
||||||
- **文件**:
|
|
||||||
- `web-ui/src/api/http.ts`
|
|
||||||
- `web-ui/src/api/rules.ts`
|
|
||||||
- `web-ui/src/api/server.ts`
|
|
||||||
- **测试**: ✅ 通过
|
|
||||||
|
|
||||||
#### 10. 路由配置 ✅
|
|
||||||
- [x] 仪表盘路由
|
|
||||||
- [x] 规则管理路由
|
|
||||||
- [x] SPA路由集成
|
|
||||||
- **文件**: `web-ui/src/router/index.ts`
|
|
||||||
- **测试**: ✅ 通过
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 🔨 构建与部署
|
|
||||||
|
|
||||||
#### 11. 前端构建 ✅
|
|
||||||
- [x] Vite配置优化
|
|
||||||
- [x] TypeScript配置
|
|
||||||
- [x] 代码分割 (vendor chunk)
|
|
||||||
- [x] 生产环境优化
|
|
||||||
- **文件**:
|
|
||||||
- `web-ui/vite.config.ts`
|
|
||||||
- `web-ui/tsconfig.json`
|
|
||||||
- **测试**: ✅ 通过
|
|
||||||
|
|
||||||
#### 12. Go嵌入集成 ✅
|
|
||||||
- [x] embed.FS配置
|
|
||||||
- [x] SPA服务器
|
|
||||||
- [x] 静态资源处理
|
|
||||||
- [x] HTML5 History模式
|
|
||||||
- **文件**:
|
|
||||||
- `web_embed.go`
|
|
||||||
- `coremain/web_ui.go`
|
|
||||||
- **测试**: ✅ 通过
|
|
||||||
|
|
||||||
#### 13. 构建脚本 ✅
|
|
||||||
- [x] Windows批处理脚本
|
|
||||||
- [x] Linux Shell脚本
|
|
||||||
- [x] 自动前端构建
|
|
||||||
- [x] 全平台编译
|
|
||||||
- **文件**:
|
|
||||||
- `build-all-platforms.bat` (已修改)
|
|
||||||
- **测试**: ✅ 通过
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 🧪 测试与文档
|
|
||||||
|
|
||||||
#### 14. 自动化测试 ✅
|
|
||||||
- [x] 依赖检查 (Go, Node.js)
|
|
||||||
- [x] 编译测试
|
|
||||||
- [x] 插件注册验证
|
|
||||||
- [x] 配置验证测试
|
|
||||||
- [x] 前端构建测试
|
|
||||||
- [x] 测试文件清理
|
|
||||||
- **文件**: `test-smart-fallback.sh` (243行)
|
|
||||||
- **测试**: ✅ 通过
|
|
||||||
|
|
||||||
#### 15. 完整文档 ✅
|
|
||||||
- [x] 架构设计文档
|
|
||||||
- [x] 二次开发总结
|
|
||||||
- [x] 错误修复记录
|
|
||||||
- [x] 配置示例
|
|
||||||
- [x] 快速开始指南
|
|
||||||
- [x] README文档
|
|
||||||
- **文件**:
|
|
||||||
- `yltx-dns-智能防污染系统-架构设计文档.md`
|
|
||||||
- `YLTX-DNS智能防污染系统-二次开发总结.md`
|
|
||||||
- `错误修复总结.md`
|
|
||||||
- `README-二开版本.md`
|
|
||||||
- `config-smart-fallback.yaml`
|
|
||||||
- **完成度**: ✅ 100%
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 📦 数据与资源
|
|
||||||
|
|
||||||
#### 16. CN IP地址表 ✅
|
|
||||||
- [x] 中国大陆IP地址段
|
|
||||||
- [x] CIDR格式
|
|
||||||
- [x] 主流ISP覆盖
|
|
||||||
- [x] 中国电信
|
|
||||||
- [x] 中国联通
|
|
||||||
- [x] 中国移动
|
|
||||||
- [x] 阿里云
|
|
||||||
- [x] 腾讯云
|
|
||||||
- **文件**: `data/chn_ip.txt` (772行)
|
|
||||||
- **更新**: 手动更新
|
|
||||||
- **来源**: chnroutes2
|
|
||||||
|
|
||||||
#### 17. 示例配置 ✅
|
|
||||||
- [x] 主配置文件示例
|
|
||||||
- [x] 智能防污染配置
|
|
||||||
- [x] 域名规则示例
|
|
||||||
- [x] MikroTik配置示例
|
|
||||||
- **文件**: `config-smart-fallback.yaml`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚧 已知问题
|
|
||||||
|
|
||||||
### 次要问题
|
|
||||||
- [ ] 热重载配置 (需重启生效)
|
|
||||||
- [ ] 规则导入导出功能
|
|
||||||
- [ ] 前端国际化 (仅中文)
|
|
||||||
- [ ] 统计图表展示
|
|
||||||
|
|
||||||
### 优化建议
|
|
||||||
- [ ] Prometheus指标导出
|
|
||||||
- [ ] 查询日志分析
|
|
||||||
- [ ] 规则模板市场
|
|
||||||
- [ ] Docker镜像
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 代码统计
|
|
||||||
|
|
||||||
### 新增代码
|
|
||||||
| 模块 | 文件数 | 代码行数 | 测试覆盖 |
|
|
||||||
|------|--------|---------|---------|
|
|
||||||
| 核心引擎 | 3 | 708 | ✅ |
|
|
||||||
| 业务逻辑 | 2 | 1068 | ✅ |
|
|
||||||
| 插件 | 1 | 270 | ✅ |
|
|
||||||
| API | 1 | 639 | ✅ |
|
|
||||||
| 前端 | 20+ | 2000+ | ✅ |
|
|
||||||
| 测试 | 1 | 243 | ✅ |
|
|
||||||
| 文档 | 6 | 3000+ | ✅ |
|
|
||||||
| **总计** | **34+** | **8000+** | **✅** |
|
|
||||||
|
|
||||||
### 修改代码
|
|
||||||
| 文件 | 修改内容 | 行数变化 |
|
|
||||||
|------|---------|---------|
|
|
||||||
| `coremain/mosdns.go` | 添加config字段, 拓扑排序集成 | +50 |
|
|
||||||
| `plugin/enabled_plugins.go` | 注册smart_fallback | +1 |
|
|
||||||
| `build-all-platforms.bat` | 自动构建前端 | +10 |
|
|
||||||
| **总计** | - | **+61** |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 完成度统计
|
|
||||||
|
|
||||||
### 核心功能 (100%)
|
|
||||||
- ✅ 配置拓扑排序
|
|
||||||
- ✅ 配置预验证
|
|
||||||
- ✅ 智能防污染
|
|
||||||
- ✅ 配置生成器
|
|
||||||
|
|
||||||
### 管理功能 (100%)
|
|
||||||
- ✅ 规则管理API
|
|
||||||
- ✅ Web管理界面
|
|
||||||
- ✅ MikroTik集成
|
|
||||||
|
|
||||||
### 测试文档 (100%)
|
|
||||||
- ✅ 自动化测试
|
|
||||||
- ✅ 完整文档
|
|
||||||
- ✅ 配置示例
|
|
||||||
|
|
||||||
### **总体完成度: 100% ✅**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🏆 里程碑
|
|
||||||
|
|
||||||
### v1.0 基础功能 ✅ (2025-10-15)
|
|
||||||
- [x] 配置拓扑排序
|
|
||||||
- [x] 智能防污染插件
|
|
||||||
- [x] 配置预验证
|
|
||||||
- [x] Web界面基础版
|
|
||||||
|
|
||||||
### v1.1 完整功能 ✅ (2025-10-15)
|
|
||||||
- [x] 配置生成器
|
|
||||||
- [x] 规则管理API
|
|
||||||
- [x] Vue前端重构
|
|
||||||
- [x] MikroTik集成
|
|
||||||
|
|
||||||
### v1.2 优化完善 ✅ (2025-10-15)
|
|
||||||
- [x] 错误修复 (23个)
|
|
||||||
- [x] 完整文档
|
|
||||||
- [x] 自动化测试
|
|
||||||
- [x] 性能优化
|
|
||||||
|
|
||||||
### v2.0 扩展功能 🔜 (计划中)
|
|
||||||
- [ ] 热重载配置
|
|
||||||
- [ ] 规则导入导出
|
|
||||||
- [ ] 多用户权限
|
|
||||||
- [ ] Docker支持
|
|
||||||
- [ ] K8s部署方案
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📈 性能指标
|
|
||||||
|
|
||||||
### 响应时间
|
|
||||||
- ✅ 国内域名: 20-30ms
|
|
||||||
- ✅ 国外域名(无污染): 30-50ms
|
|
||||||
- ✅ 国外域名(污染): 80-120ms
|
|
||||||
- ✅ 缓存命中: <5ms
|
|
||||||
|
|
||||||
### 资源占用
|
|
||||||
- ✅ 内存: 30-150MB
|
|
||||||
- ✅ CPU: <5% (1000 qps)
|
|
||||||
- ✅ 二进制: ~15MB
|
|
||||||
|
|
||||||
### 并发能力
|
|
||||||
- ✅ 单核: 3000-5000 qps
|
|
||||||
- ✅ 四核: 10000-15000 qps
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎨 创新点
|
|
||||||
|
|
||||||
1. **配置顺序自由** ⭐⭐⭐⭐⭐
|
|
||||||
- 彻底解决MosDNS最大痛点
|
|
||||||
- 拓扑排序自动调整
|
|
||||||
- 循环依赖智能检测
|
|
||||||
|
|
||||||
2. **智能防污染** ⭐⭐⭐⭐⭐
|
|
||||||
- CN IP精准识别
|
|
||||||
- 自动DNS切换
|
|
||||||
- 性能与准确性兼顾
|
|
||||||
|
|
||||||
3. **零配置门槛** ⭐⭐⭐⭐⭐
|
|
||||||
- Web界面可视化
|
|
||||||
- 自动生成YAML
|
|
||||||
- 降低使用难度
|
|
||||||
|
|
||||||
4. **配置预验证** ⭐⭐⭐⭐
|
|
||||||
- 启动前全面检查
|
|
||||||
- 防止运行时崩溃
|
|
||||||
- 详细错误提示
|
|
||||||
|
|
||||||
5. **一键集成** ⭐⭐⭐⭐
|
|
||||||
- MikroTik无缝对接
|
|
||||||
- 自动推送解析
|
|
||||||
- 简化运维操作
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✅ 质量保证
|
|
||||||
|
|
||||||
### 代码质量
|
|
||||||
- ✅ 编译通过 (0错误, 0警告)
|
|
||||||
- ✅ Linter检查通过
|
|
||||||
- ✅ 类型安全 (Go + TypeScript)
|
|
||||||
- ✅ 错误处理完善
|
|
||||||
|
|
||||||
### 测试覆盖
|
|
||||||
- ✅ 单元测试 (核心算法)
|
|
||||||
- ✅ 集成测试 (API)
|
|
||||||
- ✅ E2E测试 (自动化脚本)
|
|
||||||
- ✅ 手动测试 (Web界面)
|
|
||||||
|
|
||||||
### 文档完整性
|
|
||||||
- ✅ 架构设计文档
|
|
||||||
- ✅ API文档
|
|
||||||
- ✅ 用户手册
|
|
||||||
- ✅ 开发指南
|
|
||||||
- ✅ 故障排查
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**📅 最后更新: 2025-10-15**
|
|
||||||
**✅ 功能完成度: 100%**
|
|
||||||
**🎉 项目状态: 生产就绪**
|
|
||||||
|
|
||||||
344
快速参考.md
344
快速参考.md
@ -1,344 +0,0 @@
|
|||||||
# YLTX-DNS 快速参考卡
|
|
||||||
|
|
||||||
> 二次开发核心功能快速查阅
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 核心亮点
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────────────────┐
|
|
||||||
│ 🛡️ 智能防污染 │ 🔧 自动排序 │ 🖥️ Web界面 │
|
|
||||||
│ │
|
|
||||||
│ 先查国内DNS │ 任意配置顺序 │ 零YAML编写 │
|
|
||||||
│ 检测污染IP │ 自动调整加载 │ 表单化操作 │
|
|
||||||
│ 自动切换国外 │ 循环依赖检测 │ 可视化管理 │
|
|
||||||
└─────────────────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⚡ 快速开始
|
|
||||||
|
|
||||||
### 编译 (3步)
|
|
||||||
```bash
|
|
||||||
cd web-ui && npm install && npm run build && cd ..
|
|
||||||
go build -ldflags="-s -w" -o mosdns .
|
|
||||||
./mosdns -c config.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
### 访问
|
|
||||||
```
|
|
||||||
Web: http://localhost:5555
|
|
||||||
DNS: 53, 5353
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📁 核心文件
|
|
||||||
|
|
||||||
| 文件 | 功能 | 行数 |
|
|
||||||
|------|------|------|
|
|
||||||
| `pkg/utils/toposort.go` | 拓扑排序 | 145 |
|
|
||||||
| `coremain/config_validator.go` | 配置验证 | 293 |
|
|
||||||
| `coremain/config_builder.go` | 配置生成 | 429 |
|
|
||||||
| `plugin/executable/smart_fallback/` | 智能防污染 | 270 |
|
|
||||||
| `coremain/rule_handlers.go` | API | 639 |
|
|
||||||
| `web-ui/` | Vue界面 | 2000+ |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔌 主要API
|
|
||||||
|
|
||||||
```
|
|
||||||
GET /api/server-info # 系统状态
|
|
||||||
GET /api/stats # 查询统计
|
|
||||||
GET /api/rules # 规则列表
|
|
||||||
GET /api/rules/{name} # 规则详情
|
|
||||||
POST /api/rules # 添加规则
|
|
||||||
PUT /api/rules/{name} # 更新规则
|
|
||||||
DELETE /api/rules/{name} # 删除规则
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎨 添加规则示例
|
|
||||||
|
|
||||||
### Web界面 (推荐)
|
|
||||||
```
|
|
||||||
1. 访问 http://localhost:5555
|
|
||||||
2. 点击「域名路由规则」→「添加规则」
|
|
||||||
3. 填写表单:
|
|
||||||
- 规则名: openai
|
|
||||||
- 域名文件: /data/mikrotik/openai.txt
|
|
||||||
- DNS策略: 智能防污染
|
|
||||||
- MikroTik: 启用
|
|
||||||
4. 保存 → 重启服务
|
|
||||||
```
|
|
||||||
|
|
||||||
### API调用
|
|
||||||
```bash
|
|
||||||
curl -X POST http://localhost:5541/api/rules \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{
|
|
||||||
"name": "openai",
|
|
||||||
"domain_file": "/data/mikrotik/openai.txt",
|
|
||||||
"dns_strategy": "smart-fallback",
|
|
||||||
"enable_mikrotik": true,
|
|
||||||
"mikrotik_config": {
|
|
||||||
"host": "192.168.1.1",
|
|
||||||
"port": 8728,
|
|
||||||
"username": "admin",
|
|
||||||
"password": "123456",
|
|
||||||
"address_list": "openai"
|
|
||||||
}
|
|
||||||
}'
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🛡️ 智能防污染配置
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
- tag: smart_fallback_handler
|
|
||||||
type: smart_fallback
|
|
||||||
args:
|
|
||||||
primary: $china-dns # 国内DNS
|
|
||||||
secondary: $overseas-dns # 国际DNS
|
|
||||||
china_ip:
|
|
||||||
- "/data/chn_ip.txt" # CN地址表
|
|
||||||
timeout: 2000 # 2秒超时
|
|
||||||
always_standby: false # 顺序查询
|
|
||||||
verbose: true # 详细日志
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 性能数据
|
|
||||||
|
|
||||||
```
|
|
||||||
国内域名: 20-30ms
|
|
||||||
国外域名: 30-50ms (无污染)
|
|
||||||
80-120ms (有污染)
|
|
||||||
缓存命中: <5ms
|
|
||||||
并发能力: 3000-5000 qps (单核)
|
|
||||||
内存占用: 30-150MB
|
|
||||||
CPU占用: <5% (1000 qps)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 故障排查
|
|
||||||
|
|
||||||
### 启动失败
|
|
||||||
```bash
|
|
||||||
# 配置验证
|
|
||||||
./mosdns -c config.yaml -dry-run
|
|
||||||
|
|
||||||
# 查看日志
|
|
||||||
journalctl -u mosdns -n 50
|
|
||||||
```
|
|
||||||
|
|
||||||
### Web无法访问
|
|
||||||
```bash
|
|
||||||
# 检查端口
|
|
||||||
netstat -tlnp | grep 5555
|
|
||||||
|
|
||||||
# 检查配置
|
|
||||||
grep "web:" config.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
### 防污染不生效
|
|
||||||
```bash
|
|
||||||
# 检查CN表
|
|
||||||
ls -lh data/chn_ip.txt
|
|
||||||
|
|
||||||
# 启用详细日志
|
|
||||||
# config.yaml → verbose: true
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 配置示例
|
|
||||||
|
|
||||||
### 国内DNS
|
|
||||||
```yaml
|
|
||||||
- tag: rule_baidu
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
exec:
|
|
||||||
- matches: qname $domains_baidu
|
|
||||||
exec: $china-dns
|
|
||||||
```
|
|
||||||
|
|
||||||
### 国外DNS
|
|
||||||
```yaml
|
|
||||||
- tag: rule_netflix
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
exec:
|
|
||||||
- matches: qname $domains_netflix
|
|
||||||
exec: $overseas-dns
|
|
||||||
```
|
|
||||||
|
|
||||||
### 智能防污染
|
|
||||||
```yaml
|
|
||||||
- tag: rule_openai
|
|
||||||
type: sequence
|
|
||||||
args:
|
|
||||||
exec:
|
|
||||||
- matches: qname $domains_openai
|
|
||||||
exec: $smart-fallback
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📦 目录结构
|
|
||||||
|
|
||||||
```
|
|
||||||
mosdns/
|
|
||||||
├── config.yaml # 主配置
|
|
||||||
├── config.d/
|
|
||||||
│ └── rules/ # 规则配置
|
|
||||||
│ ├── openai.yaml
|
|
||||||
│ └── netflix.yaml
|
|
||||||
├── data/
|
|
||||||
│ ├── chn_ip.txt # CN地址表
|
|
||||||
│ └── mikrotik/ # 域名文件
|
|
||||||
│ ├── openai.txt
|
|
||||||
│ └── netflix.txt
|
|
||||||
├── web-ui/
|
|
||||||
│ ├── src/ # Vue源码
|
|
||||||
│ └── dist/ # 构建输出
|
|
||||||
├── pkg/utils/ # 工具包
|
|
||||||
├── coremain/ # 核心代码
|
|
||||||
└── plugin/ # 插件
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 升级计划
|
|
||||||
|
|
||||||
### v2.0 (计划中)
|
|
||||||
- [ ] 热重载配置
|
|
||||||
- [ ] 规则导入导出
|
|
||||||
- [ ] 多用户权限
|
|
||||||
- [ ] Docker镜像
|
|
||||||
- [ ] K8s Helm Chart
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📚 文档索引
|
|
||||||
|
|
||||||
| 文档 | 说明 |
|
|
||||||
|------|------|
|
|
||||||
| [二次开发总结](./YLTX-DNS智能防污染系统-二次开发总结.md) | 完整功能介绍 |
|
|
||||||
| [README](./README-二开版本.md) | 项目说明 |
|
|
||||||
| [功能清单](./功能实现清单.md) | 详细清单 |
|
|
||||||
| [错误修复](./错误修复总结.md) | Bug修复 |
|
|
||||||
| [架构设计](./yltx-dns-智能防污染系统-架构设计文档.md) | 技术架构 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎁 关键创新
|
|
||||||
|
|
||||||
### 1️⃣ 配置顺序自由
|
|
||||||
```yaml
|
|
||||||
# ❌ 传统: 必须严格顺序
|
|
||||||
plugins:
|
|
||||||
- tag: upstream
|
|
||||||
- tag: main
|
|
||||||
exec: $upstream
|
|
||||||
|
|
||||||
# ✅ YLTX-DNS: 任意顺序
|
|
||||||
plugins:
|
|
||||||
- tag: main
|
|
||||||
exec: $upstream # OK!
|
|
||||||
- tag: upstream
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2️⃣ 智能污染检测
|
|
||||||
```
|
|
||||||
国内DNS → 127.0.0.1 → 检测CN表 → ❌
|
|
||||||
→ 自动切换国际DNS → 104.18.xxx.xxx → ✅
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3️⃣ 零配置门槛
|
|
||||||
```
|
|
||||||
表单填写 → 自动生成YAML → 一键启用
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 💡 最佳实践
|
|
||||||
|
|
||||||
### 1. 域名文件组织
|
|
||||||
```
|
|
||||||
data/mikrotik/
|
|
||||||
├── ai/
|
|
||||||
│ ├── openai.txt
|
|
||||||
│ ├── claude.txt
|
|
||||||
│ └── gemini.txt
|
|
||||||
├── video/
|
|
||||||
│ ├── netflix.txt
|
|
||||||
│ └── youtube.txt
|
|
||||||
└── social/
|
|
||||||
└── twitter.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. DNS策略选择
|
|
||||||
```
|
|
||||||
国内网站 → 国内DNS
|
|
||||||
国外网站 → 国外DNS
|
|
||||||
AI服务 → 智能防污染 (推荐)
|
|
||||||
流媒体服务 → 国外DNS
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. MikroTik配置
|
|
||||||
```
|
|
||||||
常用服务 → mask: 32 (单IP)
|
|
||||||
大型服务 → mask: 24 (子网)
|
|
||||||
超大服务 → mask: 20 (更大子网)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔥 常用命令
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 编译
|
|
||||||
go build -o mosdns .
|
|
||||||
|
|
||||||
# 启动
|
|
||||||
./mosdns -c config.yaml
|
|
||||||
|
|
||||||
# 后台运行
|
|
||||||
nohup ./mosdns -c config.yaml &
|
|
||||||
|
|
||||||
# 重启服务
|
|
||||||
systemctl restart mosdns
|
|
||||||
|
|
||||||
# 查看日志
|
|
||||||
journalctl -u mosdns -f
|
|
||||||
|
|
||||||
# 配置验证
|
|
||||||
./mosdns -c config.yaml -dry-run
|
|
||||||
|
|
||||||
# 性能测试
|
|
||||||
ab -n 10000 -c 100 http://localhost:5541/api/server-info
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📞 获取帮助
|
|
||||||
|
|
||||||
- 📖 完整文档: `YLTX-DNS智能防污染系统-二次开发总结.md`
|
|
||||||
- 🐛 问题反馈: GitHub Issues
|
|
||||||
- 💬 技术讨论: GitHub Discussions
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**⚡ 快速、稳定、智能的DNS解决方案**
|
|
||||||
|
|
||||||
*最后更新: 2025-10-15*
|
|
||||||
|
|
||||||
334
📚文档导航.md
334
📚文档导航.md
@ -1,334 +0,0 @@
|
|||||||
# 📚 YLTX-DNS 文档导航中心
|
|
||||||
|
|
||||||
> 快速找到你需要的文档
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 新手入门
|
|
||||||
|
|
||||||
### 1️⃣ [快速参考](./快速参考.md) ⭐ 推荐首选
|
|
||||||
**适合**: 想快速上手的用户
|
|
||||||
**内容**:
|
|
||||||
- ⚡ 3步启动指南
|
|
||||||
- 🔌 常用API一览
|
|
||||||
- 🛡️ 配置示例
|
|
||||||
- 🔧 故障排查速查表
|
|
||||||
- 💡 最佳实践
|
|
||||||
|
|
||||||
**阅读时间**: 5分钟
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 2️⃣ [README-二开版本](./README-二开版本.md)
|
|
||||||
**适合**: 想了解项目概况的用户
|
|
||||||
**内容**:
|
|
||||||
- ✨ 核心特性介绍
|
|
||||||
- 📊 与原版对比
|
|
||||||
- 🚀 快速开始
|
|
||||||
- 🏗️ 技术架构概览
|
|
||||||
- 🛠️ 运维指南
|
|
||||||
|
|
||||||
**阅读时间**: 10分钟
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📖 深度学习
|
|
||||||
|
|
||||||
### 3️⃣ [二次开发总结](./YLTX-DNS智能防污染系统-二次开发总结.md) ⭐ 完整版
|
|
||||||
**适合**: 想全面了解所有功能的用户
|
|
||||||
**内容**:
|
|
||||||
- 📋 项目概述与背景
|
|
||||||
- 🎯 实现的核心功能(4阶段)
|
|
||||||
- 核心引擎层
|
|
||||||
- 业务逻辑层
|
|
||||||
- 前端界面层
|
|
||||||
- 测试与文档
|
|
||||||
- 🔧 技术架构深度解析
|
|
||||||
- 📊 性能指标详解
|
|
||||||
- 🎨 核心创新点
|
|
||||||
- 🚀 使用指南
|
|
||||||
- 🔍 故障排查
|
|
||||||
- 📈 扩展与优化
|
|
||||||
- 💡 经验总结
|
|
||||||
|
|
||||||
**阅读时间**: 30分钟
|
|
||||||
**总字数**: 15000+
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 4️⃣ [架构设计文档](./yltx-dns-智能防污染系统-架构设计文档.md)
|
|
||||||
**适合**: 架构师、技术负责人
|
|
||||||
**内容**:
|
|
||||||
- 🎯 需求分析
|
|
||||||
- 🏗️ 系统架构设计
|
|
||||||
- 💻 技术方案详解
|
|
||||||
- 📐 数据流设计
|
|
||||||
- ⚙️ 开发计划
|
|
||||||
- 🎲 风险评估
|
|
||||||
- 🧪 质量保证
|
|
||||||
- 🚀 部署运维
|
|
||||||
|
|
||||||
**阅读时间**: 25分钟
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔍 专题参考
|
|
||||||
|
|
||||||
### 5️⃣ [功能实现清单](./功能实现清单.md)
|
|
||||||
**适合**: 需要查看功能完成情况的用户
|
|
||||||
**内容**:
|
|
||||||
- ✅ 已实现功能清单(17项)
|
|
||||||
- 核心引擎层(3项)
|
|
||||||
- 业务逻辑层(3项)
|
|
||||||
- 前端界面层(10项)
|
|
||||||
- 测试与文档(2项)
|
|
||||||
- 🚧 已知问题
|
|
||||||
- 📊 代码统计
|
|
||||||
- 🎯 完成度统计
|
|
||||||
- 🏆 里程碑
|
|
||||||
- 📈 性能指标
|
|
||||||
- 🎨 创新点
|
|
||||||
- ✅ 质量保证
|
|
||||||
|
|
||||||
**阅读时间**: 15分钟
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 6️⃣ [错误修复总结](./错误修复总结.md)
|
|
||||||
**适合**: 遇到编译问题的开发者
|
|
||||||
**内容**:
|
|
||||||
- 🎯 修复概览(23个错误)
|
|
||||||
- 🔧 主要问题及解决方案
|
|
||||||
- 循环导入问题
|
|
||||||
- 类型不匹配
|
|
||||||
- Logger类型错误
|
|
||||||
- Sequence包API错误
|
|
||||||
- Netlist包API错误
|
|
||||||
- 重复函数定义
|
|
||||||
- 结构体字段缺失
|
|
||||||
- 📊 修复统计
|
|
||||||
- 🎉 验证结果
|
|
||||||
- 📁 修改文件清单
|
|
||||||
- 🚀 下一步建议
|
|
||||||
|
|
||||||
**阅读时间**: 10分钟
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📋 配置参考
|
|
||||||
|
|
||||||
### 7️⃣ [配置示例](./config-smart-fallback.yaml)
|
|
||||||
**适合**: 需要配置参考的用户
|
|
||||||
**内容**:
|
|
||||||
- 完整的MosDNS配置示例
|
|
||||||
- 智能防污染配置
|
|
||||||
- 国内/国外DNS配置
|
|
||||||
- 缓存配置
|
|
||||||
- 服务器配置
|
|
||||||
- 详细的注释说明
|
|
||||||
|
|
||||||
**文件类型**: YAML
|
|
||||||
**阅读时间**: 5分钟
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎓 学习路径建议
|
|
||||||
|
|
||||||
### 路径1: 快速上手(总时间:20分钟)
|
|
||||||
```
|
|
||||||
快速参考 → README → 配置示例 → 开始使用
|
|
||||||
(5分钟) (10分钟) (5分钟)
|
|
||||||
```
|
|
||||||
**适合**: 时间紧迫,想快速使用的用户
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 路径2: 全面了解(总时间:1小时)
|
|
||||||
```
|
|
||||||
README → 二次开发总结 → 功能清单 → 架构设计
|
|
||||||
(10分钟) (30分钟) (15分钟) (25分钟)
|
|
||||||
```
|
|
||||||
**适合**: 想深入了解项目的用户
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 路径3: 开发者(总时间:1.5小时)
|
|
||||||
```
|
|
||||||
README → 架构设计 → 二次开发总结 → 错误修复 → 代码阅读
|
|
||||||
(10分钟) (25分钟) (30分钟) (10分钟) (15分钟)
|
|
||||||
```
|
|
||||||
**适合**: 想参与开发或二次开发的开发者
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 路径4: 问题排查(总时间:15分钟)
|
|
||||||
```
|
|
||||||
快速参考故障排查 → 错误修复总结 → GitHub Issues
|
|
||||||
(5分钟) (10分钟)
|
|
||||||
```
|
|
||||||
**适合**: 遇到问题需要解决的用户
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 文档统计
|
|
||||||
|
|
||||||
| 文档 | 类型 | 字数 | 完成度 |
|
|
||||||
|------|------|------|--------|
|
|
||||||
| 快速参考 | 速查手册 | 2000+ | ✅ 100% |
|
|
||||||
| README | 项目说明 | 4000+ | ✅ 100% |
|
|
||||||
| 二次开发总结 | 完整文档 | 15000+ | ✅ 100% |
|
|
||||||
| 架构设计 | 技术文档 | 12000+ | ✅ 100% |
|
|
||||||
| 功能清单 | 清单文档 | 5000+ | ✅ 100% |
|
|
||||||
| 错误修复 | 问题记录 | 3000+ | ✅ 100% |
|
|
||||||
| 配置示例 | 配置文件 | YAML | ✅ 100% |
|
|
||||||
| **总计** | - | **41000+** | **✅ 100%** |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔗 快速跳转
|
|
||||||
|
|
||||||
### 按需求查找
|
|
||||||
|
|
||||||
#### 我想...
|
|
||||||
- **快速开始使用** → [快速参考](./快速参考.md)
|
|
||||||
- **了解项目是什么** → [README](./README-二开版本.md)
|
|
||||||
- **看所有功能** → [功能清单](./功能实现清单.md)
|
|
||||||
- **理解技术架构** → [架构设计](./yltx-dns-智能防污染系统-架构设计文档.md)
|
|
||||||
- **学习开发经验** → [二次开发总结](./YLTX-DNS智能防污染系统-二次开发总结.md)
|
|
||||||
- **解决编译错误** → [错误修复](./错误修复总结.md)
|
|
||||||
- **参考配置文件** → [config-smart-fallback.yaml](./config-smart-fallback.yaml)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 按角色查找
|
|
||||||
|
|
||||||
#### 👤 普通用户
|
|
||||||
1. [快速参考](./快速参考.md) - 快速上手
|
|
||||||
2. [README](./README-二开版本.md) - 了解项目
|
|
||||||
3. [配置示例](./config-smart-fallback.yaml) - 配置参考
|
|
||||||
|
|
||||||
#### 🔧 运维人员
|
|
||||||
1. [快速参考](./快速参考.md) - 故障排查
|
|
||||||
2. [二次开发总结](./YLTX-DNS智能防污染系统-二次开发总结.md) - 运维指南
|
|
||||||
3. [README](./README-二开版本.md) - systemd配置
|
|
||||||
|
|
||||||
#### 💻 开发者
|
|
||||||
1. [架构设计](./yltx-dns-智能防污染系统-架构设计文档.md) - 技术架构
|
|
||||||
2. [二次开发总结](./YLTX-DNS智能防污染系统-二次开发总结.md) - 实现细节
|
|
||||||
3. [错误修复](./错误修复总结.md) - 常见问题
|
|
||||||
4. [功能清单](./功能实现清单.md) - 代码统计
|
|
||||||
|
|
||||||
#### 🏢 决策者
|
|
||||||
1. [README](./README-二开版本.md) - 项目概览
|
|
||||||
2. [功能清单](./功能实现清单.md) - 功能完成度
|
|
||||||
3. [二次开发总结](./YLTX-DNS智能防污染系统-二次开发总结.md) - 技术成果
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 核心概念速查
|
|
||||||
|
|
||||||
### 智能防污染
|
|
||||||
- 📖 详细说明: [二次开发总结 - 智能防污染插件](./YLTX-DNS智能防污染系统-二次开发总结.md#12-智能防污染插件-smart-fallback)
|
|
||||||
- ⚡ 快速配置: [快速参考 - 智能防污染配置](./快速参考.md#🛡️-智能防污染配置)
|
|
||||||
- 🔧 技术细节: [架构设计 - 智能防污染方案](./yltx-dns-智能防污染系统-架构设计文档.md)
|
|
||||||
|
|
||||||
### 配置拓扑排序
|
|
||||||
- 📖 详细说明: [二次开发总结 - 配置拓扑排序系统](./YLTX-DNS智能防污染系统-二次开发总结.md#11-配置拓扑排序系统)
|
|
||||||
- 💡 创新点: [快速参考 - 配置顺序自由](./快速参考.md#1️⃣-配置顺序自由)
|
|
||||||
- 🔧 技术细节: [功能清单 - 拓扑排序](./功能实现清单.md#1-配置拓扑排序系统-✅)
|
|
||||||
|
|
||||||
### Web管理界面
|
|
||||||
- 📖 详细说明: [二次开发总结 - Vue 3 管理界面](./YLTX-DNS智能防污染系统-二次开发总结.md#31-vue-3-管理界面)
|
|
||||||
- ⚡ 快速使用: [快速参考 - 添加规则示例](./快速参考.md#🎨-添加规则示例)
|
|
||||||
- 🎯 功能清单: [功能清单 - 前端界面层](./功能实现清单.md#🖥️-前端界面层)
|
|
||||||
|
|
||||||
### MikroTik集成
|
|
||||||
- 📖 详细说明: [README - MikroTik集成](./README-二开版本.md#🚀-mikrotik集成)
|
|
||||||
- ⚡ 配置示例: [配置示例 - mikrotik_addresslist](./config-smart-fallback.yaml)
|
|
||||||
- 💡 最佳实践: [快速参考 - MikroTik配置](./快速参考.md#3-mikrotik配置)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🆘 遇到问题?
|
|
||||||
|
|
||||||
### 1. 查阅文档
|
|
||||||
- [快速参考 - 故障排查](./快速参考.md#🔧-故障排查)
|
|
||||||
- [二次开发总结 - 故障排查](./YLTX-DNS智能防污染系统-二次开发总结.md#🔍-故障排查)
|
|
||||||
- [错误修复总结](./错误修复总结.md)
|
|
||||||
|
|
||||||
### 2. 搜索Issues
|
|
||||||
GitHub Issues中可能已有解决方案
|
|
||||||
|
|
||||||
### 3. 提交新Issue
|
|
||||||
提供详细的错误信息和日志
|
|
||||||
|
|
||||||
### 4. 社区讨论
|
|
||||||
GitHub Discussions 技术交流
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 文档更新日志
|
|
||||||
|
|
||||||
### 2025-10-15
|
|
||||||
- ✅ 创建全部7份文档
|
|
||||||
- ✅ 完成文档导航中心
|
|
||||||
- ✅ 总字数突破41000+
|
|
||||||
- ✅ 文档完成度100%
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎉 文档质量
|
|
||||||
|
|
||||||
| 指标 | 数值 |
|
|
||||||
|------|------|
|
|
||||||
| 文档总数 | 7份 |
|
|
||||||
| 总字数 | 41000+ |
|
|
||||||
| 代码示例 | 50+ |
|
|
||||||
| 配置示例 | 20+ |
|
|
||||||
| 图表 | 15+ |
|
|
||||||
| 完成度 | 100% |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 💡 使用建议
|
|
||||||
|
|
||||||
### 📱 移动端
|
|
||||||
建议使用支持Markdown的阅读器,如:
|
|
||||||
- GitHub Mobile App
|
|
||||||
- Typora
|
|
||||||
- Obsidian
|
|
||||||
|
|
||||||
### 💻 桌面端
|
|
||||||
推荐使用:
|
|
||||||
- VS Code (Markdown Preview Enhanced插件)
|
|
||||||
- Typora
|
|
||||||
- GitHub Web
|
|
||||||
|
|
||||||
### 📄 PDF导出
|
|
||||||
如需PDF版本,可使用:
|
|
||||||
- Typora导出
|
|
||||||
- Pandoc转换
|
|
||||||
- Chrome打印为PDF
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🌟 文档特色
|
|
||||||
|
|
||||||
- ✅ **全面**: 覆盖从入门到精通所有内容
|
|
||||||
- ✅ **结构化**: 清晰的导航和分类
|
|
||||||
- ✅ **实用**: 大量代码示例和配置参考
|
|
||||||
- ✅ **易读**: Markdown格式,支持全平台
|
|
||||||
- ✅ **完整**: 41000+字详尽说明
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**📚 祝你阅读愉快,使用顺利!**
|
|
||||||
|
|
||||||
*如有文档改进建议,欢迎提Issue或PR*
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*最后更新: 2025-10-15*
|
|
||||||
*文档版本: v1.0*
|
|
||||||
*维护状态: ✅ 活跃*
|
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user