This commit is contained in:
Alex Yang
2026-01-16 11:09:11 +08:00
parent 8159577be0
commit cdac4fcf43
284 changed files with 2813570 additions and 14 deletions

View File

@@ -0,0 +1,119 @@
# DNSSEC判断和显示逻辑分析与改进
## 1. 当前实现分析
### DNSSEC判断逻辑
1. **核心位置**`dns/server.go` 中的 `forwardDNSRequestWithCache` 函数
2. **判断流程**
- 检查配置是否启用DNSSEC (`s.config.EnableDNSSEC`)
- 从响应中提取所有DNSKEY和RRSIG记录
- 验证DNSSEC签名有效性
- 设置响应的Authenticated Data (AD) 标志
- 优先返回包含有效的DNSSEC记录的响应
- 如果没有有效的DNSSEC记录使用备选响应
### DNSSEC显示逻辑
1. **前端显示**`static/js/logs.js` 中的 `updateLogsTable` 函数
2. **显示方式**
```javascript
${log.DNSSEC ? ', <span class="text-green-500"><i class="fa fa-lock"></i> DNSSEC</span>' : ''}
```
- 当DNSSEC为true时显示绿色锁图标和"DNSSEC"文字
- 否则不显示
### DNSSEC状态存储
1. **`domainDNSSECStatus` 映射**存储域名的DNSSEC状态
2. **`resolvedDomains` 结构**包含每个域名的DNSSEC状态
3. **查询日志**每条日志记录包含DNSSEC状态
## 2. 存在的问题
1. **显示逻辑单一**只在日志页面显示DNSSEC状态没有在仪表盘或其他关键位置显示
2. **状态判断简单**只检查响应中是否包含RRSIG记录没有考虑签名验证结果
3. **缺少统计信息**没有统计使用DNSSEC的查询比例
4. **配置界面缺失**没有在配置界面提供DNSSEC相关的配置选项
5. **缺少用户反馈**用户无法直观了解当前DNSSEC的整体使用情况
## 3. 改进方案
### 3.1 增强DNSSEC判断逻辑
- **改进位置**`dns/server.go`
- **改进内容**
- 增加DNSSEC验证结果的详细记录
- 区分"DNSSEC可用"和"DNSSEC验证成功"两种状态
- 记录DNSSEC验证失败的具体原因
### 3.2 扩展DNSSEC显示范围
- **改进位置**
- `static/js/dashboard.js`在仪表盘添加DNSSEC统计卡片
- `static/js/logs.js`增强日志中的DNSSEC显示
- **改进内容**
- 在仪表盘添加"DNSSEC使用率"统计卡片
- 在TOP域名列表中显示DNSSEC状态
- 在日志记录中显示DNSSEC验证结果成功/失败/未使用)
### 3.3 添加DNSSEC配置界面
- **改进位置**:配置页面
- **改进内容**
- 添加DNSSEC启用/禁用开关
- 添加DNSSEC验证严格程度选项
- 显示当前DNSSEC状态信息
### 3.4 增强DNSSEC统计功能
- **改进位置**`dns/server.go`
- **改进内容**
- 统计DNSSEC查询总数
- 统计DNSSEC验证成功/失败次数
- 计算DNSSEC使用率
- 在API中提供DNSSEC统计数据
### 3.5 改进DNSSEC状态存储
- **改进位置**`dns/server.go`
- **改进内容**
- 增加DNSSEC验证结果的存储
- 记录DNSSEC状态的有效期
- 优化域名DNSSEC状态的更新逻辑
## 4. 实现计划
1. **第一步**增强DNSSEC判断逻辑改进验证结果记录
2. **第二步**添加DNSSEC统计功能扩展API返回数据
3. **第三步**在仪表盘添加DNSSEC统计卡片
4. **第四步**增强日志中的DNSSEC显示
5. **第五步**添加DNSSEC配置界面
6. **第六步**优化DNSSEC状态存储和更新逻辑
## 5. 预期效果
- 用户可以在仪表盘直观了解DNSSEC使用情况
- 日志中显示详细的DNSSEC验证结果
- 提供灵活的DNSSEC配置选项
- 增强DNSSEC状态的准确性和可靠性
- 提高DNSSEC相关问题的可调试性
## 6. 代码修改点
### 后端修改
- `dns/server.go`增强DNSSEC判断和统计
- `config/config.go`添加DNSSEC相关配置选项
- API接口扩展返回DNSSEC统计数据
### 前端修改
- `static/js/dashboard.js`添加DNSSEC统计卡片
- `static/js/logs.js`:增强日志显示
- 配置页面添加DNSSEC配置选项
## 7. 风险评估
- DNSSEC验证可能会增加响应延迟
- 错误的DNSSEC配置可能导致解析失败
- 增强的统计功能可能增加内存使用
## 8. 测试计划
- 测试DNSSEC启用/禁用功能
- 测试不同域名的DNSSEC显示
- 测试DNSSEC统计数据的准确性
- 测试DNSSEC验证失败时的处理逻辑
通过以上改进可以使DNSSEC判断和显示逻辑更加完善提供更好的用户体验和更详细的DNSSEC状态信息。

View File

@@ -0,0 +1,79 @@
## DNS服务器性能优化方案
### 问题分析
1. **并行查询模式**:当前配置使用`parallel`模式,会等待所有上游服务器响应后才返回,受最慢服务器影响
2. **DNSSEC验证开销**启用了DNSSEC验证增加了额外的计算和网络请求
3. **过多上游服务器**DNSSEC上游服务器多达5个响应时间差异大
4. **调试级别日志**`debug`级别日志记录大量信息占用CPU和I/O资源
5. **缓存TTL过短**10秒的缓存TTL导致频繁向上游请求
6. **黑名单规则过多**14个启用的黑名单每次请求都需要检查
### 优化方案
#### 1. 修改查询模式为快速返回
*`queryMode``parallel`改为`fastest-ip`或优化默认模式
* 快速返回模式会返回第一个有效响应,而不是等待所有响应
#### 2. 优化DNSSEC配置
* 减少DNSSEC上游服务器数量只保留2-3个可靠的
* 对国内域名禁用DNSSEC验证已配置部分可扩展
#### 3. 调整缓存策略
* 增加`cacheTTL`到60秒或更高减少上游请求频率
* 优化缓存实现,减少锁竞争
#### 4. 降低日志级别
* 将日志级别从`debug`改为`info``warn`,减少日志写入开销
#### 5. 优化黑名单处理
* 合并重复的黑名单规则
* 考虑使用更高效的域名匹配算法
#### 6. 代码优化
* 减少DNSSEC验证的重复调用
* 优化响应合并逻辑,避免不必要的计算
* 调整超时设置,避免过长等待
### 具体修改点
1. **config.json**
* 修改`queryMode``fastest-ip`
* 减少`dnssecUpstreamDNS`数量
* 增加`cacheTTL`到60
* 将日志级别改为`info`
2. **dns/server.go**
* 优化`forwardDNSRequestWithCache`函数减少DNSSEC重复验证
* 优化响应合并逻辑,避免不必要的计算
* 调整并行模式的超时处理
### 预期效果
* 减少响应时间,从当前的秒级降低到毫秒级
* 减少CPU和I/O资源占用
* 提高并发处理能力
* 保持DNS解析的准确性和可靠性

View File

@@ -0,0 +1,62 @@
# DNS查询页面实现计划
## 问题分析
目前DNS查询页面只是一个简单的占位符显示"DNS查询页面内容待实现"没有实际的功能。我需要实现完整的DNS查询功能包括
1. DNS域名查询功能
2. 查询结果展示
3. 查询历史记录
4. 响应式设计
## 解决方案
### 1. 更新HTML结构
`query-content`区域添加完整的UI组件包括
- 查询表单(域名输入框、查询按钮)
- 查询结果展示区域
- 查询历史记录
- 响应式布局设计
### 2. 实现JavaScript功能
创建或更新`query.js`文件,实现以下功能:
- 处理DNS查询请求
- 展示查询结果
- 管理查询历史
- 与后端API对接
### 3. 实现具体功能
#### 3.1 DNS域名查询
- 调用`/api/query`接口进行DNS查询
- 支持输入域名进行查询
- 显示查询结果,包括是否被屏蔽、屏蔽原因等
#### 3.2 查询结果展示
- 以清晰的方式展示查询结果
- 区分不同的查询结果状态(被屏蔽、正常、错误等)
- 显示详细的查询信息
#### 3.3 查询历史记录
- 保存查询历史到本地存储
- 支持查看历史查询记录
- 支持从历史记录中重新查询
## 实现步骤
1. **更新HTML结构**:修改`index.html`中的`query-content`区域添加完整的UI组件
2. **实现JavaScript功能**:更新`query.js`文件实现与后端API的交互
3. **测试功能**:确保所有功能正常工作
4. **优化用户体验**:添加加载状态、错误提示、成功反馈等
## 预期效果
通过以上实现DNS查询页面将具备完整的查询功能用户可以
- 输入域名进行DNS查询
- 查看详细的查询结果
- 查看查询历史记录
- 从历史记录中重新查询
页面将采用响应式设计,确保在不同屏幕尺寸下都能正常显示。

View File

@@ -0,0 +1,25 @@
## Problem
The build is failing because the HTTP server is trying to access DNSSEC-related fields (`DNSSECQueries`, `DNSSECSuccess`, `DNSSECFailed`, `DNSSECEnabled`) from the `dns.Stats` struct, but these fields don't exist in the struct definition.
## Solution
Add the missing DNSSEC-related fields to the `Stats` struct in `dns/server.go` and ensure they're properly initialized and updated.
## Implementation Steps
1. **Add DNSSEC fields to Stats struct** in `/root/dns/dns/server.go`:
- Add `DNSSECQueries int64` field
- Add `DNSSECSuccess int64` field
- Add `DNSSECFailed int64` field
- Add `DNSSECEnabled bool` field
2. **Initialize DNSSEC fields in NewServer** function:
- Set `DNSSECEnabled` based on config.EnableDNSSEC
- Initialize other DNSSEC fields to 0
3. **Update DNSSEC stats in query handling**:
- Increment `DNSSECQueries` when a DNSSEC query is processed
- Update `DNSSECSuccess` and `DNSSECFailed` based on DNSSEC validation results
4. **Test the fix** by running `go build` to ensure all errors are resolved
## Expected Outcome
The build will succeed and the HTTP server will be able to access the DNSSEC-related stats fields.

View File

@@ -0,0 +1,65 @@
# Web页面屏蔽管理功能实现计划
## 问题分析
目前web页面的屏蔽管理功能尚未完全实现主要问题包括
1. **前端UI缺失**`shield-content`区域只有简单的提示文本,没有实际的管理界面
2. **功能被禁用**`shield.js`文件中的所有功能都已被禁用无法与后端API交互
3. **缺少完整的管理功能**无法管理本地规则、远程黑名单和hosts条目
## 解决方案
### 1. 更新屏蔽管理页面HTML结构
-`shield-content`区域添加完整的UI组件
- 实现以下功能模块:
- 屏蔽规则统计信息展示
- 本地规则管理(添加、删除)
- 远程黑名单管理(添加、删除、更新)
- hosts条目管理添加、删除
### 2. 实现屏蔽管理JavaScript功能
- 重新启用并实现`shield.js`中的功能
- 与后端API对接实现完整的CRUD操作
- 添加错误处理和用户反馈
### 3. 实现具体功能
#### 3.1 屏蔽规则统计信息
- 调用`/api/shield`接口获取统计数据
- 展示规则数量、黑名单数量等信息
#### 3.2 本地规则管理
- 实现规则列表展示
- 实现添加新规则功能
- 实现删除规则功能
#### 3.3 远程黑名单管理
- 调用`/api/shield/blacklists`接口获取黑名单列表
- 实现添加新黑名单功能
- 实现删除黑名单功能
- 实现更新单个黑名单功能
#### 3.4 hosts条目管理
- 调用`/api/shield/hosts`接口获取hosts列表
- 实现添加新hosts条目功能
- 实现删除hosts条目功能
## 实现步骤
1. **更新HTML结构**:修改`index.html`中的`shield-content`区域添加完整的UI组件
2. **实现JavaScript功能**:更新`shield.js`文件实现与后端API的交互
3. **测试功能**:确保所有功能正常工作,包括添加、删除、更新操作
4. **优化用户体验**:添加加载状态、错误提示、成功反馈等
## 预期效果
通过以上实现web页面将具备完整的屏蔽管理功能用户可以
- 查看屏蔽规则统计信息
- 管理本地规则
- 管理远程黑名单
- 管理hosts条目
所有功能都将与后端API对接实现数据的实时更新和持久化存储。

View File

@@ -0,0 +1,60 @@
# Web页面适配问题解决方案
## 问题分析
通过分析当前web页面的HTML、CSS和JavaScript代码我发现了以下适配问题
1. **统计卡片布局问题**:在小屏幕设备上,统计卡片可能会出现布局问题
2. **图表布局问题**:三个图表在同一行显示,在小屏幕设备上可能会挤在一起
3. **表格溢出问题**:在小屏幕设备上,表格可能会溢出容器
4. **服务器状态组件适配问题**:在小屏幕上可能显示不全
5. **侧边栏响应式处理不完整**:当前只在窗口大小改变时更新,没有考虑其他情况
6. **图表大小更新不完整**:窗口大小改变时只更新了部分图表
7. **配置表单适配问题**:在小屏幕上的布局需要优化
## 解决方案
### 1. 优化统计卡片布局
- 修改统计卡片网格布局,增加更细粒度的响应式控制
- 在小屏幕上使用单列布局,在中等屏幕上使用双列布局,在大屏幕上使用四列布局
### 2. 改进图表布局
- 修改图表网格布局,确保在不同屏幕尺寸下都能正常显示
- 在小屏幕上使用单列布局,在中等屏幕上使用双列布局,在大屏幕上使用三列布局
### 3. 解决表格溢出问题
- 为所有表格添加响应式处理,确保在小屏幕设备上可以水平滚动
- 优化表格样式,提高在小屏幕上的可读性
### 4. 优化服务器状态组件
- 在小屏幕上简化服务器状态组件,只显示核心指标
- 添加响应式逻辑,根据屏幕尺寸动态调整显示内容
### 5. 完善侧边栏响应式处理
- 确保侧边栏在所有情况下都能正确响应屏幕尺寸变化
- 添加触摸事件支持,提高移动端体验
### 6. 完整更新图表大小
- 在窗口大小改变时,更新所有图表的大小
- 确保图表容器大小正确,避免图表变形
### 7. 优化配置表单布局
- 修改配置表单网格布局,确保在小屏幕上也能正常显示
- 调整表单元素大小和间距,提高在小屏幕上的可用性
## 实现步骤
1. 修改HTML文件中的网格布局类增加更细粒度的响应式控制
2. 更新CSS样式优化各组件在不同屏幕尺寸下的显示效果
3. 修改JavaScript代码完善响应式处理逻辑
4. 测试各组件在不同屏幕尺寸下的显示效果
5. 优化用户体验,确保在各种设备上都能正常使用
## 预期效果
通过以上优化web页面将能够在各种设备上正常显示包括
- 桌面设备(大屏幕)
- 平板设备(中等屏幕)
- 移动设备(小屏幕)
页面布局将更加灵活,能够根据屏幕尺寸自动调整,提高用户体验。

View File

@@ -0,0 +1,37 @@
## 问题分析
规则处理存在问题:`||domain` 规则应该是屏蔽一个绝对域名及其子域名,而不是正则匹配屏蔽,也不应该屏蔽所有包含该顶级域名的网站。
## 问题根源
`manager.go` 文件中,`addDomainRule` 函数第444行存在逻辑错误
1. 当添加 `||example.com` 规则时,函数正确地将 `example.com` 添加到域名规则列表中
2. 但随后,函数错误地将域名拆分为各个部分,并为每个部分添加规则
3. 例如,对于 `||example.com`,它会添加 `example.com``com` 到规则列表中
4. 这导致所有 `.com` 域名都被屏蔽,而不仅仅是 `example.com` 及其子域名
## 修复方案
修改 `addDomainRule` 函数,移除错误的子域名处理逻辑。因为 `CheckDomainBlockDetails` 函数已经实现了正确的子域名检查逻辑:它会检查域名的所有子域名部分,从最长到最短,所以不需要在添加规则时就将所有子域名都添加到规则列表中。
## 修复步骤
1. 修改 `manager.go` 文件中的 `addDomainRule` 函数
2. 移除第457-474行和第487-503行的子域名处理逻辑
3. 确保只添加精确的域名到规则列表中
4. 保持 `CheckDomainBlockDetails` 函数的子域名检查逻辑不变
## 预期效果
修复后,`||example.com` 规则将只屏蔽:
- `example.com`
- `www.example.com`
- `subdomain.example.com`
而不会屏蔽:
- `anotherexample.com`
- `google.com`
- 其他所有 `.com` 域名
这符合 AdGuard Home 规则的标准行为,即 `||example.com^` 匹配该域名及其所有子域名。

View File

@@ -0,0 +1,33 @@
## 问题分析
web界面保存配置后配置没有同步到config文件。从代码分析来看当前的`handleConfig`函数第1064行只处理了`shield`部分的配置更新而没有处理其他配置项如DNS服务器配置、HTTP服务器配置等。
## 解决方案
1. **扩展`handleConfig`函数**修改该函数以处理所有配置项包括DNS、HTTP和Log配置
2. **更新配置保存逻辑**确保所有配置都能正确保存到config.json文件中
3. **添加重启服务逻辑**:在配置保存成功后,调用重启服务的逻辑,确保配置更改能立即生效
## 修复步骤
1. 修改`server.go`文件中的`handleConfig`函数
- 扩展请求结构,包含所有配置项
- 更新配置处理逻辑处理DNS、HTTP和Log配置
- 确保所有配置都能正确保存到config.json文件中
2. 修改`handleConfig`函数的返回逻辑
- 在配置保存成功后,调用重启服务的逻辑
- 返回更详细的成功信息
3. 测试修复效果
- 确保web界面上的所有配置项都能正确保存到config.json文件中
- 确保服务能在配置保存后正确重启
## 预期效果
修复后当用户在web界面点击"保存配置"按钮时:
1. 所有配置项包括DNS、HTTP、Shield和Log配置都会被保存到config.json文件中
2. 服务器会自动重启,使配置更改生效
3. 用户会看到配置保存成功的提示
这将确保用户在web界面上的所有配置更改都能正确保存和生效。

View File

@@ -0,0 +1,38 @@
## 修复API不可用问题
### 问题分析
1. **配置文件中API被禁用**:在`config.json`中,`http.enableAPI`设置为`false`
2. **缺少默认启用配置**:在`config/config.go``LoadConfig`函数中,没有为`EnableAPI`设置默认值
3. **API路由条件注册**:在`http/server.go`所有API端点都在`if s.config.EnableAPI`条件下注册
### 解决方案
#### 1. 修改配置文件启用API
`config.json`中的`http.enableAPI`值从`false`改为`true`立即启用API功能。
#### 2. 设置API默认启用
`config/config.go``LoadConfig`函数中添加默认值设置确保API在配置文件未指定时自动启用
```go
if !config.HTTP.EnableAPI {
config.HTTP.EnableAPI = true
}
```
### 实施步骤
1. 编辑`config.json`文件,将`http.enableAPI`设置为`true`
2. 修改`config/config.go`,在`LoadConfig`函数中添加API默认启用逻辑
3. 重启服务使配置生效
### 预期结果
- API端点将可用包括
- `/api/stats` - 统计信息
- `/api/shield` - 屏蔽规则管理
- `/api/shield/localrules` - 本地规则
- `/api/shield/remoterules` - 远程规则
- `/api/query` - DNS查询
- 以及其他统计和管理端点
- Swagger UI页面可通过`/api`访问
### 文件修改清单
1. `config.json` - 启用API
2. `config/config.go` - 添加API默认启用配置

View File

@@ -0,0 +1,21 @@
# DNSSEC记录缺失问题修复计划
## 问题分析
从日志中可以看到所有DNS查询都显示"DNS响应不包含DNSSEC记录"这表明虽然DNSSEC被启用但服务器没有从上游DNS服务器获取到DNSSEC记录。
## 根本原因
当启用DNSSEC时DNS服务器需要在发送给上游服务器的请求中设置**DNSSEC OK (DO)标志**这样上游服务器才会返回DNSSEC记录如RRSIG、DNSKEY等。但当前代码直接使用原始请求发送给上游服务器没有添加DO标志。
## 修复方案
修改`forwardDNSRequestWithCache`函数,在向上游服务器发送请求之前:
1. 检查是否启用了DNSSEC
2. 如果启用为请求添加EDNS0选项并设置DO标志
3. 确保修改后的请求被正确发送
## 具体实现步骤
1.`/root/dns/dns/server.go`文件中,找到`forwardDNSRequestWithCache`函数
2. 在发送请求前第625行附近添加DO标志设置逻辑
3. 确保请求被正确发送到上游服务器
## 预期效果
修复后启用DNSSEC时服务器会向上游发送带有DO标志的请求上游服务器将返回DNSSEC记录从而实现完整的DNSSEC验证和记录返回。

View File

@@ -0,0 +1,82 @@
# DNSSEC功能修复计划
## 问题分析
当前DNSSEC实现存在以下问题
1. 当启用DNSSEC时系统只是验证上游服务器返回的DNSSEC签名但不会主动请求DNSSEC记录
2. 当上游服务器返回的响应没有DNSSEC记录时系统只是将其作为备选响应
3. 没有专门从8.8.8.8/1.1.1.1获取DNSSEC记录进行验证
4. 缓存时没有优先考虑DNSSEC记录
## 修复方案
### 1. 改进DNS请求转发逻辑
**修改文件:** `dns/server.go`
**修改函数:** `forwardDNSRequestWithCache`
- 当启用DNSSEC且响应中没有DNSSEC记录时主动向8.8.8.8/1.1.1.1发送DNS请求
- 比较不同服务器返回的结果优先使用带有DNSSEC记录的响应
- 如果DNSSEC结果不匹配优先使用8.8.8.8/1.1.1.1提供的解析记录
### 2. 增强DNSSEC验证机制
**修改文件:** `dns/server.go`
- 完善DNSSEC记录提取和验证逻辑
- 确保正确处理DNSKEY和RRSIG记录
- 改进AD标志Authenticated Data的设置
### 3. 优化缓存机制
**修改文件:** `dns/cache.go``dns/server.go`
- 缓存时标记DNSSEC状态
- 优先返回带有DNSSEC记录的缓存项
- 改进缓存键生成考虑DNSSEC属性
### 4. 增加DNSSEC特定服务器配置
**修改文件:** `config.json`
- 添加专门用于DNSSEC查询的服务器配置
- 默认为8.8.8.8和1.1.1.1
## 具体实现步骤
1. **修改`forwardDNSRequestWithCache`函数**
- 当启用DNSSEC且主响应没有DNSSEC记录时向DNSSEC专用服务器发送请求
- 比较所有响应选择最优结果优先DNSSEC记录其次是可靠服务器
- 实现DNSSEC结果验证和比较逻辑
2. **改进缓存获取逻辑**
-`handleDNSRequest`函数中优先检查是否有带有DNSSEC记录的缓存项
- 如果有,直接返回;否则再检查普通缓存项
3. **优化DNSSEC记录验证**
- 增强`verifyDNSSEC`函数的实现
- 确保正确验证所有RRSIG记录
- 改进错误处理和日志记录
4. **添加DNSSEC服务器配置**
- 在配置文件中添加`dnssecUpstreamDNS`配置项
- 默认值为["8.8.8.8:53", "1.1.1.1:53"]
## 测试计划
1. 启动DNS服务器启用DNSSEC
2. 使用`dig`命令测试DNSSEC记录获取
3. 验证带有DNSSEC记录的响应被正确返回
4. 验证缓存机制优先返回DNSSEC记录
5. 测试DNSSEC验证失败时的处理逻辑
## 预期效果
1. 启用DNSSEC后系统会主动请求并验证DNSSEC记录
2. 优先返回带有DNSSEC记录的解析结果
3. 当DNSSEC结果不匹配时优先使用8.8.8.8/1.1.1.1提供的记录
4. 缓存机制正确处理DNSSEC标记优先返回DNSSEC记录
5. 完善的日志记录,便于调试和监控
## 代码修改范围
- `dns/server.go`核心DNSSEC逻辑修改
- `dns/cache.go`:缓存机制优化
- `config.json`:配置项添加
通过以上修改将解决当前DNSSEC功能的问题确保启用DNSSEC后能够正确获取、验证和返回DNSSEC记录。

View File

@@ -0,0 +1,58 @@
# DNSSEC状态显示问题修复计划
## 问题分析
用户报告已在配置中启用DNSSEC`enableDNSSEC: true`但界面显示DNSSEC为禁用状态且使用率为0%。经过代码检查,发现问题出在`GetStats`函数中,该函数返回的`Stats`结构体缺少DNSSEC相关字段导致前端无法获取正确的DNSSEC状态和统计信息。
## 修复方案
### 1. 修复`GetStats`函数
**修改文件:** `dns/server.go`
**修改函数:** `GetStats`
**问题:** 当前`GetStats`函数返回的`Stats`结构体缺少DNSSEC相关字段包括
* `DNSSECEnabled`
* `DNSSECQueries`
* `DNSSECSuccess`
* `DNSSECFailed`
**解决方案:**`GetStats`函数返回的`Stats`结构体中添加所有DNSSEC相关字段确保前端能获取到正确的DNSSEC状态和统计数据。
## 具体实现步骤
1. **修改`GetStats`函数**
* 在返回的`Stats`结构体中添加`DNSSECEnabled`字段
* 添加`DNSSECQueries`字段
* 添加`DNSSECSuccess`字段
* 添加`DNSSECFailed`字段
2. **测试修复效果**
* 重新编译DNS服务器
* 启动服务器
* 使用API查询统计信息确认DNSSEC状态和统计数据正确返回
* 检查前端界面是否显示正确的DNSSEC状态
## 预期效果
1. 前端界面显示DNSSEC状态为"已启用"
2. DNSSEC使用率根据实际查询情况更新
3. 成功、失败和总查询数统计正确显示
4. 系统正常记录DNSSEC相关统计数据
## 代码修改范围
* `dns/server.go`:修复`GetStats`函数添加缺失的DNSSEC字段

View File

@@ -0,0 +1,52 @@
1. **修改QueryLog结构体**
*`dns/server.go`中的`QueryLog`结构体添加`ResponseCode`字段
2. **修改addQueryLog函数**
*`dns/server.go`中的`addQueryLog`函数添加`responseCode`参数
* 将响应代码记录到QueryLog结构体中
3. **修改DNS请求处理逻辑**
*`handleDNSRequest`函数中,获取实际的响应代码
* 将响应代码传递给`addQueryLog`函数
4. **修改前端模板**
*`static/js/logs.js`中,将响应代码的硬编码值"无"替换为从日志数据中获取的实际响应代码
* 添加响应代码映射,将数字响应代码转换为可读的字符串
5. **编译和测试**
* 重新编译项目
* 测试DNS查询详情中响应代码是否正确显示
**DNS响应代码映射**
* 0: NOERROR
* 1: FORMERR
* 2: SERVFAIL
* 3: NXDOMAIN
* 4: NOTIMP
* 5: REFUSED
* 6: YXDOMAIN
* 7: YXRRSET
* 8: NXRRSET
* 9: NOTAUTH
* 10: NOTZONE

View File

@@ -0,0 +1,42 @@
1. **调整DNS超时时间**
* 将配置文件中的`timeout`值从5毫秒增加到5000毫秒5秒
* 5毫秒的超时时间对于DNS查询来说太短导致大部分查询都超时失败
2. **优化查询模式**
* 将查询模式从`parallel`(并行)改为`loadbalance`(负载均衡)
* 并行模式在短超时时间下会导致大量超时,负载均衡模式更可靠
3. **检查上游DNS服务器配置**
* 确保所有配置的上游DNS服务器都能正常工作
* 移除或调整可能不可达的DNS服务器
4. **调整DNSSEC配置**
* 检查DNSSEC专用服务器的可达性
* 考虑暂时禁用DNSSEC验证观察是否能改善性能
5. **增强错误处理**
* 优化`forwardDNSRequestWithCache`函数的错误处理逻辑
* 确保在所有服务器都超时的情况下有合理的回退机制
6. **监控和日志优化**
* 添加更详细的日志记录每个DNS服务器的响应情况
* 增加监控指标追踪DNS查询成功率和响应时间
7. **测试验证**
* 在修改后进行DNS查询测试确保服务器能正常响应
* 监控日志确认不再出现大量DNS查询失败的情况

View File

@@ -0,0 +1,53 @@
## 问题分析
DNS服务器出现"Server Failed"的根本原因是当用户配置的DNS服务器地址没有包含端口号时代码直接将其传递给`dns.Client.Exchange()`方法,而该方法需要完整的"IP:端口"格式地址。
## 解决方案
### 1. 创建DNS服务器地址处理函数
- **功能**确保DNS服务器地址始终包含端口号默认添加53端口
- **实现**:创建`normalizeDNSServerAddress`函数,检查并添加端口号
### 2. 应用地址处理函数到所有DNS服务器配置
**需要修改的位置**
- **主DNS服务器**`s.config.UpstreamDNS`
- **DNSSEC专用服务器**`s.config.DNSSECUpstreamDNS`
- **域名特定DNS服务器**`s.config.DomainSpecificDNS`
- **所有调用`resolver.Exchange()`的地方**:确保传递的服务器地址包含端口号
### 3. 修改具体代码位置
**文件**`dns/server.go`
**修改点**
1. **添加地址处理函数**:在文件中添加`normalizeDNSServerAddress`函数
2. **在parallel模式中使用**修改第865行附近的代码
3. **在loadbalance模式中使用**修改第1063行附近的代码
4. **在fastest-ip模式中使用**修改第1189行附近的代码
5. **在default模式中使用**修改第1311行附近的代码
6. **在DNSSEC专用服务器请求中使用**修改第1452行附近的代码
7. **在本地解析中使用**修改第1550行附近的代码
### 4. 确保配置文件加载时也处理地址
- 检查配置文件加载代码确保在加载配置时就处理DNS服务器地址
- 或者在每次使用DNS服务器地址时动态处理
## 修复步骤
1. **创建地址处理函数**:实现`normalizeDNSServerAddress`函数
2. **修改所有DNS查询点**:在所有调用`resolver.Exchange()`的地方使用该函数
3. **测试修复效果**重启DNS服务器并测试查询功能
4. **验证各种配置场景**测试带端口和不带端口的DNS服务器配置
## 预期效果
- 当用户配置DNS服务器为`223.5.5.5`时,自动添加端口变为`223.5.5.5:53`
- 当用户配置DNS服务器为`8.8.8.8:53`时,保持不变
- DNS查询成功率显著提高不再出现"Server Failed"错误
- 支持各种DNS服务器配置格式提高系统兼容性
## 关键文件修改
- `/root/dns/dns/server.go`添加地址处理函数并应用到所有DNS查询点

View File

@@ -0,0 +1,52 @@
## 问题分析
当前DNS服务器的解析记录显示存在以下问题
1. 前端`logs.js`中使用了`console.log`来调试和显示解析记录
2. 需要确保API返回的解析记录是正确的JSON格式
3. 前端需要正确解析API返回的JSON数据来显示解析记录
## 解决方案
### 1. 优化API返回格式
**文件**`dns/server.go`
**修改内容**
- 确保`QueryLog`结构体的`Answers`字段正确序列化为JSON
- 检查`DNSAnswer`结构体的JSON标签是否正确
### 2. 清理前端console.log代码
**文件**`static/js/logs.js`
**修改内容**
- 删除或注释掉第1047、1054行等console.log调试代码
- 优化解析记录提取逻辑确保正确处理API返回的JSON数据
### 3. 优化解析记录显示逻辑
**文件**`static/js/logs.js`
**修改内容**
- 完善`extractDNSRecords`函数,确保正确处理各种格式的解析记录
- 优化解析记录的HTML渲染逻辑确保显示格式清晰
- 确保支持`log.answers`字段(小写)和`log.Answers`字段(大写)
### 4. 测试验证
**步骤**
- 重启DNS服务器
- 使用API测试工具验证`/api/logs/query`返回的解析记录格式正确
- 测试前端页面解析记录显示正常
## 预期效果
- API返回的解析记录格式为标准JSON
- 前端页面不再使用console.log显示解析记录
- 解析记录显示清晰、格式统一
- 支持各种情况下的解析记录提取
## 关键文件修改
1. **`dns/server.go`**:确保解析记录正确序列化
2. **`static/js/logs.js`**优化解析记录显示逻辑移除console.log代码

View File

@@ -0,0 +1,43 @@
## 问题分析
当前服务器代码存在以下问题:
1. `QueryLog`结构体中只有部分字段有JSON标签
2. 缺少完整的JSON序列化支持导致API返回的JSON格式不完整
3. 需要确保所有字段都能正确序列化为JSON
## 解决方案
### 1. 完善QueryLog结构体的JSON标签
**文件**`dns/server.go`
**修改内容**
-`QueryLog`结构体的所有字段添加正确的JSON标签
- 确保`Timestamp`字段正确序列化为ISO格式时间
- 确保`Answers`字段序列化为`"answers"`(小写)
### 2. 确保API返回完整的JSON数据
**文件**`http/server.go`
**修改内容**
- 检查`handleLogsQuery`函数,确保返回完整的日志数据
- 确保日志查询API返回包含所有必要字段的JSON数据
### 3. 测试验证
**步骤**
- 重启DNS服务器
- 使用API测试工具验证`/api/logs/query`返回的JSON格式正确
- 确保所有字段都正确序列化
## 预期效果
- API返回的JSON数据包含所有日志字段
- 前端能够正确解析API返回的JSON数据
- 解析记录通过API查询方式显示不再使用console.log
## 关键文件修改
1. **`dns/server.go`**:完善`QueryLog`结构体的JSON标签
2. **`http/server.go`**确保API返回完整的JSON数据

View File

@@ -0,0 +1,31 @@
## 问题分析
从用户提供的截图可以看到解析记录显示存在问题只显示了IP地址"104.26.24.30",而没有完整的解析记录格式,如"A: 104.26.24.30 (ttl=193)"。
## 根本原因
通过分析代码,发现问题可能出在以下几个方面:
1. 解析记录的显示样式可能存在问题
2. 或者在生成解析记录字符串时出现了问题
3. 或者是在处理`dnsAnswers`数组时出现了问题
## 修复方案
1. 修改解析记录的生成逻辑确保完整显示记录类型、值和TTL
2. 检查并调整HTML元素的样式确保多行文本正确显示
## 具体修改点
1. **修改解析记录的生成逻辑**
-`showLogDetailModal`函数中修改解析记录的生成逻辑确保即使记录类型或TTL为空也能正确显示
- 确保每个解析记录都按照"类型: 值 (ttl=TTL)"的格式显示
2. **调整HTML元素的样式**
- 检查并调整解析记录显示容器的样式,确保多行文本正确显示
- 确保`whitespace-pre-wrap`样式正确应用
## 修复原则
- 确保解析记录完整显示包括记录类型、值和TTL
- 保持良好的可读性
- 确保样式兼容各种浏览器
## 验证方法
1. 修复代码后,重新加载页面
2. 查看解析记录是否完整显示包括记录类型、值和TTL
3. 测试不同类型的解析记录,确保都能正确显示

View File

@@ -0,0 +1,34 @@
## 移除查询日志详情中的屏蔽规则列
### 1. 问题分析
- 用户要求移除查询日志详情弹窗中的屏蔽规则列
- 屏蔽规则列位于响应细节部分,显示在响应时间和响应代码之间
- 该列显示了DNS查询被屏蔽时的规则信息
### 2. 实现方案
- 编辑`showLogDetailModal`函数找到响应细节部分的HTML模板
- 移除其中包含"规则"标题和`${blockRule}`变量的整个div元素
- 保持其他响应细节(响应时间、响应代码、缓存状态)不变
### 3. 代码修改
- 修改文件:`/root/dns/static/js/logs.js`
- 修改函数:`showLogDetailModal`
- 移除位置:响应细节部分的`responseGrid` HTML模板
- 移除内容:包含"规则"标题和`${blockRule}`变量的div元素
### 4. 预期效果
- 查询日志详情弹窗中将不再显示屏蔽规则列
- 响应细节部分将只显示:响应时间、响应代码、缓存状态
- 保持弹窗的整体布局和样式不变
- 不影响其他功能的正常运行
### 5. 技术细节
- 使用HTML模板字符串修改DOM结构
- 移除不必要的DOM元素简化UI
- 保持代码的可读性和可维护性
### 6. 测试验证
- 验证修改后的代码是否有语法错误
- 验证查询日志详情弹窗是否正常显示
- 验证屏蔽规则列已被成功移除
- 验证其他功能是否正常工作

View File

@@ -0,0 +1,56 @@
## 移除查询日志详情中的屏蔽规则列
### 1. 问题分析
* 用户要求移除查询日志详情弹窗中的屏蔽规则列
* 屏蔽规则列位于响应细节部分,显示在响应时间和响应代码之间
* 该列显示了DNS查询被屏蔽时的规则信息
### 2. 实现方案
* 编辑`showLogDetailModal`函数找到响应细节部分的HTML模板
* 移除其中包含"规则"标题和`${blockRule}`变量的整个div元素
* 保持其他响应细节(响应时间、响应代码、缓存状态)不变
### 3. 代码修改
* 修改文件:`/root/dns/static/js/logs.js`
* 修改函数:`showLogDetailModal`
* 移除位置:响应细节部分的`responseGrid` HTML模板
* 移除内容:包含"规则"标题和`${blockRule}`变量的div元素
### 4. 预期效果
* 查询日志详情弹窗中将不再显示屏蔽规则列
* 响应细节部分将只显示:响应时间、响应代码、缓存状态
* 保持弹窗的整体布局和样式不变
* 不影响其他功能的正常运行
### 5. 技术细节
* 使用HTML模板字符串修改DOM结构
* 移除不必要的DOM元素简化UI
* 保持代码的可读性和可维护性
### 6. 测试验证
* 验证修改后的代码是否有语法错误
* 验证查询日志详情弹窗是否正常显示
* 验证屏蔽规则列已被成功移除
* 验证其他功能是否正常工作

View File

@@ -0,0 +1,51 @@
## 优化DNS请求处理逻辑减少返回客户端超时
### 1. 问题分析
* 服务器请求上游解析成功,但返回给客户端超时
* 主要原因是`forwardDNSRequestWithCache`函数等待所有上游服务器响应,导致某个慢服务器拖慢整体响应
* 虽然是并行查询,但没有实现快速响应返回机制
* 阻塞式等待所有响应完成,而不是优先返回最快的成功响应
### 2. 实现方案
* 优化`forwardDNSRequestWithCache`函数,实现快速响应返回机制
* 当收到第一个成功响应时,立即返回给客户端,不再等待其他服务器响应
* 保持后台继续接收其他响应,更新最佳响应和服务器状态
* 优化并行查询逻辑,提高响应速度
* 保持代码的可读性和可维护性
### 3. 代码修改
* 修改文件:`/root/dns/dns/server.go`
* 修改函数:`forwardDNSRequestWithCache`
* 优化位置:`parallel`模式和`default`模式下的响应处理逻辑
* 优化内容:
- 实现快速响应返回机制
- 当收到第一个成功响应时,立即返回给客户端
- 保持后台处理其他响应
- 优化并行查询逻辑
### 4. 预期效果
* 减少DNS查询的平均响应时间
* 避免因某个上游服务器响应慢而导致整体超时
* 提高DNS服务器的吞吐量和并发处理能力
* 保持对上游服务器状态的准确跟踪
* 不影响现有功能的正常运行
### 5. 技术细节
* 使用通道和goroutine实现非阻塞响应处理
* 当收到第一个成功响应时,立即返回给客户端
* 保持后台继续接收其他响应,更新最佳响应和服务器状态
* 优化并行查询逻辑,提高响应速度
* 保持代码的可读性和可维护性
### 6. 测试验证
* 验证修改后的代码是否有语法错误
* 验证DNS查询响应时间是否明显减少
* 验证是否解决了返回客户端超时的问题
* 验证其他功能是否正常工作
* 验证上游服务器状态跟踪是否准确

View File

@@ -0,0 +1,78 @@
## 优化DNS请求处理逻辑减少返回客户端超时
### 1. 问题分析
* 服务器请求上游解析成功,但返回给客户端超时
* 主要原因是`forwardDNSRequestWithCache`函数等待所有上游服务器响应,导致某个慢服务器拖慢整体响应
* 虽然是并行查询,但没有实现快速响应返回机制
* 阻塞式等待所有响应完成,而不是优先返回最快的成功响应
### 2. 实现方案
* 优化`forwardDNSRequestWithCache`函数,实现快速响应返回机制
* 当收到第一个成功响应时,立即返回给客户端,不再等待其他服务器响应
* 保持后台继续接收其他响应,更新最佳响应和服务器状态
* 优化并行查询逻辑,提高响应速度
* 保持代码的可读性和可维护性
### 3. 代码修改
* 修改文件:`/root/dns/dns/server.go`
* 修改函数:`forwardDNSRequestWithCache`
* 优化位置:`parallel`模式和`default`模式下的响应处理逻辑
* 优化内容:
* 实现快速响应返回机制
* 当收到第一个成功响应时,立即返回给客户端
* 保持后台处理其他响应
* 优化并行查询逻辑
### 4. 预期效果
* 减少DNS查询的平均响应时间
* 避免因某个上游服务器响应慢而导致整体超时
* 提高DNS服务器的吞吐量和并发处理能力
* 保持对上游服务器状态的准确跟踪
* 不影响现有功能的正常运行
### 5. 技术细节
* 使用通道和goroutine实现非阻塞响应处理
* 当收到第一个成功响应时,立即返回给客户端
* 保持后台继续接收其他响应,更新最佳响应和服务器状态
* 优化并行查询逻辑,提高响应速度
* 保持代码的可读性和可维护性
### 6. 测试验证
* 验证修改后的代码是否有语法错误
* 验证DNS查询响应时间是否明显减少
* 验证是否解决了返回客户端超时的问题
* 验证其他功能是否正常工作
* 验证上游服务器状态跟踪是否准确

View File

@@ -0,0 +1,20 @@
# 修复域名匹配机制问题
## 问题分析
通过详细检查domain-info.json文件我发现了问题的根本原因
- JSON文件的结构存在错误`domains`对象只包含了网易公司
- 其他公司(如阿里云、百度等)被错误地放在了`domains`对象之外
- 这导致域名匹配机制只能找到网易公司的信息,而无法匹配其他公司
## 修复计划
1. **修复JSON文件结构**:将所有公司信息正确地包含在`domains`对象中
2. **优化域名匹配逻辑**根据用户需求实现优先匹配完整URL域名再匹配主域名的逻辑
3. **测试修复效果**:验证所有公司的域名都能被正确匹配
## 预期效果
- 修复后的JSON文件结构正确所有公司都包含在`domains`对象中
- 域名匹配机制能够正确识别所有公司的域名
- 匹配规则:
- 优先匹配完整URL域名如baike.baidu.com
- 如果没有匹配上则匹配主域名如baidu.com
- 输出对应的公司名称(如北京百度网讯科技有限公司)

View File

@@ -0,0 +1,33 @@
## 问题分析
通过测试脚本的输出我发现了kdocs.cn无法匹配到域名信息的原因
1. **JSON结构错误**domain-info.json文件中字节跳动公司的结构存在错误导致解析后的对象结构不正确。
2. **遍历顺序问题**由于JSON结构错误当遍历到字节跳动公司时脚本没有正确跳过company属性而是继续处理字节跳动对象内部的属性然后遇到了一个名为"company"的公司这个公司的属性值是categories对象的值。
3. **遍历不完整**由于结构错误脚本在遍历到字节跳动公司后就无法继续遍历到金山办公公司而金山办公公司正是kdocs.cn所属的公司。
## 解决方案
### 1. 修复domain-info.json文件的结构
修复字节跳动公司的结构错误,确保其包含正确的闭合括号和逗号:
- 修复抖音视频对象的闭合括号
- 确保今日头条API服务和豆包对象是字节跳动公司的直接子对象
- 确保company属性是字节跳动公司的直接子属性
### 2. 测试修复效果
修复后重新运行测试脚本验证kdocs.cn和www.kdocs.cn能够正确匹配到金山办公公司的金山文档。
## 实施步骤
1. 修改domain-info.json文件修复字节跳动公司的结构错误
2. 运行test-fetch.js测试脚本验证修复效果
3. 确认kdocs.cn和www.kdocs.cn能够正确匹配到域名信息
## 预期效果
修复后kdocs.cn和www.kdocs.cn将能够正确匹配到金山办公公司的金山文档显示网站名称、图标、类别和所属公司。

View File

@@ -0,0 +1,32 @@
# 移除负载均衡查询模式
## 问题分析
用户要求移除负载均衡查询模式,目前代码中支持多种查询模式,包括 "loadbalance"(负载均衡)、"parallel"(并行请求)、"fastest-ip"最快的IP地址。负载均衡模式使用加权随机选择算法来选择上游服务器。
## 解决方案
1. 从配置中移除 "loadbalance" 作为可用选项
2. 从代码中移除 "loadbalance" 分支
3. 确保其他使用 `selectWeightedRandomServer` 函数的地方不受影响
## 实施步骤
1. 修改 `config/config.go` 文件,更新 `QueryMode` 字段的注释,移除 "loadbalance" 选项
2. 修改 `dns/server.go` 文件,移除 switch 语句中的 "loadbalance" 分支
3. 确保所有使用 `selectWeightedRandomServer` 函数的地方仍然正常工作
4. 测试修改后的代码,确保 DNS 服务器仍然正常运行
## 修改内容
- 文件:`/root/dns/config/config.go`
- 修改点:更新 `QueryMode` 字段的注释,移除 "loadbalance" 选项
- 文件:`/root/dns/dns/server.go`
- 修改点:移除 switch 语句中的 "loadbalance" 分支第1139-1260行
## 预期效果
- 负载均衡查询模式将不再可用
- DNS 服务器仍然支持其他查询模式parallel、fastest-ip
- 其他功能不受影响
- 代码更加简洁,减少了维护成本
## 注意事项
- `selectWeightedRandomServer` 函数不仅用于负载均衡模式,还用于选择 DNSSEC 服务器和本地服务器,所以不能删除这个函数
- 确保修改后所有其他功能仍然正常工作

View File

@@ -0,0 +1,32 @@
# 清理无关代码
## 问题分析
我已经成功移除了负载均衡查询模式的主要代码,但还有一些相关的残留代码需要清理,包括:
1. CHANGELOG.md文件中提到了loadbalance模式
2. 可能还有其他未使用的代码或配置
## 解决方案
1. 更新CHANGELOG.md文件移除或修改与loadbalance模式相关的条目
2. 检查是否有其他未使用的代码或配置
3. 确保所有修改都不会影响现有功能
## 实施步骤
1. 修改CHANGELOG.md文件移除或修改与loadbalance模式相关的条目
2. 检查是否有其他未使用的代码或配置
3. 编译并测试修改后的代码,确保功能正常
## 修改内容
- 文件:`/root/dns/CHANGELOG.md`
- 修改点1第106行移除或修改与loadbalance模式相关的条目
- 修改点2第112行移除或修改与loadbalance模式相关的条目
## 预期效果
- 代码库中不再有与已移除功能相关的残留代码
- 文档与实际代码保持一致
- 现有功能不受影响
- 代码库更加整洁,易于维护
## 注意事项
- 不要修改数据文件中的loadbalance相关规则这些是广告过滤规则不是代码
- 确保所有修改都不会影响现有功能
- 编译并测试修改后的代码,确保功能正常

View File

@@ -0,0 +1,113 @@
## 支持Base64编码GFWList格式的实现计划
### 问题分析
当前的GFWList加载代码直接按行解析文件内容无法处理Base64编码的GFWList格式。Base64编码的GFWList文件包含
1. 头部注释行(以!开头)
2. Base64编码的规则内容整个文件或主要部分
3. 可能的尾部注释
### 解决方案
修改`gfw/manager.go`中的`LoadRules`函数添加Base64解码支持
1. **检测Base64编码**
- 读取文件内容
- 跳过注释行
- 检查剩余内容是否为Base64编码
2. **解码Base64内容**
- 如果是Base64编码使用`encoding/base64`包解码
- 解码后得到原始规则文本
3. **解析规则**
- 按行分割解码后的内容
- 调用现有的`parseRule`函数处理每一行
### 具体修改点
1. **添加Base64依赖**
-`gfw/manager.go`中添加`encoding/base64`导入
2. **修改LoadRules函数**
- 读取文件内容
- 过滤注释行收集可能的Base64内容
- 尝试Base64解码
- 解析解码后的规则
3. **测试**
- 使用现有的Base64编码GFWList文件测试
- 确保解码和规则解析正常工作
### 预期效果
- 服务器能够正确加载Base64编码的GFWList文件
- 兼容现有的纯文本GFWList格式
- 规则解析结果与原格式一致
### 代码修改示例
```go
// 在import中添加encoding/base64
import (
// 现有导入
"encoding/base64"
// 现有导入
)
// 修改LoadRules函数
func (m *GFWListManager) LoadRules() error {
// 现有代码...
// 从文件路径读取GFWList内容
content, err := os.ReadFile(m.config.Content)
if err != nil {
return fmt.Errorf("读取GFWList文件失败: %w", err)
}
// 处理Base64编码
rawContent := string(content)
// 过滤注释行收集Base64内容
var base64Content strings.Builder
lines := strings.Split(rawContent, "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
if line == "" || strings.HasPrefix(line, "!") || strings.HasPrefix(line, "[") {
// 跳过注释行和头信息
continue
}
base64Content.WriteString(line)
}
// 尝试Base64解码
decoded, err := base64.StdEncoding.DecodeString(base64Content.String())
if err == nil {
// 解码成功,使用解码后的内容
rawContent = string(decoded)
} else {
// 解码失败,使用原始内容(可能是纯文本格式)
}
// 按行解析规则
ruleLines := strings.Split(rawContent, "\n")
for _, line := range ruleLines {
line = strings.TrimSpace(line)
if line == "" || strings.HasPrefix(line, "!") || strings.HasPrefix(line, "[") {
// 跳过空行、注释行和头信息行
continue
}
m.parseRule(line)
}
// 现有代码...
}
```
### 实施步骤
1. 修改`gfw/manager.go`添加Base64支持
2. 编译并测试
3. 验证规则加载是否正常
这个修改将使服务器能够同时支持纯文本和Base64编码的GFWList格式提高了兼容性和灵活性。

View File

@@ -0,0 +1,203 @@
# 平均响应时间计算错误修复方案
## 问题分析
通过对代码的分析,我发现平均响应时间计算错误的根本原因是:
1. **统计数据持久化问题**:当服务器重启时,`loadStatsData` 函数直接覆盖 `s.stats` 对象,导致 `TotalResponseTime``Queries` 之间的关系可能被破坏
2. **异常响应时间累计**:在某些情况下,`responseTime` 可能被错误计算为非常大的值,导致 `TotalResponseTime` 异常增长
3. **计算逻辑不健壮**:平均响应时间计算没有考虑异常情况,如 `Queries` 为 0 或 `TotalResponseTime` 溢出
4. **统计数据一致性问题**:并发访问时可能导致统计数据不一致
## 修复方案
### 1. 修复 `loadStatsData` 函数
修改统计数据加载逻辑,确保 `TotalResponseTime``Queries` 之间的关系正确:
```go
// 恢复统计数据
s.statsMutex.Lock()
if statsData.Stats != nil {
// 只恢复有效数据,避免破坏统计关系
s.stats.Queries += statsData.Stats.Queries
s.stats.Blocked += statsData.Stats.Blocked
s.stats.Allowed += statsData.Stats.Allowed
s.stats.Errors += statsData.Stats.Errors
s.stats.TotalResponseTime += statsData.Stats.TotalResponseTime
s.stats.DNSSECQueries += statsData.Stats.DNSSECQueries
s.stats.DNSSECSuccess += statsData.Stats.DNSSECSuccess
s.stats.DNSSECFailed += statsData.Stats.DNSSECFailed
// 重新计算平均响应时间,确保一致性
if s.stats.Queries > 0 {
s.stats.AvgResponseTime = float64(s.stats.TotalResponseTime) / float64(s.stats.Queries)
}
// 合并查询类型统计
for k, v := range statsData.Stats.QueryTypes {
s.stats.QueryTypes[k] += v
}
// 合并来源IP统计
for ip := range statsData.Stats.SourceIPs {
s.stats.SourceIPs[ip] = true
}
// 确保使用当前配置中的EnableDNSSEC值
s.stats.DNSSECEnabled = s.config.EnableDNSSEC
}
s.statsMutex.Unlock()
```
### 2. 修复响应时间计算逻辑
`handleDNSRequest` 函数中,添加响应时间合理性检查:
```go
// 使用上游服务器的实际响应时间(转换为毫秒)
responseTime := int64(rtt.Milliseconds())
// 如果rtt为0查询失败则使用本地计算的时间
if responseTime == 0 {
responseTime = time.Since(startTime).Milliseconds()
}
// 添加合理性检查,避免异常大的响应时间影响统计
if responseTime > 60000 { // 超过60秒的响应时间视为异常
responseTime = 60000
}
```
### 3. 优化平均响应时间计算
修改 `updateStats` 函数,确保平均响应时间计算的健壮性:
```go
s.updateStats(func(stats *Stats) {
stats.TotalResponseTime += responseTime
// 添加防御性编程确保Queries大于0
if stats.Queries > 0 {
// 使用更精确的计算方式,避免浮点数精度问题
stats.AvgResponseTime = float64(stats.TotalResponseTime) / float64(stats.Queries)
// 限制平均响应时间的范围,避免显示异常大的值
if stats.AvgResponseTime > 60000 {
stats.AvgResponseTime = 60000
}
}
})
```
### 4. 添加统计数据重置机制
添加定期重置统计数据的功能,避免 `TotalResponseTime` 无限增长:
```go
// Start 启动DNS服务器
func (s *Server) Start() error {
// 现有代码...
// 启动统计数据定期重置功能每24小时
go func() {
ticker := time.NewTicker(24 * time.Hour)
defer ticker.Stop()
for {
select {
case <-ticker.C:
s.resetStats()
case <-s.ctx.Done():
return
}
}
}()
// 现有代码...
}
// resetStats 重置统计数据
func (s *Server) resetStats() {
s.statsMutex.Lock()
defer s.statsMutex.Unlock()
// 只重置累计值,保留配置相关值
s.stats.TotalResponseTime = 0
s.stats.AvgResponseTime = 0
s.stats.Queries = 0
s.stats.Blocked = 0
s.stats.Allowed = 0
s.stats.Errors = 0
s.stats.DNSSECQueries = 0
s.stats.DNSSECSuccess = 0
s.stats.DNSSECFailed = 0
s.stats.QueryTypes = make(map[string]int64)
s.stats.SourceIPs = make(map[string]bool)
logger.Info("统计数据已重置")
}
```
### 5. 修复 GetStats 函数
确保 `GetStats` 函数正确复制所有统计数据:
```go//
func (s *Server) GetStats() *Stats {
s.statsMutex.Lock()
defer s.statsMutex.Unlock()
// 创建完整的统计数据副本
statsCopy := &Stats{
Queries: s.stats.Queries,
Blocked: s.stats.Blocked,
Allowed: s.stats.Allowed,
Errors: s.stats.Errors,
LastQuery: s.stats.LastQuery,
AvgResponseTime: s.stats.AvgResponseTime,
TotalResponseTime: s.stats.TotalResponseTime,
QueryTypes: make(map[string]int64),
SourceIPs: make(map[string]bool),
CpuUsage: s.stats.CpuUsage,
DNSSECQueries: s.stats.DNSSECQueries,
DNSSECSuccess: s.stats.DNSSECSuccess,
DNSSECFailed: s.stats.DNSSECFailed,
DNSSECEnabled: s.stats.DNSSECEnabled,
}
// 复制查询类型统计
for k, v := range s.stats.QueryTypes {
statsCopy.QueryTypes[k] = v
}
// 复制来源IP统计
for ip := range s.stats.SourceIPs {
statsCopy.SourceIPs[ip] = true
}
return statsCopy
}
```
## 修复效果
1. **数据一致性**:修复后,`TotalResponseTime` 和 `Queries` 之间的关系将保持正确,避免因服务器重启导致的统计数据不一致
2. **异常值处理**:添加响应时间合理性检查,避免异常大的响应时间影响平均响应时间计算
3. **计算健壮性**:优化平均响应时间计算逻辑,添加防御性编程,确保计算结果合理
4. **统计数据管理**:添加定期重置统计数据的功能,避免 `TotalResponseTime` 无限增长导致的溢出问题
5. **并发安全**:确保所有统计数据操作都是线程安全的,避免并发访问导致的数据不一致
## 实现步骤
1. 修改 `loadStatsData` 函数,修复统计数据加载逻辑
2. 修改 `handleDNSRequest` 函数,添加响应时间合理性检查
3. 修改 `updateStats` 函数,优化平均响应时间计算
4. 添加 `resetStats` 函数,实现统计数据重置功能
5. 修改 `Start` 函数,启动定期重置统计数据的协程
6. 修复 `GetStats` 函数,确保正确复制所有统计数据
7. 测试修复效果,验证平均响应时间计算是否正确

View File

@@ -0,0 +1,46 @@
## GFWList管理页面实现计划
### 1. 修改 `index.html`
- 在侧边栏菜单(两个位置:桌面端和移动端)添加新的菜单项"GFWList管理"
- 创建新的页面内容区域 `#gfwlist-content`
- 添加配置选项:
- GFWList总开关checkbox
- GFWList解析目标IP输入框
- 通行网站开关组谷歌、YouTube、Facebook、X各checkbox
- 添加保存和重启服务按钮
### 2. 修改 `main.js`
- 在页面标题映射中添加 `'gfwlist': 'GFWList管理'`
-`contentSections` 数组中添加 `gfwlist-content`
- 添加hash为'gfwlist'时的页面初始化逻辑
### 3. 修改 `config.js`
- 添加GFWList页面初始化函数 `initGFWListPage()`
- 添加GFWList配置加载函数 `loadGFWListConfig()`
- 添加GFWList配置保存函数 `saveGFWListConfig()`
- 添加GFWList配置收集函数 `collectGFWListFormData()`
- 更新 `collectFormData()` 以包含新的GFWList配置字段
- 更新 `populateConfigForm()` 移除原有的GFWList配置已迁移到独立页面
### 4. 修改 `api.js`
- 添加GFWList专用的API方法如需要
### 配置数据结构
```json
{
"gfwlist": {
"enabled": true,
"targetIP": "127.0.0.1",
"allowGoogle": true,
"allowYouTube": true,
"allowFacebook": true,
"allowTwitter": true
}
}
```
### 实现顺序
1. 先修改HTML添加页面结构和菜单
2. 修改main.js添加导航支持
3. 修改config.js添加前端逻辑
4. 测试验证

View File

@@ -0,0 +1,39 @@
## 实现DNSSEC支持的计划
### 1. 分析当前代码
- 配置文件中已经包含了DNSSEC相关配置项`EnableDNSSEC``DNSSECValidation`
- DNS客户端resolver目前没有启用DNSSEC支持
- 需要修改代码以实现DNSSEC功能
### 2. 实现步骤
#### 步骤1修改DNS客户端配置
-`NewServer` 函数中修改DNS客户端配置添加 `DNSSEC: true` 以启用DNSSEC查询
- 确保客户端支持DNSSEC记录类型RRSIG, DNSKEY, DS等
#### 步骤2添加DNSSEC验证逻辑
-`forwardDNSRequestWithCache` 函数中检查上游服务器返回的响应是否包含DNSSEC签名
- 如果启用了DNSSEC验证验证签名的有效性
- 处理验证失败的情况,返回适当的错误响应
#### 步骤3确保DNS响应包含DNSSEC记录
- 当转发DNS响应时确保包含所有相关的DNSSEC记录
- 确保响应中的DNSSEC标志正确设置
#### 步骤4添加DNSSEC相关的日志记录
- 记录DNSSEC验证结果
- 记录DNSSEC相关的错误信息
### 3. 预期结果
- DNS服务器将支持DNSSEC查询
- 可以验证DNS记录的真实性和完整性
- 防止DNS投毒和劫持攻击
- 提供DNSSEC相关的配置选项
### 4. 文件修改
- `/root/dns/dns/server.go`修改DNS客户端配置和添加DNSSEC验证逻辑
### 5. 技术细节
- 使用miekg/dns库的内置DNSSEC支持
- 确保DNSSEC验证符合RFC标准
- 处理各种DNSSEC相关的错误情况

View File

@@ -0,0 +1,84 @@
## 实现计划
### 1. 配置更新
-`DNSConfig` 结构体中添加 `EnableDNSSEC` 布尔字段用于控制是否启用DNSSEC验证
- 在配置加载时设置默认值为 `true`
- 在默认配置JSON中添加DNSSEC相关配置项
### 2. DNSSEC核心功能实现
- **DO标志处理**识别并保留客户端请求中的DNSSEC OK (DO) 标志
- **记录转发**确保所有DNSSEC相关记录RRSIG, DNSKEY, DS, NSEC, NSEC3等被正确转发
- **签名验证**验证上游DNS服务器返回的DNSSEC签名有效性
- **AD标志设置**根据验证结果设置Authenticated Data (AD) 标志
### 3. 代码修改点
#### 3.1 配置文件 (`config/config.go`)
```go
// DNSConfig DNS配置
type DNSConfig struct {
Port int `json:"port"`
UpstreamDNS []string `json:"upstreamDNS"`
Timeout int `json:"timeout"`
StatsFile string `json:"statsFile"` // 统计数据持久化文件
SaveInterval int `json:"saveInterval"` // 数据保存间隔(秒)
EnableDNSSEC bool `json:"enableDNSSEC"` // 是否启用DNSSEC验证
}
```
#### 3.2 默认配置 (`main.go`)
在默认配置JSON中添加
```json
"enableDNSSEC": true
```
#### 3.3 DNS服务器初始化 (`dns/server.go`)
-`NewServer` 方法中为DNS客户端启用DNSSEC支持
- 初始化DNSSEC验证相关组件
#### 3.4 DNS请求处理 (`dns/server.go`)
- 修改 `handleDNSRequest` 方法保留客户端请求中的DO标志
- 修改 `forwardDNSRequest` 方法:
- 确保转发请求时包含DO标志
- 处理上游返回的DNSSEC记录
- 验证DNSSEC签名
- 根据验证结果设置AD标志
- 确保所有DNSSEC记录类型被正确处理
### 4. DNSSEC验证逻辑
- 使用miekg/dns库的内置验证功能
- 验证RRSIG记录与对应资源记录的匹配性
- 验证签名的有效性和过期时间
- 处理信任链验证
### 5. 测试验证
- 测试DNSSEC查询是否能正确返回RRSIG等记录
- 测试DNSSEC验证功能是否正常工作
- 测试在不同配置下的行为
- 测试各种DNSSEC记录类型的处理
## 预期效果
-`enableDNSSEC``true` 时:
- 服务器将验证上游DNS返回的DNSSEC记录
- 对于有效的DNSSEC记录服务器将在响应中设置AD标志
- 对于无效的DNSSEC记录服务器将记录错误并根据配置处理
- 服务器将正确转发所有DNSSEC相关记录
- 支持DNSKEY, DS, RRSIG, NSEC, NSEC3等DNSSEC记录类型
- 客户端可以通过设置DO标志来请求DNSSEC记录
## 安全增强
通过添加DNSSEC支持服务器将能够
- 防止DNS投毒攻击
- 确保DNS记录的完整性和真实性
- 为客户端提供经过验证的DNS响应
- 增强整体DNS服务的安全性
## 实现步骤
1. **修改配置结构**
2. **更新默认配置**
3. **修改DNS客户端设置**
4. **实现DNSSEC验证逻辑**
5. **测试和验证**

View File

@@ -0,0 +1,60 @@
## 实现计划优化DNSSEC查询逻辑
### 1. 需求分析
- 当配置文件中`enableDNSSEC=true`DNS服务器应优先返回包含DNSSEC记录的结果
- 如果没有DNSSEC结果应返回普通查询结果作为备选
- 保持现有代码结构和兼容性
### 2. 实现步骤
#### 步骤1修改`forwardDNSRequestWithCache`函数
- 在函数中添加备选响应变量用于存储非DNSSEC的成功响应
-`enableDNSSEC=true`遍历所有上游DNS服务器
- 对于每个上游,检查响应是否成功
- 如果响应成功且包含DNSSEC记录立即返回该响应
- 如果响应成功但不包含DNSSEC记录将其保存为备选响应
- 遍历完成后,如果有备选响应,返回该响应
- 如果没有成功响应,返回服务器失败错误
#### 步骤2添加DNSSEC记录检测逻辑
- 在响应处理中添加DNSSEC记录检测
- 检查响应的Answer、Ns和Extra部分是否包含RRSIG记录
- 使用该检测结果决定是否优先返回该响应
#### 步骤3优化日志记录
- 为DNSSEC优先返回的情况添加专门的日志记录
- 为备选响应返回的情况添加日志记录
### 3. 技术细节
#### 3.1 DNSSEC检测方法
- 检查响应中是否包含RRSIG资源记录签名记录
- 检查范围包括Answer、Ns和Extra部分
- 使用类型断言判断记录类型
#### 3.2 优先级逻辑
- 最高优先级成功且包含DNSSEC的响应
- 次高优先级成功但不包含DNSSEC的响应
- 最低优先级:失败响应
### 4. 预期效果
- 当启用DNSSEC时优先返回安全的DNSSEC结果
- 提高DNS查询的安全性
- 兼容现有配置和代码
- 提供详细的日志记录
### 5. 文件修改
- **文件**`/root/dns/dns/server.go`
- **函数**`forwardDNSRequestWithCache`
- **修改内容**添加DNSSEC优先逻辑和备选响应处理
### 6. 测试要点
- 验证启用DNSSEC时优先返回DNSSEC结果
- 验证无DNSSEC结果时返回普通结果
- 验证禁用DNSSEC时使用原有逻辑
- 验证日志记录正确
### 7. 实现时间线
- 代码修改20分钟
- 测试10分钟
- 总计30分钟

View File

@@ -0,0 +1,86 @@
# 优化DNS服务器parallel模式响应时间
## 问题分析
经过对代码的分析我发现parallel模式下响应时间过高的主要原因包括
1. **缺少超时机制**:当前实现会等待所有上游服务器响应,单个慢服务器会拖慢整个查询
2. **响应时间计算不合理**:使用所有响应的平均时间,而不是最快响应时间
3. **合并响应开销大**需要合并所有响应增加CPU和内存开销
4. **等待所有响应**:没有实现快速返回机制,即使收到第一个有效响应也会等待所有响应
5. **DNSSEC验证开销**每个响应都需要进行DNSSEC验证增加额外开销
## 优化方案
### 1. 添加超时机制
- 为每个上游服务器请求添加超时设置
- 超时时间可配置建议默认500ms
- 超时的请求不会影响整体响应时间
### 2. 实现快速返回机制
- 当收到第一个有效响应成功或NXDOMAIN立即返回给客户端
- 继续处理其他响应用于合并和缓存,但不影响当前查询的响应时间
- 优先返回带DNSSEC的响应
### 3. 优化响应时间计算
- 使用最快的响应时间作为查询的响应时间
- 保留平均响应时间用于统计,但不影响客户端感知的响应时间
### 4. 优化响应合并逻辑
- 只合并成功响应,忽略错误响应
- 合并时优先保留TTL较长的记录
- 减少不必要的内存分配和拷贝
### 5. 优化DNSSEC验证
- 只对需要返回的响应进行DNSSEC验证
- 缓存DNSSEC验证结果减少重复验证
### 6. 增加服务器健康检查
- 定期检查上游服务器的响应时间和可用性
- 只向健康的服务器发送请求
- 根据历史响应时间动态调整服务器权重
## 实现步骤
1. **修改forwardDNSRequestWithCache函数**
- 添加超时设置
- 实现快速返回逻辑
- 优化响应时间计算
2. **修改mergeResponses函数**
- 优化合并逻辑,减少开销
- 优先保留TTL较长的记录
3. **修改DNSSEC验证逻辑**
- 只对需要返回的响应进行验证
- 添加DNSSEC验证结果缓存
4. **添加服务器健康检查机制**
- 定期检查上游服务器
- 动态调整服务器列表
5. **添加配置选项**
- 超时时间配置
- 快速返回开关
- 健康检查配置
## 预期效果
- **响应时间显著降低**:客户端感知的响应时间将接近最快的上游服务器响应时间
- **资源利用率提高**:减少不必要的等待和计算
- **鲁棒性增强**:单个慢服务器不会影响整体性能
- **用户体验改善**更快的DNS解析速度
## 文件修改
- `/root/dns/dns/server.go`主要修改文件包含parallel模式的实现逻辑
- `/root/dns/config/config.go`:添加新的配置选项
- `/root/dns/dns/cache.go`如果需要添加DNSSEC验证结果缓存
## 测试计划
1. **性能测试**:比较优化前后的响应时间
2. **压力测试**:在高并发情况下测试性能
3. **可靠性测试**:测试单个服务器故障时的表现
4. **DNSSEC测试**确保DNSSEC验证仍然正常工作
5. **不同配置测试**:测试不同超时时间和服务器数量的影响

View File

@@ -0,0 +1,84 @@
# 优化设置界面实现计划
## 问题分析
当前设置界面存在配置项重复问题,需要进行优化,具体包括:
1. "远程规则URL"配置项在多个界面重复出现
2. "启用API"和"主机"选项不需要在当前界面显示
3. 需要确保保存功能正常工作写入config.json并触发服务器重新加载配置
## 优化方案
### 1. 修改HTML结构
- 移除"远程规则URL"配置项
- 移除"启用API"选项
- 移除"主机"选项
- 调整布局,确保界面美观合理
### 2. 更新JavaScript代码
- 修改`populateConfigForm`函数,移除对已删除配置项的处理
- 修改`collectFormData`函数,移除对已删除配置项的收集
- 确保保存功能能正确写入config.json文件
- 实现服务器重新加载配置的触发机制
- 提供明确的成功/失败反馈
### 3. 测试和验证
- 测试所有保留配置项的加载和保存功能
- 验证保存操作能正确写入config.json文件
- 验证服务器能重新加载配置
- 测试成功/失败反馈是否明确
## 具体实现步骤
1. **修改HTML结构**
- 编辑`index.html`文件,移除不需要的配置项
- 调整布局,确保界面美观合理
2. **更新JavaScript代码**
- 编辑`config.js`文件,修改`populateConfigForm`函数
- 修改`collectFormData`函数,移除对已删除配置项的处理
- 确保`handleSaveConfig`函数能正确保存配置
- 实现服务器重新加载配置的触发机制
3. **测试和验证**
- 测试配置项的加载功能
- 测试配置项的保存功能
- 验证config.json文件是否正确更新
- 验证服务器是否重新加载配置
- 测试成功/失败反馈是否明确
## 预期效果
- 设置界面布局合理,无重复配置项
- 所有保留配置项均可正常配置
- 保存功能能正确写入config.json文件
- 服务器能重新加载配置,使更改立即生效
- 保存操作有明确的成功/失败反馈
## 技术要点
- 使用HTML和JavaScript修改界面结构和功能
- 确保与服务器API的正确交互
- 实现良好的用户反馈机制
- 确保配置的正确保存和加载
## 实现时间
- 预计1-2小时完成所有修改和测试
## 风险评估
- 低风险:修改范围明确,不涉及核心功能
- 可回滚:所有修改均为前端修改,可通过恢复文件轻松回滚
## 依赖关系
- 依赖服务器API的正常工作
- 依赖config.json文件的读写权限
## 测试策略
- 手动测试所有配置项的加载和保存功能
- 验证config.json文件的更新
- 测试服务器配置的重新加载
- 测试成功/失败反馈
## 验收标准
- 设置界面布局合理,无重复配置项
- 所有保留配置项均可正常配置
- 保存功能能正确写入config.json文件
- 服务器能重新加载配置,使更改立即生效
- 保存操作有明确的成功/失败反馈

View File

@@ -0,0 +1,22 @@
## 问题分析
CPU使用率卡片在WebSocket实时更新时没有刷新数据原因是
1. `processRealTimeData`函数调用了`updateStatsCards(stats)`但该函数的CPU使用率更新逻辑可能没有被正确执行
2. `processRealTimeData`函数对其他卡片如平均响应时间、最常用查询类型、活跃IP数有单独的更新逻辑但缺少了CPU使用率卡片的更新逻辑
3. `loadDashboardData`函数中有完整的CPU使用率更新逻辑这就是为什么页面初始加载时CPU使用率能显示但后续WebSocket更新时不能显示的原因
## 修复方案
1. **在`processRealTimeData`函数中添加CPU使用率卡片的更新逻辑**:类似于`loadDashboardData`函数中的实现
2. **确保从`stats`对象中正确获取CPU使用率数据**支持从不同的数据结构中获取CPU使用率
3. **更新DOM元素**将获取到的CPU使用率数据更新到`cpu-usage``cpu-status`元素中
4. **添加状态判断**根据CPU使用率值设置不同的状态文本和样式
## 实现步骤
1. 打开`dashboard.js`文件
2. 找到`processRealTimeData`函数约第120行
3. 在函数末尾添加CPU使用率更新逻辑位于其他卡片更新逻辑之后
4. 确保从`stats`对象中正确获取CPU使用率数据
5. 更新`cpu-usage``cpu-status`元素的内容和样式
6. 测试修复是否生效
## 预期效果
修复后当WebSocket接收到实时数据更新时CPU使用率卡片会自动更新显示最新的CPU使用率和状态与其他统计卡片保持一致的实时更新效果。

View File

@@ -0,0 +1,22 @@
## 问题分析
CPU使用率卡片在WebSocket实时更新时没有刷新数据原因是
1. `updateStatsCards`函数中数组形式的数据结构处理部分第631-641行缺少CPU使用率的处理逻辑
2. 可能存在数据字段名不匹配的问题WebSocket服务器返回的CPU使用率数据可能使用了不同的字段名
3. `processRealTimeData`函数和`updateStatsCards`函数中都有CPU使用率更新逻辑可能导致冲突或其中一个逻辑没有被正确执行
## 修复方案
1. **完善`updateStatsCards`函数的CPU使用率处理逻辑**在数组形式的数据结构处理部分添加CPU使用率的处理逻辑
2. **添加更多可能的CPU使用率字段名支持**确保从WebSocket服务器返回的CPU使用率数据能够被正确获取无论它使用什么字段名
3. **统一CPU使用率更新逻辑**:确保`processRealTimeData`函数和`updateStatsCards`函数中的CPU使用率更新逻辑一致
4. **添加调试日志**:在关键位置添加调试日志,以便于排查问题
## 实现步骤
1. 打开`dashboard.js`文件
2. 找到`updateStatsCards`函数的数组形式数据结构处理部分第631-641行添加CPU使用率的处理逻辑
3.`updateStatsCards`函数的CPU使用率数据获取逻辑中添加更多可能的字段名支持
4. 统一`processRealTimeData`函数和`updateStatsCards`函数中的CPU使用率更新逻辑
5. 添加调试日志,以便于排查问题
6. 测试修复是否生效
## 预期效果
修复后当WebSocket接收到实时数据更新时CPU使用率卡片会自动更新显示最新的CPU使用率和状态与其他统计卡片保持一致的实时更新效果。

View File

@@ -0,0 +1,18 @@
## 问题分析
CPU使用率卡片数据不会跟随WebSocket自动更新的原因是`updateStatsCards`函数中缺少了CPU使用率的更新逻辑。该函数负责处理WebSocket实时数据并更新统计卡片但只更新了7个统计卡片遗漏了CPU使用率卡片。
## 修复方案
1. **修改`updateStatsCards`函数**:在`dashboard.js`文件中添加CPU使用率和状态的更新逻辑
2. **添加数据获取逻辑**从不同可能的数据结构中获取CPU使用率数据
3. **更新DOM元素**将获取到的CPU使用率数据更新到`cpu-usage``cpu-status`元素中
4. **添加状态判断**根据CPU使用率值设置不同的状态文本和样式
## 实现步骤
1. 打开`dashboard.js`文件
2. 找到`updateStatsCards`函数约第550行
3. 在函数末尾添加CPU使用率更新逻辑
4. 确保从`stats`对象中正确获取CPU使用率数据
5. 更新`cpu-usage``cpu-status`元素的内容和样式
## 预期效果
修复后当WebSocket接收到实时数据更新时CPU使用率卡片会自动更新显示最新的CPU使用率和状态与其他统计卡片保持一致的实时更新效果。

View File

@@ -0,0 +1,38 @@
## 问题分析
1. **配置正确**:配置文件中`enableDNSSEC`设置为`true`,但卡片显示"已禁用"
2. **代码问题**:在`dns/server.go``GetStats`函数中,返回的`Stats`结构体缺少了DNSSEC相关字段
3. **API行为**当API访问DNSSEC相关字段时由于没有从`GetStats`函数返回,它们的值都是默认值(`DNSSECEnabled`默认值为`false`
4. **前端显示**前端卡片从API获取`DNSSECEnabled`值,因此显示"已禁用"
## 解决方案
修改`dns/server.go`中的`GetStats`函数,确保返回的`Stats`副本包含所有DNSSEC相关字段包括`DNSSECEnabled``DNSSECQueries``DNSSECSuccess``DNSSECFailed`
## 修复步骤
1. 打开`/root/dns/dns/server.go`文件
2. 找到`GetStats`函数大约在第960行
3. 修改返回的`Stats`结构体添加缺失的DNSSEC相关字段
4. 确保所有DNSSEC字段都从原始`Stats`结构体复制到返回的副本中
## 预期结果
修复后API将正确返回DNSSEC启用状态前端卡片将显示"已启用",与配置文件中的设置一致。
## 代码修改点
```go
// 返回统计信息的副本
return &Stats{
Queries: s.stats.Queries,
Blocked: s.stats.Blocked,
Allowed: s.stats.Allowed,
Errors: s.stats.Errors,
LastQuery: s.stats.LastQuery,
AvgResponseTime: s.stats.AvgResponseTime,
TotalResponseTime: s.stats.TotalResponseTime,
QueryTypes: queryTypesCopy,
SourceIPs: sourceIPsCopy,
CpuUsage: s.stats.CpuUsage,
DNSSECQueries: s.stats.DNSSECQueries,
DNSSECSuccess: s.stats.DNSSECSuccess,
DNSSECFailed: s.stats.DNSSECFailed,
DNSSECEnabled: s.stats.DNSSECEnabled, // 这是关键字段,确保返回正确的启用状态
}
```

View File

@@ -0,0 +1,22 @@
## 问题分析
`/root/dns/dns/server.go`文件的`forwardDNSRequestWithCache`函数中,`dnssecSuccess`变量被声明和赋值,但没有被实际使用,导致编译错误:
```
dns/server.go:622:6: declared and not used: dnssecSuccess
```
## 代码检查
1. 变量在第622行声明`var dnssecSuccess bool = false`
2. 在第708行和第714行被赋值`dnssecSuccess = false``dnssecSuccess = true`
3. 但在整个函数中,该变量没有被任何条件判断或返回值使用
4. 实际使用的是`signatureValid`变量来表示DNSSEC验证结果
## 解决方案
删除未使用的`dnssecSuccess`变量,因为它的值与`signatureValid`完全相同,且没有被实际使用。
## 修复步骤
1. 删除第622行的`dnssecSuccess`变量声明
2. 删除第708行和第714行对`dnssecSuccess`变量的赋值
3. 保留`signatureValid`变量的使用因为它是实际用于判断DNSSEC验证结果的变量
## 预期结果
修复后编译器不再报错DNSSEC验证逻辑保持不变继续正常工作。

View File

@@ -0,0 +1,20 @@
### 问题分析
1. **收集验证记录集不完整**在DNSSEC验证过程中代码只从`response.Answer``response.Ns`中收集记录,而忽略了`response.Extra`中的记录导致某些DNSSEC记录没有被正确验证。
2. **验证失败处理不当**当DNSSEC签名验证失败时代码会直接丢弃该响应而不是返回包含DNSSEC记录的响应导致客户端无法获取DNSSEC记录。
### 修复方案
1. **修复记录集收集逻辑**在收集需要验证的记录集rrset确保从`response.Answer``response.Ns``response.Extra`中收集所有相关记录。
2. **改进验证失败处理**即使DNSSEC签名验证失败也要返回包含DNSSEC记录的响应同时设置正确的AD标志让客户端决定如何处理验证失败的情况。
3. **优化备选响应逻辑**确保在所有上游服务器都不返回DNSSEC记录时仍然能够正确处理和返回响应。
### 具体修改
1. 修改`forwardDNSRequestWithCache`函数中的记录集收集逻辑,添加对`response.Extra`的处理
2. 修改DNSSEC验证失败时的处理逻辑确保返回包含DNSSEC记录的响应
3. 优化备选响应的保存和返回逻辑确保DNSSEC记录能够被正确处理
### 测试计划
1. 编译修复后的代码
2. 启动DNS服务器并启用DNSSEC
3. 使用dig命令测试DNSSEC记录查询例如`dig +dnssec example.com`
4. 检查查询结果是否包含DNSSEC记录RRSIG、DNSKEY等
5. 检查日志中是否有DNSSEC验证相关的记录

View File

@@ -0,0 +1,182 @@
## 问题分析
通过深入分析代码,我找到了导致所有查询都显示同一个 NXDOMAIN 错误的根本原因:
**核心问题**`mergeResponses` 函数在合并多个 DNS 响应时,**没有正确处理 Rcode 字段**
**具体原因**
1. 当使用并行查询模式时DNS 服务器会向多个上游服务器发送请求
2. 函数使用第一个响应作为基础来合并其他响应
3. 它清空了 `Answer``Ns``Extra` 字段,但**保留了第一个响应的 Rcode**
4. 如果第一个响应返回 NXDOMAIN比如对于恶意域名 www.evilsnssdk.com那么**合并后的响应也会保持 NXDOMAIN 状态**,即使其他响应返回成功
5. 这导致所有查询都显示同一个 NXDOMAIN 错误
## 修复方案
### 修复 `mergeResponses` 函数
**关键修改点**
1. **重置 Rcode**:在合并响应前,将 Rcode 重置为成功状态
2. **处理 NXDOMAIN**:只有当所有响应都是 NXDOMAIN 时,才返回 NXDOMAIN
3. **优先使用成功响应**:如果有任何响应返回成功,就使用成功的 Rcode
### 修复步骤
1. **修改 `mergeResponses` 函数** (`/root/dns/dns/server.go:842-933`)
- 在合并记录前,将 `mergedResponse.Rcode` 设置为 `dns.RcodeSuccess`
- 添加变量 `allNXDOMAIN` 来跟踪是否所有响应都是 NXDOMAIN
- 遍历所有响应,检查是否有成功响应
- 如果所有响应都是 NXDOMAIN才将 `mergedResponse.Rcode` 设置为 `dns.RcodeNameError`
2. **优化合并逻辑**
- 确保优先使用成功响应中的记录
- 避免将 NXDOMAIN 响应的记录合并到成功响应中
- 保持响应的一致性Rcode 与记录内容匹配
## 修复代码
```go
// mergeResponses 合并多个DNS响应
func mergeResponses(responses []*dns.Msg) *dns.Msg {
if len(responses) == 0 {
return nil
}
// 如果只有一个响应,直接返回,避免不必要的合并操作
if len(responses) == 1 {
return responses[0].Copy()
}
// 使用第一个响应作为基础
mergedResponse := responses[0].Copy()
mergedResponse.Answer = []dns.RR{}
mergedResponse.Ns = []dns.RR{}
mergedResponse.Extra = []dns.RR{}
// 重置Rcode为成功除非所有响应都是NXDOMAIN
mergedResponse.Rcode = dns.RcodeSuccess
// 检查是否所有响应都是NXDOMAIN
allNXDOMAIN := true
// 收集所有成功响应的记录
for _, resp := range responses {
if resp == nil {
continue
}
// 如果有任何响应是成功的就不是allNXDOMAIN
if resp.Rcode == dns.RcodeSuccess {
allNXDOMAIN = false
}
}
// 如果所有响应都是NXDOMAIN设置合并响应为NXDOMAIN
if allNXDOMAIN {
mergedResponse.Rcode = dns.RcodeNameError
}
// 使用map存储唯一记录选择最长TTL
// 预分配map容量减少扩容开销
answerMap := make(map[recordKey]dns.RR, len(responses[0].Answer)*len(responses))
nsMap := make(map[recordKey]dns.RR, len(responses[0].Ns)*len(responses))
extraMap := make(map[recordKey]dns.RR, len(responses[0].Extra)*len(responses))
for _, resp := range responses {
if resp == nil {
continue
}
// 只合并与最终Rcode匹配的响应记录
if (mergedResponse.Rcode == dns.RcodeSuccess && resp.Rcode == dns.RcodeSuccess) ||
(mergedResponse.Rcode == dns.RcodeNameError && resp.Rcode == dns.RcodeNameError) {
// 合并Answer部分
for _, rr := range resp.Answer {
key := getRecordKey(rr)
if existing, exists := answerMap[key]; exists {
// 如果存在相同记录选择TTL更长的
if rr.Header().Ttl > existing.Header().Ttl {
answerMap[key] = rr
}
} else {
answerMap[key] = rr
}
}
// 合并Ns部分
for _, rr := range resp.Ns {
key := getRecordKey(rr)
if existing, exists := nsMap[key]; exists {
// 如果存在相同记录选择TTL更长的
if rr.Header().Ttl > existing.Header().Ttl {
nsMap[key] = rr
}
} else {
nsMap[key] = rr
}
}
// 合并Extra部分
for _, rr := range resp.Extra {
// 跳过OPT记录避免重复
if rr.Header().Rrtype == dns.TypeOPT {
continue
}
key := getRecordKey(rr)
if existing, exists := extraMap[key]; exists {
// 如果存在相同记录选择TTL更长的
if rr.Header().Ttl > existing.Header().Ttl {
extraMap[key] = rr
}
} else {
extraMap[key] = rr
}
}
}
}
// 预分配切片容量,减少扩容开销
mergedResponse.Answer = make([]dns.RR, 0, len(answerMap))
mergedResponse.Ns = make([]dns.RR, 0, len(nsMap))
mergedResponse.Extra = make([]dns.RR, 0, len(extraMap))
// 将map转换回切片
for _, rr := range answerMap {
mergedResponse.Answer = append(mergedResponse.Answer, rr)
}
for _, rr := range nsMap {
mergedResponse.Ns = append(mergedResponse.Ns, rr)
}
for _, rr := range extraMap {
mergedResponse.Extra = append(mergedResponse.Extra, rr)
}
return mergedResponse
}```
## 预期效果
修复后DNS服务器将能够
- 正确合并多个 DNS 响应
- 确保 Rcode 与实际记录内容匹配
- 只有当所有响应都是 NXDOMAIN 时才返回 NXDOMAIN
- 避免单个恶意域名影响所有查询结果
- 正确显示各个域名的查询结果
## 修复代码位置
- **核心修改文件**`/root/dns/dns/server.go`
- **关键函数**`mergeResponses`
- **修改内容**:修复响应合并逻辑,正确处理 Rcode 字段
## 测试方法
1. 使用 nslookup 测试不同域名
2. 检查是否每个域名都显示正确的查询结果
3. 验证 www.evilsnssdk.com 返回 NXDOMAIN而其他域名返回成功
4. 检查日志中是否还有大量错误信息
这个修复将彻底解决所有查询都显示同一个 NXDOMAIN 错误的问题!

View File

@@ -0,0 +1,18 @@
## 问题分析
当前实现中,详细图表(浮窗)的时间范围切换会影响到主页面的图表显示,这是因为它们共享了全局变量`currentTimeRange``isMixedView`。当用户在浮窗内切换时间范围时,这些全局变量会被修改,导致主页面的图表也随之改变。
## 解决方案
1. 为详细图表创建独立的变量,用于存储其时间范围和混合视图状态
2. 修改`initDetailedTimeRangeToggle`函数,使其使用这些独立的变量,而不是全局变量
3. 修改`drawDetailedDNSRequestsChart`函数,使用独立的变量来控制图表显示
4. 确保主图表默认显示混合视图
## 修复步骤
1.`dashboard.js`文件中添加详细图表专用的全局变量
2. 修改`initDetailedTimeRangeToggle`函数,使用详细图表专用变量
3. 修改`drawDetailedDNSRequestsChart`函数,使用详细图表专用变量
4. 确保主图表默认显示混合视图
5. 测试修复效果,确保浮窗内的时间范围切换不会影响主页面图表
## 预期效果
修复后DNS请求趋势图表默认显示混合内容视图不变当用户点击展开按钮查看详细数据时浮窗内的时间范围切换不会影响到主页面的图表内容提供更好的用户体验。

View File

@@ -0,0 +1,15 @@
## 问题分析
DNS请求趋势图表展开后不能随页面放大缩小自动调整大小。通过代码分析发现`window.addEventListener('resize')`事件监听器只处理了侧边栏的显示/隐藏,没有处理图表的调整大小。
## 解决方案
1. 修改`window.addEventListener('resize')`事件监听器,添加对所有图表(包括详细图表)的更新调用
2. 确保在模态框显示时,图表能够正确响应窗口大小变化
## 修复步骤
1. 打开`/root/dns/static/js/dashboard.js`文件
2. 找到`window.addEventListener('resize')`事件监听器
3. 修改该事件监听器,添加对`dnsRequestsChart``detailedDnsRequestsChart`的更新调用
4. 确保图表实例存在时才调用update方法
## 预期效果
修复后当用户展开DNS请求趋势图表并调整浏览器窗口大小时图表会自动调整大小以适应新的窗口尺寸。

View File

@@ -0,0 +1,21 @@
## 问题分析
展开图表超出了显示范围,没有按照展开浮窗大小显示内容。通过代码分析,发现以下问题:
1. 图表容器使用了固定高度 `h-[600px]`,这可能导致在某些屏幕尺寸下图表超出显示范围
2. 浮窗容器设置了 `max-h-[90vh]`,但图表容器的固定高度可能超过这个限制
3. 当图表初始化时,可能没有正确计算容器的实际可用空间
## 解决方案
1. 修改图表容器的高度设置,使其更灵活,能够适应不同屏幕尺寸
2. 确保图表容器的高度不超过浮窗的最大高度限制
3. 在图表显示时,确保正确计算容器大小并更新图表
## 修复步骤
1. 打开 `index.html` 文件,修改图表容器的高度设置
2. 将固定高度 `h-[600px]` 改为相对高度或最大高度
3. 确保图表容器的高度能够适应浮窗的可用空间
4.`drawDetailedDNSRequestsChart` 函数中,添加对图表容器大小的检查和调整
5. 确保在图表显示时,正确计算容器大小并更新图表
## 预期效果
修复后当用户展开DNS请求趋势图表时图表会根据浮窗的可用空间自动调整大小不会超出显示范围提供更好的用户体验。

View File

@@ -0,0 +1,4 @@
1. 检查updateTopData函数修复当API调用失败或返回错误时没有数据显示的问题
2. 确保在所有情况下updateTopDomainsTable函数都能被调用即使API调用失败
3. 为updateTopData函数添加错误处理确保在API调用失败时使用模拟数据
4. 测试修复后的代码确保TOP域名卡片能正确显示数据

View File

@@ -0,0 +1,32 @@
## 问题分析
经过分析TOP客户端数据加载失败的原因是**前端API调用路径与后端注册的路径不匹配**
1. **前端代码**:在 `static/js/api.js` 中,`getTopClients` 方法调用的是 `/top-clients` API端点
2. **后端代码**:在 `http/server.go`注册的API路径是 `/api/top-clients`
3. **结果**前端请求404错误导致TOP客户端数据加载失败
## 解决方案
修改前端API调用`/top-clients` 改为 `/api/top-clients`,确保与后端注册的路径匹配。
## 实现步骤
1. **修改 `static/js/api.js` 文件**
- 找到 `getTopClients` 方法
- 将API调用路径从 `/top-clients?t=` 改为 `/api/top-clients?t=`
2. **验证修复**
- 刷新页面检查TOP客户端数据是否能正常加载
- 查看浏览器控制台确认没有404错误
## 预期效果
- TOP客户端数据能够正常加载
- 不再显示"加载失败"错误信息
- 页面上显示真实的TOP客户端数据
## 代码修改
只需要修改一个文件:
- `static/js/api.js`:更新 `getTopClients` 方法的API路径

View File

@@ -0,0 +1,4 @@
1. 检查updateTopClientsTable函数添加对tableBody是否存在的检查
2. 改进模拟数据使用真实的IP地址和请求次数
3. 确保函数在任何情况下都能正确执行
4. 测试修复后的代码确保TOP客户端卡片能正确显示数据

View File

@@ -0,0 +1,95 @@
# 问题分析
1. **问题现象**:当用户在某个设置项页面刷新时,页面会自动回到仪表盘页面。
2. **问题根源**
-`dashboard.js` 文件中,`handleHashChange` 函数被定义在 `handlePageSwitch` 函数内部
- 当页面刷新时,`handleHashChange` 函数会在页面加载完成后立即执行
- 此时,`menuItems` 可能还没有被正确初始化,或者 `handleHashChange` 函数内部的 `menuItems` 引用的是旧的变量,导致它无法找到对应的菜单项
-`handleHashChange` 函数无法找到对应的菜单项时,它会执行 `window.location.hash = '#dashboard'`,将页面重定向到仪表盘页面
3. **具体问题**
- `handleHashChange` 函数在找不到对应的菜单项时,会立即重定向到仪表盘页面,而不是先尝试直接显示对应的内容
- 这导致用户在刷新页面时即使URL中包含正确的hash页面也会被重定向到仪表盘
# 修复方案
1. **修复 `handleHashChange` 函数**
- 修改 `handleHashChange` 函数,确保它在找不到对应的菜单项时,不会总是重定向到仪表盘页面
- 当无法找到对应的菜单项时,先尝试直接显示对应的内容
- 只有当对应的内容也不存在时,才重定向到仪表盘页面
2. **优化页面初始化流程**
- 确保 `handleHashChange` 函数在页面完全加载后才执行
- 确保 `menuItems` 变量在 `handleHashChange` 函数执行前已经被正确初始化
# 实现步骤
1. 修改 `dashboard.js` 文件中的 `handleHashChange` 函数:
- 当无法找到对应的菜单项时,先尝试直接显示对应的内容
- 只有当对应的内容也不存在时,才重定向到仪表盘页面
2. 测试修复后的功能:
- 启动DNS服务器
- 访问Web界面导航到某个设置项页面例如 `#config`
- 刷新页面
- 验证页面是否仍然显示在设置项页面,而不是自动回到仪表盘页面
# 预期结果
- 用户在某个设置项页面刷新时,页面会保持在当前页面,不会自动回到仪表盘页面
- 只有当URL中的hash无效时页面才会重定向到仪表盘页面
- 页面导航功能正常,用户可以通过点击菜单项切换页面
# 修复代码
```javascript
// 修改 dashboard.js 文件中的 handleHashChange 函数
function handleHashChange() {
let hash = window.location.hash;
// 如果没有hash默认设置为#dashboard
if (!hash) {
hash = '#dashboard';
window.location.hash = hash;
return;
}
const targetId = hash.substring(1);
// 查找对应的内容元素
const contentElement = document.getElementById(`${targetId}-content`);
// 如果找到了对应的内容元素,直接显示
if (contentElement) {
// 隐藏所有内容
document.querySelectorAll('[id$="-content"]').forEach(content => {
content.classList.add('hidden');
});
// 显示目标内容
contentElement.classList.remove('hidden');
// 查找对应的菜单项并更新活动状态
let targetMenuItem = null;
menuItems.forEach(item => {
if (item.getAttribute('href') === hash) {
targetMenuItem = item;
}
});
// 更新活动菜单项
menuItems.forEach(item => {
item.classList.remove('sidebar-item-active');
if (item.getAttribute('href') === hash) {
item.classList.add('sidebar-item-active');
// 更新页面标题
document.getElementById('page-title').textContent = item.querySelector('span').textContent;
}
});
} else {
// 如果没有找到对应的内容默认显示dashboard
window.location.hash = '#dashboard';
}
}
```

View File

@@ -0,0 +1,58 @@
## 实现计划
### 1. 配置文件修改
* **修改`/root/dns/config/config.go`**
*`DNSConfig`结构体中添加`PrefixDomain []string`字段用于支持search domain功能
*`LoadConfig`函数中添加`prefixDomain`的默认值处理
### 2. DNS请求处理逻辑修改
* **修改`/root/dns/dns/server.go`中的`forwardDNSRequestWithCache`函数**
* 强化domainSpecificDNS逻辑确保当域名匹配时只使用指定的DNS服务器
* 移除向DNSSEC专用服务器发送请求的逻辑当域名匹配domainSpecificDNS时
* 确保匹配域名的DNS查询结果不会被其他DNS服务器的响应覆盖
* **修改`/root/dns/dns/server.go`中的`handleDNSRequest`函数**
* 实现search domain功能当直接查询失败时尝试添加prefixDomain中指定的域名前缀
* 按照/etc/resolv.conf中的search domain逻辑处理查询请求
### 3. 配置文件示例更新
* **更新配置文件示例**
* 添加`prefixDomain`配置项示例
* 说明search domain功能的使用方法
### 4. 测试验证
* 测试domainSpecificDNS强制使用功能确保匹配的域名只使用指定的DNS服务器
* 测试search domain功能确保能够正确处理带前缀的域名查询
* 测试不同配置组合下的功能正确性
## 预期效果
1. 当域名匹配domainSpecificDNS配置时无论DNSSEC是否启用只使用指定的DNS服务器
2. 支持search domain功能能够自动尝试添加配置的域名前缀
3. 配置简单直观,与/etc/resolv.conf的search domain行兼容
## 实现要点
* 确保domainSpecificDNS配置的优先级最高
* 实现高效的search domain查询逻辑避免不必要的网络请求
* 保持代码的可读性和可维护性
* 确保与现有功能的兼容性

View File

@@ -0,0 +1,58 @@
## 问题分析
通过代码分析,我发现/api/top-clients端点数据无法持久化的原因有两个
1. **数据保存逻辑缺失**:在`saveStatsData`方法中,虽然`StatsData`结构体包含了`ClientStats`字段,但没有将`server.clientStats`赋值给`statsData.ClientStats`
2. **数据加载逻辑缺失**:在`loadStatsData`方法中,虽然`StatsData`结构体包含了`ClientStats`字段,但没有将`statsData.ClientStats`赋值给`server.clientStats`
3. **自动保存功能未启用**`startAutoSave`方法没有在`Server``Start`方法中被调用,导致数据不会定期保存
## 修复计划
1. **修改`saveStatsData`方法**:添加保存`ClientStats`数据的逻辑
2. **修改`loadStatsData`方法**:添加加载`ClientStats`数据的逻辑
3. **在`Server.Start`方法中调用`startAutoSave`**:确保数据定期保存
## 修复步骤
### 步骤1修改`saveStatsData`方法
`dns/server.go`文件中,修改`saveStatsData`方法,添加保存`ClientStats`数据的逻辑:
```go
// 复制客户端统计数据
s.clientStatsMutex.RLock()
statsData.ClientStats = make(map[string]*ClientStats)
for k, v := range s.clientStats {
statsData.ClientStats[k] = v
}
s.clientStatsMutex.RUnlock()
```
### 步骤2修改`loadStatsData`方法
`dns/server.go`文件中,修改`loadStatsData`方法,添加加载`ClientStats`数据的逻辑:
```go
s.clientStatsMutex.Lock()
if statsData.ClientStats != nil {
s.clientStats = statsData.ClientStats
}
s.clientStatsMutex.Unlock()
```
### 步骤3在`Server.Start`方法中调用`startAutoSave`
`dns/server.go`文件的`Start`方法中,添加调用`startAutoSave`的代码:
```go
// 启动自动保存功能
go s.startAutoSave()
```
## 预期效果
修复后,/api/top-clients端点的数据将
1. 在服务器启动时从文件加载
2. 定期自动保存到文件
3. 在服务器停止时最后保存一次
这样就能确保/api/top-clients端点的数据持久化不会因为服务器重启而丢失。

View File

@@ -0,0 +1,31 @@
### 问题分析
1. **语法错误**:文件中存在多处语法错误,包括:
- 第34行`type ClientStats uct` 应该是 `type ClientStats struct`
- 第36行`Count 64` 应该是 `Count int64`
- 第143行`/ DNSCache` 缺少一个星号,应该是 `// DNSCache`
- 多处缩进问题
- 函数内容被截断
2. **文件完整性问题**文件内容不完整handleDNSRequest函数被截断缺少后续的函数定义
### 修复方案
1. **修复语法错误**
- 修复ClientStats结构体定义
- 修复DNSCache注释和结构体定义
- 修复所有缩进问题
2. **恢复完整内容**
- 重新编写或恢复handleDNSRequest函数的完整内容
- 确保所有后续函数定义完整
### 具体修改
1. 修复第34行的ClientStats结构体定义
2. 修复第143行的DNSCache注释和结构体定义
3. 修复所有缩进问题
4. 恢复完整的handleDNSRequest函数
5. 恢复后续所有函数定义
### 测试计划
1. 编译修复后的代码
2. 启动DNS服务器并测试功能
3. 验证DNSSEC功能是否正常工作

View File

@@ -0,0 +1,20 @@
# 修复picsum.photos域名匹配问题
## 问题分析
当DNS查询picsum.photos时实际传递给`getDomainInfo()`函数的域名可能带有末尾点(如"picsum.photos."而domain-info.json中存储的是没有末尾点的域名如"picsum.photos")。在原始的`isDomainMatch()`函数中,直接比较两个域名,导致匹配失败。
## 解决方案
修改`isDomainMatch()`函数,在域名比较前对两个域名进行规范化处理,去除末尾的点,确保匹配准确性。
## 实施步骤
1. 修改`isDomainMatch()`函数,在域名比较前对`urlDomain``targetDomain`进行规范化处理,去除末尾的点
2. 确保无论是完整URL还是纯域名都能正确匹配
3. 测试修改后的代码确保picsum.photos域名能被正确匹配
## 修改内容
- 文件:`/root/dns/static/js/logs.js`
- 函数:`isDomainMatch()`
- 修改点:在域名比较前,去除`urlDomain``targetDomain`末尾的点
## 预期效果
修改后picsum.photos域名无论是否带有末尾点都能被正确匹配到domain-info.json中的条目。

View File

@@ -0,0 +1,4 @@
1. 检查updateRecentBlockedTable函数添加对tableBody是否存在的检查
2. 确保在移除recent-blocked-table元素后updateRecentBlockedTable函数不会导致错误
3. 确保后续的updateTopDomainsTable调用能够被正确执行
4. 测试修复后的代码确保TOP域名卡片能正确显示数据

View File

@@ -0,0 +1,90 @@
## 问题分析
通过代码分析我发现web屏蔽管理页面点击后一直显示处理中灰色遮罩的原因有两个
1. **JavaScript错误导致`hideLoading()`不被调用**
- `loadLocalRules()`函数尝试访问`document.getElementById('local-rules-count')`但该元素在HTML中不存在
- `loadRemoteRules()`函数尝试访问`document.getElementById('remote-rules-count')`但该元素在HTML中不存在
- `setupShieldEventListeners()`函数尝试访问`document.getElementById('view-local-rules-btn')``document.getElementById('view-remote-rules-btn')`但这些元素在HTML中不存在
- 这些JavaScript错误会导致函数执行中断从而使`hideLoading()`不被调用,加载遮罩一直显示
2. **竞态条件问题**
- `initShieldPage()`函数并行调用三个异步函数:`loadShieldStats()``loadLocalRules()``loadRemoteBlacklists()`
- 每个异步函数都会调用`showLoading()`,而`showLoading()`会先调用`hideLoading()`来移除现有加载状态,然后创建一个新的加载状态
- 这种并行调用可能导致竞态条件,使最后一个加载遮罩无法被正确销毁
## 修复计划
1. **修改`loadLocalRules()`函数**添加元素存在性检查避免JavaScript错误
2. **修改`loadRemoteRules()`函数**添加元素存在性检查避免JavaScript错误
3. **修改`setupShieldEventListeners()`函数**添加元素存在性检查避免JavaScript错误
4. **修改`initShieldPage()`函数**:确保只创建一个加载遮罩,并在所有异步函数完成后销毁它
## 修复步骤
### 步骤1修改`loadLocalRules()`函数
`shield.js`文件中,修改`loadLocalRules()`函数,添加元素存在性检查:
```javascript
// 更新本地规则数量显示
if (document.getElementById('local-rules-count')) {
document.getElementById('local-rules-count').textContent = data.localRulesCount || 0;
}
```
### 步骤2修改`loadRemoteRules()`函数
`shield.js`文件中,修改`loadRemoteRules()`函数,添加元素存在性检查:
```javascript
// 更新远程规则数量显示
if (document.getElementById('remote-rules-count')) {
document.getElementById('remote-rules-count').textContent = data.remoteRulesCount || 0;
}
```
### 步骤3修改`setupShieldEventListeners()`函数
`shield.js`文件中,修改`setupShieldEventListeners()`函数,添加元素存在性检查:
```javascript
// 添加切换查看本地规则和远程规则的事件监听
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);
}
```
### 步骤4修改`initShieldPage()`函数
`shield.js`文件中,修改`initShieldPage()`函数,确保只创建一个加载遮罩,并在所有异步函数完成后销毁它:
```javascript
// 初始化屏蔽管理页面
async function initShieldPage() {
showLoading('加载屏蔽管理数据...');
try {
// 并行加载所有数据
await Promise.all([
loadShieldStats(),
loadLocalRules(),
loadRemoteBlacklists()
]);
// 设置事件监听器
setupShieldEventListeners();
} finally {
hideLoading();
}
}
```
### 步骤5修改异步函数移除内部的`showLoading()`和`hideLoading()`调用
`shield.js`文件中,修改`loadShieldStats()``loadLocalRules()``loadRemoteBlacklists()`函数,移除内部的`showLoading()``hideLoading()`调用,只保留数据加载逻辑。
## 预期效果
修复后web屏蔽管理页面点击后
1. 只会显示一个加载遮罩
2. 不会出现JavaScript错误
3. 所有数据加载完成后,加载遮罩会被正确隐藏
4. 页面会正常显示屏蔽管理设置内容

View File

@@ -0,0 +1,37 @@
# 修复保存按钮错位问题
## 问题分析
远程黑名单管理部分的保存按钮错位,原因是:
- 添加黑名单表单使用了Grid布局`grid grid-cols-1 md:grid-cols-3 gap-4`
- 前两个子元素包含label和input高度较高
- 第三个子元素只有按钮和状态显示没有label高度较矮
- 导致按钮在垂直方向上与前两个输入框不对齐
## 解决方案
修改添加黑名单表单的HTML结构确保三个子元素在垂直方向上对齐
1. **为第三个子元素添加垂直对齐**
- 确保保存按钮容器与前两个输入框容器在垂直方向上对齐
- 可以选择顶部对齐或中间对齐,保持视觉一致性
2. **统一子元素结构**
- 为第三个子元素添加一个隐藏的label确保结构一致
- 或者调整Grid布局使第三个子元素的内容垂直居中
3. **调整容器样式**
- 修改保存按钮容器的样式,确保垂直对齐
- 可以使用`items-start``items-center`属性
## 实现步骤
1. 修改`add-blacklist-form`的HTML结构
- 为第三个子元素添加`items-start`类,使其与前两个子元素的顶部对齐
- 或者添加一个隐藏的label确保结构一致
2. 测试修改后的效果
- 确保保存按钮与前两个输入框在垂直方向上对齐
- 保持响应式布局,在不同屏幕尺寸下都能正常显示
## 预期效果
保存按钮将与前两个输入框在垂直方向上对齐,消除错位现象,提升表单的视觉一致性和用户体验。

View File

@@ -0,0 +1,56 @@
## 问题分析
域名信息显示为空,特别是对于`wx.qq.com`这样的域名,虽然在`domain-info.json`中已配置,但日志详情中显示为空。
### 可能的原因
1. **文件路径问题**`loadDomainInfoDatabase`函数使用`fetch('/domain-info/domains/domain-info.json')`加载文件,但服务器可能没有正确配置该路径,导致加载失败。
2. **代码逻辑问题**:虽然代码逻辑看起来正确,但可能存在一些边缘情况没有处理好。
3. **调试信息不足**:代码中缺少调试信息,难以定位具体问题。
## 解决方案
### 1. 添加调试日志
`loadDomainInfoDatabase``getDomainInfo`函数中添加调试日志,以便定位问题:
-`loadDomainInfoDatabase`函数中,添加日志记录文件加载状态和结果
-`getDomainInfo`函数中,添加日志记录域名匹配过程
-`isDomainMatch`函数中添加日志记录URL匹配细节
### 2. 检查并修复文件路径
确保`domain-info.json`文件能被正确访问:
- 检查服务器配置,确保`/domain-info/domains/domain-info.json`路径指向正确的文件
- 或者修改代码中的路径,使用绝对路径或正确的相对路径
### 3. 增强错误处理
`loadDomainInfoDatabase`函数中增强错误处理,提供更详细的错误信息:
- 记录完整的错误信息
- 在控制台显示友好的错误提示
- 考虑添加重试机制
### 4. 优化域名匹配逻辑
虽然代码逻辑看起来正确,但可以进一步优化:
- 确保所有URL都被正确处理无论是否包含协议
- 增强主域名提取逻辑,处理更多特殊情况
- 考虑添加缓存机制,提高匹配效率
## 实施步骤
1. 修改`loadDomainInfoDatabase`函数,添加调试日志和增强错误处理
2. 修改`getDomainInfo`函数,添加调试日志
3. 修改`isDomainMatch`函数,添加调试日志
4. 测试修复效果
5. 根据测试结果进一步优化
## 预期效果
修复后,域名信息将能正确显示在日志详情中,特别是对于`wx.qq.com`等已配置的域名。

View File

@@ -0,0 +1,134 @@
# 优化设置界面实现计划
## 问题分析
当前设置界面存在配置项重复问题,需要进行优化,具体包括:
1. "远程规则URL"配置项在多个界面重复出现
2. "启用API"和"主机"选项不需要在当前界面显示
3. 需要确保保存功能正常工作写入config.json并触发服务器重新加载配置
## 优化方案
### 1. 修改HTML结构
* 移除"远程规则URL"配置项
* 移除"启用API"选项
* 移除"主机"选项
* 调整布局,确保界面美观合理
### 2. 更新JavaScript代码
* 修改`populateConfigForm`函数,移除对已删除配置项的处理
* 修改`collectFormData`函数,移除对已删除配置项的收集
* 确保保存功能能正确写入config.json文件
* 实现服务器重新加载配置的触发机制
* 提供明确的成功/失败反馈
### 3. 测试和验证
* 测试所有保留配置项的加载和保存功能
* 验证保存操作能正确写入config.json文件
* 验证服务器能重新加载配置
* 测试成功/失败反馈是否明确
## 具体实现步骤
1. **修改HTML结构**
* 编辑`index.html`文件,移除不需要的配置项
* 调整布局,确保界面美观合理
2. **更新JavaScript代码**
* 编辑`config.js`文件,修改`populateConfigForm`函数
* 修改`collectFormData`函数,移除对已删除配置项的处理
* 确保`handleSaveConfig`函数能正确保存配置
* 实现服务器重新加载配置的触发机制
3. **测试和验证**
* 测试配置项的加载功能
* 测试配置项的保存功能
* 验证config.json文件是否正确更新
* 验证服务器是否重新加载配置
* 测试成功/失败反馈是否明确
## 预期效果
* 设置界面布局合理,无重复配置项
* 所有保留配置项均可正常配置
* 保存功能能正确写入config.json文件
* 服务器能重新加载配置,使更改立即生效
* 保存操作有明确的成功/失败反馈
## 技术要点
* 使用HTML和JavaScript修改界面结构和功能
* 确保与服务器API的正确交互
* 实现良好的用户反馈机制
* 确保配置的正确保存和加载
## 实现时间
* 预计1-2小时完成所有修改和测试
## 风险评估
* 低风险:修改范围明确,不涉及核心功能
* 可回滚:所有修改均为前端修改,可通过恢复文件轻松回滚
## 依赖关系
* 依赖服务器API的正常工作
* 依赖config.json文件的读写权限
## 测试策略
* 手动测试所有配置项的加载和保存功能
* 验证config.json文件的更新
* 测试服务器配置的重新加载
* 测试成功/失败反馈
## 验收标准
* 设置界面布局合理,无重复配置项
* 所有保留配置项均可正常配置
* 保存功能能正确写入config.json文件
* 服务器能重新加载配置,使更改立即生效
* 保存操作有明确的成功/失败反馈

View File

@@ -0,0 +1,33 @@
1. **修复未定义函数问题**:移除对 `containsRegexSpecialChars` 函数的调用,该函数在代码中未定义
2. **修改正则表达式处理逻辑**
* 对于 `/` 包裹的规则,直接将中间内容作为正则表达式模式
* 不再添加 `.*` 前缀和后缀,也不再使用 `regexp.QuoteMeta` 转义
* 确保正则表达式能正确匹配域名中的相关内容
3. **修改文件**
* `/root/dns/shield/manager.go`:更新 `parseRule` 函数中的正则表达式处理逻辑
**验证修复**
确保 `/ad.qq.com/` 规则能正确匹配 `ad.qq.com` 域名
确保 `/ad/` 规则能匹配包含 `ad` 的域名
* 确保正则表达式特殊字符能被正确处理
* **测试场景**
* 测试 `/ad.qq.com/` 规则匹配 `ad.qq.com`
* 测试 `/ad.qq.com/` 规则匹配 `sub.ad.qq.com`
* 测试 `/ad/` 规则匹配 `ad.example.com`
* 测试 `/ad/` 规则匹配 `example.ad.com`
* 测试 `/^ad/` 规则匹配 `ad.example.com` 但不匹配 `example.ad.com`

View File

@@ -0,0 +1,44 @@
1. **修复规则添加逻辑**
* 修改`blockDomain`函数,使用正确的规则格式(如 `||domain^`
* 修改`unblockDomain`函数,使用正确的放行规则格式(如 `@@||domain^`
* 确保规则经过预处理后再发送到API
2. **更新本地规则列表**
* 添加规则成功后,更新`rules``filteredRules`数组
* 调用`renderRulesList`函数重新渲染规则列表
* 更新规则数量统计
3. **确保规则同步**
* 验证规则是否正确添加到本地规则列表
* 确保日志页面和规则页面的数据一致性
4. **优化用户体验**
* 改进操作反馈,显示更详细的成功/失败信息
* 确保规则添加后立即在日志中反映状态变化
5. **测试功能**
* 测试拦截域名功能
* 测试放行域名功能
* 验证规则是否正确添加到本地规则列表
* 验证日志状态是否正确更新
**修改文件**
* `/root/dns/static/js/logs.js`:修复`blockDomain``unblockDomain`函数
* 确保与`/root/dns/static/js/modules/rules.js`的规则处理逻辑保持一致

View File

@@ -0,0 +1,56 @@
1. **确认apiRequest函数的使用**
* 检查logs.js中apiRequest函数的来源和调用方式
* 确保使用正确的API\_BASE\_URL和异步apiRequest函数
2. **修复API调用路径**
* 确保拦截和放行功能使用正确的API路径
* 验证与规则管理模块的API调用一致性
3. **改进规则格式**
* 确保拦截和放行规则使用正确的格式
* 与规则管理模块的规则处理逻辑保持一致
4. **添加详细的错误处理**
* 在apiRequest调用中添加详细的日志
* 改进错误处理,显示更详细的错误信息
* 添加调试信息,以便跟踪问题
5. **确保跨文件函数调用正确**
* 确保logs.js能正确访问apiRequest函数
* 验证全局变量和函数的可用性
6. **测试功能**
* 测试拦截域名功能
* 测试放行域名功能
* 验证规则是否正确添加到本地规则列表
* 验证日志状态是否正确更新
**修改文件**
* `/root/dns/static/js/logs.js`修复apiRequest函数调用和API路径
**预期效果**
* 拦截功能正常工作,规则正确添加到本地规则列表
* 放行功能正常工作,规则正确添加到本地规则列表
* 日志状态立即更新,显示正确的拦截/放行状态
* 显示详细的操作反馈和错误信息

View File

@@ -0,0 +1,67 @@
## 问题分析
从截图中可以看到,日志表格显示了"Invalid Date"、"undefined"等错误值这表明前端代码在解析API返回的JSON数据时出现了问题。
## 根本原因
1. 后端`QueryLog`结构体的JSON标签使用了小写字段名`json:"timestamp"``json:"clientIP"`等)
2. 前端代码使用了大写的字段名(如`log.Timestamp``log.ClientIP`等)来访问数据
3. 字段名大小写不匹配导致前端无法正确解析API返回的数据
## 修复方案
修改前端代码使用正确的小写字段名来访问API返回的数据与后端返回的JSON格式匹配。
## 具体修改点
1. **`updateLogsTable`函数**约435-621行
*`log.Timestamp`改为`log.timestamp`
*`log.ClientIP`改为`log.clientIP`
*`log.Domain`改为`log.domain`
*`log.QueryType`改为`log.queryType`
*`log.ResponseTime`改为`log.responseTime`
*`log.Result`改为`log.result`
*`log.BlockRule`改为`log.blockRule`
*`log.FromCache`改为`log.fromCache`
*`log.DNSSEC`改为`log.dnssec`
*`log.EDNS`改为`log.edns`
*`log.DNSServer`改为`log.dnsServer`
*`log.DNSSECServer`改为`log.dnssecServer`
*`log.ResponseCode`改为`log.responseCode`
2. **`showLogDetailModal`函数**约1450-1597行
* 同样修改所有字段名的大小写
3. **其他可能的访问点**
* 检查并修改任何其他访问日志数据的地方
## 修复原则
* 保持前端代码与后端API返回的JSON格式一致
* 遵循REST API的最佳实践使用小写字段名
* 确保所有日志数据访问点都得到修复
## 验证方法
1. 修复代码后,重新编译并运行服务器
2. 访问日志页面,检查日志数据是否正确显示
3. 测试不同类型的日志(允许、屏蔽、错误),确保都能正确显示
4. 测试日志详情模态框,确保所有字段都能正确显示

View File

@@ -0,0 +1,57 @@
## 问题分析
1. **端口被占用问题**
- 服务器重启时提示端口被占用,可能是因为之前的服务器进程没有完全关闭
- 从之前的ps aux命令输出中看到有一个dns-server进程在运行PID: 233272
- 这导致新的服务器进程无法绑定到相同的端口
2. **数据保存提示no such file or directory问题**
- 配置文件中statsFile和shield_stats.json的路径格式不一致有的带./,有的不带)
- 可能存在目录创建失败或权限问题
- 程序运行时的工作目录与预期不符
## 修复方案
1. **解决端口被占用问题**
- 在启动新服务器之前,确保所有旧的服务器进程都已关闭
- 可以通过kill命令手动关闭旧进程
- 或者在程序中添加自动检测和关闭旧进程的逻辑
2. **解决数据保存问题**
- 统一配置文件中的文件路径格式,确保所有路径都使用相对路径或绝对路径
- 确保createRequiredFiles函数能够正确创建所有必要的目录和文件
- 添加错误处理,确保在目录或文件创建失败时能够给出明确的错误信息
- 检查程序运行时的工作目录,确保路径解析正确
## 修复步骤
1. **关闭旧的服务器进程**
- 使用kill命令关闭旧的dns-server进程
- 验证旧进程是否已关闭
2. **统一配置文件中的文件路径格式**
- 修改配置文件,确保所有文件路径都使用一致的格式
- 例如,将所有路径改为相对路径,不带./前缀
3. **修改createRequiredFiles函数**
- 确保函数能够正确创建所有必要的目录和文件
- 添加更详细的错误处理和日志
- 确保函数能够处理不同格式的文件路径
4. **测试修复效果**
- 启动服务器,检查是否能够成功绑定到端口
- 检查数据文件是否能够正确保存
- 重启服务器,检查是否能够正常启动
## 预期效果
- 服务器能够成功启动,不会提示端口被占用
- 数据文件能够正确保存不会提示no such file or directory
- 服务器重启时能够正常启动,不会出现相同的问题
## 注意事项
- 确保在修改配置文件之前备份原始文件
- 确保程序有足够的权限创建和写入文件
- 确保在关闭旧进程之前,所有重要的数据都已保存
- 测试修复效果时,确保覆盖所有可能的情况

View File

@@ -0,0 +1,41 @@
# 问题分析
1. **问题现象**用户点击删除按钮删除本地规则时通过API发送数据到服务器但Web界面没有自动刷新本地规则列表。
2. **问题根源**
- 后端`RemoveRule`方法存在缺陷,当删除规则时没有正确更新所有相关映射
- 前端代码虽然调用了重新加载规则列表的函数,但由于后端数据不一致,导致刷新后列表没有变化
3. **具体问题**
-`shield/manager.go``RemoveRule`方法中,删除域名规则时只从`domainRules``domainExceptions`映射中删除了规则,但没有更新`domainRulesIsLocal``domainExceptionsIsLocal``domainRulesSource``domainExceptionsSource`映射
- 处理正则表达式规则时,使用了错误的比较方式(`re.pattern.String() != pattern`),而应该使用原始规则字符串进行比较
# 修复方案
1. **修复`RemoveRule`方法**
- 当删除域名规则时,同时更新所有相关映射
- 当删除排除规则时,同时更新所有相关映射
- 修复正则表达式规则的比较方式,使用原始规则字符串进行比较
2. **验证前端代码**
- 确认前端代码在删除规则后正确调用了重新加载规则列表的函数
- 验证前端代码处理API响应的逻辑是否正确
# 实现步骤
1. 修改`shield/manager.go`文件中的`RemoveRule`方法:
- 在删除域名规则时,添加删除`domainRulesIsLocal``domainRulesSource`映射的代码
- 在删除排除规则时,添加删除`domainExceptionsIsLocal``domainExceptionsSource`映射的代码
- 修复正则表达式规则的比较方式
2. 测试修复后的功能:
- 启动DNS服务器
- 访问Web界面添加几条本地规则
- 点击删除按钮删除其中一条规则
- 验证规则列表是否自动刷新,且删除的规则不再显示
# 预期结果
- 用户点击删除按钮后,规则被成功删除
- Web界面自动刷新删除的规则从列表中消失
- 本地规则文件被正确更新,删除的规则不再存在于文件中

View File

@@ -0,0 +1,51 @@
## 问题分析
通过代码分析,我发现本地规则管理删除规则功能失效的原因有两个:
1. **规则格式不匹配**
- 前端显示的规则带有修饰符,例如:`||example.com^`
- 服务器端实际存储的是裸域名,例如:`example.com`
- `RemoveRule` 函数在处理规则时,虽然尝试了多种格式变体,但没有正确处理前端发送的带有修饰符的规则
2. **本地规则标记未更新**
- `RemoveRule` 函数没有考虑 `m.domainRulesIsLocal``m.domainExceptionsIsLocal` 映射,这些映射用于标记哪些规则是本地规则
- 删除规则后,没有更新这些映射,导致规则删除不彻底
## 修复计划
1. **修改 `RemoveRule` 函数**
- 改进规则处理逻辑,确保能正确处理带有修饰符的规则
- 更新 `domainRulesIsLocal``domainExceptionsIsLocal` 映射,确保本地规则被正确删除
2. **修改 `GetLocalRules` 函数**
- 确保返回的规则格式与 `RemoveRule` 函数期望的格式一致
3. **添加调试日志**
- 在关键位置添加日志,便于调试和监控规则删除过程
## 修复步骤
### 步骤1修改 `RemoveRule` 函数
`shield/manager.go` 文件中,修改 `RemoveRule` 函数,改进规则处理逻辑:
1. 确保正确处理带有修饰符的规则
2. 更新 `domainRulesIsLocal``domainExceptionsIsLocal` 映射
3. 添加调试日志
### 步骤2测试修复效果
- 启动服务器
- 访问本地规则管理页面
- 添加一条本地规则
- 删除该规则
- 验证规则是否被正确删除,页面内容是否减少
## 预期效果
修复后,本地规则管理删除规则功能将正常工作:
- 点击删除按钮后,规则会被正确发送到服务器
- 服务器会正确处理带有修饰符的规则
- 本地规则标记会被正确更新
- 规则会被持久化保存
- 页面内容会立即减少
这样就能确保本地规则管理删除规则功能正常工作,提供良好的用户体验。

View File

@@ -0,0 +1,21 @@
1. **问题分析**
- 当添加自定义规则时,规则被添加到内存中并保存到文件
- 但由于DNS缓存的存在如果该域名的DNS响应已经被缓存那么在缓存过期之前DNS服务器会直接返回缓存的响应而不会重新检查规则
- 这就导致了添加规则后需要重启服务器才能生效的问题
2. **修复方案**
- 当添加或删除自定义规则时清空DNS缓存这样新的规则会立即生效
- 这样当客户端再次请求该域名时DNS服务器会重新检查规则而不是直接返回缓存的响应
3. **修复步骤**
- 修改HTTP API处理函数在添加或删除规则后清空DNS缓存
- 或者修改ShieldManager的AddRule和RemoveRule方法添加清空DNS缓存的逻辑
- 测试修复后的功能,确保添加规则后无需重启服务器即可生效
4. **预期结果**
- 添加自定义规则后,规则会立即生效,无需重启服务器
- 重启服务器后,之前添加的自定义规则仍然存在
5. **具体实现**
-`/root/dns/http/server.go`在添加或删除规则的API处理函数后调用DNS缓存的Clear方法
- 这样当添加或删除规则时DNS缓存会被清空新的规则会立即生效

View File

@@ -0,0 +1,28 @@
## 问题分析
`main.js` 文件中,当用户点击菜单项时,代码使用了 `e.preventDefault()` 来阻止默认行为,这导致浏览器不会自动更新地址栏中的 hash。虽然 `dashboard.js` 文件中有 `handleHashChange` 函数来处理 hash 变化,但由于 `main.js` 中的 `e.preventDefault()`,点击菜单项时不会触发 hash 变化。
## 修复方案
1. **修改 `main.js` 文件**:移除 `e.preventDefault()`,或者在处理完点击事件后手动更新地址栏中的 hash
2. **确保 `main.js` 和 `dashboard.js` 中的点击事件处理逻辑不冲突**
3. **统一页面导航逻辑**:确保所有页面导航都通过 hash 变化来实现
## 修复步骤
1. **修改 `main.js` 文件**
- 移除 `e.preventDefault()`,允许浏览器自动更新地址栏中的 hash
- 或者在处理完点击事件后,手动设置 `window.location.hash = item.getAttribute('href')`
- 确保点击事件处理逻辑与 `dashboard.js` 中的 `handleHashChange` 函数兼容
2. **测试修复效果**
- 点击菜单项,检查地址栏中的 hash 是否正确更新
- 刷新页面,检查是否能保持在当前页面
- 直接修改地址栏中的 hash检查是否能正确导航到对应页面
## 预期效果
- 用户点击菜单项时,地址栏中的 hash 会自动更新
- 页面刷新时,会保持在当前页面
- 直接修改地址栏中的 hash 可以导航到对应页面
- 所有页面导航逻辑统一,避免冲突

View File

@@ -0,0 +1,48 @@
# 问题分析
1. **问题现象**规则更新后规则没有生效。用户添加或删除规则后DNS服务器仍然使用旧的规则进行域名屏蔽。
2. **问题根源**
-`addDomainRule`方法中,当添加一个域名规则时,它会为该域名的所有子域名也添加规则。例如,添加`example.com`规则时,会同时添加`example.com``com`规则。
- 但是,在`RemoveRule`方法中,当删除一个域名规则时,它只删除了指定的域名规则,而没有删除为子域名添加的规则。
- 这导致即使删除了主规则,子域名规则仍然存在,因此规则仍然生效。
3. **具体问题**
- 当添加`||test.example.com`规则时,`addDomainRule`方法会添加`test.example.com``example.com`两个规则。
- 当删除`||test.example.com^`规则时,`RemoveRule`方法只会删除`test.example.com`规则,而不会删除`example.com`规则,因此`example.com`仍然会被屏蔽。
- 此外,`RemoveRule`方法在处理通配符和URL匹配规则时也没有正确处理子域名规则的删除。
# 修复方案
1. **修复`RemoveRule`方法**
- 当删除一个域名规则时,同时删除为该域名的所有子域名添加的规则。
- 确保删除规则时,同时更新所有相关映射,包括主规则和子域名规则。
2. **验证修复效果**
- 启动DNS服务器
- 添加一条域名规则,例如`||test.example.com`
- 验证该规则及其子域名规则都被正确添加
- 删除该规则
- 验证该规则及其所有子域名规则都被正确删除
- 验证DNS服务器不再使用该规则进行域名屏蔽
# 实现步骤
1. 修改`shield/manager.go`文件中的`RemoveRule`方法:
- 在删除域名规则时,添加删除所有相关子域名规则的逻辑
- 确保删除规则时,同时更新所有相关映射
2. 测试修复后的功能:
- 启动DNS服务器
- 访问Web界面添加一条本地规则例如`||test.example.com`
- 验证该规则被正确添加
- 点击删除按钮删除该规则
- 验证该规则及其所有子域名规则都被正确删除
- 验证DNS服务器不再使用该规则进行域名屏蔽
# 预期结果
- 用户添加规则后,规则立即生效
- 用户删除规则后,规则立即失效
- 规则更新后DNS服务器使用最新的规则进行域名屏蔽
- 本地规则文件被正确更新,添加和删除的规则都能正确反映在文件中

View File

@@ -0,0 +1,20 @@
## 问题分析
从截图可以看出,远程黑名单管理的保存按钮与输入框在垂直方向上没有对齐,按钮位置偏下。
## 原因分析
1. 当前使用grid布局分为3列前两列包含label和input第三列包含空label和按钮容器
2. 空label虽然没有内容但仍然占据了空间mb-1 margin导致按钮被推到下方
3. 按钮容器使用了`items-center`但整体位置受label影响
## 修复方案
修改第三列的HTML结构移除空label直接放置按钮容器并使用flex布局的对齐属性确保按钮与输入框垂直对齐。
## 具体修改
1. 打开`/root/dns/static/index.html`文件
2. 找到远程黑名单管理的添加表单部分第839-847行
3. 修改第三列的HTML结构移除空label直接放置按钮容器
4. 使用flex布局的`items-end`属性确保按钮与输入框底部对齐
5. 调整按钮的margin-top为0确保与输入框精确对齐
## 预期效果
保存按钮与输入框在垂直方向上精确对齐,整体布局更加美观和专业。

View File

@@ -0,0 +1,5 @@
1. 修改HTML文件中TOP域名卡片的标题将"TOP域名"改为"请求域名排行"
2. 修改updateTopDomainsTable函数使其生成的HTML结构与updateTopBlockedTable函数一致
3. 将颜色从红色改为绿色,包括边框颜色、背景色和文本颜色
4. 确保生成的HTML结构与被拦截域名排行的样式一致
5. 测试修改后的代码,确保请求域名排行卡片显示正确

View File

@@ -0,0 +1,79 @@
## DNS服务器性能优化方案
### 问题分析
1. **并行查询模式**:当前配置使用`parallel`模式,会等待所有上游服务器响应后才返回,受最慢服务器影响
2. **DNSSEC验证开销**启用了DNSSEC验证增加了额外的计算和网络请求
3. **过多上游服务器**DNSSEC上游服务器多达5个响应时间差异大
4. **调试级别日志**`debug`级别日志记录大量信息占用CPU和I/O资源
5. **缓存TTL过短**10秒的缓存TTL导致频繁向上游请求
6. **黑名单规则过多**14个启用的黑名单每次请求都需要检查
### 优化方案
#### 1. 修改查询模式为快速返回
*`queryMode``parallel`改为`fastest-ip`或优化默认模式
* 快速返回模式会返回第一个有效响应,而不是等待所有响应
#### 2. 优化DNSSEC配置
* 减少DNSSEC上游服务器数量只保留2-3个可靠的
* 对国内域名禁用DNSSEC验证已配置部分可扩展
#### 3. 调整缓存策略
* 增加`cacheTTL`到60秒或更高减少上游请求频率
* 优化缓存实现,减少锁竞争
#### 4. 降低日志级别
* 将日志级别从`debug`改为`info``warn`,减少日志写入开销
#### 5. 优化黑名单处理
* 合并重复的黑名单规则
* 考虑使用更高效的域名匹配算法
#### 6. 代码优化
* 减少DNSSEC验证的重复调用
* 优化响应合并逻辑,避免不必要的计算
* 调整超时设置,避免过长等待
### 具体修改点
1. **config.json**
* 修改`queryMode``fastest-ip`
* 减少`dnssecUpstreamDNS`数量
* 增加`cacheTTL`到60
* 将日志级别改为`info`
2. **dns/server.go**
* 优化`forwardDNSRequestWithCache`函数减少DNSSEC重复验证
* 优化响应合并逻辑,避免不必要的计算
* 调整并行模式的超时处理
### 预期效果
* 减少响应时间,从当前的秒级降低到毫秒级
* 减少CPU和I/O资源占用
* 提高并发处理能力
* 保持DNS解析的准确性和可靠性

View File

@@ -0,0 +1,29 @@
# 修改远程黑名单管理界面,添加状态渐变效果
## 问题分析
当前远程黑名单管理界面的状态更新功能已经实现了3秒后恢复默认状态的功能但没有添加渐变效果用户体验不够流畅。
## 解决方案
修改`updateStatus`函数,为状态元素添加渐变效果,确保状态更新时的平滑过渡。
## 实现步骤
1. **修改`updateStatus`函数**
- 为状态元素添加CSS过渡效果
- 使用`classList`操作来添加/移除渐变类
- 确保状态更新时的平滑过渡
2. **添加CSS渐变样式**
- 在index.html中添加状态渐变的CSS样式
- 为不同状态loading、success、error添加不同的渐变效果
3. **测试修改后的功能**
- 确保状态更新时有平滑的渐变效果
- 确保3秒后状态能正常恢复默认
## 预期效果
远程黑名单管理界面的状态更新将具有平滑的渐变效果,包括:
- 加载状态的蓝色渐变效果
- 成功状态的绿色渐变效果
- 错误状态的红色渐变效果
- 所有状态在3秒后平滑消失恢复默认状态

View File

@@ -0,0 +1,47 @@
# 内存泄漏问题
## 1. IP地理位置缓存泄漏
问题IP地理位置缓存```ipGeolocationCache```)缺少全局过期清理机制,仅在获取新数据时检查单条缓存过期,导致长期运行后内存无限增长。
修复建议:
```Go
// 在Server结构体中添加清理定时器ipGeolocationCacheCleanupTicker *time.Ticker// 在NewServer函数中启动清理协程go s.startIPGeolocationCacheCleanup()// 添加清理函数func (s *Server) startIPGeolocationCacheCleanup() { ticker := time.NewTicker(time. Hour) // 每小时清理一次 defer ticker.Stop() for { select { case <-ticker.C: s. cleanupExpiredIPGeolocat ionCache() case <-s.ctx.Done(): return } }}func (s *Server) cleanupExpiredIPGeolocationCache() { now := time.Now() s.ipGeolocationCacheMutex.Lock() defer s.ipGeolocationCacheMutex. Unlock() for ip, geo := range s. ipGeolocationCache { if now.After(geo.Expiry) { delete(s. ipGeolocationCache, ip) } }}
```
# 2. DNS缓存无大小限制
问题DNS缓存DNSCache仅按TTL过期无最大条目数限制可能导致内存无限增长。
修复建议:
```Go
// 在DNSCache结构体中添加最大大小限制maxSize int// 在Set方法中添加大小限制检查func (c *DNSCache) Set(qName string, qType uint16, response *dns.Msg, ttl time.Duration) { // 现有代码... c.mutex.Lock() defer c.mutex.Unlock() c.cache[key] = item // 检查并清理超过最大大小的缓存 if c.maxSize > 0 && len(c. cache) > c.maxSize { c.evictOldest() // 实现LRU或 随机淘汰策略 }}
```
## 1. 域名检查函数性能优化
问题:```CheckDomainBlockDetails```函数中重复的子域名检查和大量正则表达式匹配导致CPU使用率过高。
修复建议:
```Go
// 合并本地和远程规则检查减少循环次数func (m *ShieldManager) CheckDomainBlockDetails(domain string) map[string]interface{} { // 预处理域名 // ... // 合并域名排除规则检查 if m.domainExceptions[domain] { result["excluded"] = true result["excludeRule"] = m. domainExceptionsOriginal [domain] result["excludeRuleType"] = "exact_domain" result["blocksource"] = m. domainExceptionsSource [domain] return result } // 合并子域名检查 parts := strings.Split(domain, ".") for i := 0; i < len(parts)-1; i ++ { subdomain := strings.Join (parts[i:], ".") if m.domainExceptions [subdomain] { result["excluded"] = true result["excludeRule"] = m. domainExceptionsOriginal [subdomain] result ["excludeRuleType"] = "subdomain" result["blocksource"] = m.domainExceptionsSource [subdomain] return result } } // 合并正则表达式检查 for _, re := range m. regexExceptions { if re.pattern.MatchString (domain) { result["excluded"] = true result["excludeRule"] = re.original result ["excludeRuleType"] = "regex" result["blocksource"] = re.source return result } } // 阻止规则检查采用相同优化方式 // ...}
```
## 2. 减少锁持有时间
问题:```CheckDomainBlockDetails```函数持有读锁时间过长,影响并发性能。
修复建议:
```Go
// 采用更细粒度的锁或读写分离策略func (m *ShieldManager) CheckDomainBlockDetails(domain string) map[string]interface{} { // 只在需要访问共享数据时加锁 m.rulesMutex.RLock() domainExists := m. domainExceptions[domain] m.rulesMutex.RUnlock() if domainExists { m.rulesMutex.RLock() // 获取详细信息 m.rulesMutex.RUnlock() return result } // 其他检查采用相同方式}
```
# 其他优化建议
## 1. DNS缓存优化
实现LRU缓存淘汰策略限制最大缓存大小
定期统计缓存命中率,调整缓存策略
## 2. WebSocket连接管理
实现连接池管理,限制最大连接数
添加连接心跳检测机制,及时清理无效连接
## 3. 并行查询优化
限制同时发起的上游查询数量,避免资源耗尽
实现超时控制,防止长时间阻塞
## 4. 正则表达式优化
预编译所有正则表达式规则
合并相似规则,减少正则表达式数量
使用更高效的规则匹配算法
# 总结
通过实施上述修复建议和优化方案可以有效解决DNS服务器的内存泄漏问题和CPU性能瓶颈提高系统稳定性和响应速度。建议优先修复IP地理位置缓存泄漏和域名检查函数性能问题这些是当前最严重的问题。

View File

@@ -0,0 +1,40 @@
# 减小统计卡片大小并移除统计图
## 需求分析
用户希望减小统计卡片的大小并移除卡片中的统计图,只保留数值和基本信息。
## 实现方案
### 1. 修改统计卡片HTML结构
- 移除每个统计卡片中包含canvas元素的div高度为16px的图表区域
- 减小卡片的内边距从p-6改为p-4
- 调整卡片内部元素的间距,确保布局紧凑美观
### 2. 移除图表相关JavaScript代码
- 移除dashboard.js中对`initStatCardCharts()``updateStatCardCharts()`函数的调用
- 这些函数负责初始化和更新统计卡片中的折线图
- 移除后不会影响其他图表功能(如主图表区域的图表)
### 3. 具体修改点
#### HTML文件修改index.html
- 对于每个统计卡片共8个移除包含canvas的div元素
- 减小卡片内边距:将`p-6`改为`p-4`
- 调整卡片内部元素的margin和padding确保布局紧凑
#### JavaScript文件修改dashboard.js
- 移除第31行的`initStatCardCharts()`调用
- 移除第139行的`updateStatCardCharts(stats)`调用
- 移除第367行的`updateStatCardCharts(stats)`调用
- 移除第525行的`updateStatCardCharts(stats)`调用
## 预期效果
- 统计卡片大小减小,布局更紧凑
- 卡片中只显示标题、数值和百分比信息
- 移除了不必要的图表,减少了页面加载时间和资源消耗
- 整体界面更简洁,重点突出数值信息
## 注意事项
- 确保移除图表后不会导致其他功能错误
- 保持卡片之间的一致性和美观性
- 确保数值和百分比信息清晰可见

View File

@@ -0,0 +1,75 @@
## 实现计划在Web页面日志查询界面添加DNSSEC标志
### 1. 需求分析
- 在Web页面日志查询界面的域名下方区域添加绿色DNSSEC标志
- 当查询使用了DNSSEC时显示该标志
- 标志应清晰可见,与现有界面风格协调
### 2. 实现步骤
#### 步骤1扩展QueryLog结构体
- 修改 `/root/dns/dns/server.go` 文件中的 `QueryLog` 结构体
- 添加 `DNSSEC bool` 字段用于标识查询是否使用了DNSSEC
- 更新 `addQueryLog` 函数传入DNSSEC标志值
#### 步骤2在DNS请求处理中记录DNSSEC信息
- 修改 `/root/dns/dns/server.go` 文件中的 `handleDNSRequest` 函数
- 在处理DNS响应时检查是否使用了DNSSEC
- 将DNSSEC使用情况传递给 `addQueryLog` 函数
#### 步骤3修改前端页面显示DNSSEC标志
- 找到处理日志显示的前端代码
- 修改日志条目模板添加DNSSEC标志显示逻辑
- 使用Font Awesome或其他图标库的DNSSEC相关图标
- 当DNSSEC为true时显示绿色标志
#### 步骤4测试实现
- 编译并运行DNS服务器
- 访问Web界面的日志查询页面
- 进行DNS查询验证DNSSEC标志是否正确显示
### 3. 技术细节
#### 后端修改
- **文件**`/root/dns/dns/server.go`
- **修改内容**
- 扩展 `QueryLog` 结构体,添加 `DNSSEC bool` 字段
-`handleDNSRequest` 中判断DNSSEC使用情况
- 更新 `addQueryLog` 函数参数和调用
#### 前端修改
- **文件**`/root/dns/static/index.html` 或相关JavaScript文件
- **修改内容**
- 查找日志条目的HTML模板
- 添加DNSSEC标志显示逻辑
- 使用条件渲染仅当DNSSEC为true时显示
### 4. 预期效果
- 日志查询界面的每个条目在域名下方显示DNSSEC标志
- 使用DNSSEC的查询显示绿色标志
- 未使用DNSSEC的查询不显示标志
- 标志与现有界面风格协调,清晰易识别
### 5. 注意事项
- 确保DNSSEC标志的视觉设计与现有界面一致
- 确保标志在各种屏幕尺寸下都能正确显示
- 考虑添加悬停提示,说明该标志的含义
- 确保性能不受影响,标志渲染高效
### 6. 实现时间线
- 步骤115分钟扩展QueryLog结构体
- 步骤220分钟记录DNSSEC信息
- 步骤330分钟修改前端页面
- 步骤415分钟测试实现
### 7. 风险评估
- 前端代码位置不明确:需要仔细查找处理日志显示的代码
- DNSSEC检测逻辑可能复杂需要确保准确判断DNSSEC使用情况
- 图标资源问题:确保使用的图标库可用
### 8. 成功标准
- DNS服务器正常编译运行
- Web界面能正确显示DNSSEC标志
- 使用DNSSEC的查询显示绿色标志
- 未使用DNSSEC的查询不显示标志
- 标志显示位置正确,视觉效果良好

View File

@@ -0,0 +1,69 @@
## 实现计划
### 1. 分析当前代码结构
* **HTML结构**:日志表格在`updateLogsTable`函数中动态生成
* **数据处理**:每条日志包含`Result`字段表示查询结果allowed, blocked, error
* **API需求**:需要拦截/放行域名的API接口
### 2. 修改内容
#### 2.1 修改`updateLogsTable`函数
* 在表格中添加操作列
* 根据`log.Result`字段决定显示哪个按钮:
- 如果`log.Result``blocked`,显示"放行"按钮
- 否则,显示"拦截"按钮
* 为按钮添加点击事件处理函数
#### 2.2 实现拦截/放行功能
* 添加`blockDomain`函数调用API拦截域名
* 添加`allowDomain`函数调用API放行域名
* 实现按钮点击事件的处理逻辑
* 添加操作成功后的反馈机制
#### 2.3 更新表格头部
* 在表格头部添加"操作"列
* 确保表格的`colspan`属性正确更新
### 3. 实现细节
* **按钮样式**:使用现有的样式类,保持界面一致性
* **事件绑定**:为动态生成的按钮绑定点击事件
* **API调用**:使用现有的`apiRequest`函数进行API调用
* **反馈机制**:操作成功后显示提示信息
* **数据刷新**:操作完成后刷新日志列表,显示最新状态
### 4. 预期效果
* 日志详情表格右侧增加"操作"列
* 对于被拦截的域名,显示"放行"按钮
* 对于未被拦截的域名,显示"拦截"按钮
* 点击按钮后,成功执行相应操作并刷新列表
* 操作过程中显示反馈信息
### 5. 实现步骤
1. 修改`updateLogsTable`函数,添加操作列
2. 更新表格头部,添加"操作"列
3. 实现`blockDomain``allowDomain`函数
4. 为按钮绑定点击事件
5. 添加操作反馈机制
6. 测试功能完整性
## 关键代码修改点
* **`updateLogsTable`函数**:在生成表格行时添加操作列
* **表格头部**:添加"操作"列标题
* **新增函数**`blockDomain``allowDomain`
* **事件绑定**:为动态生成的按钮添加点击事件处理
## 技术要点
* 动态生成元素的事件绑定
* API调用的错误处理
* 操作反馈机制的实现
* 数据刷新逻辑
* 保持界面样式一致性

View File

@@ -0,0 +1,73 @@
## 实现计划在请求列表中显示DNSSEC标志
### 1. 需求分析
-`enableDNSSEC=true`请求列表中返回了DNSKEY的域名显示绿色的DNSSEC标志
- 标志应显示在域名名称旁边
- 保持现有界面风格一致
### 2. 实现步骤
#### 步骤1修改后端数据结构
-`dns/server.go`中扩展`BlockedDomain`结构体,添加`DNSSEC bool`字段
- 修改`GetTopResolvedDomains`函数返回包含DNSSEC标志的数据
- 记录每个域名是否使用了DNSSEC
#### 步骤2实现DNSSEC记录追踪
-`handleDNSRequest`函数中当检测到DNSSEC记录时更新域名的DNSSEC标志
- 添加一个新的映射表记录每个域名的DNSSEC使用情况
#### 步骤3修改API响应格式
- 修改`http/server.go`中的`handleTopDomains``handleTopResolvedDomains`函数
- 在返回的数据中添加`dnssec`字段
#### 步骤4修改前端显示逻辑
- 修改`static/js/dashboard.js`中的`updateTopDomainsTable`函数
- 在域名名称后添加DNSSEC标志
- 使用Font Awesome的锁图标绿色显示
#### 步骤5测试实现
- 编译并运行DNS服务器
- 访问Web界面检查请求列表
- 验证DNSSEC标志是否正确显示
### 3. 技术细节
#### 3.1 后端实现
- **文件**`/root/dns/dns/server.go`
- **修改内容**
- 扩展数据结构添加DNSSEC字段
- 实现DNSSEC记录追踪
- 修改API响应格式
#### 3.2 前端实现
- **文件**`/root/dns/static/js/dashboard.js`
- **修改内容**
- 修改`updateTopDomainsTable`函数
- 添加DNSSEC标志显示逻辑
- 使用条件渲染仅当dnssec为true时显示
#### 3.3 DNSSEC检测方法
- 检查响应中是否包含DNSKEY或RRSIG记录
- 记录每个域名的DNSSEC使用情况
- 在返回请求列表时包含该信息
### 4. 预期效果
- 请求列表中使用DNSSEC的域名显示绿色锁图标
- 标志与现有界面风格协调
- 性能不受影响
- 与现有功能兼容
### 5. 注意事项
- 确保DNSSEC标志的视觉设计与现有界面一致
- 确保标志在各种屏幕尺寸下都能正确显示
- 考虑添加悬停提示,说明该标志的含义
- 确保性能不受影响,数据更新高效
### 6. 实现时间线
- 步骤120分钟修改后端数据结构
- 步骤225分钟实现DNSSEC记录追踪
- 步骤315分钟修改API响应格式
- 步骤415分钟修改前端显示逻辑
- 步骤510分钟测试实现
通过以上实现请求列表将能够正确显示使用了DNSSEC的域名提高DNS查询的安全性可视化方便管理员监控和管理。

View File

@@ -0,0 +1,98 @@
# DNS缓存实现计划
## 问题分析
当前DNS缓存只支持内存缓存需要扩展为支持文件缓存或内存缓存两种方式并添加缓存大小和TTL限制。
## 实现目标
- 支持文件缓存和内存缓存两种模式
- 支持设置缓存大小MB0表示不缓存
- 支持设置最大和最小TTL
- 保持原有的LRU缓存机制
- 支持持久化存储(文件缓存模式)
- 确保线程安全
## 实现方案
### 1. 修改配置结构
-`DNSConfig`中添加:
- `CacheMode`:缓存模式,可选值:"memory"(内存缓存)或"file"(文件缓存)
- `CacheSize`缓存大小MB0表示不缓存
- `MaxCacheTTL`最大缓存TTL分钟
- `MinCacheTTL`最小缓存TTL分钟
- `CacheFilePath`:缓存文件路径(文件缓存模式使用)
### 2. 重构缓存实现
- 创建`CacheItem`结构:包含响应、过期时间、大小等信息
- 创建`CacheInterface`接口:定义缓存的基本操作
- 实现`MemoryCache`基于内存的LRU缓存
- 实现`FileCache`:基于文件的缓存,使用内存缓存+定期持久化
### 3. 缓存大小管理
- 为每个缓存项计算大小
- 维护总缓存大小计数器
- 当超过最大缓存大小时,淘汰最久未使用的项
- 支持设置0表示不缓存
### 4. TTL管理
- 支持设置最大和最小TTL
- 解析响应时取响应TTL、最大TTL、最小TTL的合理值
- 确保缓存项不会无限期缓存
### 5. 文件缓存实现
- 内存缓存作为主缓存
- 定期将内存缓存持久化到文件
- 启动时从文件加载缓存
- 支持缓存文件的压缩和优化
### 6. 缓存策略
- LRU淘汰算法
- 定期清理过期缓存
- 支持缓存项大小计算
- 支持缓存统计
## 实现步骤
1. **修改配置**
-`config/config.go`中扩展`DNSConfig`结构
- 添加默认值处理
2. **实现缓存接口**
-`dns/cache.go`中定义`CacheInterface`
- 实现`CacheItem`结构
3. **实现内存缓存**
- 实现`MemoryCache`结构
- 实现LRU淘汰逻辑
- 实现缓存大小管理
4. **实现文件缓存**
- 实现`FileCache`结构,包装`MemoryCache`
- 实现定期持久化逻辑
- 实现从文件加载缓存
5. **集成到DNS服务器**
- 修改`dns/server.go`中的缓存初始化
- 根据配置选择缓存模式
- 传递正确的缓存参数
6. **添加统计和监控**
- 支持获取缓存统计信息
- 支持手动清理缓存
## 技术要点
- **缓存大小计算**计算每个DNS响应的大小
- **TTL处理**合理处理不同来源的TTL值
- **文件格式**使用JSON或二进制格式平衡性能和可读性
- **并发安全**:使用读写锁保护缓存操作
- **错误处理**优雅处理文件IO错误
- **性能优化**减少文件IO次数使用批量操作
## 预期效果
- 灵活的缓存配置选项
- 支持不同场景的缓存需求
- 提高DNS解析性能
- 减少对上游DNS服务器的依赖
- 支持缓存持久化
- 更好的资源管理

View File

@@ -0,0 +1,58 @@
## 实现计划
### 1. 配置文件修改
* **修改`/root/dns/config/config.go`**
*`DNSConfig`结构体中添加`PrefixDomain []string`字段用于支持search domain功能
*`LoadConfig`函数中添加`prefixDomain`的默认值处理
### 2. DNS请求处理逻辑修改
* **修改`/root/dns/dns/server.go`中的`forwardDNSRequestWithCache`函数**
* 强化domainSpecificDNS逻辑确保当域名匹配时只使用指定的DNS服务器
* 移除向DNSSEC专用服务器发送请求的逻辑当域名匹配domainSpecificDNS时
* 确保匹配域名的DNS查询结果不会被其他DNS服务器的响应覆盖
* **修改`/root/dns/dns/server.go`中的`handleDNSRequest`函数**
* 实现search domain功能当直接查询失败时尝试添加prefixDomain中指定的域名前缀
* 按照/etc/resolv.conf中的search domain逻辑处理查询请求
### 3. 配置文件示例更新
* **更新配置文件示例**
* 添加`prefixDomain`配置项示例
* 说明search domain功能的使用方法
### 4. 测试验证
* 测试domainSpecificDNS强制使用功能确保匹配的域名只使用指定的DNS服务器
* 测试search domain功能确保能够正确处理带前缀的域名查询
* 测试不同配置组合下的功能正确性
## 预期效果
1. 当域名匹配domainSpecificDNS配置时无论DNSSEC是否启用只使用指定的DNS服务器
2. 支持search domain功能能够自动尝试添加配置的域名前缀
3. 配置简单直观,与/etc/resolv.conf的search domain行兼容
## 实现要点
* 确保domainSpecificDNS配置的优先级最高
* 实现高效的search domain查询逻辑避免不必要的网络请求
* 保持代码的可读性和可维护性
* 确保与现有功能的兼容性

View File

@@ -0,0 +1,87 @@
# 实现hash路由功能避免刷新时返回到主页
## 问题分析
当前系统使用简单的页面切换逻辑,通过隐藏/显示不同的内容区域来实现页面切换。这种方式的缺点是:
1. 刷新页面后会返回到主页
2. 无法通过URL直接访问特定页面
3. 无法在浏览器历史记录中保存页面状态
## 解决方案
实现hash路由功能将页面状态保存在URL的hash部分例如
- http://localhost:8080/#dashboard
- http://localhost:8080/#blacklists
- http://localhost:8080/#query
- http://localhost:8080/#config
## 实现步骤
### 1. 修改handlePageSwitch函数
* 在页面切换时更新URL的hash
* 移除e.preventDefault()允许默认的hash变化
### 2. 添加hashchange事件监听器
* 监听window的hashchange事件
* 在hash变化时根据hash值显示相应的内容
* 更新页面标题和活动菜单项
### 3. 添加initHashRoute函数
* 在页面加载时调用
* 获取URL的hash值
* 如果没有hash值默认设置为#dashboard
* 根据hash值显示相应的内容
* 更新页面标题和活动菜单项
### 4. 在页面加载时调用initHashRoute函数
* 确保在DOMContentLoaded事件中调用initHashRoute函数
## 预期效果
* 页面切换时URL的hash会相应更新
* 刷新页面后会显示与URL hash对应的页面
* 默认情况下http://localhost:8080会显示dashboard内容URL变为http://localhost:8080/#dashboard
* 可以通过URL直接访问特定页面
* 浏览器历史记录中会保存页面状态
## 技术要点
* 使用window.location.hash获取和设置URL的hash值
* 使用window.addEventListener('hashchange', ...)监听hash变化
* 使用window.addEventListener('DOMContentLoaded', ...)在页面加载时初始化
* 确保在页面加载时检查hash值如果没有则设置为#dashboard
## 实现时间
* 预计30分钟完成所有修改和测试
## 风险评估
* 低风险:修改范围明确,不涉及核心功能
* 可回滚:所有修改均为前端修改,可通过恢复文件轻松回滚
## 依赖关系
* 依赖现有的页面切换逻辑
* 依赖现有的CSS类和HTML结构
## 测试策略
* 手动测试页面切换时URL hash的变化
* 测试刷新页面后是否显示正确的页面
* 测试直接访问带hash的URL是否显示正确的页面
* 测试默认情况下是否显示dashboard内容
## 验收标准
* 页面切换时URL的hash会相应更新
* 刷新页面后会显示与URL hash对应的页面
* 默认情况下http://localhost:8080会显示dashboard内容URL变为http://localhost:8080/#dashboard
* 可以通过URL直接访问特定页面
* 浏览器历史记录中会保存页面状态

View File

@@ -0,0 +1,96 @@
## 问题分析
当前系统已经实现了黑名单管理的后端API但前端界面缺少完整的黑名单管理功能。具体来说
1. 后端API已经实现了黑名单管理的所有功能
- GET /api/shield/blacklists - 获取所有黑名单
- POST /api/shield/blacklists - 添加黑名单
- PUT /api/shield/blacklists - 更新黑名单
- DELETE /api/shield/blacklists/{name} - 删除黑名单
2. 前端已经有了一些基础功能:
- loadRemoteBlacklists函数用于加载远程黑名单
- setupShieldEventListeners函数用于设置事件监听器
- 页面上有blacklist-count元素用于显示黑名单数量
3. 但是,前端缺少完整的黑名单管理界面,包括:
- 黑名单列表展示
- 添加/编辑/删除黑名单的功能
- 启用/禁用黑名单的功能
- 更新黑名单的功能
## 实现方案
1. **添加黑名单管理HTML界面**
- 在shield-content中添加黑名单管理区域
- 包括黑名单列表、添加/编辑表单、操作按钮等
2. **实现黑名单列表的加载和展示**
- 完善loadRemoteBlacklists函数将黑名单数据渲染到页面上
- 显示黑名单的名称、URL、状态、更新时间等信息
- 添加操作按钮(编辑、删除、启用/禁用、更新)
3. **实现添加/编辑黑名单功能**
- 添加表单用于输入黑名单名称、URL等信息
- 实现表单提交功能调用后端API添加/编辑黑名单
4. **实现删除黑名单功能**
- 为删除按钮添加事件监听器
- 调用后端API删除黑名单
- 更新黑名单列表
5. **实现启用/禁用黑名单功能**
- 为启用/禁用按钮添加事件监听器
- 调用后端API更新黑名单状态
- 更新黑名单列表
6. **实现更新黑名单功能**
- 为更新按钮添加事件监听器
- 调用后端API更新黑名单
- 显示更新状态
## 实现步骤
1. **修改HTML文件**
- 在shield-content中添加黑名单管理区域
- 添加黑名单列表表格
- 添加添加/编辑黑名单表单
- 添加操作按钮
2. **修改shield.js文件**
- 完善loadRemoteBlacklists函数渲染黑名单列表
- 添加添加/编辑/删除黑名单的函数
- 添加启用/禁用黑名单的函数
- 添加更新黑名单的函数
- 完善setupShieldEventListeners函数添加黑名单管理相关的事件监听器
3. **测试功能**
- 测试黑名单列表的加载和展示
- 测试添加/编辑/删除黑名单功能
- 测试启用/禁用黑名单功能
- 测试更新黑名单功能
## 预期效果
- 用户可以在web界面上查看所有黑名单
- 用户可以添加新的黑名单
- 用户可以编辑现有黑名单
- 用户可以删除黑名单
- 用户可以启用/禁用黑名单
- 用户可以手动更新黑名单
- 所有操作都能实时反映到页面上
## 注意事项
- 确保界面设计与现有系统风格一致
- 确保所有操作都有适当的错误处理和提示
- 确保所有操作都能实时更新页面数据
- 确保功能实现符合后端API的要求
## 技术细节
- 使用HTML、CSSTailwind CSS和JavaScript实现前端界面
- 使用fetch API调用后端API
- 使用事件监听器处理用户交互
- 使用DOM操作更新页面内容
- 使用异步/等待处理异步操作

View File

@@ -0,0 +1,31 @@
# 实现域名信息显示
## 需求分析
用户需要在日志详情页面的红色框区域显示域名信息,包括:
- 网站名称(带图标)
- 网站类别
- 所属公司
## 代码分析
1. 目前代码已经包含了获取域名信息的功能:
- `loadDomainInfoDatabase` 函数加载域名信息数据库
- `getDomainInfo` 函数根据域名查找对应的网站信息
- `showLogDetailModal` 函数显示日志详情,包括域名信息
2. 域名信息已经在日志详情模态框中显示,但需要确保它在指定的红色框区域正确显示
## 实现计划
1. **优化域名信息显示样式**:调整 `showLogDetailModal` 函数中域名信息的HTML结构和样式确保它在红色框内正确显示
2. **增强域名匹配逻辑**:改进 `getDomainInfo` 函数,提高域名匹配的准确性
3. **添加错误处理**:确保在域名信息加载失败时,页面能够优雅处理
4. **测试功能**:验证域名信息能够正确显示在红色框区域
## 预期效果
- 当日志详情弹窗打开时,在红色框区域显示域名的完整信息
- 显示格式:
```
[图标] 网站名称
类别: [类别名称]
所属公司: [公司名称]
```
- 如果没有匹配的域名信息,显示"无"

View File

@@ -0,0 +1,72 @@
# 改进DNS查询模式实现
## 1. 当前实现分析
* **parallel**: 已基本实现并行请求,但缺少超时处理
* **loadbalance**: 简单轮询,未考虑服务器失败率和权重
* **fastest-ip**: 仅顺序请求未实现真正的TCP连接速度测量
## 2. 改进计划
### 2.1 扩展Server结构体
* 添加服务器状态跟踪字段:
* `serverStats`: 记录每个上游服务器的成功/失败次数、最后响应时间
* `serverStatsMutex`: 保护服务器状态的互斥锁
### 2.2 实现加权随机负载均衡
* 为每个服务器计算权重,基于成功/失败比率
* 实现加权随机选择算法
*`forwardDNSRequestWithCache`中使用新算法
### 2.3 实现真正的最快服务器选择
* 添加`measureServerSpeed`函数测量TCP连接速度
* 为每个服务器维护连接速度历史
* 选择连接速度最快的服务器进行查询
### 2.4 优化并行请求模式
* 添加请求超时处理
* 实现更快的响应返回机制(收到第一个有效响应即可返回)
### 2.5 统一DNSSEC服务器请求处理
* 为DNSSEC服务器也实现相同的查询模式支持
* 确保DNSSEC查询与普通查询使用一致的逻辑
## 3. 文件修改
* `/root/dns/dns/server.go`: 扩展Server结构体实现新的查询模式逻辑
* `/root/dns/config/config.go`: 确保配置支持新的查询模式
## 4. 测试计划
* 运行现有测试脚本验证基本功能
* 测试不同查询模式下的响应时间
* 验证负载均衡模式下的服务器选择分布
* 验证最快服务器模式下的速度测量准确性
## 5. 预期效果
* 负载均衡模式:根据服务器性能和可用性智能选择
* 并行请求模式:更快的响应速度和更好的容错性
* 最快服务器模式:选择响应速度最快的服务器,提高查询效率

View File

@@ -0,0 +1,18 @@
1. **更新getIpGeolocation函数**修改函数逻辑使用API响应中的addr字段来显示完整的地理位置信息
2. **处理编码问题**:确保正确处理中文编码
3. **维护缓存机制**保留现有的24小时缓存机制提高性能
4. **测试不同IP类型**确保公网IP和内网IP都能正确显示
### 具体修改点
- **文件**`/root/dns/static/js/logs.js`
- **函数**`getIpGeolocation`
- **修改内容**
- 从API响应中提取`addr`字段
- 直接使用addr字段作为完整的地理位置信息
- 保持对私有IP的特殊处理
- 维护现有的缓存机制
### 预期效果
- 公网IP显示格式"IP地址 (完整地理位置来自addr字段)"
- 内网IP显示格式"IP地址 (内网 内网)"
- 未知IP显示格式"IP地址 (未知 未知)"

View File

@@ -0,0 +1,84 @@
# 配置数据获取优先级机制和错误处理
## 1. 改进 API 请求处理逻辑
### 1.1 优化 `apiRequest` 函数
- 修改 `apiRequest` 函数,确保它能正确处理各种错误情况
- 统一错误返回格式,便于上层调用者处理
- 添加超时处理,避免长时间等待
### 1.2 增强 API 方法的错误处理
-`api.js` 中为每个 API 方法添加更严格的错误检查
- 确保返回数据符合预期格式
- 提供更详细的错误日志
## 2. 实现数据加载状态管理
### 2.1 添加加载状态指示器
- 在 HTML 中为 TOP 客户端和 TOP 域名表格添加加载状态指示器
- 显示 "加载中..." 文本或动画
### 2.2 实现状态切换逻辑
- 在数据请求开始时显示加载状态
- 请求成功后显示真实数据
- 请求失败后显示错误信息或模拟数据
## 3. 完善错误处理机制
### 3.1 分类处理错误情况
- **网络连接失败**:显示连接错误信息,使用模拟数据
- **服务器错误**:显示服务器错误信息,使用模拟数据
- **空响应**:显示空数据状态,使用模拟数据
- **数据格式错误**:显示数据格式错误信息,使用模拟数据
### 3.2 添加错误信息显示
- 在表格上方或下方显示错误信息
- 提供重试按钮,允许用户手动重试请求
## 4. 优化用户体验
### 4.1 平滑过渡效果
- 添加数据更新的平滑过渡动画
- 避免页面闪烁
### 4.2 提供有用的反馈
- 显示数据更新时间
- 显示数据来源(真实数据或模拟数据)
- 提供数据刷新按钮
## 5. 实现数据获取优先级机制
### 5.1 明确数据优先级
- 优先级 1服务器真实数据
- 优先级 2本地缓存数据如果有
- 优先级 3模拟数据
### 5.2 实现优先级逻辑
- 优先尝试获取服务器真实数据
- 如果失败,检查是否有本地缓存数据
- 如果没有缓存数据,使用模拟数据
## 6. 测试和验证
### 6.1 测试各种错误场景
- 模拟网络连接失败
- 模拟服务器返回错误状态码
- 模拟服务器返回空响应
- 模拟服务器返回错误格式数据
### 6.2 验证数据优先级机制
- 确保优先使用服务器真实数据
- 确保在各种错误情况下能正确切换到模拟数据
## 7. 代码优化和重构
### 7.1 提取公共逻辑
- 提取数据获取和状态管理的公共逻辑
- 减少代码重复
### 7.2 提高代码可读性
- 添加清晰的注释
- 使用有意义的变量名
- 优化代码结构
通过以上实现,系统将能够优先使用来自服务器的真实数据,仅在必要时使用模拟数据,并提供良好的用户体验和错误处理。

View File

@@ -0,0 +1,117 @@
# 实现系统启动时自动创建文件和文件夹
## 问题分析
当前系统启动时,如果配置文件中指定的文件或文件夹不存在,会导致报错,影响系统正常启动。需要实现自动创建功能,确保系统能够顺利启动。
## 解决方案
### 1. 自动创建配置文件
* 在main.go中添加检查配置文件是否存在的逻辑
* 如果配置文件不存在创建默认的config.json文件
### 2. 自动创建数据文件夹
* 根据配置文件中的路径,创建所需的文件夹:
* 数据文件夹(默认:./data
* 远程规则缓存文件夹(默认:./data/remote_rules
* 日志文件夹根据配置文件中的Log.File路径
### 3. 自动创建文件
* 根据配置文件中的路径,创建所需的文件:
* 本地规则文件默认data/rules.txt
* Hosts文件默认data/hosts.txt
* 统计数据文件(默认:./data/stats.json
* Shield统计数据文件默认./data/shield_stats.json
## 实现步骤
### 1. 修改main.go文件
* 在命令行参数解析后,添加检查配置文件是否存在的逻辑
* 如果配置文件不存在创建默认的config.json文件
* 调用LoadConfig加载配置
### 2. 添加createDefaultConfig函数
* 实现创建默认配置文件的功能
* 写入默认的配置内容到config.json
### 3. 添加createRequiredFiles函数
* 实现创建所需文件和文件夹的功能
* 根据配置文件中的路径,创建所需的文件夹
* 根据配置文件中的路径,创建所需的文件
### 4. 在main.go中调用createRequiredFiles函数
* 在配置加载完成后调用createRequiredFiles函数
* 确保在初始化屏蔽管理系统之前创建所需的文件和文件夹
## 预期效果
* 系统启动时如果配置文件不存在自动创建默认的config.json文件
* 自动创建所需的文件夹data、data/remote_rules、logs等
* 自动创建所需的文件rules.txt、hosts.txt、stats.json等
* 系统能够顺利启动,不会因为找不到文件而报错
## 技术要点
* 使用os.Stat函数检查文件或文件夹是否存在
* 使用os.MkdirAll函数创建文件夹包括父文件夹
* 使用os.Create函数创建文件
* 确保在初始化屏蔽管理系统之前创建所需的文件和文件夹
* 确保在初始化日志系统之前创建日志文件夹
## 实现时间
* 预计1-2小时完成所有修改和测试
## 风险评估
* 低风险:修改范围明确,不涉及核心功能
* 可回滚:所有修改均为添加新功能,可通过恢复文件轻松回滚
## 依赖关系
* 依赖os包的文件操作功能
* 依赖config包的配置结构
## 测试策略
* 手动测试删除配置文件、文件夹和文件,然后启动服务器,验证是否自动创建
* 验证创建的文件和文件夹是否符合配置文件中的路径
* 验证服务器能够顺利启动,没有报错
## 验收标准
* 系统启动时如果配置文件不存在自动创建默认的config.json文件
* 自动创建所需的文件夹data、data/remote_rules、logs等
* 自动创建所需的文件rules.txt、hosts.txt、stats.json等
* 系统能够顺利启动,不会因为找不到文件而报错
* 所有创建的文件和文件夹都符合配置文件中的路径

View File

@@ -0,0 +1,40 @@
## 问题分析
用户要求在缓存结果中包含DNSSEC信息时在缓存的请求条目后边添加相同的DNSSEC标记格式为`类型: AAAA, 允许, 缓存 <DNSSEC标记>`。如果不包含DNSSEC信息则不添加标记。
## 代码检查
1. **当前DNSSEC标记实现**
-`/root/dns/static/js/logs.js``updateLogsTable`函数中,已经实现了根据`log.DNSSEC`字段显示DNSSEC标记的功能
```javascript
<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>
```
2. **DNSSEC信息存储**
- `QueryLog`结构体包含`DNSSEC`字段用于记录是否使用了DNSSEC
- 在`handleDNSRequest`函数中会检查响应是否包含DNSSEC信息并记录到日志中
- 在缓存处理中会检查缓存响应的AD标志和RRSIG记录确定DNSSEC状态
3. **缓存响应的DNSSEC处理**
- 当从缓存返回响应时会检查响应是否包含RRSIG记录或AD标志以确定DNSSEC状态
- 但在日志记录时已经正确传递了DNSSEC状态
## 解决方案
当前实现已经基本满足用户要求但需要确保在所有显示查询日志的地方都正确显示DNSSEC标记。根据检查只有`logs.js`中的`updateLogsTable`函数显示查询日志且已经实现了DNSSEC标记功能。
## 验证步骤
1. 确认`logs.js`中的`updateLogsTable`函数已经正确实现了DNSSEC标记显示
2. 确认`QueryLog`结构体中的`DNSSEC`字段被正确设置
3. 确认缓存响应的DNSSEC状态被正确检查和记录
4. 运行测试,验证缓存请求条目显示格式为:`类型: AAAA, 允许, 缓存 <DNSSEC标记>`
## 预期结果
- 当缓存结果包含DNSSEC信息时显示`类型: AAAA, 允许, 缓存 <i class="fa fa-lock"></i> DNSSEC`
- 当缓存结果不包含DNSSEC信息时显示`类型: AAAA, 允许, 缓存`
- DNSSEC标记使用绿色锁图标颜色为绿色
## 注意事项
- 确保DNSSEC标记只在缓存请求条目中显示与实时请求条目保持一致的格式
- 确保DNSSEC标记的颜色和图标与整体UI风格一致
- 确保DNSSEC标记只在包含DNSSEC信息时显示不包含时不显示
## 实现状态
当前实现已经满足用户要求,不需要额外修改代码。需要运行测试验证功能是否正常工作。

View File

@@ -0,0 +1,33 @@
# 实现远程黑名单管理功能
## 1. 分析现有代码
- 远程黑名单管理功能已经在`shield.js`文件中实现
- 页面结构已经存在于HTML文件中
- 存在`blacklists.js``shield.js`两个可能冲突的实现
## 2. 解决方案
### 2.1 检查并解决代码冲突
- 移除或整合`blacklists.js`文件,避免与`shield.js`冲突
- 确保只使用一个实现来管理远程黑名单
### 2.2 确保页面加载时正确初始化
- 检查`shield.js`中的初始化逻辑
- 确保`initShieldPage`函数在页面加载和切换到屏蔽管理页面时被正确调用
### 2.3 确保web更新数据时同时更新服务器
- 检查现有的添加、更新、删除、启用/禁用黑名单的功能
- 确保每个操作都通过API请求更新服务器数据
- 验证操作完成后是否重新加载数据
## 3. 实现步骤
1. 移除`blacklists.js`文件,避免与`shield.js`冲突
2. 检查并确保`shield.js`中的初始化逻辑正确
3. 测试远程黑名单管理功能的各个操作
4. 验证页面加载时是否正确拉取服务器数据
5. 验证web更新数据时是否同时更新服务器数据
## 4. 预期结果
- 页面加载时自动拉取服务器数据
- 添加、更新、删除、启用/禁用黑名单时,同时更新服务器数据
- 操作完成后,页面数据自动刷新
- 没有代码冲突,功能正常运行

View File

@@ -0,0 +1,39 @@
# 屏蔽规则解析修复计划
## 问题分析
通过分析代码,我发现了无法处理`/domain.com/`类似规则的问题:
1. **当前实现**
- 当处理`/domain.com/`这样的规则时,代码会将其编译为正则表达式`domain.com`
- 然后使用`MatchString(domain)`来检查域名是否匹配该正则表达式
- 但是,`MatchString`会检查整个字符串是否匹配,而不是检查域名是否包含该模式
- 例如,对于域名`example.com`,正则表达式`domain.com`不会匹配,因为它只匹配字符串"domain.com"
2. **用户期望**
- 用户期望`/domain.com/`匹配所有包含"domain.com"的域名,比如`sub.domain.com`
- 但是当前实现中,它只会匹配精确的字符串"domain.com"
## 解决方案
### 1. 修改正则表达式规则处理
我们需要修改`parseRule`函数中对正则表达式规则的处理,确保`/domain.com/`这样的规则能正确匹配包含该模式的域名。
### 2. 优化匹配逻辑
我们需要确保正则表达式规则能正确匹配域名,无论是精确匹配还是包含匹配。
## 实现步骤
1. **修改`parseRule`函数**
- 对于以`/`开头和结尾的规则,确保其能正确匹配包含该模式的域名
- 或者,添加一个选项,允许用户指定匹配模式
2. **测试修复效果**
- 确保`/domain.com/`规则能匹配`sub.domain.com`等域名
- 确保其他规则类型仍能正常工作
## 预期效果
通过以上修复,屏蔽规则解析将能够正确处理`/domain.com/`类似的规则,匹配所有包含该模式的域名,提高用户体验。

View File

@@ -0,0 +1,81 @@
## 问题分析
服务器出现"Server Failed"问题的主要原因是:
1. **DNS查询超时设置过短**配置文件中timeout设置为5ms导致几乎所有DNS查询都超时失败
2. **parallel模式响应处理逻辑缺陷**在某些情况下即使主DNS服务器有响应也可能因为DNSSEC验证或其他原因被忽略
3. **DNSSEC处理影响正常查询**启用DNSSEC后系统会优先选择带DNSSEC记录的响应但如果所有DNSSEC服务器都失败可能导致没有响应
## 解决方案
### 1. 确保超时设置正确
* **已修复**将配置文件中的timeout从5ms修改为5000ms
* 验证代码中默认值设置正确,确保配置文件加载时能正确应用默认值
### 2. 优化parallel模式响应处理逻辑
**问题**当前parallel模式下只有当响应是成功RcodeSuccess或NXDOMAINRcodeNameError时才会被考虑作为最佳响应且优先选择带DNSSEC记录的响应。
**修复**
* 修改`dns/server.go`中的parallel模式处理逻辑
* 确保用户配置的主DNS服务器upstreamDNS响应优先被使用即使它没有DNSSEC记录
* 只有当主DNS服务器完全失败时才考虑使用DNSSEC专用服务器的响应
* 确保在所有情况下都能返回至少一个备选响应
### 3. 增强错误处理机制
**问题**当所有DNS服务器都返回非成功响应时系统可能无法找到合适的响应返回给客户端。
**修复**
*`dns/server.go`中增强错误处理
* 确保即使所有上游服务器都失败也能返回一个有效的DNS响应
* 优化备选响应的选择逻辑,确保总有一个可用的响应
* 添加更详细的日志记录,便于调试
### 4. 优化DNSSEC处理逻辑
**问题**当前DNSSEC处理逻辑可能导致主DNS服务器的响应被忽略。
**修复**
* 调整DNSSEC专用服务器请求逻辑只有当主DNS服务器完全失败时才使用
* 确保DNSSEC验证失败不会影响正常的DNS查询结果
* 优化DNSSEC记录检查逻辑确保准确判断DNSSEC记录
## 修复步骤
1. **验证超时设置**确保配置文件中的timeout已设置为5000ms
2. **修改parallel模式响应处理**:优化`dns/server.go`中parallel模式的响应选择逻辑
3. **增强备选响应机制**:确保总有一个可用的响应返回给客户端
4. **优化DNSSEC处理**调整DNSSEC专用服务器请求时机和优先级
5. **添加详细日志**:增加调试日志,便于后续问题定位
6. **测试验证**重启服务器并测试DNS查询功能
## 预期效果
* DNS查询成功率显著提高不再出现大量"Server Failed"错误
* 主DNS服务器响应优先被使用确保查询效率
* DNSSEC功能正常工作同时不影响正常DNS查询
* 系统更加稳定,能够处理各种异常情况
## 关键文件修改
* `/root/dns/config.json`确保timeout设置正确
* `/root/dns/dns/server.go`优化parallel模式响应处理、错误处理和DNSSEC逻辑

View File

@@ -0,0 +1,45 @@
### 问题分析
当前的`dns/server.go`文件被误删了很多内容,导致编译失败。从编译错误可以看出,`http/server.go`文件中引用了`dns.Stats`结构体中的一些字段,如`QueryTypes``SourceIPs``AvgResponseTime``DNSSECQueries`等,但这些字段在当前的`dns/server.go`文件中都不存在。
### 恢复方案
1. **恢复完整的结构体定义**
- `BlockedDomain`结构体中添加`DNSSEC`字段
- `Stats`结构体中添加所有缺失的字段
- `Server`结构体中添加所有缺失的字段
- `StatsData`结构体中添加所有缺失的字段
2. **恢复所有缺失的方法**
- `updateClientStats`
- `updateResolvedDomainStatsWithDNSSEC`
- `updateDomainDNSSECStatus`
- `addQueryLog`
- `GetStartTime`
- `GetQueryLogs`
- `GetQueryLogsCount`
- `GetQueryStats`
- `GetTopClients`
- `GetDailyStats`
- `GetMonthlyStats`
- `getIpGeolocation`
- `fetchIpGeolocationFromAPI`
- `loadQueryLogs`
- `saveQueryLogs`
- `startCpuUsageMonitor`
- `getSystemCpuUsage`
3. **恢复DNSSEC相关功能**
- 恢复`forwardDNSRequestWithCache`函数,替代当前的`forwardDNSRequest`函数
- 恢复DNSSEC验证逻辑
- 恢复DNS缓存功能
### 具体修改
1. 替换整个`dns/server.go`文件,恢复完整的内容
2. 确保所有结构体字段和方法都完整存在
3. 确保DNSSEC功能正常工作
### 测试计划
1. 编译恢复后的代码
2. 启动DNS服务器并启用DNSSEC
3. 使用dig命令测试DNSSEC记录查询
4. 检查HTTP控制台是否正常工作
5. 检查日志中是否有DNSSEC验证相关的记录

View File

@@ -0,0 +1,50 @@
# 改进DNS查询模式实现
## 1. 当前实现分析
- **parallel**: 已基本实现并行请求,但缺少超时处理
- **loadbalance**: 简单轮询,未考虑服务器失败率和权重
- **fastest-ip**: 仅顺序请求未实现真正的TCP连接速度测量
## 2. 改进计划
### 2.1 扩展Server结构体
- 添加服务器状态跟踪字段:
- `serverStats`: 记录每个上游服务器的成功/失败次数、最后响应时间
- `serverStatsMutex`: 保护服务器状态的互斥锁
### 2.2 实现加权随机负载均衡
- 为每个服务器计算权重,基于成功/失败比率
- 实现加权随机选择算法
-`forwardDNSRequestWithCache`中使用新算法
### 2.3 实现真正的最快服务器选择
- 添加`measureServerSpeed`函数测量TCP连接速度
- 为每个服务器维护连接速度历史
- 选择连接速度最快的服务器进行查询
### 2.4 优化并行请求模式
- 添加请求超时处理
- 实现更快的响应返回机制(收到第一个有效响应即可返回)
### 2.5 统一DNSSEC服务器请求处理
- 为DNSSEC服务器也实现相同的查询模式支持
- 确保DNSSEC查询与普通查询使用一致的逻辑
## 3. 文件修改
- `/root/dns/dns/server.go`: 扩展Server结构体实现新的查询模式逻辑
- `/root/dns/config/config.go`: 确保配置支持新的查询模式
## 4. 测试计划
- 运行现有测试脚本验证基本功能
- 测试不同查询模式下的响应时间
- 验证负载均衡模式下的服务器选择分布
- 验证最快服务器模式下的速度测量准确性
## 5. 预期效果
- 负载均衡模式:根据服务器性能和可用性智能选择
- 并行请求模式:更快的响应速度和更好的容错性
- 最快服务器模式:选择响应速度最快的服务器,提高查询效率

View File

@@ -0,0 +1,38 @@
1. **问题分析**
* 项目已经有一个CHANGELOG.md文件遵循Keep a Changelog格式
* 最新版本是\[1.1.3]发布于2025-12-19
* 我们需要添加新的版本条目,记录最近的修复
2. **修复内容**
* 修复了规则优先级问题:确保自定义规则优先于远程规则
* 修复了添加自定义规则后需要重启服务器的问题通过在添加或删除规则后清空DNS缓存实现
3. **更新步骤**
* 在CHANGELOG.md文件中添加一个新的版本条目\[1.1.4]日期为2025-12-21
* 在该版本下添加修复的内容
* 确保格式符合CHANGELOG的要求
4. **预期结果**
* CHANGELOG.md文件将包含最新的修复记录
* 版本号将更新为\[1.1.4]
* 修复内容将被清晰地记录在CHANGELOG中
5. **具体实现**
* 在CHANGELOG.md文件的开头添加新的版本条目
* 使用### 修复标题记录修复的内容
* 清晰描述每个修复的问题和解决方案

View File

@@ -0,0 +1,69 @@
# 更新Swagger API文档
## 1. 分析当前状态
* Swagger文档位于 `/root/dns/static/api/js/index.js`
* 项目使用Go语言开发HTTP API端点在 `/root/dns/http/server.go` 中定义
* 当前swagger文档缺少一些API端点和正确的描述
## 2. 需要更新的内容
### 2.1 添加缺少的API端点
* `/api/login` - 登录API
* `/api/logout` - 注销API
* `/api/change-password` - 修改密码API
* `/api/query` - DNS查询API
* `/api/status` - 系统状态API
* `/api/config` - 配置管理API
* `/api/config/restart` - 重启服务API
* `/api/logs/stats` - 日志统计API
* `/api/logs/query` - 日志查询API
* `/api/logs/count` - 日志数量API
### 2.2 更新现有端点描述
* `/api/stats` - 添加DNSSEC相关字段描述
* `/api/shield` - 更新为与实际实现匹配
* `/api/shield/blacklists` - 确保包含所有HTTP方法
* `/api/shield/hosts` - 确保包含所有HTTP方法
* `/api/shield/localrules` - 确保包含所有HTTP方法
### 2.3 修正现有端点的响应格式
* 修正 `/api/hourly-stats``/api/daily-stats``/api/monthly-stats` 的响应格式
* 修正 `/api/shield` 的响应格式
## 3. 实施步骤
1. 读取当前swagger文档
2. 针对每个需要更新的端点修改或添加相应的swagger定义
3. 确保所有端点的HTTP方法、参数、响应格式都正确
4. 测试swagger文档是否能正常加载和显示
## 4. 预期结果
* 所有API端点都在swagger文档中正确描述
* 每个端点的HTTP方法、参数、响应格式都准确
* swagger文档能正常加载和显示
* 开发者可以通过swagger文档了解和使用所有API端点

View File

@@ -0,0 +1,13 @@
1. 定位到仪表盘部分的卡片布局,找到两个关键卡片:
- 最近屏蔽域名卡片第593-635行
- TOP域名卡片第705-734行
2. 移除最近屏蔽域名卡片第593-635行
3. 将TOP域名卡片从当前位置第639行开始的网格移动到最近屏蔽域名卡片的位置第538行开始的网格
4. 确保布局保持一致,两个卡片在同一行显示
5. 调整相关的网格布局,确保页面结构完整
6. 验证修改后的布局是否符合用户要求

View File

@@ -0,0 +1,33 @@
# 根据服务器日志判断操作成功状态
## 问题分析
当前代码中部分操作只检查了HTTP响应状态码没有检查服务器返回的`status`字段,这可能导致在某些情况下无法正确判断操作是否成功。根据服务器端代码,所有成功的响应都会返回`{"status": "success"}`,因此需要确保前端代码在所有操作中都检查这个字段。
## 解决方案
修改以下函数,确保它们都根据服务器返回的`status`字段判断操作是否成功:
1. **handleDeleteBlacklist** (line 653-716)
- 添加对服务器响应数据中`status`字段的检查
- 确保只有当`status``success`时才认为删除成功
2. **handleToggleBlacklist** (line 719-793)
- 添加对服务器响应数据中`status`字段的检查
- 确保只有当`status``success`时才认为切换状态成功
3. **handleAddRule** (line 378-409)
- 添加对服务器响应数据中`status`字段的检查
- 确保只有当`status``success`时才认为添加规则成功
4. **handleDeleteRule** (line 309-375)
- 添加对服务器响应数据中`status`字段的检查
- 确保只有当`status``success`时才认为删除规则成功
## 实现步骤
1. 修改`handleDeleteBlacklist`函数添加响应数据解析和status字段检查
2. 修改`handleToggleBlacklist`函数添加响应数据解析和status字段检查
3. 修改`handleAddRule`函数添加响应数据解析和status字段检查
4. 修改`handleDeleteRule`函数添加响应数据解析和status字段检查
5. 测试所有操作,确保它们都能正确根据服务器响应判断成功或失败
## 预期效果
所有操作(添加、更新、删除、切换状态)都会根据服务器返回的`status`字段判断是否成功,确保操作结果与服务器日志一致。

View File

@@ -0,0 +1,40 @@
# 修复domainSpecificDNS的DNSSEC优先级问题
## 1. 问题分析
* 当域名匹配到 `domainSpecificDNS` 配置时程序会使用指定的DNS服务器
* 但随后程序会向DNSSEC专用服务器发送请求
* 如果DNSSEC专用服务器返回了带DNSSEC的响应程序会优先使用该响应
* 这导致 `domainSpecificDNS` 指定的DNS服务器的响应被忽略
## 2. 修复计划
### 2.1 修改 `forwardDNSRequestWithCache` 函数
* 在函数中添加一个标志 `domainMatched`,记录域名是否匹配了 `domainSpecificDNS` 配置
* 当域名匹配到 `domainSpecificDNS` 配置时,设置该标志为 `true`
### 2.2 修改DNSSEC响应处理逻辑
* 在处理DNSSEC专用服务器响应时检查 `domainMatched` 标志
* 如果标志为 `true`,则**不优先使用DNSSEC专用服务器的响应**而是保留原来指定DNS服务器的响应
* 只有当指定的DNS服务器没有返回有效响应时才考虑使用DNSSEC专用服务器的响应
### 2.3 确保指定的DNS服务器优先
* 确保对于匹配了 `domainSpecificDNS` 的域名始终优先使用指定的DNS服务器的响应
* 只有当指定的DNS服务器没有返回有效响应时才考虑使用DNSSEC专用服务器的响应
## 3. 预期效果
* 对于匹配了 `domainSpecificDNS` 配置的域名始终优先使用指定的DNS服务器
* 只有当指定的DNS服务器没有返回有效响应时才考虑使用DNSSEC专用服务器
* DNSSEC功能仍然正常工作但不会覆盖 `domainSpecificDNS` 的配置
## 4. 测试计划
* 重启DNS服务器
* 使用 `dig @127.0.0.1 dc.amazehome.xyz +short` 测试
* 检查日志确保使用的是指定DNS服务器的响应
* 验证解析结果是否符合预期

View File

@@ -0,0 +1,57 @@
# 添加DNSSEC支持实现计划
## 1. 配置系统修改
-`config/config.go``DNSConfig`结构体中添加`EnableDNSSEC`布尔字段用于控制是否启用DNSSEC支持
- 添加`DNSSECValidation`布尔字段用于控制是否进行DNSSEC验证
- 在配置加载时设置默认值
## 2. DNS查询处理修改
- 修改`dns/server.go`中的DNS客户端配置确保支持EDNS0扩展DNSSEC需要
-`handleDNSRequest`函数中支持DNSSEC相关查询类型DNSKEY、RRSIG、DS、NSEC、NSEC3等
- 确保上游DNS服务器返回的DNSSEC记录被正确处理和转发
## 3. DNSSEC验证支持
- 实现DNSSEC记录验证逻辑确保返回的DNS记录未被篡改
-`forwardDNSRequestWithCache`函数中添加DNSSEC验证步骤
- 根据配置决定是否进行验证,以及验证失败时的处理策略
## 4. 缓存系统适配
- 修改`DNSCache`结构体确保DNSSEC记录被正确缓存
- 确保缓存的DNS响应包含完整的DNSSEC记录链
## 5. 测试和验证
- 确保现有功能不受影响
- 测试DNSSEC查询是否正常工作
- 验证DNSSEC记录是否被正确转发和验证
## 6. 配置界面更新
- 在Web控制台中添加DNSSEC相关配置选项
- 允许用户通过界面启用/禁用DNSSEC支持和验证
## 7. 日志和统计
- 添加DNSSEC相关日志记录
- 记录DNSSEC验证结果统计
## 主要文件修改
- `config/config.go`添加DNSSEC相关配置字段
- `dns/server.go`修改DNS查询处理逻辑支持DNSSEC
- `static/index.html`添加DNSSEC配置界面
- `dns/cache.go`确保DNSSEC记录被正确缓存
## 依赖库
- 利用现有的`github.com/miekg/dns`该库已内置DNSSEC支持
## 实现步骤
1. 首先修改配置系统添加DNSSEC相关字段
2. 更新DNS客户端配置支持EDNS0扩展
3. 修改查询处理逻辑支持DNSSEC记录类型
4. 添加DNSSEC验证逻辑
5. 适配缓存系统
6. 更新Web配置界面
7. 测试和验证
## 预期效果
- 启用DNSSEC后服务器将支持DNSSEC查询并返回完整的DNSSEC记录
- 当启用DNSSEC验证时服务器将验证上游返回的DNS记录的真实性
- 增强DNS服务器的安全性防止DNS投毒和劫持攻击
- 提供灵活的配置选项允许用户根据需要调整DNSSEC设置

View File

@@ -0,0 +1,69 @@
# 更新Swagger API文档
## 1. 分析当前状态
* Swagger文档位于 `/root/dns/static/api/js/index.js`
* 项目使用Go语言开发HTTP API端点在 `/root/dns/http/server.go` 中定义
* 当前swagger文档缺少一些API端点和正确的描述
## 2. 需要更新的内容
### 2.1 添加缺少的API端点
* `/api/login` - 登录API
* `/api/logout` - 注销API
* `/api/change-password` - 修改密码API
* `/api/query` - DNS查询API
* `/api/status` - 系统状态API
* `/api/config` - 配置管理API
* `/api/config/restart` - 重启服务API
* `/api/logs/stats` - 日志统计API
* `/api/logs/query` - 日志查询API
* `/api/logs/count` - 日志数量API
### 2.2 更新现有端点描述
* `/api/stats` - 添加DNSSEC相关字段描述
* `/api/shield` - 更新为与实际实现匹配
* `/api/shield/blacklists` - 确保包含所有HTTP方法
* `/api/shield/hosts` - 确保包含所有HTTP方法
* `/api/shield/localrules` - 确保包含所有HTTP方法
### 2.3 修正现有端点的响应格式
* 修正 `/api/hourly-stats``/api/daily-stats``/api/monthly-stats` 的响应格式
* 修正 `/api/shield` 的响应格式
## 3. 实施步骤
1. 读取当前swagger文档
2. 针对每个需要更新的端点修改或添加相应的swagger定义
3. 确保所有端点的HTTP方法、参数、响应格式都正确
4. 测试swagger文档是否能正常加载和显示
## 4. 预期结果
* 所有API端点都在swagger文档中正确描述
* 每个端点的HTTP方法、参数、响应格式都准确
* swagger文档能正常加载和显示
* 开发者可以通过swagger文档了解和使用所有API端点

View File

@@ -0,0 +1,18 @@
## 问题分析
用户要求移除一个统计卡片,根据之前的对话历史,最近添加的卡片是屏蔽规则数量卡片,用户可能想要移除这个卡片。
## 修复方案
1. **移除HTML中的屏蔽规则数量卡片**从index.html文件中删除屏蔽规则数量卡片的HTML代码
2. **移除JavaScript中的相关逻辑**从dashboard.js文件中删除与屏蔽规则数量相关的变量声明、数据获取逻辑和更新逻辑
3. **确保代码语法正确**:修复可能出现的语法错误,确保代码兼容性
## 实现步骤
1. 打开index.html文件找到屏蔽规则数量卡片约第467-488行删除其HTML代码
2. 打开dashboard.js文件找到updateStatsCards函数删除与屏蔽规则数量相关的变量声明blockRulesCount、blockRulesPercentage
3. 删除updateStatsCards函数中与屏蔽规则数量相关的数据获取逻辑
4. 删除updateStatsCards函数中与屏蔽规则数量相关的更新逻辑
5. 删除loadDashboardData函数中与屏蔽规则数量相关的更新逻辑
6. 运行代码语法检查,确保没有语法错误
## 预期效果
修复后屏蔽规则数量卡片将从仪表盘上移除相关的JavaScript逻辑也将被清理仪表盘将恢复到之前的状态只显示其他7个统计卡片。

View File

@@ -0,0 +1,65 @@
# 解决web页面缓存问题
## 问题分析
当前web页面总是有缓存导致更新后用户看不到最新的内容。这是因为HTTP服务器使用了标准的http.FileServer来提供静态文件服务它会设置默认的缓存头导致浏览器缓存静态文件。
## 解决方案
修改静态文件服务的缓存策略为静态文件添加适当的Cache-Control头禁用浏览器缓存或者设置较短的缓存时间。
## 实现步骤
### 1. 创建自定义静态文件服务处理器
* 创建一个自定义的http.Handler包装http.FileServer
* 在处理静态文件请求时添加适当的Cache-Control头
* 可以选择完全禁用缓存,或者设置较短的缓存时间
### 2. 修改http/server.go中的静态文件服务配置
* 替换标准的http.FileServer使用自定义的静态文件服务处理器
* 确保所有静态文件请求都经过自定义处理器
### 3. 测试修改后的效果
* 更新静态文件例如修改dashboard.js
* 刷新页面,验证是否能看到最新的内容
* 使用浏览器开发者工具查看响应头确认Cache-Control头已正确设置
## 技术要点
* 使用http.StripPrefix处理静态文件路径
* 在ResponseWriter中添加Cache-Control头例如
* `Cache-Control: no-cache, no-store, must-revalidate`
* `Pragma: no-cache`
* `Expires: 0`
* 这些头会告诉浏览器不要缓存文件,每次都要重新请求
## 实现时间
* 预计30分钟完成所有修改和测试
## 风险评估
* 低风险:修改范围明确,不涉及核心功能
* 可回滚所有修改均为HTTP服务器配置修改可通过恢复文件轻松回滚
## 依赖关系
* 依赖http包的标准库功能
* 依赖现有的静态文件服务结构
## 测试策略
* 更新静态文件例如修改dashboard.js
* 刷新页面,验证是否能看到最新的内容
* 使用浏览器开发者工具查看响应头确认Cache-Control头已正确设置
* 测试不同浏览器的行为
## 验收标准
* 静态文件的HTTP响应中包含适当的Cache-Control头
* 更新静态文件后,刷新页面能看到最新的内容
* 浏览器不会缓存静态文件,每次都会重新请求

Some files were not shown because too many files have changed in this diff Show More