优化web显示

This commit is contained in:
Alex Yang
2025-12-16 20:23:18 +08:00
parent d599fce4c0
commit 62f4b28f42
9 changed files with 603 additions and 37650 deletions

View File

@@ -41,7 +41,7 @@
"name": "CHN-anti-AD", "name": "CHN-anti-AD",
"url": "https://gitea.amazehome.xyz/AMAZEHOME/hosts-and-Filters/raw/branch/main/list/easylist.txt", "url": "https://gitea.amazehome.xyz/AMAZEHOME/hosts-and-Filters/raw/branch/main/list/easylist.txt",
"enabled": true, "enabled": true,
"lastUpdateTime": "2025-11-28T15:26:24.833Z" "lastUpdateTime": "2025-12-16T08:50:10.180Z"
}, },
{ {
"name": "My GitHub Rules", "name": "My GitHub Rules",

Binary file not shown.

View File

@@ -58,6 +58,7 @@ type QueryLog struct {
BlockType string // 屏蔽类型(如果被屏蔽) BlockType string // 屏蔽类型(如果被屏蔽)
FromCache bool // 是否来自缓存 FromCache bool // 是否来自缓存
DNSSEC bool // 是否使用了DNSSEC DNSSEC bool // 是否使用了DNSSEC
EDNS bool // 是否使用了EDNS
} }
// StatsData 用于持久化的统计数据结构 // StatsData 用于持久化的统计数据结构
@@ -352,7 +353,7 @@ func (s *Server) handleDNSRequest(w dns.ResponseWriter, r *dns.Msg) {
}) })
// 添加查询日志 // 添加查询日志
s.addQueryLog(sourceIP, domain, queryType, responseTime, "error", "", "", false, false) s.addQueryLog(sourceIP, domain, queryType, responseTime, "error", "", "", false, false, true)
return return
} }
@@ -369,7 +370,7 @@ func (s *Server) handleDNSRequest(w dns.ResponseWriter, r *dns.Msg) {
}) })
// 添加查询日志 // 添加查询日志
s.addQueryLog(sourceIP, domain, queryType, responseTime, "allowed", "", "", false, false) s.addQueryLog(sourceIP, domain, queryType, responseTime, "allowed", "", "", false, false, true)
return return
} }
@@ -391,7 +392,7 @@ func (s *Server) handleDNSRequest(w dns.ResponseWriter, r *dns.Msg) {
}) })
// 添加查询日志 // 添加查询日志
s.addQueryLog(sourceIP, domain, queryType, responseTime, "blocked", blockRule, blockType, false, false) s.addQueryLog(sourceIP, domain, queryType, responseTime, "blocked", blockRule, blockType, false, false, true)
return return
} }
@@ -420,7 +421,7 @@ func (s *Server) handleDNSRequest(w dns.ResponseWriter, r *dns.Msg) {
cachedResponseCopy := cachedResponse.Copy() // 创建响应副本避免并发修改问题 cachedResponseCopy := cachedResponse.Copy() // 创建响应副本避免并发修改问题
cachedResponseCopy.Id = r.Id // 更新ID以匹配请求 cachedResponseCopy.Id = r.Id // 更新ID以匹配请求
cachedResponseCopy.Compress = true cachedResponseCopy.Compress = true
// 如果客户端请求包含EDNS记录确保响应也包含EDNS // 如果客户端请求包含EDNS记录确保响应也包含EDNS
if opt := r.IsEdns0(); opt != nil { if opt := r.IsEdns0(); opt != nil {
// 检查响应是否已经包含EDNS记录 // 检查响应是否已经包含EDNS记录
@@ -442,7 +443,7 @@ func (s *Server) handleDNSRequest(w dns.ResponseWriter, r *dns.Msg) {
} }
} }
} }
w.WriteMsg(cachedResponseCopy) w.WriteMsg(cachedResponseCopy)
// 计算响应时间 // 计算响应时间
@@ -464,7 +465,7 @@ func (s *Server) handleDNSRequest(w dns.ResponseWriter, r *dns.Msg) {
} }
// 添加查询日志 - 标记为缓存 // 添加查询日志 - 标记为缓存
s.addQueryLog(sourceIP, domain, queryType, responseTime, "allowed", "", "", true, cachedDNSSEC) s.addQueryLog(sourceIP, domain, queryType, responseTime, "allowed", "", "", true, cachedDNSSEC, true)
logger.Debug("从缓存返回DNS响应", "domain", domain, "type", queryType, "dnssec", cachedDNSSEC) logger.Debug("从缓存返回DNS响应", "domain", domain, "type", queryType, "dnssec", cachedDNSSEC)
return return
} }
@@ -493,7 +494,7 @@ func (s *Server) handleDNSRequest(w dns.ResponseWriter, r *dns.Msg) {
} }
} }
} }
// 写入响应给客户端 // 写入响应给客户端
w.WriteMsg(response) w.WriteMsg(response)
} }
@@ -540,7 +541,7 @@ func (s *Server) handleDNSRequest(w dns.ResponseWriter, r *dns.Msg) {
} }
// 添加查询日志 - 标记为实时 // 添加查询日志 - 标记为实时
s.addQueryLog(sourceIP, domain, queryType, responseTime, "allowed", "", "", false, responseDNSSEC) s.addQueryLog(sourceIP, domain, queryType, responseTime, "allowed", "", "", false, responseDNSSEC, true)
} }
// handleHostsResponse 处理hosts文件匹配的响应 // handleHostsResponse 处理hosts文件匹配的响应
@@ -1093,7 +1094,7 @@ func (s *Server) updateStats(update func(*Stats)) {
} }
// addQueryLog 添加查询日志 // addQueryLog 添加查询日志
func (s *Server) addQueryLog(clientIP, domain, queryType string, responseTime int64, result, blockRule, blockType string, fromCache, dnssec bool) { func (s *Server) addQueryLog(clientIP, domain, queryType string, responseTime int64, result, blockRule, blockType string, fromCache, dnssec, edns bool) {
// 获取IP地理位置 // 获取IP地理位置
location := s.getIpGeolocation(clientIP) location := s.getIpGeolocation(clientIP)
@@ -1110,6 +1111,7 @@ func (s *Server) addQueryLog(clientIP, domain, queryType string, responseTime in
BlockType: blockType, BlockType: blockType,
FromCache: fromCache, FromCache: fromCache,
DNSSEC: dnssec, DNSSEC: dnssec,
EDNS: edns,
} }
// 添加到日志列表 // 添加到日志列表

File diff suppressed because it is too large Load Diff

View File

@@ -1,28 +0,0 @@
time="2025-12-16T00:37:59+08:00" level=debug msg="尝试加载Shield统计数据" file=/root/dns/data/test_shield_stats.json
time="2025-12-16T00:37:59+08:00" level=info msg="Shield计数数据加载成功" blocked_entries=0 resolved_entries=0
time="2025-12-16T00:38:00+08:00" level=info msg="规则加载完成,域名规则: 122426, 排除规则: 654, 正则规则: 473, hosts规则: 0"
time="2025-12-16T00:38:00+08:00" level=info msg="统计数据加载成功"
time="2025-12-16T00:38:00+08:00" level=info msg="查询日志加载成功" count=118
time="2025-12-16T00:38:00+08:00" level=info msg="DNS服务器已启动监听端口: 5353"
time="2025-12-16T00:38:00+08:00" level=info msg="HTTP控制台已启动监听端口: 8081"
time="2025-12-16T00:38:00+08:00" level=info msg="DNS TCP服务器启动监听端口: 5353"
time="2025-12-16T00:38:00+08:00" level=info msg="启动统计数据自动保存功能" file=data/test_stats.json interval=300
time="2025-12-16T00:38:00+08:00" level=info msg="DNS UDP服务器启动监听端口: 5353"
time="2025-12-16T00:38:00+08:00" level=info msg="启动Shield计数数据自动保存功能" file=./data/test_shield_stats.json interval=60
time="2025-12-16T00:38:00+08:00" level=info msg="规则自动更新已启动" interval=3600
time="2025-12-16T00:38:00+08:00" level=info msg="HTTP控制台服务器启动监听地址: 0.0.0.0:8081"
time="2025-12-16T00:38:00+08:00" level=info msg="Shield计数数据保存成功" blocked_entries=0 file=/root/dns/data/test_shield_stats.json resolved_entries=0
time="2025-12-16T00:38:14+08:00" level=debug msg="接收到DNS查询" client="127.0.0.1:52388" domain=google.com type=A
time="2025-12-16T00:38:14+08:00" level=debug msg="DNS响应不包含DNSSEC记录" domain=google.com server="223.5.5.5:53"
time="2025-12-16T00:38:14+08:00" level=debug msg="DNS查询成功" domain=google.com rtt=6.030332ms server="223.5.5.5:53"
time="2025-12-16T00:38:14+08:00" level=debug msg="DNS响应已缓存" domain=google.com ttl=30m0s type=A
time="2025-12-16T00:38:44+08:00" level=info msg="正在关闭服务..."
time="2025-12-16T00:38:44+08:00" level=info msg="统计数据保存成功" file=/root/dns/data/test_stats.json
time="2025-12-16T00:38:44+08:00" level=info msg="查询日志保存成功" file=/root/dns/data/querylog.json
time="2025-12-16T00:38:44+08:00" level=info msg="DNS服务器已停止"
time="2025-12-16T00:38:44+08:00" level=error msg="HTTP控制台服务器启动失败" error="http: Server closed"
time="2025-12-16T00:38:44+08:00" level=info msg="HTTP控制台服务器已停止"
time="2025-12-16T00:38:44+08:00" level=info msg="Shield计数数据保存成功" blocked_entries=0 file=/root/dns/data/test_shield_stats.json resolved_entries=0
time="2025-12-16T00:38:44+08:00" level=info msg="规则自动更新已停止"
time="2025-12-16T00:38:44+08:00" level=info msg="服务已关闭"
time="2025-12-16T00:38:44+08:00" level=warning msg="日志系统已关闭"

18
package.json Normal file
View File

@@ -0,0 +1,18 @@
{
"name": "dns-server-console",
"version": "1.0.0",
"description": "DNS服务器Web控制台",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"tailwindcss": "^3.3.3",
"font-awesome": "^4.7.0",
"chart.js": "^4.4.8"
},
"devDependencies": {},
"keywords": ["dns", "server", "console", "web"],
"author": "",
"license": "ISC"
}

View File

@@ -33,6 +33,203 @@
} }
], ],
"paths": { "paths": {
"/login": {
"post": {
"summary": "用户登录",
"description": "使用用户名和密码登录DNS服务器API。",
"tags": ["auth"],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"username": {"type": "string", "description": "用户名"},
"password": {"type": "string", "description": "密码"}
}
},
"example": {
"username": "admin",
"password": "admin"
}
}
}
},
"responses": {
"200": {
"description": "登录成功",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"status": {"type": "string", "description": "操作状态"},
"message": {"type": "string", "description": "操作信息"}
}
},
"example": {
"status": "success",
"message": "登录成功"
}
}
}
},
"400": {
"description": "请求参数错误",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {"type": "string", "description": "错误信息"}
}
},
"example": {
"error": "无效的请求体"
}
}
}
},
"401": {
"description": "用户名或密码错误",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {"type": "string", "description": "错误信息"}
}
},
"example": {
"error": "用户名或密码错误"
}
}
}
}
}
}
},
"/logout": {
"post": {
"summary": "用户注销",
"description": "注销当前登录的用户会话。",
"tags": ["auth"],
"responses": {
"200": {
"description": "注销成功",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"status": {"type": "string", "description": "操作状态"},
"message": {"type": "string", "description": "操作信息"}
}
},
"example": {
"status": "success",
"message": "注销成功"
}
}
}
}
}
}
},
"/change-password": {
"post": {
"summary": "修改密码",
"description": "修改当前登录用户的密码。",
"tags": ["auth"],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"currentPassword": {"type": "string", "description": "当前密码"},
"newPassword": {"type": "string", "description": "新密码"}
}
},
"example": {
"currentPassword": "admin",
"newPassword": "newpassword"
}
}
}
},
"responses": {
"200": {
"description": "密码修改成功",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"status": {"type": "string", "description": "操作状态"},
"message": {"type": "string", "description": "操作信息"}
}
},
"example": {
"status": "success",
"message": "密码修改成功"
}
}
}
},
"400": {
"description": "请求参数错误",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {"type": "string", "description": "错误信息"}
}
},
"example": {
"error": "无效的请求体"
}
}
}
},
"401": {
"description": "当前密码错误",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {"type": "string", "description": "错误信息"}
}
},
"example": {
"error": "当前密码错误"
}
}
}
},
"500": {
"description": "服务器内部错误",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {"type": "string", "description": "错误信息"}
}
},
"example": {
"error": "保存密码失败"
}
}
}
}
}
}
},
"/stats": { "/stats": {
"get": { "get": {
"summary": "获取系统统计信息", "summary": "获取系统统计信息",
@@ -58,7 +255,11 @@
"TotalResponseTime": {"type": "number", "description": "总响应时间(毫秒)"}, "TotalResponseTime": {"type": "number", "description": "总响应时间(毫秒)"},
"QueryTypes": {"type": "object", "description": "查询类型统计"}, "QueryTypes": {"type": "object", "description": "查询类型统计"},
"SourceIPs": {"type": "object", "description": "来源IP统计"}, "SourceIPs": {"type": "object", "description": "来源IP统计"},
"CpuUsage": {"type": "number", "description": "CPU使用率(百分比)"} "CpuUsage": {"type": "number", "description": "CPU使用率(百分比)"},
"DNSSECQueries": {"type": "integer", "description": "DNSSEC查询次数"},
"DNSSECSuccess": {"type": "integer", "description": "DNSSEC成功次数"},
"DNSSECFailed": {"type": "integer", "description": "DNSSEC失败次数"},
"DNSSECEnabled": {"type": "boolean", "description": "是否启用DNSSEC"}
} }
}, },
"shield": {"type": "object", "description": "Shield统计信息"}, "shield": {"type": "object", "description": "Shield统计信息"},
@@ -66,6 +267,11 @@
"activeIPs": {"type": "integer", "description": "活跃IP数量"}, "activeIPs": {"type": "integer", "description": "活跃IP数量"},
"avgResponseTime": {"type": "number", "description": "平均响应时间(毫秒)"}, "avgResponseTime": {"type": "number", "description": "平均响应时间(毫秒)"},
"cpuUsage": {"type": "number", "description": "CPU使用率(百分比)"}, "cpuUsage": {"type": "number", "description": "CPU使用率(百分比)"},
"dnssecEnabled": {"type": "boolean", "description": "是否启用DNSSEC"},
"dnssecQueries": {"type": "integer", "description": "DNSSEC查询次数"},
"dnssecSuccess": {"type": "integer", "description": "DNSSEC成功次数"},
"dnssecFailed": {"type": "integer", "description": "DNSSEC失败次数"},
"dnssecUsage": {"type": "number", "description": "DNSSEC使用率(百分比)"},
"time": {"type": "string", "description": "统计时间"} "time": {"type": "string", "description": "统计时间"}
} }
}, },
@@ -82,13 +288,22 @@
"TotalResponseTime": 15625, "TotalResponseTime": 15625,
"QueryTypes": {"A": 850, "AAAA": 250, "CNAME": 150}, "QueryTypes": {"A": 850, "AAAA": 250, "CNAME": 150},
"SourceIPs": {"192.168.1.100": 500, "192.168.1.101": 750}, "SourceIPs": {"192.168.1.100": 500, "192.168.1.101": 750},
"CpuUsage": 0.15 "CpuUsage": 0.15,
"DNSSECQueries": 500,
"DNSSECSuccess": 480,
"DNSSECFailed": 20,
"DNSSECEnabled": true
}, },
"shield": {}, "shield": {},
"topQueryType": "A", "topQueryType": "A",
"activeIPs": 2, "activeIPs": 2,
"avgResponseTime": 12.5, "avgResponseTime": 12.5,
"cpuUsage": 0.15, "cpuUsage": 0.15,
"dnssecEnabled": true,
"dnssecQueries": 500,
"dnssecSuccess": 480,
"dnssecFailed": 20,
"dnssecUsage": 40.0,
"time": "2023-07-15T14:30:45Z" "time": "2023-07-15T14:30:45Z"
} }
} }
@@ -274,20 +489,16 @@
"content": { "content": {
"application/json": { "application/json": {
"schema": { "schema": {
"type": "array", "type": "object",
"items": { "properties": {
"type": "object", "labels": {"type": "array", "items": {"type": "string"}, "description": "小时标签"},
"properties": { "data": {"type": "array", "items": {"type": "integer"}, "description": "查询次数数据"}
"hour": {"type": "string", "description": "小时"},
"queries": {"type": "integer", "description": "查询次数"},
"blocked": {"type": "integer", "description": "被阻止次数"}
}
} }
}, },
"example": [ "example": {
{"hour": "00", "queries": 120, "blocked": 20}, "labels": ["15:00", "16:00", "17:00"],
{"hour": "01", "queries": 90, "blocked": 15} "data": [120, 90, 150]
] }
} }
} }
} }
@@ -305,20 +516,16 @@
"content": { "content": {
"application/json": { "application/json": {
"schema": { "schema": {
"type": "array", "type": "object",
"items": { "properties": {
"type": "object", "labels": {"type": "array", "items": {"type": "string"}, "description": "日期标签"},
"properties": { "data": {"type": "array", "items": {"type": "integer"}, "description": "查询次数数据"}
"date": {"type": "string", "description": "日期"},
"queries": {"type": "integer", "description": "查询次数"},
"blocked": {"type": "integer", "description": "被阻止次数"}
}
} }
}, },
"example": [ "example": {
{"date": "2023-07-09", "queries": 2500, "blocked": 450}, "labels": ["01-02", "01-03", "01-04"],
{"date": "2023-07-10", "queries": 2700, "blocked": 480} "data": [2500, 2700, 2300]
] }
} }
} }
} }
@@ -336,20 +543,16 @@
"content": { "content": {
"application/json": { "application/json": {
"schema": { "schema": {
"type": "array", "type": "object",
"items": { "properties": {
"type": "object", "labels": {"type": "array", "items": {"type": "string"}, "description": "日期标签"},
"properties": { "data": {"type": "array", "items": {"type": "integer"}, "description": "查询次数数据"}
"date": {"type": "string", "description": "日期"},
"queries": {"type": "integer", "description": "查询次数"},
"blocked": {"type": "integer", "description": "被阻止次数"}
}
} }
}, },
"example": [ "example": {
{"date": "2023-06-15", "queries": 2500, "blocked": 450}, "labels": ["01-01", "01-02", "01-03"],
{"date": "2023-06-16", "queries": 2700, "blocked": 480} "data": [2500, 2700, 2300]
] }
} }
} }
} }
@@ -387,30 +590,157 @@
} }
} }
}, },
"/shield": { "/logs/stats": {
"get": { "get": {
"summary": "获取Shield配置", "summary": "获取日志统计信息",
"description": "获取Shield的完整配置信息包括启用状态、规则等。", "description": "获取DNS查询日志的统计信息。",
"tags": ["shield"], "tags": ["logs"],
"responses": { "responses": {
"200": { "200": {
"description": "成功获取配置信息", "description": "成功获取日志统计信息",
"content": {
"application/json": {
"schema": {
"type": "object",
"description": "日志统计信息"}
}
}
}
}
}
},
"/logs/query": {
"get": {
"summary": "查询日志",
"description": "根据条件查询DNS查询日志。",
"tags": ["logs"],
"parameters": [
{
"name": "limit",
"in": "query",
"schema": {
"type": "integer",
"default": 100
},
"description": "返回结果数量限制"
},
{
"name": "offset",
"in": "query",
"schema": {
"type": "integer",
"default": 0
},
"description": "结果偏移量"
},
{
"name": "sort",
"in": "query",
"schema": {
"type": "string"
},
"description": "排序字段"
},
{
"name": "direction",
"in": "query",
"schema": {
"type": "string"
},
"description": "排序方向"
},
{
"name": "result",
"in": "query",
"schema": {
"type": "string"
},
"description": "查询结果过滤"
},
{
"name": "search",
"in": "query",
"schema": {
"type": "string"
},
"description": "搜索关键词"
}
],
"responses": {
"200": {
"description": "成功查询日志",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"type": "object",
"description": "日志条目"
}
}
}
}
}
}
}
},
"/logs/count": {
"get": {
"summary": "获取日志总数",
"description": "获取DNS查询日志的总数。",
"tags": ["logs"],
"responses": {
"200": {
"description": "成功获取日志总数",
"content": { "content": {
"application/json": { "application/json": {
"schema": { "schema": {
"type": "object", "type": "object",
"properties": { "properties": {
"enabled": {"type": "boolean", "description": "是否启用Shield"}, "count": {"type": "integer", "description": "日志总数"}
"rulesCount": {"type": "integer", "description": "规则数量"},
"lastUpdate": {"type": "string", "description": "最后更新时间"},
"blacklists": {"type": "array", "description": "黑名单列表", "items": {"type": "object"}}
} }
}, },
"example": { "example": {
"enabled": true, "count": 1000
"rulesCount": 5000, }
"lastUpdate": "2023-07-15T10:00:00Z", }
"blacklists": [] }
}
}
}
},
"/shield": {
"get": {
"summary": "获取Shield配置和统计信息",
"description": "获取Shield的配置信息和规则统计包括更新间隔、屏蔽方法、黑名单数量等。",
"tags": ["shield"],
"responses": {
"200": {
"description": "成功获取配置和统计信息",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"updateInterval": {"type": "integer", "description": "更新间隔(秒)"},
"blockMethod": {"type": "string", "description": "屏蔽方法"},
"blacklistCount": {"type": "integer", "description": "黑名单数量"},
"domainRulesCount": {"type": "integer", "description": "域名规则数量"},
"domainExceptionsCount": {"type": "integer", "description": "域名例外规则数量"},
"regexRulesCount": {"type": "integer", "description": "正则规则数量"},
"regexExceptionsCount": {"type": "integer", "description": "正则例外规则数量"},
"hostsRulesCount": {"type": "integer", "description": "Hosts规则数量"}
}
},
"example": {
"updateInterval": 3600,
"blockMethod": "NXDOMAIN",
"blacklistCount": 4,
"domainRulesCount": 1000,
"domainExceptionsCount": 100,
"regexRulesCount": 50,
"regexExceptionsCount": 10,
"hostsRulesCount": 200
} }
} }
} }
@@ -432,8 +762,8 @@
} }
}, },
"post": { "post": {
"summary": "更新Shield配置", "summary": "添加屏蔽规则",
"description": "更新Shield的全局配置信息。", "description": "添加新的屏蔽规则到Shield。",
"tags": ["shield"], "tags": ["shield"],
"requestBody": { "requestBody": {
"required": true, "required": true,
@@ -442,20 +772,18 @@
"schema": { "schema": {
"type": "object", "type": "object",
"properties": { "properties": {
"enabled": {"type": "boolean", "description": "是否启用Shield"}, "rule": {"type": "string", "description": "屏蔽规则"}
"updateInterval": {"type": "integer", "description": "更新间隔(秒)"}
} }
}, },
"example": { "example": {
"enabled": true, "rule": "example.com"
"updateInterval": 3600
} }
} }
} }
}, },
"responses": { "responses": {
"200": { "200": {
"description": "成功更新配置", "description": "成功添加规则",
"content": { "content": {
"application/json": { "application/json": {
"schema": { "schema": {
@@ -492,19 +820,35 @@
"error": {"type": "string", "description": "错误信息"} "error": {"type": "string", "description": "错误信息"}
} }
}, },
"example": {"error": "更新配置失败"} "example": {"error": "添加规则失败"}
} }
} }
} }
} }
}, },
"put": { "delete": {
"summary": "重启Shield", "summary": "删除屏蔽规则",
"description": "重新加载和应用Shield规则。", "description": "从Shield中删除指定的屏蔽规则。",
"tags": ["shield"], "tags": ["shield"],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"rule": {"type": "string", "description": "要删除的屏蔽规则"}
}
},
"example": {
"rule": "example.com"
}
}
}
},
"responses": { "responses": {
"200": { "200": {
"description": "成功重启Shield", "description": "成功删除规则",
"content": { "content": {
"application/json": { "application/json": {
"schema": { "schema": {
@@ -517,6 +861,20 @@
} }
} }
}, },
"400": {
"description": "请求参数错误",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {"type": "string", "description": "错误信息"}
}
},
"example": {"error": "参数格式错误"}
}
}
},
"500": { "500": {
"description": "服务器内部错误", "description": "服务器内部错误",
"content": { "content": {
@@ -527,7 +885,46 @@
"error": {"type": "string", "description": "错误信息"} "error": {"type": "string", "description": "错误信息"}
} }
}, },
"example": {"error": "重启失败"} "example": {"error": "删除规则失败"}
}
}
}
}
},
"put": {
"summary": "重新加载规则",
"description": "重新加载和应用Shield规则。",
"tags": ["shield"],
"responses": {
"200": {
"description": "成功重新加载规则",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"status": {"type": "string", "description": "操作状态"},
"message": {"type": "string", "description": "操作信息"}
}
},
"example": {
"status": "success",
"message": "规则重新加载成功"
}
}
}
},
"500": {
"description": "服务器内部错误",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {"type": "string", "description": "错误信息"}
}
},
"example": {"error": "重新加载规则失败"}
} }
} }
} }
@@ -1139,7 +1536,7 @@
"/status": { "/status": {
"get": { "get": {
"summary": "获取服务器状态", "summary": "获取服务器状态",
"description": "获取DNS服务器的状态信息。", "description": "获取DNS服务器的状态信息,包括查询统计、运行时间等。",
"tags": ["server"], "tags": ["server"],
"responses": { "responses": {
"200": { "200": {
@@ -1150,14 +1547,32 @@
"type": "object", "type": "object",
"properties": { "properties": {
"status": {"type": "string", "description": "服务器状态"}, "status": {"type": "string", "description": "服务器状态"},
"uptime": {"type": "integer", "description": "运行时间(秒)"}, "queries": {"type": "integer", "description": "总查询次数"},
"version": {"type": "string", "description": "服务器版本"} "blocked": {"type": "integer", "description": "被阻止的查询次数"},
"allowed": {"type": "integer", "description": "允许的查询次数"},
"errors": {"type": "integer", "description": "错误查询次数"},
"lastQuery": {"type": "string", "description": "最近一次查询时间"},
"avgResponseTime": {"type": "number", "description": "平均响应时间(毫秒)"},
"activeIPs": {"type": "integer", "description": "活跃IP数量"},
"startTime": {"type": "string", "description": "服务器启动时间"},
"uptime": {"type": "integer", "description": "运行时间(毫秒)"},
"cpuUsage": {"type": "number", "description": "CPU使用率(百分比)"},
"timestamp": {"type": "string", "description": "当前时间"}
} }
}, },
"example": { "example": {
"status": "running", "status": "running",
"uptime": 3600, "queries": 1250,
"version": "1.0.0" "blocked": 230,
"allowed": 1020,
"errors": 0,
"lastQuery": "2023-07-15T14:30:45Z",
"avgResponseTime": 12.5,
"activeIPs": 2,
"startTime": "2023-07-15T10:00:00Z",
"uptime": 16200000,
"cpuUsage": 0.15,
"timestamp": "2023-07-15T14:30:45Z"
} }
} }
} }
@@ -1168,7 +1583,7 @@
"/config": { "/config": {
"get": { "get": {
"summary": "获取服务器配置", "summary": "获取服务器配置",
"description": "获取DNS服务器的配置信息。", "description": "获取DNS服务器的配置信息包括Shield配置。",
"tags": ["server"], "tags": ["server"],
"responses": { "responses": {
"200": { "200": {
@@ -1178,13 +1593,30 @@
"schema": { "schema": {
"type": "object", "type": "object",
"properties": { "properties": {
"port": {"type": "integer", "description": "服务器端口"}, "shield": {
"logLevel": {"type": "string", "description": "日志级别"} "type": "object",
"properties": {
"blockMethod": {"type": "string", "description": "屏蔽方法"},
"customBlockIP": {"type": "string", "description": "自定义屏蔽IP"},
"blacklists": {"type": "array", "description": "黑名单列表", "items": {"type": "object"}},
"updateInterval": {"type": "integer", "description": "更新间隔(秒)"}
}
}
} }
}, },
"example": { "example": {
"port": 53, "shield": {
"logLevel": "info" "blockMethod": "NXDOMAIN",
"customBlockIP": "",
"blacklists": [
{
"name": "AdGuard DNS filter",
"url": "https://example.com/ads.txt",
"enabled": true
}
],
"updateInterval": 3600
}
} }
} }
} }
@@ -1193,7 +1625,7 @@
}, },
"post": { "post": {
"summary": "更新服务器配置", "summary": "更新服务器配置",
"description": "更新DNS服务器的配置信息。", "description": "更新DNS服务器的配置信息包括Shield配置。",
"tags": ["server"], "tags": ["server"],
"requestBody": { "requestBody": {
"required": true, "required": true,
@@ -1202,13 +1634,30 @@
"schema": { "schema": {
"type": "object", "type": "object",
"properties": { "properties": {
"port": {"type": "integer", "description": "服务器端口"}, "shield": {
"logLevel": {"type": "string", "description": "日志级别"} "type": "object",
"properties": {
"blockMethod": {"type": "string", "description": "屏蔽方法"},
"customBlockIP": {"type": "string", "description": "自定义屏蔽IP"},
"blacklists": {"type": "array", "description": "黑名单列表", "items": {"type": "object"}},
"updateInterval": {"type": "integer", "description": "更新间隔(秒)"}
}
}
} }
}, },
"example": { "example": {
"port": 53, "shield": {
"logLevel": "info" "blockMethod": "NXDOMAIN",
"customBlockIP": "",
"blacklists": [
{
"name": "AdGuard DNS filter",
"url": "https://example.com/ads.txt",
"enabled": true
}
],
"updateInterval": 3600
}
} }
} }
} }
@@ -1221,10 +1670,14 @@
"schema": { "schema": {
"type": "object", "type": "object",
"properties": { "properties": {
"status": {"type": "string", "description": "操作状态"} "success": {"type": "boolean", "description": "是否成功"},
"message": {"type": "string", "description": "操作信息"}
} }
}, },
"example": {"status": "success"} "example": {
"success": true,
"message": "配置已更新"
}
} }
} }
}, },
@@ -1238,7 +1691,9 @@
"error": {"type": "string", "description": "错误信息"} "error": {"type": "string", "description": "错误信息"}
} }
}, },
"example": {"error": "参数格式错误"} "example": {
"error": "无效的请求体"
}
} }
} }
}, },
@@ -1252,7 +1707,9 @@
"error": {"type": "string", "description": "错误信息"} "error": {"type": "string", "description": "错误信息"}
} }
}, },
"example": {"error": "更新配置失败"} "example": {
"error": "保存配置失败"
}
} }
} }
} }
@@ -1298,6 +1755,10 @@
} }
}, },
"tags": [ "tags": [
{
"name": "auth",
"description": "认证相关API"
},
{ {
"name": "stats", "name": "stats",
"description": "统计相关API" "description": "统计相关API"
@@ -1309,6 +1770,10 @@
{ {
"name": "server", "name": "server",
"description": "服务器相关API" "description": "服务器相关API"
},
{
"name": "logs",
"description": "日志相关API"
} }
] ]
}; };

View File

@@ -399,7 +399,7 @@ function updateLogsTable(logs) {
</td> </td>
<td class="py-3 px-4 text-sm"> <td class="py-3 px-4 text-sm">
<div class="font-medium">${log.Domain}</div> <div class="font-medium">${log.Domain}</div>
<div class="text-xs text-gray-500 mt-1">类型: ${log.QueryType}, <span class="${statusClass}">${statusText}</span>, <span class="${cacheStatusClass}">${log.FromCache ? '缓存' : '实时'}</span>${log.DNSSEC ? ', <span class="text-green-500"><i class="fa fa-lock"></i> DNSSEC</span>' : ''}</div> <div class="text-xs text-gray-500 mt-1">类型: ${log.QueryType}, <span class="${statusClass}">${statusText}</span>, <span class="${cacheStatusClass}">${log.FromCache ? '缓存' : '实时'}</span>${log.DNSSEC ? ', <span class="text-green-500"><i class="fa fa-lock"></i> DNSSEC</span>' : ''}${log.EDNS ? ', <span class="text-blue-500"><i class="fa fa-exchange"></i> EDNS</span>' : ''}</div>
</td> </td>
<td class="py-3 px-4 text-sm">${log.ResponseTime}ms</td> <td class="py-3 px-4 text-sm">${log.ResponseTime}ms</td>
<td class="py-3 px-4 text-sm text-gray-500">${log.BlockRule || '-'}</td> <td class="py-3 px-4 text-sm text-gray-500">${log.BlockRule || '-'}</td>

24
tailwind.config.js Normal file
View File

@@ -0,0 +1,24 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./static/**/*.{html,js}",
],
theme: {
extend: {
colors: {
primary: '#165DFF',
secondary: '#36CFFB',
success: '#00B42A',
warning: '#FF7D00',
danger: '#F53F3F',
info: '#86909C',
dark: '#1D2129',
light: '#F2F3F5',
},
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif'],
},
},
},
plugins: [],
}