增加了API断电
This commit is contained in:
81
ReadMe.md
81
ReadMe.md
@@ -1,81 +0,0 @@
|
||||
# DNS服务器项目介绍
|
||||
## 项目概述
|
||||
这是一个基于Go语言开发的高性能DNS服务器,具备域名屏蔽、Hosts管理、统计分析和远程规则管理等功能。服务器支持通过Web界面进行管理配置,同时能够自动更新和缓存远程规则列表。
|
||||
|
||||
## 技术架构
|
||||
### 核心组件
|
||||
1. DNS服务模块 ( `server.go` )
|
||||
- 基于 github.com/miekg/dns 库实现高性能DNS查询处理
|
||||
- 支持配置上游DNS服务器进行递归查询
|
||||
- 实现域名屏蔽、统计数据收集等核心功能
|
||||
|
||||
2. 屏蔽管理系统 ( `manager.go` )
|
||||
- 管理本地和远程屏蔽规则
|
||||
- 支持规则缓存、自动更新和统计
|
||||
- 实现域名和正则表达式规则的解析和匹配
|
||||
|
||||
3. HTTP控制台 ( `server.go` )
|
||||
- 提供Web管理界面
|
||||
- 实现REST API用于配置管理和数据查询
|
||||
|
||||
4. 配置管理 ( `config.go` )
|
||||
- 定义配置结构和加载功能
|
||||
- 支持JSON格式配置文件
|
||||
|
||||
## 主要功能特性
|
||||
### 1. 域名屏蔽系统
|
||||
- 支持本地规则文件和远程规则URL
|
||||
- 多种屏蔽方式:NXDOMAIN、refused、emptyIP、customIP
|
||||
- 支持域名精确匹配和正则表达式匹配
|
||||
- 远程规则自动缓存和更新机制
|
||||
### 2. Hosts管理
|
||||
- 支持自定义Hosts映射
|
||||
- 提供Web界面管理Hosts条目
|
||||
- 自动保存Hosts配置
|
||||
### 3. 统计分析功能
|
||||
- 记录屏蔽域名统计信息
|
||||
- 记录解析域名统计信息
|
||||
- 提供按小时统计的屏蔽数据
|
||||
- 支持查询最常屏蔽和解析的域名
|
||||
### 4. 远程规则管理
|
||||
- 支持添加多个远程规则URL
|
||||
- 自动定期更新远程规则
|
||||
- 本地缓存机制确保规则可用性
|
||||
- Web界面可视化管理
|
||||
### 5. 管理界面
|
||||
- 提供直观的Web控制台
|
||||
- 支持查看服务器状态和统计信息
|
||||
- 规则管理和配置修改
|
||||
- DNS查询测试工具
|
||||
## 项目结构
|
||||
```
|
||||
/root/dns/
|
||||
├── config/ # 配置管理
|
||||
├── data/ # 数据目录(包含缓存和统计)
|
||||
│ └── remote_rules/ # 远程规则缓存
|
||||
├── dns/ # DNS服务器核心
|
||||
├── http/ # HTTP控制台
|
||||
├── logger/ # 日志系统
|
||||
├── shield/ # 屏蔽规则管理
|
||||
├── static/ # 静态Web文件
|
||||
├── main.go # 程序入口
|
||||
└── config.json # 配置文件
|
||||
```
|
||||
## 配置项说明
|
||||
主要配置文件 `config.json` 包含以下部分:
|
||||
|
||||
- DNS配置 :端口、上游DNS服务器、超时设置等
|
||||
- HTTP配置 :控制台端口、主机绑定等
|
||||
- 屏蔽配置 :规则文件路径、远程规则URL、更新间隔等
|
||||
- 日志配置 :日志文件路径、级别设置等
|
||||
## 使用场景
|
||||
1. 网络内容过滤(广告、恶意网站屏蔽)
|
||||
2. 本地DNS缓存加速
|
||||
3. 企业/家庭网络DNS管理
|
||||
4. 开发测试环境DNS重定向
|
||||
## 技术栈
|
||||
- 语言 :Go
|
||||
- DNS库 :github.com/miekg/dns
|
||||
- 日志库 :github.com/sirupsen/logrus
|
||||
- Web前端 :HTML/CSS/JavaScript
|
||||
该DNS服务器具有高性能、功能全面、易于配置等特点,适用于需要精确控制DNS查询结果的各种网络环境。
|
||||
@@ -66,6 +66,24 @@ func (s *Server) Start() error {
|
||||
if s.config.EnableAPI {
|
||||
mux.HandleFunc("/api/stats", s.handleStats)
|
||||
mux.HandleFunc("/api/shield", s.handleShield)
|
||||
mux.HandleFunc("/api/shield/localrules", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if r.Method == http.MethodGet {
|
||||
localRules := s.shieldManager.GetLocalRules()
|
||||
json.NewEncoder(w).Encode(localRules)
|
||||
return
|
||||
}
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
})
|
||||
mux.HandleFunc("/api/shield/remoterules", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if r.Method == http.MethodGet {
|
||||
remoteRules := s.shieldManager.GetRemoteRules()
|
||||
json.NewEncoder(w).Encode(remoteRules)
|
||||
return
|
||||
}
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
})
|
||||
mux.HandleFunc("/api/shield/hosts", s.handleShieldHosts)
|
||||
mux.HandleFunc("/api/shield/blacklists", s.handleShieldBlacklists)
|
||||
mux.HandleFunc("/api/query", s.handleQuery)
|
||||
@@ -596,6 +614,7 @@ func (s *Server) handleTopDomains(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *Server) handleShield(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
// 默认处理逻辑
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
// 检查是否需要返回完整规则列表
|
||||
@@ -619,6 +638,8 @@ func (s *Server) handleShield(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
json.NewEncoder(w).Encode(shieldInfo)
|
||||
return
|
||||
}
|
||||
switch r.Method {
|
||||
case http.MethodPost:
|
||||
// 添加屏蔽规则
|
||||
var req struct {
|
||||
|
||||
@@ -1275,6 +1275,131 @@ func (m *ShieldManager) GetHostsCount() int {
|
||||
return len(m.hostsMap)
|
||||
}
|
||||
|
||||
// GetLocalRules 获取仅本地规则
|
||||
func (m *ShieldManager) GetLocalRules() map[string]interface{} {
|
||||
m.rulesMutex.RLock()
|
||||
defer m.rulesMutex.RUnlock()
|
||||
|
||||
// 转换map和slice为字符串列表,只包含本地规则
|
||||
domainRulesList := make([]string, 0)
|
||||
for domain, isLocal := range m.domainRulesIsLocal {
|
||||
if isLocal && m.domainRules[domain] {
|
||||
domainRulesList = append(domainRulesList, "||"+domain+"^")
|
||||
}
|
||||
}
|
||||
|
||||
domainExceptionsList := make([]string, 0)
|
||||
for domain, isLocal := range m.domainExceptionsIsLocal {
|
||||
if isLocal && m.domainExceptions[domain] {
|
||||
domainExceptionsList = append(domainExceptionsList, "@@||"+domain+"^")
|
||||
}
|
||||
}
|
||||
|
||||
// 获取本地正则规则原始字符串
|
||||
regexRulesList := make([]string, 0)
|
||||
for _, re := range m.regexRules {
|
||||
if re.isLocal {
|
||||
regexRulesList = append(regexRulesList, re.original)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取本地正则排除规则原始字符串
|
||||
regexExceptionsList := make([]string, 0)
|
||||
for _, re := range m.regexExceptions {
|
||||
if re.isLocal {
|
||||
regexExceptionsList = append(regexExceptionsList, re.original)
|
||||
}
|
||||
}
|
||||
|
||||
// 计算本地规则数量
|
||||
localDomainRulesCount := 0
|
||||
for _, isLocal := range m.domainRulesIsLocal {
|
||||
if isLocal {
|
||||
localDomainRulesCount++
|
||||
}
|
||||
}
|
||||
localRegexRulesCount := 0
|
||||
for _, re := range m.regexRules {
|
||||
if re.isLocal {
|
||||
localRegexRulesCount++
|
||||
}
|
||||
}
|
||||
localRulesCount := localDomainRulesCount + localRegexRulesCount
|
||||
|
||||
return map[string]interface{}{
|
||||
"domainRules": domainRulesList,
|
||||
"domainExceptions": domainExceptionsList,
|
||||
"regexRules": regexRulesList,
|
||||
"regexExceptions": regexExceptionsList,
|
||||
"localRulesCount": localRulesCount,
|
||||
"localDomainRulesCount": localDomainRulesCount,
|
||||
"localRegexRulesCount": localRegexRulesCount,
|
||||
}
|
||||
}
|
||||
|
||||
// GetRemoteRules 获取仅远程规则
|
||||
func (m *ShieldManager) GetRemoteRules() map[string]interface{} {
|
||||
m.rulesMutex.RLock()
|
||||
defer m.rulesMutex.RUnlock()
|
||||
|
||||
// 转换map和slice为字符串列表,只包含远程规则
|
||||
domainRulesList := make([]string, 0)
|
||||
for domain, isLocal := range m.domainRulesIsLocal {
|
||||
if !isLocal && m.domainRules[domain] {
|
||||
domainRulesList = append(domainRulesList, "||"+domain+"^")
|
||||
}
|
||||
}
|
||||
|
||||
domainExceptionsList := make([]string, 0)
|
||||
for domain, isLocal := range m.domainExceptionsIsLocal {
|
||||
if !isLocal && m.domainExceptions[domain] {
|
||||
domainExceptionsList = append(domainExceptionsList, "@@||"+domain+"^")
|
||||
}
|
||||
}
|
||||
|
||||
// 获取远程正则规则原始字符串
|
||||
regexRulesList := make([]string, 0)
|
||||
for _, re := range m.regexRules {
|
||||
if !re.isLocal {
|
||||
regexRulesList = append(regexRulesList, re.original)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取远程正则排除规则原始字符串
|
||||
regexExceptionsList := make([]string, 0)
|
||||
for _, re := range m.regexExceptions {
|
||||
if !re.isLocal {
|
||||
regexExceptionsList = append(regexExceptionsList, re.original)
|
||||
}
|
||||
}
|
||||
|
||||
// 计算远程规则数量
|
||||
remoteDomainRulesCount := 0
|
||||
for _, isLocal := range m.domainRulesIsLocal {
|
||||
if !isLocal {
|
||||
remoteDomainRulesCount++
|
||||
}
|
||||
}
|
||||
remoteRegexRulesCount := 0
|
||||
for _, re := range m.regexRules {
|
||||
if !re.isLocal {
|
||||
remoteRegexRulesCount++
|
||||
}
|
||||
}
|
||||
remoteRulesCount := remoteDomainRulesCount + remoteRegexRulesCount
|
||||
|
||||
return map[string]interface{}{
|
||||
"domainRules": domainRulesList,
|
||||
"domainExceptions": domainExceptionsList,
|
||||
"regexRules": regexRulesList,
|
||||
"regexExceptions": regexExceptionsList,
|
||||
"remoteRulesCount": remoteRulesCount,
|
||||
"remoteDomainRulesCount": remoteDomainRulesCount,
|
||||
"remoteRegexRulesCount": remoteRegexRulesCount,
|
||||
"blacklists": m.config.Blacklists,
|
||||
}
|
||||
}
|
||||
|
||||
// GetRules 获取所有规则
|
||||
func (m *ShieldManager) GetRules() map[string]interface{} {
|
||||
m.rulesMutex.RLock()
|
||||
|
||||
@@ -53,7 +53,7 @@ async function loadShieldStats() {
|
||||
async function loadLocalRules() {
|
||||
showLoading('加载本地规则...');
|
||||
try {
|
||||
const response = await fetch('/api/shield?all=true');
|
||||
const response = await fetch('/api/shield/localrules');
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`加载失败: ${response.status}`);
|
||||
@@ -61,6 +61,11 @@ async function loadLocalRules() {
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
// 更新本地规则数量显示
|
||||
if (document.getElementById('local-rules-count')) {
|
||||
document.getElementById('local-rules-count').textContent = data.localRulesCount || 0;
|
||||
}
|
||||
|
||||
// 合并所有本地规则
|
||||
let rules = [];
|
||||
// 添加域名规则
|
||||
@@ -89,6 +94,51 @@ async function loadLocalRules() {
|
||||
}
|
||||
}
|
||||
|
||||
// 加载远程规则
|
||||
async function loadRemoteRules() {
|
||||
showLoading('加载远程规则...');
|
||||
try {
|
||||
const response = await fetch('/api/shield/remoterules');
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`加载失败: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
// 更新远程规则数量显示
|
||||
if (document.getElementById('remote-rules-count')) {
|
||||
document.getElementById('remote-rules-count').textContent = data.remoteRulesCount || 0;
|
||||
}
|
||||
|
||||
// 合并所有远程规则
|
||||
let rules = [];
|
||||
// 添加域名规则
|
||||
if (Array.isArray(data.domainRules)) {
|
||||
rules = rules.concat(data.domainRules);
|
||||
}
|
||||
// 添加域名排除规则
|
||||
if (Array.isArray(data.domainExceptions)) {
|
||||
rules = rules.concat(data.domainExceptions);
|
||||
}
|
||||
// 添加正则规则
|
||||
if (Array.isArray(data.regexRules)) {
|
||||
rules = rules.concat(data.regexRules);
|
||||
}
|
||||
// 添加正则排除规则
|
||||
if (Array.isArray(data.regexExceptions)) {
|
||||
rules = rules.concat(data.regexExceptions);
|
||||
}
|
||||
|
||||
updateRulesTable(rules);
|
||||
hideLoading();
|
||||
} catch (error) {
|
||||
console.error('加载远程规则失败:', error);
|
||||
showErrorMessage('加载远程规则失败');
|
||||
hideLoading();
|
||||
}
|
||||
}
|
||||
|
||||
// 更新规则表格
|
||||
function updateRulesTable(rules) {
|
||||
const tbody = document.getElementById('rules-table-body');
|
||||
@@ -416,6 +466,15 @@ function setupShieldEventListeners() {
|
||||
|
||||
// 远程黑名单管理事件
|
||||
document.getElementById('save-blacklist-btn').addEventListener('click', handleAddBlacklist);
|
||||
|
||||
// 添加切换查看本地规则和远程规则的事件监听
|
||||
if (document.getElementById('view-local-rules-btn')) {
|
||||
document.getElementById('view-local-rules-btn').addEventListener('click', loadLocalRules);
|
||||
}
|
||||
|
||||
if (document.getElementById('view-remote-rules-btn')) {
|
||||
document.getElementById('view-remote-rules-btn').addEventListener('click', loadRemoteRules);
|
||||
}
|
||||
}
|
||||
|
||||
// 显示成功消息
|
||||
|
||||
Reference in New Issue
Block a user