This commit is contained in:
Alex Yang
2026-04-12 21:40:22 +08:00
parent 7abc2b5339
commit f9e2e5a6bc
52 changed files with 3388 additions and 368846 deletions
@@ -0,0 +1,79 @@
# DNS 查询超时问题分析与修复计划
## 问题现状
- 客户端请求 DNS 解析需要两次才能成功
- 第一次返回 SERVFAIL,第二次才有正确结果
- 错误数量高达 29,594 条
## 已尝试的修复
-`queryTimeout` 从 5ms 修改为 5000ms
- 服务器已重启
## 需要深入调查的问题
### 1. 超时配置的实际生效情况
- 检查配置文件中 queryTimeout 的单位(毫秒还是秒)
- 验证代码中如何解析和使用这个配置值
- 确认配置是否真正被重新加载
### 2. 上游 DNS 服务器可达性
- 测试上游 DNS 服务器 (10.35.10.200, 106.14.121.141) 是否可达
- 检查上游服务器的响应时间
- 验证上游服务器是否支持递归查询
### 3. 网络层面问题
- 检查是否有防火墙规则阻止 DNS 查询
- 验证 UDP 53 端口是否畅通
- 检查是否存在网络延迟或丢包
### 4. DNS 缓存逻辑问题
- 检查缓存是否正常工作
- 验证缓存 TTL 设置是否合理
- 确认缓存命中时是否还会超时
### 5. 代码逻辑问题
- 检查并行查询模式的实现
- 验证超时处理逻辑是否正确
- 查看是否有竞态条件导致的问题
## 调查步骤
### 第一步:检查当前配置和日志
1. 查看当前配置文件中的 queryTimeout 值
2. 检查最新日志中的超时设置
3. 统计错误日志中的错误类型分布
### 第二步:测试上游 DNS 服务器
1. 直接测试上游 DNS 服务器的响应
2. 测量到上游服务器的网络延迟
3. 验证上游服务器是否工作正常
### 第三步:分析代码中的超时处理
1. 查看 forwardDNSRequestWithCache 函数中的超时逻辑
2. 检查 dns.Client 的 Timeout 设置
3. 验证并行查询的超时处理
### 第四步:检查网络配置
1. 检查防火墙规则
2. 测试 DNS 端口连通性
3. 检查路由表和网络接口
## 可能的修复方案
### 方案 A:修复配置单位问题
如果配置单位是秒而不是毫秒,需要将 5000 改为 5
### 方案 B:修复上游服务器配置
如果上游服务器不可达,需要更换可用的 DNS 服务器
### 方案 C:修复代码中的超时逻辑
如果代码中存在超时处理 bug,需要修改相关代码
### 方案 D:优化查询模式
如果并行查询模式有问题,可以切换到 fastest-ip 模式
## 验证标准
1. DNS 查询一次成功,不需要重试
2. 错误率降低到接近 0
3. 平均响应时间合理(<100ms)
4. 日志中不再有大量 SERVFAIL 记录
@@ -0,0 +1,368 @@
# DNS 查询 SERVFAIL 问题分析(已禁用 DNSSEC
## 问题描述
客户端请求 DNS 解析时,需要请求两次才能得到正常结果:
* 第一次请求:返回 SERVFAIL(服务器失败)
* 第二次请求:返回正常解析结果
## 重要信息
**DNSSEC 已禁用** - 因此问题与 DNSSEC 验证无关
## 可能的原因分析
### 1. 缓存初始化时机问题
**现象**:第一次查询时缓存为空,第二次查询命中缓存
**可能原因**
* 缓存加载逻辑可能存在问题
* 第一次查询的响应没有正确缓存
* 缓存键生成或查找逻辑有问题
**相关代码位置**
* `/root/dns-server/dns/cache.go` - `Get``Set` 方法
* `/root/dns-server/dns/server.go` - `handleCacheResponse` 方法
### 2. DNSSEC 验证超时或失败
**现象**:第一次查询触发 DNSSEC 验证,验证超时导致 SERVFAIL;第二次直接使用缓存结果
**可能原因**
* DNSSEC 验证逻辑可能存在超时
* 验证失败后没有正确处理响应
* `verifyDNSSEC` 方法可能阻塞或失败
**相关代码位置**
* `/root/dns-server/dns/server.go` - `verifyDNSSEC` 方法
* 第 1563 行左右的 DNSSEC 验证逻辑
### 3. 上游服务器选择逻辑问题
**现象**:第一次查询时服务器状态统计为空,导致选择了不可用的服务器
**可能原因**
* 服务器健康检查逻辑可能有问题
* 第一次查询时没有正确选择最快的服务器
* 并行查询逻辑可能存在竞态条件
**相关代码位置**
* `/root/dns-server/dns/server.go` - `forwardDNSRequestWithCache` 方法
* 第 1473-1600 行的并行查询逻辑
### 4. 响应处理逻辑问题
**现象**:第一次查询返回的响应被错误地判断为失败
**可能原因**
* 响应代码判断逻辑可能有误
* `hasValidRecords` 判断可能过于严格
* 某些类型的响应被错误地拒绝
**相关代码位置**
* `/root/dns-server/dns/server.go` - 第 871-891 行的响应验证逻辑
### 5. 并发锁竞争问题
**现象**:第一次查询时遇到锁竞争,导致超时返回 SERVFAIL
**可能原因**
* 缓存访问锁可能与其他操作冲突
* 统计信息更新可能导致阻塞
* 日志写入可能阻塞查询流程
**相关代码位置**
* `/root/dns-server/dns/cache.go` - 各种锁操作
* `/root/dns-server/dns/server.go` - 统计更新操作
## 调试建议
### 方案 1:增强日志记录
在关键位置添加详细日志:
* 缓存命中/未命中时
* DNSSEC 验证开始/结束/结果
* 上游服务器选择和响应
* 响应验证过程
### 方案 2:检查时间戳
分析查询日志中的时间戳:
* 第一次查询的实际处理时间
* 是否有超时现象
* DNSSEC 验证耗时
### 方案 3:复现测试
使用 `dig` 命令测试:
```bash
# 清除缓存后测试
dig @127.0.0.1 example.com +norecurse
dig @127.0.0.1 example.com
```
## 根本原因已确定
经过详细代码分析,发现问题出在 **并行请求模式下的响应处理逻辑缺陷**
### 问题流程:
1. **第一次查询**
* 缓存未命中,向上游服务器发起并行查询
* 代码进入并行请求模式(第 1490-1777 行)
* 收到上游返回的响应,`resp.response.Rcode == dns.RcodeSuccess`
* **关键问题**:在 `noDNSSEC` 模式下(第 1572-1588 行),代码直接返回第一个成功响应
* **但是**:没有检查响应是否包含有效记录(Answer/Ns/Extra
* 如果上游返回的是 `Rcode=Success``Answer 为空` 的响应(例如某些 DNS 服务器的截断响应)
* 该响应被直接发送给客户端
*`handleUpstreamRequest` 第 870-891 行,由于 `hasValidRecords` 检查失败(Answer 为空),`response.Rcode` 没有被设置为 `RcodeSuccess`
* 最终客户端收到 SERVFAIL 错误
2. **第二次查询**
* 第一次查询的响应已经被缓存(即使 Answer 为空,只要 Rcode=Success 就会被缓存)
* 直接从缓存返回
* 但此时缓存的可能是完整响应(因为上游第二次返回了完整结果)
* 客户端收到正常解析结果
### 具体代码问题:
**问题 1:并行模式下缺少 hasValidRecords 检查**
`/root/dns-server/dns/server.go` 第 1572-1588 行(并行模式,noDNSSEC 分支):
```go
if noDNSSEC && !bestResponseSent {
// 不验证 DNSSEC 的域名:直接返回第一个成功响应
if fastestResponse == nil || resp.rtt < fastestRtt {
fastestResponse = resp.response
fastestRtt = resp.rtt
fastestServer = resp.server
fastestDnssecServer = dnssecServerForResponse
fastestHasDnssec = false
// 立即发送结果,快速返回(只发送一次)
resultChan <- struct {
response: fastestResponse, // 可能 Answer 为空!
...
}
bestResponseSent = true
}
}
```
**对比**:在串行模式(第 1452-1469 行)中有 `hasValidRecords` 检查:
```go
// 检查响应是否包含有效的记录,如果包含,将 Rcode 设置为成功
hasValidRecords := false
if len(response.Answer) > 0 {
hasValidRecords = true
} else if len(response.Ns) > 0 {
hasValidRecords = true
} else if len(response.Extra) > 0 {
for _, rr := range response.Extra {
if rr.Header().Rrtype != dns.TypeOPT {
hasValidRecords = true
break
}
}
}
if hasValidRecords {
response.Rcode = dns.RcodeSuccess
}
```
**问题 2:Rcode 判断逻辑不准确**
第 1562 行只检查 `resp.response.Rcode == dns.RcodeSuccess`,但有些 DNS 服务器可能返回:
* `Rcode=Success``Answer 为空`(例如需要 TCP 回退时)
* 这种情况下应该继续等待其他服务器的响应,而不是立即返回
## 建议的修复步骤
### 方案 1:在并行模式下添加 hasValidRecords 检查(推荐)
**问题**:并行模式(noDNSSEC 分支)缺少 hasValidRecords 检查
**解决方案**
在并行模式的快速返回逻辑中添加 hasValidRecords 检查,确保只返回包含有效记录的响应
```go
// 修改前
if noDNSSEC && !bestResponseSent {
// 不验证 DNSSEC 的域名:直接返回第一个成功响应
if fastestResponse == nil || resp.rtt < fastestRtt {
fastestResponse = resp.response
fastestRtt = resp.rtt
fastestServer = resp.server
fastestDnssecServer = dnssecServerForResponse
fastestHasDnssec = false
// 立即发送结果,快速返回(只发送一次)
resultChan <- struct {
response: fastestResponse,
...
}
bestResponseSent = true
}
}
// 修改后
if noDNSSEC && !bestResponseSent {
// 不验证 DNSSEC 的域名:返回第一个包含有效记录的成功响应
if fastestResponse == nil || resp.rtt < fastestRtt {
// 检查响应是否包含有效记录
hasValidRecords := false
if len(resp.response.Answer) > 0 {
hasValidRecords = true
} else if len(resp.response.Ns) > 0 {
hasValidRecords = true
} else if len(resp.response.Extra) > 0 {
for _, rr := range resp.response.Extra {
if rr.Header().Rrtype != dns.TypeOPT {
hasValidRecords = true
break
}
}
}
// 只有包含有效记录才返回
if hasValidRecords {
fastestResponse = resp.response
fastestRtt = resp.rtt
fastestServer = resp.server
fastestDnssecServer = dnssecServerForResponse
fastestHasDnssec = false
// 立即发送结果,快速返回(只发送一次)
resultChan <- struct {
response: fastestResponse,
...
}
bestResponseSent = true
}
}
}
```
### 方案 2:改进 Rcode 判断逻辑
**问题**:只检查 Rcode,不检查 Answer 内容
**解决方案**
将 Rcode 检查和 Answer 检查结合起来,确保响应真正有效
```go
// 修改前
if resp.response.Rcode == dns.RcodeSuccess || resp.response.Rcode == dns.RcodeNameError {
// 处理响应
}
// 修改后
// 检查 Rcode 和 Answer 内容
isValidResponse := false
if resp.response.Rcode == dns.RcodeSuccess {
// 成功响应需要包含有效记录
if len(resp.response.Answer) > 0 || len(resp.response.Ns) > 0 {
isValidResponse = true
}
} else if resp.response.Rcode == dns.RcodeNameError {
// NXDOMAIN 响应可以没有 Answer
isValidResponse = true
}
if isValidResponse {
// 处理有效响应
}
```
### 方案 3:增加重试机制
**问题**:第一次返回空 Answer 后没有重试
**解决方案**
检测到空 Answer 时,继续等待其他服务器的响应或重试
```go
// 在并行模式中添加重试逻辑
if len(resp.response.Answer) == 0 && resp.response.Rcode == dns.RcodeSuccess {
// Answer 为空,可能是截断响应,继续等待其他服务器
logger.Debug("响应 Answer 为空,继续等待其他服务器", "domain", domain)
continue // 不立即返回,继续等待
}
```
### 方案 4:调整上游 DNS 服务器配置
**问题**:某些上游 DNS 服务器可能返回截断响应
**解决方案**
1. 检查上游 DNS 服务器配置
2. 尝试更换更可靠的上游 DNS 服务器
3. 增加 UDP 缓冲区大小,避免截断
## 推荐修复顺序
1. **立即修复**:方案 1(在并行模式下添加 hasValidRecords 检查)- 直接解决问题
2. **优化改进**:方案 2(改进 Rcode 判断逻辑)- 提高健壮性
3. **可选优化**:方案 3(增加重试机制)- 进一步提高可靠性
## 需要查看的关键代码
1. `verifyDNSSEC` 方法实现
2. `forwardDNSRequestWithCache` 中的 DNSSEC 验证逻辑
3. `handleUpstreamRequest` 中的响应处理
4. DNSSEC 相关配置和超时设置
@@ -0,0 +1,332 @@
# 域名信息管理项重新设计计划
## 1. 现状分析
### 1.1 现有实现
- **后端实现**`shield/domain_info_manager.go` 实现了域名信息管理器
- **前端实现**`static/js/modules/domain-info.js` 实现了前端管理界面
- **API接口**`http/domain_info_handlers.go` 提供了相关API
- **配置管理**`config/config.go` 定义了配置结构
### 1.2 现有功能
1. **三个列表管理**
- 域名信息列表 (domain-info)
- 威胁域名列表 (threat-database)
- 跟踪器列表 (tracker)
2. **现有API**
- `/api/domain-info` - 获取域名信息列表和统计
- `/api/domain-info/update` - 更新所有域名信息
- `/api/domain-info/update/{type}` - 更新指定类型的域名信息
- `/api/domain-info/query` - 查询单个域名信息
3. **现有前端功能**
- 显示三个列表的详细信息
- 显示各列表的规则数量
- 显示最后更新时间
- 支持更新所有列表和单个列表
### 1.3 问题与不足
1. **数据更新机制**
- 威胁数据库的URL配置错误(使用了src路径而非raw路径)
- 缺少更新状态的实时反馈
2. **前端界面**
- 界面设计较为简单
- 缺少视觉层次感和交互体验
3. **数据管理**
- 缺少数据验证和错误处理
- 缓存机制可以进一步优化
4. **用户功能**
- 缺少用户增加和删除列表的功能
### 1.4 列表文件分析
通过下载和分析列表文件,了解到:
1. **domain-info.json**
- 格式:JSON
- 结构:
- categories: 分类信息(键值对)
- domains: 域名信息(嵌套结构,第一层公司名称,第二层具体域名服务)
- timeUpdated: 更新时间
- 规模:4444行
- 用途:提供域名分类信息
2. **threats-database.csv**
- 格式:CSV
- 结构:包含 type, name, riskLevel, domain 字段
- 规模:73012行(约3.1MB
- 用途:提供威胁域名数据库
3. **trackers.json**
- 格式:JSON
- 结构:
- categories: 分类信息
- timeUpdated: 更新时间
- trackerDomains: 跟踪器域名
- trackers: 跟踪器信息(嵌套结构)
- 规模:25345行
- 用途:提供跟踪器域名信息
### 1.5 嵌套结构处理注意事项
- **domain-info.json**domains字段包含多层嵌套结构,需要递归处理
- **trackers.json**trackers字段包含嵌套结构,需要正确解析
- **数据量级**:威胁数据库较大(7万多行),需要考虑性能优化
## 2. 重新设计方案
### 2.1 后端改进
1. **修复URL配置**
- 修正威胁数据库的URL,使用raw路径
2. **增强更新机制**
- 添加更新状态的实时反馈
- 改进错误处理和日志记录
3. **优化缓存策略**
- 实现更智能的缓存过期机制
- 增加缓存验证
4. **添加API端点**
- `/api/domain-info/status` - 获取更新状态
- `/api/domain-info/refresh` - 强制刷新缓存
- `/api/domain-info/add` - 添加新的域名信息列表
- `/api/domain-info/remove` - 删除域名信息列表
5. **实现用户增删功能**
- 支持用户添加自定义域名信息列表
- 支持用户删除现有列表
- 实现列表配置的持久化存储
6. **嵌套结构处理**
- 优化JSON嵌套结构的解析和处理
- 实现高效的嵌套数据存储和查询
### 2.2 前端改进
1. **界面重新设计**
- 采用卡片式布局,增强视觉层次感
- 添加统计信息概览区域
- 优化表格布局和交互体验
2. **功能增强**
- 添加更新进度指示
- 实现批量操作功能
- 增加数据导出功能
- 添加列表增加和删除功能
- 实现列表编辑功能
3. **响应式设计**
- 优化移动端显示
- 确保在不同设备上的良好体验
4. **数据展示优化**
- 实现嵌套结构的可视化展示
- 支持展开/折叠嵌套数据
### 2.3 数据管理优化
1. **数据验证**
- 增加URL格式验证
- 实现数据完整性检查
- 验证列表类型和格式
2. **错误处理**
- 提供更详细的错误信息
- 实现优雅的错误展示
3. **性能优化**
- 减少不必要的网络请求
- 优化数据加载和渲染
- 实现大型列表的分页加载
- 优化嵌套结构的处理性能
## 3. 具体实现步骤
### 3.1 后端修改
1. **修复配置**
- 修正 `config/config.go` 中的威胁数据库URL
2. **增强域名信息管理器**
-`shield/domain_info_manager.go` 中添加更新状态管理
- 实现更详细的错误处理
- 完善列表增删功能
- 优化嵌套JSON结构的解析
3. **扩展API接口**
-`http/domain_info_handlers.go` 中添加新的API端点
- 实现状态查询、缓存刷新、列表增删功能
4. **实现配置持久化**
- 确保用户添加的列表配置能够持久保存
- 实现配置文件的自动更新
### 3.2 前端修改
1. **重新设计界面**
- 更新 `static/js/modules/domain-info.js` 中的渲染逻辑
- 实现卡片式布局和统计概览
2. **增强交互功能**
- 添加更新进度指示
- 实现批量操作和数据导出
- 添加列表增加和删除功能
- 实现列表编辑表单
3. **优化用户体验**
- 添加加载动画和过渡效果
- 实现更友好的错误提示
- 提供操作确认机制
4. **实现嵌套数据展示**
- 支持展开/折叠嵌套结构
- 优化大型嵌套数据的渲染性能
### 3.3 测试与验证
1. **功能测试**
- 测试所有API端点
- 验证数据更新功能
- 测试列表增删功能
- 测试错误处理
2. **性能测试**
- 测试数据加载速度
- 验证缓存机制
- 测试响应式布局
3. **安全性测试**
- 验证输入验证
- 测试错误处理安全性
## 4. 预期效果
### 4.1 功能改进
- ✅ 正确显示三个列表的数量
- ✅ 支持更新所有/单个列表
- ✅ 显示更新时间
- ✅ 提供更新状态反馈
- ✅ 实现批量操作功能
- ✅ 支持用户增加和删除列表
- ✅ 实现列表编辑功能
- ✅ 正确处理JSON嵌套结构
### 4.2 界面改进
- ✅ 现代化的卡片式布局
- ✅ 清晰的统计信息概览
- ✅ 良好的响应式设计
- ✅ 流畅的交互体验
- ✅ 直观的列表管理界面
- ✅ 嵌套数据的可视化展示
### 4.3 性能改进
- ✅ 优化的数据加载速度
- ✅ 智能的缓存机制
- ✅ 减少网络请求
- ✅ 提高系统稳定性
- ✅ 支持大型列表的高效处理
- ✅ 优化嵌套结构的处理性能
## 5. 风险与应对措施
### 5.1 风险
1. **数据加载失败**
- 远程数据源不可用
- 网络连接问题
2. **性能问题**
- 大量数据导致加载缓慢
- 缓存策略不当
- 嵌套结构处理性能问题
3. **兼容性问题**
- 浏览器兼容性
- 移动设备适配
4. **用户操作风险**
- 误删除重要列表
- 添加无效的列表配置
5. **数据结构风险**
- JSON嵌套结构解析错误
- 数据格式不一致
### 5.2 应对措施
1. **数据加载失败**
- 实现错误重试机制
- 使用缓存数据作为备用
- 提供详细的错误信息
2. **性能问题**
- 实现数据分页加载
- 优化缓存策略
- 使用异步加载
- 实现嵌套结构的懒加载
3. **兼容性问题**
- 使用现代前端技术
- 测试主流浏览器
- 实现响应式设计
4. **用户操作风险**
- 实现操作确认机制
- 提供默认列表恢复功能
- 验证用户输入的有效性
5. **数据结构风险**
- 实现健壮的JSON解析
- 添加数据结构验证
- 提供详细的错误提示
## 6. 实施步骤
1. **准备阶段**
- 代码分析和问题识别
- 设计新的界面和功能
2. **后端开发**
- 修复URL配置
- 扩展API接口
- 实现列表增删功能
- 优化嵌套结构处理
3. **前端开发**
- 重新设计界面
- 实现交互功能
- 添加列表管理功能
- 实现嵌套数据展示
4. **测试阶段**
- 功能测试
- 性能测试
- 兼容性测试
5. **部署阶段**
- 代码审查
- 部署更新
- 监控运行状态
## 7. 结论
通过重新设计域名信息管理项,我们将实现:
1. **功能完善**:确保三个列表的数量显示、更新功能、时间显示,以及用户增删列表的能力,同时正确处理JSON嵌套结构
2. **界面优化**:提供现代化、美观的用户界面,支持嵌套数据的可视化展示
3. **性能提升**:优化数据加载和缓存机制,提高嵌套结构处理性能
4. **用户体验**:提供流畅、直观的操作体验
这些改进将使域名信息管理系统更加实用、可靠和用户友好,满足用户对域名信息管理的各种需求。
@@ -0,0 +1,186 @@
# 域名信息远程列表功能实施计划
## 概述
在 DNS 服务器的屏蔽管理系统中增加三类域名信息的远程异步加载功能,用于增强日志详情 API 和威胁告警 API 的域名信息查询能力。
## 需要添加的远程域名信息
### 1. 域名信息列表
- **URL**: `https://gitea.amazehome.xyz/AMAZEHOME/domain-info/raw/branch/main/domains/domain-info.json`
- **用途**: 用于查询日志详情 API 中的域名信息
- **格式**: JSON
### 2. 威胁告警域名列表
- **URL**: `https://gitea.amazehome.xyz/AMAZEHOME/domain-info/src/branch/main/threats/threats-database.csv`
- **用途**: 用于威胁告警 API 的威胁域名信息
- **格式**: CSV
### 3. 跟踪器域名列表
- **URLs**:
- `https://gitea.amazehome.xyz/AMAZEHOME/domain-info/raw/branch/main/tracker/trackers.json`
- **用途**: 用于查询日志详情 API 中的跟踪器信息
- **格式**: JSON
## 实施步骤
### 步骤 1: 扩展配置文件结构
1.1 在 `config/config.go` 中添加新的配置结构:
- `DomainInfoConfig` - 域名信息配置
- 包含三个远程列表的配置条目(类似 `BlacklistEntry`
- 添加更新间隔、启用状态等配置项
1.2 在 `Config` 结构体中添加 `DomainInfo DomainInfoConfig` 字段
1.3 实现配置解析函数:
- `parseDomainInfoLists()` - 解析域名信息列表配置
- 支持 INI 格式配置
### 步骤 2: 创建域名信息管理器
2.1 创建新文件 `shield/domain_info_manager.go`
2.2 实现 `DomainInfoManager` 结构体:
- 存储域名信息数据(JSON 格式)
- 存储威胁域名数据(CSV 格式)
- 存储跟踪器数据(JSON 格式)
- 缓存管理和过期检查机制
- 异步加载和更新逻辑
2.3 实现核心方法:
- `LoadDomainInfo()` - 加载所有域名信息
- `fetchRemoteDomainInfo()` - 获取远程域名信息
- `fetchThreatDatabase()` - 获取威胁数据库
- `fetchTrackerInfo()` - 获取跟踪器信息
- `shouldUpdateCache()` - 检查缓存是否需要更新
- `GetDomainInfo(domain)` - 查询域名信息
- `GetThreatInfo(domain)` - 查询威胁信息
- `GetTrackerInfo(domain)` - 查询跟踪器信息
- `GetAllDomainInfo()` - 获取所有域名信息(用于 API)
2.4 实现缓存机制:
- 使用内存缓存存储加载的数据
- 定期后台刷新(根据配置的更新间隔)
- 支持手动刷新
### 步骤 3: 实现后端 API
3.1 在 `http/server.go` 中添加新的 API 路由:
- `/api/shield/domain-info` - 获取域名信息列表(GET
- `/api/shield/domain-info/update` - 手动更新所有域名信息(POST)
- `/api/shield/domain-info/{type}/update` - 更新指定类型的域名信息(POST)
- `/api/domain/info` - 查询单个域名的详细信息(GET)
3.2 实现 API 处理函数:
- `handleDomainInfo()` - 处理域名信息列表的获取
- `handleUpdateDomainInfo()` - 处理手动更新请求
- `handleDomainInfoQuery()` - 处理域名信息查询
3.3 在服务器初始化时:
- 创建 `DomainInfoManager` 实例
- 启动后台定期更新任务
### 步骤 4: 实现前端界面
4.1 创建 `static/js/modules/domain-info.js` 模块:
- `loadDomainInfoLists()` - 加载域名信息列表
- `updateDomainInfo(type)` - 更新域名信息
- `renderDomainInfoLists()` - 渲染域名信息列表表格
- `showDomainInfoDetails()` - 显示域名信息详情
4.2 在 `static/js/shield.js` 中添加:
- `loadRemoteDomainInfoLists()` - 异步加载远程域名信息列表
- `updateDomainInfoListsTable()` - 更新域名信息列表 UI
- 添加状态指示器和通知逻辑
4.3 创建前端管理界面 `static/domain-info.html`(或集成到现有 shield.html):
- 域名信息列表管理表格
- 显示各列表的状态、规则数量、最后更新时间
- 手动更新按钮
- 启用/禁用切换
### 步骤 5: 集成到日志详情 API
5.1 修改日志详情查询接口:
- 在返回的日志详情中添加域名信息字段
- 添加跟踪器信息字段
- 如果域名在威胁数据库中,添加威胁告警信息
5.2 优化查询性能:
- 使用缓存避免重复查询
- 批量查询优化
### 步骤 6: 集成到威胁告警 API
6.1 修改威胁告警查询接口:
- 使用远程威胁数据库进行匹配
- 返回威胁类型、风险等级等详细信息
### 步骤 7: 测试和文档
7.1 功能测试:
- 测试远程列表加载
- 测试缓存机制
- 测试 API 接口
- 测试前端界面
7.2 更新文档:
- 更新 README.md
- 添加配置示例
- 更新 API 文档
## 技术要点
### 异步加载机制
- 使用 goroutine 进行后台异步加载
- 使用 channel 或 context 控制加载流程
- 支持并发加载多个远程列表
### 缓存策略
- 内存缓存 + 文件缓存双重机制
- 基于时间的过期策略
- 支持手动刷新和自动刷新
### 错误处理
- 网络错误的重试机制
- 加载失败时的降级处理(使用缓存)
- 详细的错误日志记录
### 性能优化
- 批量处理减少锁竞争
- 使用 RWMutex 优化读写性能
- 延迟加载和按需加载
## 文件清单
### 新增文件
- `shield/domain_info_manager.go` - 域名信息管理器
- `static/js/modules/domain-info.js` - 前端域名信息管理模块
- `static/domain-info.html` - 域名信息管理界面(可选,如集成到现有页面则不需要)
### 修改文件
- `config/config.go` - 添加域名信息配置
- `http/server.go` - 添加 API 路由和处理函数
- `shield/manager.go` - 集成域名信息管理(可选)
- `static/js/shield.js` - 添加前端加载逻辑
- `README.md` - 更新文档
## 配置示例
```ini
[domainInfo]
; 域名信息列表配置
; 格式:name = url,enabled
domainInfoList = https://gitea.amazehome.xyz/AMAZEHOME/domain-info/raw/branch/main/domains/domain-info.json,true
threatDatabase = https://gitea.amazehome.xyz/AMAZEHOME/domain-info/src/branch/main/threats/threats-database.csv,true
trackerList = https://gitea.amazehome.xyz/AMAZEHOME/domain-info/raw/branch/main/tracker/trackers.json,true
; 更新间隔(秒)
updateInterval = 3600
; 是否启用自动更新
enableAutoUpdate = true
```
## 时间估算
- 步骤 1: 配置文件扩展 - 30 分钟
- 步骤 2: 域名信息管理器 - 2 小时
- 步骤 3: 后端 API 实现 - 1 小时
- 步骤 4: 前端界面实现 - 1.5 小时
- 步骤 5-6: API 集成 - 1 小时
- 步骤 7: 测试和文档 - 1 小时
**总计**: 约 7-8 小时
+87
View File
@@ -0,0 +1,87 @@
# DNS服务器间歇性SERVFAIL错误修复计划
## 问题分析
通过分析代码和测试脚本,发现DNS服务器存在间歇性SERVFAIL错误,表现为:
- 第一次查询失败(返回SERVFAIL)
- 第二次查询成功
## 可能的原因
1. **上游服务器连接问题**:上游DNS服务器偶尔响应失败,导致第一次查询时所有服务器都失败
2. **缓存机制问题**:缓存未正确处理失败响应,导致第二次查询时能够从缓存中获取到正确的响应
3. **并行查询逻辑问题**:在parallel模式下,响应处理可能存在竞态条件
4. **超时处理问题**:超时设置不合理或处理不当
## 代码分析
### 关键问题点
1. **forwardDNSRequestWithCache函数**server.go:1191):
- 当所有上游服务器都失败时,可能返回nil响应,导致SERVFAIL
- 并行查询时的响应处理逻辑可能存在问题
2. **handleUpstreamRequest函数**server.go:825):
- 当response为nil时,直接返回SERVFAIL
3. **客户端池管理**
- 使用sync.Pool管理DNS客户端实例,但可能存在并发问题
## 修复方案
### 1. 改进上游请求处理逻辑
- **增加重试机制**:当第一次查询失败时,自动重试一次
- **优化超时设置**:确保超时时间合理,避免过早超时
- **改进错误处理**:当所有上游服务器都失败时,尝试使用备选服务器
### 2. 优化缓存机制
- **缓存失败响应**:暂时缓存失败响应,避免短时间内重复查询失败的域名
- **改进缓存键设计**:确保缓存键能够正确标识不同的查询条件
### 3. 改进并行查询逻辑
- **优化响应处理**:确保并行查询时能够正确处理所有响应
- **增加响应验证**:验证响应的有效性,避免返回无效响应
### 4. 增加监控和日志
- **增加详细日志**:记录每次查询的详细信息,包括上游服务器响应情况
- **增加统计信息**:统计上游服务器的响应成功率,便于问题定位
## 实施步骤
1. **修改forwardDNSRequestWithCache函数**
- 增加重试机制
- 优化错误处理逻辑
- 改进并行查询的响应处理
2. **修改handleUpstreamRequest函数**
- 增加对nil响应的处理
- 优化响应验证
3. **修改缓存机制**
- 增加失败响应的缓存
- 改进缓存键设计
4. **增加监控和日志**
- 增加详细的查询日志
- 增加上游服务器响应统计
5. **测试验证**
- 使用test_servfail.sh脚本测试修复效果
- 进行压力测试,确保修复后系统稳定
## 预期效果
- 消除间歇性SERVFAIL错误
- 提高DNS服务器的稳定性和可靠性
- 减少对上游服务器的重复查询
- 提供更详细的日志和监控信息
## 风险评估
- **性能影响**:增加重试机制可能会增加响应时间,但可以通过合理的超时设置来平衡
- **内存使用**:增加失败响应的缓存可能会增加内存使用,但可以通过设置合理的缓存大小和过期时间来控制
- **兼容性**:修改缓存机制可能会影响现有缓存的使用,但可以通过平滑过渡来避免问题
+1
View File
@@ -0,0 +1 @@
代码逻辑严谨有序。
+47 -3
View File
@@ -15,17 +15,20 @@
## 功能特性
### 1. DNS查询处理
- 支持UDP和TCP协议
- 支持常见DNS查询类型(A, AAAA, CNAME, MX, NS, TXT等)
- 高性能查询处理
### 2. 屏蔽规则管理
- 支持域名规则和正则表达式规则
- 支持规则例外
- 支持远程规则列表
- 支持自定义规则管理
### 3. 查询日志记录和统计
- 实时记录DNS查询日志
- 支持日志持久化到文件
- 提供查询统计和趋势分析
@@ -33,6 +36,7 @@
- 支持日志排序
### 4. Web 控制台
- 直观的仪表盘
- 实时统计数据
- 图表可视化
@@ -40,12 +44,23 @@
- 查询日志详情页面
- 支持分页和自定义记录数量
### 5. 域名信息管理
- 支持远程域名信息列表
- 支持威胁域名数据库
- 支持跟踪器域名列表
- 异步加载和自动更新
- 内存 + 文件双重缓存
- 集成到日志详情查询
### 5. WebSocket实时更新
- 实时更新统计数据
- 实时更新图表
- 支持连接状态管理
### 6. 查询日志持久化
- 将查询日志保存到`querylog.json`文件
- 定期自动保存
- 服务器重启后自动加载
@@ -160,6 +175,18 @@ content = ./data/gfwlist.txt
# 是否启用 GFWList 功能
enabled = true
[domainInfo]
# 域名信息列表更新间隔(秒)
updateInterval = 3600
# 是否启用自动更新
enableAutoUpdate = true
# 域名信息列表配置
# 格式:domainInfo_名称 = URL,类型,enabled
# 类型:domain-info(域名信息)、threat-database(威胁数据库)、tracker(跟踪器)
domainInfo_域名信息列表 = https://gitea.amazehome.xyz/AMAZEHOME/domain-info/raw/branch/main/domains/domain-info.json,domain-info,true
domainInfo_威胁数据库 = https://gitea.amazehome.xyz/AMAZEHOME/domain-info/src/branch/main/threats/threats-database.csv,threat-database,true
domainInfo_跟踪器列表 = https://gitea.amazehome.xyz/AMAZEHOME/domain-info/raw/branch/main/tracker/trackers.json,tracker,true
[log]
# 日志级别:debug, info, warn, error
level = debug
@@ -182,8 +209,9 @@ maxAge = 30
### 访问Web控制台
在浏览器中访问:
```
http://localhost:8080
http://localhost:8081
```
### 管理屏蔽规则
@@ -207,11 +235,13 @@ http://localhost:8080
### 主要API端点
#### 1. DNS查询
```
GET /api/query?domain=example.com
```
#### 2. 屏蔽规则管理
```
GET /api/shield/rules
POST /api/shield/rules
@@ -219,6 +249,7 @@ DELETE /api/shield/rules/:id
```
#### 3. Hosts管理
```
GET /api/hosts
POST /api/hosts
@@ -226,6 +257,7 @@ DELETE /api/hosts/:id
```
#### 4. 查询日志
```
GET /api/logs/stats
GET /api/logs/query
@@ -233,10 +265,20 @@ GET /api/logs/count
```
#### 5. WebSocket
```
ws://localhost:8080/ws/stats
```
#### 6. 域名信息管理
```
GET /api/domain-info # 获取域名信息列表
POST /api/domain-info/update # 更新所有域名信息
POST /api/domain-info/update/{type} # 更新指定类型的域名信息
GET /api/domain-info/query?domain=xxx # 查询单个域名的详细信息
```
## 开发说明
### 项目结构
@@ -283,12 +325,13 @@ MIT License
如有问题或建议,请通过以下方式联系:
- Email: wxf26054@live.cn
- Git: https://gitea.amazehome.xyz/AMAZEHOME/dns-server
- Email: <wxf26054@live.cn>
- Git: <https://gitea.amazehome.xyz/AMAZEHOME/dns-server>
## 更新日志
### v1.0.0 (2025-11-30)
- 初始版本
- 实现基本DNS服务器功能
- 实现屏蔽规则管理
@@ -298,6 +341,7 @@ MIT License
- 实现查询日志持久化
### v1.0.1 (2025-11-30)
- 修复搜索和过滤功能
- 优化查询日志显示
- 修复样式间隔问题
-5
View File
@@ -1,5 +0,0 @@
CGO_ENABLED=1 \
GOOS=windows \
GOARCH=amd64 \
CC=gcc \
go build -o dns-server.exe main.go
+2 -4
View File
@@ -2,7 +2,5 @@ export CGO_ENABLED=1
export GOOS=linux
export GOARCH=amd64
export CC=gcc
#service dns-server stop &&
go build -o dns-server main.go
#&& service dns-server start
#service dns-server stop && go build -o dns-server main.go && service dns-server start
go build
+14 -31
View File
@@ -1,25 +1,25 @@
[dns]
port = 53
upstreamDNS = 10.35.10.200, 106.14.121.141
upstreamDNS = 10.35.10.200
dnssecUpstreamDNS = 208.67.220.220, 208.67.222.222
saveInterval = 10
cacheTTL = 60
cacheTTL = 10
enableDNSSEC = false
queryMode = parallel
queryTimeout = 5
queryTimeout = 5000
enableFastReturn = true
noDNSSECDomains = amazehome.cn, addr.arpa, amazehome.xyz, .cn
enableIPv6 = false
cacheMode = file
cacheSize = 100
maxCacheTTL = 60
minCacheTTL = 30
domain_akamai = 10.35.10.200:53
maxCacheTTL = 30
minCacheTTL = 5
domain_amazehome.cn = 10.35.10.200:53
domain_amazehome.xyz = 10.35.10.200:53
domain_microsoft.com = 10.35.10.200:53
domain_addr.arpa = 10.35.10.200:53
domain_akadns = 10.35.10.200:53
domain_akamai = 10.35.10.200:53
[http]
port = 8081
@@ -60,31 +60,6 @@ maxSize = 100
maxBackups = 10
maxAge = 30
[queryLog]
# 基本配置
enabled = true
ringBufferSize = 10000
# SQLite 主库配置
databasePath = data/query_logs.db
maxDatabaseSizeMB = 1024
enableWAL = true
# 归档配置
archiveEnabled = true
archiveDir = data/archive
archivePrefix = querylog
compressionLevel = 6
# 清理配置
retentionDays = 0
retentionMonths = 0
# 查询配置
queryTimeout = 5
enableCache = true
cacheTTL = 300
[threat]
enabled = true
queryRateThreshold = 0
@@ -94,3 +69,11 @@ suspiciousPatterns = malware,phishing,trojan,virus,ransomware
unusualQueryTypes = TXT, SRV, MX
alertRetentionDays = 0
threatDatabasePath = ./static/domain-info/threats/threats-database.csv
[domainInfo]
updateInterval = 3600
enableAutoUpdate = true
domainInfo_威胁数据库 = https://gitea.amazehome.xyz/AMAZEHOME/domain-info/src/branch/main/threats/threats-database.csv,threat-database,true
domainInfo_跟踪器列表 = https://gitea.amazehome.xyz/AMAZEHOME/domain-info/raw/branch/main/tracker/trackers.json,tracker,true
domainInfo_111 = https://gitea.amazehome.xyz/AMAZEHOME/domain-info/src/commit/b085e15b1ec593deeff1b8ea53bfc82a8669a020/domains/domain-info.json,domain-info,true
domainInfo_11 = https://gitea.amazehome.xyz/AMAZEHOME/domain-info/src/commit/b085e15b1ec593deeff1b8ea53bfc82a8669a020/domains/domain-info.json,domain-info,true
+64 -2
View File
@@ -52,11 +52,28 @@ type BlacklistEntry struct {
LastUpdateTime string `json:"lastUpdateTime,omitempty"`
}
// DomainInfoEntry 域名信息条目
type DomainInfoEntry struct {
Name string `json:"name"`
URL string `json:"url"`
Enabled bool `json:"enabled"`
Type string `json:"type"` // domain-info, threat-database, tracker
RuleCount int `json:"ruleCount,omitempty"`
LastUpdateTime string `json:"lastUpdateTime,omitempty"`
}
// DomainInfoConfig 域名信息配置
type DomainInfoConfig struct {
DomainInfoLists []DomainInfoEntry `json:"domainInfoLists"`
UpdateInterval int `json:"updateInterval"` // 更新间隔(秒)
EnableAutoUpdate bool `json:"enableAutoUpdate"` // 是否启用自动更新
}
// ShieldConfig 屏蔽规则配置
type ShieldConfig struct {
Blacklists []BlacklistEntry `json:"blacklists"`
UpdateInterval int `json:"updateInterval"`
BlockMethod string `json:"blockMethod"` // 屏蔽方法: "NXDOMAIN", "refused", "emptyIP", "customIP"
BlockMethod string `json:"blockMethod"` // 屏蔽方法"NXDOMAIN", "refused", "emptyIP", "customIP"
CustomBlockIP string `json:"customBlockIP"` // 自定义屏蔽 IP,当 BlockMethod 为"customIP"时使用
StatsSaveInterval int `json:"statsSaveInterval"` // 计数数据保存间隔(秒)
}
@@ -109,6 +126,7 @@ type Config struct {
Threat ThreatConfig `json:"threat"` // 威胁检测配置
Log LogConfig `json:"log"`
QueryLog QueryLogConfig `json:"queryLog"` // 查询日志配置
DomainInfo DomainInfoConfig `json:"domainInfo"` // 域名信息配置
}
// ThreatConfig 威胁检测配置
@@ -209,6 +227,11 @@ func LoadConfig(path string) (*Config, error) {
AlertRetentionDays: cfg.Section("threat").Key("alertRetentionDays").MustInt(0),
ThreatDatabasePath: cfg.Section("threat").Key("threatDatabasePath").MustString("./static/domain-info/threats/threats-database.csv"),
},
DomainInfo: DomainInfoConfig{
UpdateInterval: cfg.Section("domainInfo").Key("updateInterval").MustInt(3600),
EnableAutoUpdate: cfg.Section("domainInfo").Key("enableAutoUpdate").MustBool(true),
DomainInfoLists: parseDomainInfoLists(cfg.Section("domainInfo")),
},
}
// 如果黑名单列表为空,添加一些默认的黑名单
@@ -221,6 +244,15 @@ func LoadConfig(path string) (*Config, error) {
}
}
// 如果域名信息列表为空,添加默认的域名信息列表
if len(config.DomainInfo.DomainInfoLists) == 0 {
config.DomainInfo.DomainInfoLists = []DomainInfoEntry{
{Name: "域名信息列表", URL: "https://gitea.amazehome.xyz/AMAZEHOME/domain-info/raw/branch/main/domains/domain-info.json", Enabled: true, Type: "domain-info"},
{Name: "威胁数据库", URL: "https://gitea.amazehome.xyz/AMAZEHOME/domain-info/raw/branch/main/threats/threats-database.csv", Enabled: true, Type: "threat-database"},
{Name: "跟踪器列表", URL: "https://gitea.amazehome.xyz/AMAZEHOME/domain-info/raw/branch/main/tracker/trackers.json", Enabled: true, Type: "tracker"},
}
}
return config, nil
}
@@ -270,7 +302,7 @@ func parseBlacklists(section *ini.Section) []BlacklistEntry {
name := strings.TrimPrefix(key.Name(), "blacklist_")
value := key.String()
// 解析黑名单URL和启用状态,格式: url,enabled
// 解析黑名单 URL 和启用状态,格式url,enabled
parts := strings.Split(value, ",")
if len(parts) >= 2 {
url := strings.TrimSpace(parts[0])
@@ -286,3 +318,33 @@ func parseBlacklists(section *ini.Section) []BlacklistEntry {
return blacklists
}
// parseDomainInfoLists 解析域名信息列表配置
func parseDomainInfoLists(section *ini.Section) []DomainInfoEntry {
domainInfoLists := []DomainInfoEntry{}
// 遍历所有键,查找以"domainInfo_"开头的键
for _, key := range section.Keys() {
if strings.HasPrefix(key.Name(), "domainInfo_") {
// 提取域名信息名称和属性
name := strings.TrimPrefix(key.Name(), "domainInfo_")
value := key.String()
// 解析域名信息 URL 和启用状态,格式:url,type,enabled
parts := strings.Split(value, ",")
if len(parts) >= 3 {
url := strings.TrimSpace(parts[0])
entryType := strings.TrimSpace(parts[1])
enabled := strings.TrimSpace(parts[2]) == "true"
domainInfoLists = append(domainInfoLists, DomainInfoEntry{
Name: name,
URL: url,
Type: entryType,
Enabled: enabled,
})
}
}
}
return domainInfoLists
}
-3
View File
@@ -1,3 +0,0 @@
# GFWList规则文件
# 格式:每行一条规则
# 例如:www.google.com
-3
View File
@@ -1,3 +0,0 @@
# Hosts文件
# 格式:IP 域名
# 例如:127.0.0.1 localhost
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,734 +0,0 @@
!Title: AWAvenue Ads Rule
!--------------------------------------
!Total lines: 725
!Version: 1.5.5-release
!Homepage: https://github.com/TG-Twilight/AWAvenue-Ads-Rule
!License: https://github.com/TG-Twilight/AWAvenue-Ads-Rule/blob/main/LICENSE
||1010pic.com^
||16dd-advertise-1252317822.file.myqcloud.com^
||16dd-advertise-1252317822.image.myqcloud.com^
||8le8le.com^
||a0.app.xiaomi.com^
||aaid.umeng.com^
||abtest-ch.snssdk.com^
||ad-cache.dopool.com^
||ad-cdn.qingting.fm^
||ad-cmp.hismarttv.com^
||ad-download.hismarttv.com^
||ad-imp.hismarttv.com^
||ad-scope.com^
||ad-scope.com.cn^
||ad-sdk-config.youdao.com^
||ad-sdk.huxiu.com^
||ad.12306.cn^
||ad.51wnl.com^
||ad.bwton.com^
||ad.cctv.com^
||ad.cyapi.cn^
||ad.doubleclick.net^
||ad.partner.gifshow.com^
||ad.qingting.fm^
||ad.qq.com^
||ad.richmob.cn^
||ad.tencentmusic.com^
||ad.toutiao.com^
||ad.v3mh.com^
||ad.winrar.com.cn^
||ad.xelements.cn^
||ad.xiaomi.com^
||ad.ximalaya.com^
||ad.zijieapi.com^
||adapi.izuiyou.com^
||adapi.yynetwk.com^
||adashbc.ut.taobao.com^
||adc.hpplay.cn^
||adcdn.hpplay.cn^
||adcdn.tencentmusic.com^
||adclick.g.doubleclick.net^
||adclick.tencentmusic.com^
||adcolony.com^
||adexpo.tencentmusic.com^
||adfilter.imtt.qq.com^
||adfstat.yandex.ru^
||adguanggao.eee114.com^
||adjust.cn^
||adjust.com^
||adkwai.com^
||adlink-api.huan.tv^
||adm.funshion.com^
||ads-api-o.api.leiniao.com^
||ads-api.tiktok.com^
||ads-api.twitter.com^
||ads-img-qc.xhscdn.com^
||ads-jp.tiktok.com^
||ads-marketing-vivofs.vivo.com.cn^
||ads-sg.tiktok.com^
||ads-us.tiktok.com^
||ads-video-al.xhscdn.com^
||ads-video-qc.xhscdn.com^
||ads.95516.com^
||ads.google.cn^
||ads.heytapmobi.com^
||ads.huan.tv^
||ads.huantest.com^
||ads.icloseli.cn^
||ads.linkedin.com^
||ads.music.126.net^
||ads.oppomobile.com^
||ads.pinterest.com^
||ads.servebom.com^
||ads.service.kugou.com^
||ads.tiktok.com^
||ads.v3mh.com^
||ads.youtube.com^
||ads3-normal-hl.zijieapi.com^
||ads3-normal-lf.zijieapi.com^
||ads3-normal-lq.zijieapi.com^
||ads3-normal.zijieapi.com^
||ads5-normal-hl.zijieapi.com^
||ads5-normal-lf.zijieapi.com^
||ads5-normal-lq.zijieapi.com^
||ads5-normal.zijieapi.com^
||adse.test.ximalaya.com^
||adse.wsa.ximalaya.com^
||adse.ximalaya.com^
||adsebs.ximalaya.com^
||adsense.google.cn^
||adserver.unityads.unity3d.com^
||adservice.google.cn^
||adservice.google.com^
||adserviceretry.kugou.com^
||adsfile.bssdlbig.kugou.com^
||adsfile.qq.com^
||adsfilebssdlbig.ali.kugou.com^
||adsfileretry.service.kugou.com^
||adsfs-sdkconfig.heytapimage.com^
||adsfs.oppomobile.com^
||adslvfile.qq.com^
||adsmart.konka.com^
||adsmind.gdtimg.com^
||adsmind.ugdtimg.com^
||adsp.xunlei.com^
||adstats.tencentmusic.com^
||adstore-1252524079.file.myqcloud.com^
||adstore-index-1252524079.file.myqcloud.com^
||adtago.s3.amazonaws.com^
||adtech.yahooinc.com^
||adtrack.quark.cn^
||adukwai.com^
||adv.fjtv.net^
||adv.sec.intl.miui.com^
||adv.sec.miui.com^
||advertiseonbing.azureedge.net^
||advertising-api-eu.amazon.com^
||advertising-api-fe.amazon.com^
||advertising-api.amazon.com^
||advertising.apple.com^
||advertising.yahoo.com^
||advertising.yandex.ru^
||advice-ads.s3.amazonaws.com^
||adview.cn^
||adx-ad.smart-tv.cn^
||adx-bj.anythinktech.com^
||adx-cn.anythinktech.com^
||adx-drcn.op.dbankcloud.cn^
||adx-open-service.youku.com^
||adx-os.anythinktech.com^
||adx.ads.heytapmobi.com^
||adx.ads.oppomobile.com^
||adxlog-adnet.vivo.com.cn^
||adxlog-adnet.vivo.com.cn.dsa.dnsv1.com.cn^
||adxserver.ad.cmvideo.cn^
||aegis.qq.com^
||afs.googlesyndication.com^
||aiseet.aa.atianqi.com^
||ali-ad.a.yximgs.com^
||alog.umeng.com^
||als.baidu.com^
||amdcopen.m.taobao.com^
||amdcopen.m.umeng.com^
||an.facebook.com^
||analysis.yozocloud.cn^
||analytics-api.samsunghealthcn.com^
||analytics.126.net^
||analytics.95516.com^
||analytics.google.com^
||analytics.pinterest.com^
||analytics.pointdrive.linkedin.com^
||analytics.query.yahoo.com^
||analytics.rayjump.com^
||analytics.s3.amazonaws.com^
||analytics.tiktok.com^
||analytics.woozooo.com^
||analyticsengine.s3.amazonaws.com^
||analyze.lemurbrowser.com^
||andrqd.play.aiseet.atianqi.com^
||ap.dongqiudi.com^
||apd-pcdnwxlogin.teg.tencent-cloud.net^
||apd-pcdnwxnat.teg.tencent-cloud.net^
||apd-pcdnwxstat.teg.tencent-cloud.net^
||api-access.pangolin-sdk-toutiao.com^
||api-access.pangolin-sdk-toutiao1.com^
||api-access.pangolin-sdk-toutiao2.com^
||api-access.pangolin-sdk-toutiao3.com^
||api-access.pangolin-sdk-toutiao4.com^
||api-access.pangolin-sdk-toutiao5.com^
||api-ad-product.huxiu.com^
||api-adservices.apple.com^
||api-gd.hiaiabc.com^
||api-htp.beizi.biz^
||api.ad.xiaomi.com^
||api.e.kuaishou.com^
||api.htp.hubcloud.com.cn^
||api.hzsanjiaomao.com^
||api.installer.xiaomi.com^
||api.jietuhb.com^
||api.kingdata.ksyun.com^
||api.statsig.com^
||api5-normal-quic-lf.ixigua.com^
||apiyd.my91app.com^
||apks.webxiaobai.top^
||app-measurement.com^
||appcloud2.in.zhihu.com^
||applog.lc.quark.cn^
||applog.uc.cn^
||applog.zijieapi.com^
||ata-sdk-uuid-report.dreport.meituan.net^
||auction.unityads.unity3d.com^
||audid-api.taobao.com^
||audid.umeng.com^
||azr.footprintdns.com^
||b1-data.ads.heytapmobi.com^
||baichuan-sdk.alicdn.com^
||baichuan-sdk.taobao.com^
||bdad.123pan.cn^
||bdapi-ads.realmemobile.com^
||bdapi-in-ads.realmemobile.com^
||bdapi.ads.oppomobile.com^
||beacon-api.aliyuncs.com^
||beacon.qq.com^
||beaconcdn.qq.com^
||beacons.gvt2.com^
||beizi.biz^
||bes-mtj.baidu.com^
||bgg.baidu.com^
||bianxian.com^
||bingads.microsoft.com^
||bj.ad.track.66mobi.com^
||books-analytics-events.apple.com^
||browsercfg-drcn.cloud.dbankcloud.cn^
||bsrv.qq.com^
||bugly.qq.com^
||business-api.tiktok.com^
||c.bidtoolads.com^
||c.evidon.com^
||c.gj.qq.com^
||c.kuaiduizuoye.com^
||c.sayhi.360.cn^
||c2.gdt.qq.com^
||canvas-cdn.gdt.qq.com^
||catalog.fjwhcbsh.com^
||cbjs.baidu.com^
||ccs.umeng.com^
||cctv.adsunion.com^
||cdn-ad.wtzw.com^
||cdn-ads.oss-cn-shanghai.aliyuncs.com^
||cdn-plugin-sync-upgrade-juui.hismarttv.com^
||cdn.ad.xiaomi.com^
||cdn.ynuf.aliapp.org^
||cfg.imtt.qq.com^
||chat1.jd.com^
||chiq-cloud.com^
||cj.qidian.com^
||ck.ads.oppomobile.com^
||click.googleanalytics.com^
||click.oneplus.cn^
||clog.miguvideo.com^
||cnlogs.umeng.com^
||cnlogs.umengcloud.com^
||cnzz.com^
||collect.kugou.com^
||commdata.v.qq.com^
||config.chsmarttv.com^
||config.unityads.unity3d.com^
||cpro.baidustatic.com^
||crashlytics.com^
||crashlyticsreports-pa.googleapis.com^
||csjplatform.com^
||cws-cctv.conviva.com^
||data.ads.oppomobile.com^
||data.chsmarttv.com^
||data.mistat.india.xiaomi.com^
||data.mistat.rus.xiaomi.com^
||data.mistat.xiaomi.com^
||diagnosis.ad.xiaomi.com^
||dig.bdurl.net^
||dl.zuimeitianqi.com^
||dlogs.bwton.com^
||dm.toutiao.com^
||domain.aishengji.com^
||doubleclick-cn.net^
||download.changhong.upgrade2.huan.tv^
||downloadxml.changhong.upgrade2.huan.tv^
||drcn-weather.cloud.huawei.com^
||dsp-x.jd.com^
||dsp.fcbox.com^
||dualstack-logs.amap.com^
||dutils.com^
||dxp.baidu.com^
||e.ad.xiaomi.com^
||eclick.baidu.com^
||edge.ads.twitch.tv^
||ef-dongfeng.tanx.com^
||entry.baidu.com^
||errlog.umeng.com^
||errnewlog.umeng.com^
||event.tradplusad.com^
||events-drcn.op.dbankcloud.cn^
||events.reddit.com^
||events.redditmedia.com^
||firebaselogging-pa.googleapis.com^
||flurry.com^
||g-adnet.hiaiabc.com^
||g-staic.ganjingworld.com^
||g2.ganjing.world^
||game.loveota.com^
||gdfp.gifshow.com^
||gemini.yahoo.com^
||geo.yahoo.com^
||getui.cn^
||getui.com^
||getui.net^
||ggx.cmvideo.cn^
||ggx01.miguvideo.com^
||ggx03.miguvideo.com^
||globalapi.ad.xiaomi.com^
||google-analytics.com^
||googleads.g.doubleclick.net^
||googleadservices-cn.com^
||googleadservices.com^
||googletagservices-cn.com^
||googletagservices.com^
||gorgon.youdao.com^
||gromore.pangolin-sdk-toutiao.com^
||grs.dbankcloud.com^
||grs.hicloud.com^
||grs.platform.dbankcloud.ru^
||h-adashx.ut.taobao.com^
||h.trace.qq.com^
||hanlanad.com^
||hexagon-analytics.com^
||hm.baidu.com^
||hmma.baidu.com^
||houyi.kkmh.com^
||hpplay.cn^
||httpdns.bcelive.com^
||httpdns.ocloud.oppomobile.com^
||hugelog.fcbox.com^
||huichuan.sm.cn^
||hw-ot-ad.a.yximgs.com^
||hw.zuimeitianqi.com^
||hwpub-s01-drcn.cloud.dbankcloud.cn^
||hya.comp.360os.com^
||hybrid.miniapp.taobao.com^
||hye.comp.360os.com^
||hyt.comp.360os.com^
||i.snssdk.com^
||iad.apple.com^
||iadctest.qwapi.com^
||iadsdk.apple.com^
||iadworkbench.apple.com^
||ifacelog.iqiyi.com^
||ifs.tanx.com^
||igexin.com^
||ii.gdt.qq.com^
||imag8.pubmatic.com^
||imag86.pubmatic.com^
||image-ad.sm.cn^
||imageplus.baidu.com^
||images.outbrainimg.com^
||images.pinduoduo.com^
||img-c.heytapimage.com^
||img.adnyg.com^
||img.adnyg.com.w.kunlungr.com^
||imtmp.net^
||iot-eu-logser.realme.com^
||iot-logser.realme.com^
||ipv4.kkmh.com^
||irc.qubiankeji.com^
||itv2-up.openspeech.cn^
||ixav-cse.avlyun.com^
||iyfbodn.com^
||janapi.jd.com^
||jiguang.cn^
||jpush.cn^
||jpush.html5.qq.com^
||jpush.io^
||jswebcollects.kugou.com^
||kepler.jd.com^
||kl.67it.com^
||knicks.jd.com^
||ks.pull.yximgs.com^
||launcher.smart-tv.cn^
||launcherimg.smart-tv.cn^
||lf3-ad-union-sdk.pglstatp-toutiao.com^
||lf6-ad-union-sdk.pglstatp-toutiao.com^
||litchiads.com^
||liveats-vod.video.ptqy.gitv.tv^
||livemonitor.huan.tv^
||livep.l.aiseet.atianqi.com^
||lives.l.aiseet.atianqi.com^
||lives.l.ott.video.qq.com^
||lm10111.jtrincc.cn^
||log-api-mn.huxiu.com^
||log-api.huxiu.com^
||log-api.pangolin-sdk-toutiao-b.com^
||log-api.pangolin-sdk-toutiao.com^
||log-report.com^
||log-sdk.gifshow.com^
||log-upload-os.hoyoverse.com^
||log-upload.mihoyo.com^
||log.ad.xiaomi.com^
||log.aispeech.com^
||log.amemv.com^
||log.appstore3.huan.tv^
||log.avlyun.com^
||log.avlyun.sec.intl.miui.com^
||log.byteoversea.com^
||log.fc.yahoo.com^
||log.kuwo.cn^
||log.pinterest.com^
||log.snssdk.com^
||log.stat.kugou.com^
||log.tagtic.cn^
||log.tbs.qq.com^
||log.vcgame.cn^
||log.web.kugou.com^
||log.zijieapi.com^
||log1.cmpassport.com^
||logbak.hicloud.com^
||logs.amap.com^
||logservice.hicloud.com^
||logservice1.hicloud.com^
||logtj.kugou.com^
||logupdate.avlyun.sec.miui.com^
||m-adnet.hiaiabc.com^
||m.ad.zhangyue.com^
||m.atm.youku.com^
||m.kubiqq.com^
||m1.ad.10010.com^
||mapi.m.jd.com^
||masdkv6.3g.qq.com^
||mazu.m.qq.com^
||mbdlog.iqiyi.com^
||metrics.apple.com^
||metrics.data.hicloud.com^
||metrics.icloud.com^
||metrics.mzstatic.com^
||metrics2.data.hicloud.com^
||metrika.yandex.ru^
||mi.gdt.qq.com^
||miav-cse.avlyun.com^
||mime.baidu.com^
||mine.baidu.com^
||mission-pub.smart-tv.cn^
||miui-fxcse.avlyun.com^
||mnqlog.ldmnq.com^
||mobads-logs.baidu.com^
||mobads-pre-config.cdn.bcebos.com^
||mobads.baidu.com^
||mobile.da.mgtv.com^
||mobilelog.upqzfile.com^
||mobileservice.cn^
||mon.zijieapi.com^
||monitor-ads-test.huan.tv^
||monitor-uu.play.aiseet.atianqi.com^
||monitor.music.qq.com^
||monitor.uu.qq.com^
||monsetting.toutiao.com^
||mssdk.volces.com^
||mssdk.zijieapi.com^
||mtj.baidu.com^
||newvoice.chiq5.smart-tv.cn^
||nmetrics.samsung.com^
||notes-analytics-events.apple.com^
||nsclick.baidu.com^
||o2o.api.xiaomi.com^
||oauth-login-drcn.platform.dbankcloud.com^
||offerwall.yandex.net^
||omgmta.play.aiseet.atianqi.com^
||open.e.kuaishou.cn^
||open.e.kuaishou.com^
||open.kuaishouzt.com^
||open.kwaishouzt.com^
||open.kwaizt.com^
||optimus-ads.amap.com^
||orbit.jd.com^
||oth.eve.mdt.qq.com^
||oth.str.mdt.qq.com^
||otheve.play.aiseet.atianqi.com^
||outlookads.live.com^
||p.l.qq.com^
||p.s.360.cn^
||p1-be-pack-sign.pglstatp-toutiao.com^
||p1-lm.adkwai.com^
||p2-be-pack-sign.pglstatp-toutiao.com^
||p2-lm.adkwai.com^
||p2p.huya.com^
||p3-be-pack-sign.pglstatp-toutiao.com^
||p3-lm.adkwai.com^
||p3-tt.byteimg.com^
||p4-be-pack-sign.pglstatp-toutiao.com^
||p5-be-pack-sign.pglstatp-toutiao.com^
||p6-be-pack-sign.pglstatp-toutiao.com^
||pagead2.googleadservices.com^
||pagead2.googlesyndication.com^
||pangolin-sdk-toutiao-b.com^
||pay.sboot.cn^
||pgdt.ugdtimg.com^
||pglstatp-toutiao.com^
||pig.pupuapi.com^
||pixon.ads-pixiv.net^
||pkoplink.com^
||plbslog.umeng.com^
||pms.mb.qq.com^
||policy.video.ptqy.gitv.tv^
||pos.baidu.com^
||proxy.advp.apple.com^
||public.gdtimg.com^
||q.i.gdt.qq.com^
||qqdata.ab.qq.com^
||qwapi.apple.com^
||qzs.gdtimg.com^
||recommend-drcn.hms.dbankcloud.cn^
||report.tv.kohesport.qq.com^
||res.hubcloud.com.cn^
||res1.hubcloud.com.cn^
||res2.hubcloud.com.cn^
||res3.hubcloud.com.cn^
||resolve.umeng.com^
||review.gdtimg.com^
||rms-drcn.platform.dbankcloud.cn^
||roi.soulapp.cn^
||rpt.gdt.qq.com^
||rtb.voiceads.cn^
||s.amazon-adsystem.com^
||s1.qq.com^
||s2.qq.com^
||s3.qq.com^
||saad.ms.zhangyue.net^
||samsung-com.112.2o7.net^
||samsungads.com^
||sanme2.taisantech.com^
||saveu5-normal-lq.zijieapi.com^
||scdown.qq.com^
||scs.openspeech.cn^
||sdk-ab-config.qquanquan.com^
||sdk-cache.video.ptqy.gitv.tv^
||sdk.1rtb.net^
||sdk.beizi.biz^
||sdk.cferw.com^
||sdk.e.qq.com^
||sdk.hzsanjiaomao.com^
||sdk.markmedia.com.cn^
||sdk.mobads.adwangmai.com^
||sdkconf.avlyun.com^
||sdkconfig.ad.intl.xiaomi.com^
||sdkconfig.ad.xiaomi.com^
||sdkconfig.play.aiseet.atianqi.com^
||sdkconfig.video.qq.com^
||sdkoptedge.chinanetcenter.com^
||sdktmp.hubcloud.com.cn^
||sdownload.stargame.com^
||search.ixigua.com^
||search3-search.ixigua.com^
||search5-search-hl.ixigua.com^
||search5-search.ixigua.com^
||securemetrics.apple.com^
||securepubads.g.doubleclick.net^
||sensors-log.dongqiudi.com^
||service.changhong.upgrade2.huan.tv^
||service.vmos.cn^
||sf16-static.i18n-pglstatp.com^
||sf3-fe-tos.pglstatp-toutiao.com^
||shouji.sogou.com^
||sigmob.cn^
||sigmob.com^
||skdisplay.jd.com^
||slb-p2p.vcloud.ks-live.com^
||smad.ms.zhangyue.net^
||smart-tv.cn^
||smartad.10010.com^
||smetrics.samsung.com^
||sms.ads.oppomobile.com^
||sngmta.qq.com^
||snowflake.qq.com^
||stat.dongqiudi.com^
||stat.y.qq.com^
||static.ads-twitter.com^
||statics.woozooo.com^
||stats.qiumibao.com^
||stats.wp.com^
||statsigapi.net^
||stg-data.ads.heytapmobi.com^
||success.ctobsnssdk.com^
||syh-imp.cdnjtzy.com^
||szbdyd.com^
||t-dsp.pinduoduo.com^
||t.l.qq.com^
||t.track.ad.xiaomi.com^
||t002.ottcn.com^
||t1.a.market.xiaomi.com^
||t2.a.market.xiaomi.com^
||t3.a.market.xiaomi.com^
||tangram.e.qq.com^
||tdc.qq.com^
||tdsdk.cpatrk.net^
||tdsdk.xdrig.com^
||tencent-dtv.m.cn.miaozhen.com^
||terms-drcn.platform.dbankcloud.cn^
||test.ad.xiaomi.com^
||test.e.ad.xiaomi.com^
||tj.b.qq.com^
||tj.video.qq.com^
||tmead.y.qq.com^
||tmeadcomm.y.qq.com^
||tmfmazu-wangka.m.qq.com^
||tmfmazu.m.qq.com^
||tmfsdk.m.qq.com^
||tmfsdktcpv4.m.qq.com^
||tnc3-aliec1.toutiaoapi.com^
||tnc3-aliec2.bytedance.com^
||tnc3-aliec2.toutiaoapi.com^
||tnc3-alisc1.bytedance.com^
||tnc3-alisc1.zijieapi.com^
||tnc3-alisc2.zijieapi.com^
||tnc3-bjlgy.bytedance.com^
||tnc3-bjlgy.toutiaoapi.com^
||tnc3-bjlgy.zijieapi.com^
||toblog.ctobsnssdk.com^
||trace.qq.com^
||tracelog-debug.qquanquan.com^
||track.lc.quark.cn^
||track.uc.cn^
||tracker.ai.xiaomi.com^
||tracker.gitee.com^
||tracking.miui.com^
||tracking.rus.miui.com^
||tsvrv.com^
||tvuser-ch.cedock.com^
||tx-ad.a.yximgs.com^
||tx-kmpaudio.pull.yximgs.com^
||tz.sec.xiaomi.com^
||uapi.ads.heytapmobi.com^
||udc.yahoo.com^
||udcm.yahoo.com^
||uedas.qidian.com^
||ulog-sdk.gifshow.com^
||ulogjs.gifshow.com^
||ulogs.umeng.com^
||ulogs.umengcloud.com^
||umengacs.m.taobao.com^
||umengjmacs.m.taobao.com^
||umini.shujupie.com^
||umsns.com^
||union.baidu.cn^
||union.baidu.com^
||update.avlyun.sec.miui.com^
||update.lejiao.tv^
||upgrade-update.hismarttv.com^
||us.l.qq.com^
||v.adintl.cn^
||v.adx.hubcloud.com.cn^
||v1-ad.video.yximgs.com^
||v2-ad.video.yximgs.com^
||v2-api-channel-launcher.hismarttv.com^
||v2.gdt.qq.com^
||v2mi.gdt.qq.com^
||v3-ad.video.yximgs.com^
||v3.gdt.qq.com^
||video-ad.sm.cn^
||video-dsp.pddpic.com^
||video.dispatch.tc.qq.com^
||virusinfo-cloudscan-cn.heytapmobi.com^
||vlive.qqvideo.tc.qq.com^
||volc.bj.ad.track.66mobi.com^
||vungle.com^
||w.l.qq.com^
||w1.askwai.com^
||w1.bskwai.com^
||w1.cskwai.com^
||w1.dskwai.com^
||w1.eskwai.com^
||w1.fskwai.com^
||w1.gskwai.com^
||w1.hskwai.com^
||w1.iskwai.com^
||w1.jskwai.com^
||w1.kskwai.com^
||w1.lskwai.com^
||w1.mskwai.com^
||w1.nskwai.com^
||w1.oskwai.com^
||w1.pskwai.com^
||w1.qskwai.com^
||w1.rskwai.com^
||w1.sskwai.com^
||w1.tskwai.com^
||w1.uskwai.com^
||w1.vskwai.com^
||w1.wskwai.com^
||w1.xskwai.com^
||w1.yskwai.com^
||w1.zskwai.com^
||watson.microsoft.com^
||watson.telemetry.microsoft.com^
||weather-analytics-events.apple.com^
||weather-community-drcn.weather.dbankcloud.cn^
||webstat.qiumibao.com^
||webview.unityads.unity3d.com^
||widgets.outbrain.com^
||widgets.pinterest.com^
||win.gdt.qq.com^
||wn.x.jd.com^
||ws-keyboard.shouji.sogou.com^
||ws.sj.qq.com^
||www42.zskwai.com^
||wxa.wxs.qq.com^
||wximg.wxs.qq.com^
||wxsmw.wxs.qq.com^
||wxsnsad.tc.qq.com^
||wxsnsdy.wxs.qq.com^
||wxsnsdythumb.wxs.qq.com^
||xc.gdt.qq.com^
||xiaomi-dtv.m.cn.miaozhen.com^
||xiaoshuo.wtzw.com^
||xlivrdr.com^
||xlmzc.cnjp-exp.com^
||xlog.jd.com^
||xlviiirdr.com^
||xlviirdr.com^
||yk-ssp.ad.youku.com^
||ykad-data.youku.com^
||ykad-gateway.youku.com^
||youku-acs.m.taobao.com^
||youxi.kugou.com^
||zeus.ad.xiaomi.com^
||zhihu-web-analytics.zhihu.com^
/.*\.*\.shouji\.sogou\.com/
/.*\.[a-zA-Z0-9.-]skwai\.com/
/.*\.a\.market\.xiaomi\.com/
/.*\.data\.hicloud\.com/
/.*\.log\.aliyuncs\.com/
/[a-zA-Z0-9.-]*-ad-[a-zA-Z0-9.-]*\.byteimg\.com/
/[a-zA-Z0-9.-]*-ad\.sm\.cn/
/[a-zA-Z0-9.-]*-ad\.video\.yximgs\.com/
/[a-zA-Z0-9.-]*-ad\.wtzw\.com/
/[a-zA-Z0-9.-]*-be-pack-sign\.pglstatp-toutiao\.com/
/[a-zA-Z0-9.-]*-lm\.adkwai\.com/
/[a-zA-Z0-9.-]*-normal-[a-zA-Z0-9.-]*\.zijieapi\.com/
/[a-zA-Z0-9.-]*-normal\.zijieapi\.com/
/cloudinject[a-zA-Z0-9.-]*-dev\.*\.[a-zA-Z0-9.-]*-[a-zA-Z0-9.-]*-[a-zA-Z0-9.-]*\.amazonaws\.com/
-3
View File
@@ -1,3 +0,0 @@
# 自定义规则文件
# 格式:域名
# 例如:example.com
-5
View File
@@ -1,5 +0,0 @@
{
"blockedDomainsCount": {},
"resolvedDomainsCount": {},
"lastSaved": "2026-04-05T02:12:23.623097707+08:00"
}
-121
View File
@@ -1,121 +0,0 @@
{
"stats": {
"Queries": 153,
"Blocked": 40,
"Allowed": 84,
"Errors": 29,
"LastQuery": "2026-04-05T02:12:23.465147386+08:00",
"AvgResponseTime": 53,
"TotalResponseTime": 8033,
"QueryTypes": {
"A": 105,
"AAAA": 48
},
"SourceIPs": {
"10.35.10.21": true,
"10.35.10.29": true,
"10.35.10.39": true,
"10.35.10.70": true,
"10.35.10.78": true
},
"CpuUsage": 0.9268537074148298,
"DNSSECQueries": 0,
"DNSSECSuccess": 0,
"DNSSECFailed": 0,
"DNSSECEnabled": false
},
"blockedDomains": {
"h-adashx.ut.taobao.com": {
"Domain": "h-adashx.ut.taobao.com",
"Count": 5,
"LastSeen": 1775326320763967699,
"DNSSEC": false
},
"log.zijieapi.com": {
"Domain": "log.zijieapi.com",
"Count": 11,
"LastSeen": 1775326340263318690,
"DNSSEC": false
},
"o1098464.ingest.sentry.io": {
"Domain": "o1098464.ingest.sentry.io",
"Count": 6,
"LastSeen": 1775326342243323063,
"DNSSEC": false
},
"oth.eve.mdt.qq.com": {
"Domain": "oth.eve.mdt.qq.com",
"Count": 4,
"LastSeen": 1775326338058395755,
"DNSSEC": false
},
"pcapp-data-collect.youku.com": {
"Domain": "pcapp-data-collect.youku.com",
"Count": 9,
"LastSeen": 1775326322906085951,
"DNSSEC": false
},
"puds.ucweb.com": {
"Domain": "puds.ucweb.com",
"Count": 1,
"LastSeen": 1775326318450490954,
"DNSSEC": false
},
"pw.mediav.com": {
"Domain": "pw.mediav.com",
"Count": 2,
"LastSeen": 1775326325615190218,
"DNSSEC": false
},
"px.effirst.com": {
"Domain": "px.effirst.com",
"Count": 1,
"LastSeen": 1775326318462130855,
"DNSSEC": false
},
"tpstelemetry.tencent.com": {
"Domain": "tpstelemetry.tencent.com",
"Count": 1,
"LastSeen": 1775326318452632826,
"DNSSEC": false
}
},
"resolvedDomains": {},
"clientStats": {
"10.35.10.21": {
"IP": "10.35.10.21",
"Count": 4,
"LastSeen": 1775326338058117035
},
"10.35.10.29": {
"IP": "10.35.10.29",
"Count": 24,
"LastSeen": 1775326329866081939
},
"10.35.10.39": {
"IP": "10.35.10.39",
"Count": 5,
"LastSeen": 1775326333564538372
},
"10.35.10.70": {
"IP": "10.35.10.70",
"Count": 80,
"LastSeen": 1775326343465148826
},
"10.35.10.78": {
"IP": "10.35.10.78",
"Count": 40,
"LastSeen": 1775326340263184353
}
},
"hourlyStats": {
"2026-04-05-02": 40
},
"dailyStats": {
"2026-04-05": 40
},
"monthlyStats": {
"2026-04": 40
},
"lastSaved": "2026-04-05T02:12:23.62184716+08:00"
}
BIN
View File
Binary file not shown.
-476
View File
@@ -1,476 +0,0 @@
# DNS 查询日志加载性能优化方案
## 问题分析
当前日志详情页面加载时间约 10 秒,主要性能瓶颈分析如下:
### 1. **主要性能瓶颈**
#### 1.1 同步 API 调用(最严重)
- **位置**: `updateLogsTable()` 函数第 1221 行
- **问题**: 对每条日志都调用 `await isDomainInTrackerDatabase(log.domain)`
- **影响**: 假设每页 10 条日志,每条日志检查跟踪器数据库需要 100-500ms,总计 1-5 秒
- **代码**:
```javascript
const trackerInfo = await isDomainInTrackerDatabase(log.domain); // ❌ 每条都 await
```
#### 1.2 跟踪器数据库加载
- **位置**: `isDomainInTrackerDatabase()` 函数
- **问题**: 每次检查都要等待数据库加载完成
- **影响**: 首次加载或数据库未加载完成时,每条日志都要等待
#### 1.3 域名信息 API 调用
- **位置**: `getDomainInfoFromAPI()` 函数
- **问题**: 如果实现中调用 API,会产生网络延迟
- **影响**: 每个域名都可能产生一次 HTTP 请求
#### 1.4 IP 地理位置查询
- **位置**: `getIpGeolocation()` 函数
- **问题**: 虽然有缓存,但首次查询仍需调用外部 API
- **影响**: 每个新 IP 地址需要 200-500ms
### 2. **性能测试数据(估算)**
| 操作 | 单次耗时 | 每页 10 条总耗时 | 优化后耗时 |
|------|---------|----------------|-----------|
| 跟踪器检查 | 100-500ms | 1-5 秒 | <100ms |
| IP 地理位置 | 200-500ms | 2-5 秒 | <500ms(缓存) |
| 后端 API 查询 | 100-300ms | 100-300ms | 不变 |
| DOM 渲染 | 50-100ms | 50-100ms | 不变 |
| **总计** | **10 秒** | **3-10 秒** | **<1 秒** |
---
## 优化方案
### 方案一:异步并行处理(推荐优先实施)⭐⭐⭐⭐⭐
#### 1.1 批量并行检查跟踪器
**问题**: 当前是串行等待每个域名的检查结果
**解决**: 使用 `Promise.all()` 并行处理所有域名的检查
```javascript
// 优化前(串行)
for (const log of logs) {
const trackerInfo = await isDomainInTrackerDatabase(log.domain);
// ... 处理逻辑
}
// 优化后(并行)
const trackerChecks = logs.map(log => isDomainInTrackerDatabase(log.domain));
const trackerResults = await Promise.all(trackerChecks);
// 然后渲染表格
logs.forEach((log, index) => {
const trackerInfo = trackerResults[index];
// ... 渲染逻辑
});
```
**预期效果**: 从 1-5 秒降低到 100-500ms
#### 1.2 预加载跟踪器数据库
**问题**: 每次检查都要等待数据库加载
**解决**: 页面初始化时立即加载,而不是延迟加载
```javascript
// 在页面加载时立即执行
document.addEventListener('DOMContentLoaded', () => {
loadTrackersDatabase(); // 提前加载,不等待日志显示
});
```
**预期效果**: 消除数据库加载等待时间
---
### 方案二:缓存优化 ⭐⭐⭐⭐
#### 2.1 增强跟踪器检查缓存
**问题**: 相同的域名被重复检查
**解决**: 添加内存缓存,避免重复检查
```javascript
// 添加缓存
const trackerCache = new Map();
const trackerCacheTimestamp = new Map();
const TRACKER_CACHE_EXPIRY = 24 * 60 * 60 * 1000; // 24 小时
async function isDomainInTrackerDatabase(domain) {
// 检查缓存
const cached = trackerCache.get(domain);
const timestamp = trackerCacheTimestamp.get(domain);
if (cached && timestamp && (Date.now() - timestamp) < TRACKER_CACHE_EXPIRY) {
return cached;
}
// 执行实际检查...
const result = // ... 检查逻辑
// 缓存结果
trackerCache.set(domain, result);
trackerCacheTimestamp.set(domain, Date.now());
return result;
}
```
**预期效果**: 重复域名检查从 100ms 降低到 <1ms
#### 2.2 IP 地理位置缓存优化
**问题**: 相同 IP 被重复查询
**解决**: 已有 LRU 缓存,确保缓存命中率高
```javascript
// 确保缓存大小足够(当前为 1000,建议保持)
const GEOLOCATION_CACHE_MAX_SIZE = 1000;
```
---
### 方案三:延迟渲染优化 ⭐⭐⭐
#### 3.1 先渲染后更新
**问题**: 等待所有数据获取完成才渲染表格
**解决**: 先渲染基本内容,再异步更新增强信息
```javascript
async function updateLogsTable(logs) {
// 第一步:立即渲染基本表格(不等待跟踪器检查)
renderBasicTable(logs);
// 第二步:异步获取跟踪器信息并更新
const trackerChecks = logs.map(log => isDomainInTrackerDatabase(log.domain));
Promise.all(trackerChecks).then(results => {
updateTrackerIcons(results); // 只更新图标部分
});
// 第三步:异步获取 IP 地理位置
logs.forEach(log => {
getIpGeolocation(log.clientIP).then(location => {
updateLocationElement(log.clientIP, location);
});
});
}
```
**预期效果**: 用户感知加载时间从 10 秒降低到 500ms 以内
#### 3.2 虚拟滚动(针对大量数据)
**问题**: 如果用户选择每页 100 条,DOM 节点过多
**解决**: 只渲染可见区域的日志
```javascript
// 使用虚拟滚动库或自定义实现
// 只渲染可视区域的 20-30 条,滚动时动态加载
```
**预期效果**: 渲染时间从 100ms 降低到 20ms
---
### 方案四:后端优化 ⭐⭐⭐⭐
#### 4.1 后端批量检查跟踪器
**问题**: 前端检查每条日志的跟踪器状态
**解决**: 后端在返回日志时直接包含跟踪器信息
```go
// 后端代码修改
type QueryLog struct {
// ... 现有字段
IsTracker bool `json:"isTracker"`
TrackerName string `json:"trackerName,omitempty"`
}
// 在返回日志前批量检查
func (s *Server) enrichLogsWithTrackerInfo(logs []QueryLog) {
for i := range logs {
logs[i].IsTracker, logs[i].TrackerName = s.checkTracker(logs[i].Domain)
}
}
```
**预期效果**: 完全消除前端跟踪器检查时间
#### 4.2 后端缓存优化
**问题**: 后端查询数据库慢
**解决**: 增加 Redis 或内存缓存
```go
// 使用内存缓存查询结果
var queryCache = lru.New(100)
```
**预期效果**: 后端查询时间从 300ms 降低到 50ms
---
### 方案五:数据库索引优化 ⭐⭐⭐
#### 5.1 添加数据库索引
**问题**: 日志查询慢
**解决**: 为常用查询字段添加索引
```sql
-- 为时间戳添加索引(加速时间范围查询)
CREATE INDEX idx_timestamp ON query_logs(timestamp DESC);
-- 为域名添加索引(加速域名搜索)
CREATE INDEX idx_domain ON query_logs(domain);
-- 为客户端 IP 添加索引
CREATE INDEX idx_client_ip ON query_logs(client_ip);
-- 组合索引(加速组合查询)
CREATE INDEX idx_timestamp_result ON query_logs(timestamp DESC, result);
```
**预期效果**: 后端查询时间从 500ms 降低到 50ms
---
## 实施优先级
### 第一阶段(立即实施,效果最明显)
1.**方案 1.1**: 并行处理跟踪器检查
2.**方案 2.1**: 添加跟踪器检查缓存
3.**方案 1.2**: 预加载跟踪器数据库
**预期效果**: 10 秒 → 2-3 秒
### 第二阶段(本周内实施)
4.**方案 3.1**: 先渲染后更新
5.**方案 4.1**: 后端批量检查跟踪器
**预期效果**: 2-3 秒 → 1 秒以内
### 第三阶段(长期优化)
6.**方案 5.1**: 数据库索引优化
7.**方案 4.2**: 后端缓存
8.**方案 3.2**: 虚拟滚动
**预期效果**: 1 秒 → 500ms 以内
---
## 具体代码修改
### 修改 1: `logs.js` - 并行处理跟踪器检查
```javascript
// 在 updateLogsTable() 函数中,替换第 1155-1353 行
async function updateLogsTable(logs) {
const tableBody = document.getElementById('logs-table-body');
if (!tableBody) return;
// 清空表格
tableBody.innerHTML = '';
if (logs.length === 0) {
// 显示空状态
tableBody.innerHTML = `
<tr>
<td colspan="5" class="py-8 text-center text-gray-500 border-b border-gray-100">
<i class="fa fa-file-text-o text-4xl mb-2 text-gray-300"></i>
<div>暂无查询日志</div>
</td>
</tr>
`;
return;
}
// 检测是否为移动设备
const isMobile = window.innerWidth <= 768;
// 【优化】并行处理所有跟踪器检查
const trackerChecks = logs.map(log => isDomainInTrackerDatabase(log.domain));
const trackerResults = await Promise.all(trackerChecks);
// 预创建文档片段,减少 DOM 操作
const fragment = document.createDocumentFragment();
// 填充表格
for (let i = 0; i < logs.length; i++) {
const log = logs[i];
const trackerInfo = trackerResults[i];
const isTracker = trackerInfo !== null;
const row = document.createElement('tr');
row.className = `border-b border-gray-100 hover:bg-gray-50 transition-colors ${
log.result === 'blocked' ? 'bg-red-50' : ''
}`;
// ... 渲染逻辑(保持不变,但移除 await)
fragment.appendChild(row);
}
// 一次性添加到 DOM
tableBody.appendChild(fragment);
// 【优化】异步更新 IP 地理位置(不阻塞渲染)
logs.forEach(log => {
if (!isPrivateIP(log.clientIP)) {
getIpGeolocation(log.clientIP).then(location => {
const locationEl = document.querySelector(`.location-${log.clientIP.replace(/[.:]/g, '-')}`);
if (locationEl) {
locationEl.textContent = location;
}
});
}
});
}
```
### 修改 2: `logs.js` - 添加跟踪器缓存
```javascript
// 在全局变量部分添加
const trackerCache = new Map();
const trackerCacheTimestamp = new Map();
const TRACKER_CACHE_EXPIRY = 24 * 60 * 60 * 1000; // 24 小时
// 修改 isDomainInTrackerDatabase 函数
async function isDomainInTrackerDatabase(domain) {
// 检查缓存
const cached = trackerCache.get(domain);
const timestamp = trackerCacheTimestamp.get(domain);
if (cached !== undefined && timestamp && (Date.now() - timestamp) < TRACKER_CACHE_EXPIRY) {
return cached;
}
// 确保数据库已加载
if (!trackersDatabase || !trackersLoaded) {
await loadTrackersDatabase();
}
if (!trackersDatabase || !trackersDatabase.trackers) {
trackerCache.set(domain, null);
trackerCacheTimestamp.set(domain, Date.now());
return null;
}
// 检查逻辑(保持不变)
let result = null;
if (trackersDatabase.trackers.hasOwnProperty(domain)) {
result = trackersDatabase.trackers[domain];
} else {
for (const trackerKey in trackersDatabase.trackers) {
const tracker = trackersDatabase.trackers[trackerKey];
if (tracker && tracker.url) {
try {
const trackerUrl = new URL(tracker.url);
if (trackerUrl.hostname === domain) {
result = tracker;
break;
}
} catch (e) {
// 忽略无效 URL
}
}
}
}
// 缓存结果
trackerCache.set(domain, result);
trackerCacheTimestamp.set(domain, Date.now());
// 限制缓存大小(LRU 简单实现)
if (trackerCache.size > 1000) {
const oldestKey = trackerCache.keys().next().value;
trackerCache.delete(oldestKey);
trackerCacheTimestamp.delete(oldestKey);
}
return result;
}
```
### 修改 3: `index.html` - 预加载跟踪器数据库
```html
<!-- 在页面底部,logs.js 加载后立即执行 -->
<script>
// 页面加载时立即预加载跟踪器数据库
document.addEventListener('DOMContentLoaded', function() {
// 异步加载,不阻塞页面
if (typeof loadTrackersDatabase === 'function') {
loadTrackersDatabase();
}
});
</script>
```
---
## 性能监控
### 添加性能日志
```javascript
// 在 loadLogs() 函数中添加性能监控
async function loadLogs() {
const startTime = performance.now();
console.log('🚀 开始加载日志...');
// ... 加载逻辑
const endTime = performance.now();
const duration = endTime - startTime;
console.log(`✅ 日志加载完成,耗时:${duration.toFixed(2)}ms`);
// 分解各阶段耗时
console.log('📊 性能分析:', {
API 请求apiTime,
跟踪器检查trackerTime,
DOM 渲染renderTime,
IP 查询ipTime
});
}
```
---
## 预期最终效果
| 优化阶段 | 加载时间 | 改善幅度 |
|---------|---------|---------|
| 优化前 | 10 秒 | - |
| 第一阶段 | 2-3 秒 | 70-80% |
| 第二阶段 | 1 秒以内 | 90% |
| 第三阶段 | 500ms 以内 | 95% |
---
## 风险与注意事项
1. **内存使用**: 缓存会增加内存占用,建议限制缓存大小
2. **缓存一致性**: 跟踪器数据库更新后需要清理缓存
3. **浏览器兼容性**: `Promise.all()` 在老旧浏览器可能不支持
4. **并发限制**: 如果日志数量过多(>100),考虑分批处理
---
## 总结
**最优先实施的优化**:
1. ✅ 并行处理跟踪器检查(方案 1.1)
2. ✅ 添加跟踪器检查缓存(方案 2.1)
3. ✅ 先渲染后更新(方案 3.1
这三项优化可以将加载时间从 10 秒降低到 1 秒以内,且实施成本低,风险小。
+64
View File
@@ -0,0 +1,64 @@
package http
import (
"dns-server/log"
)
// enrichLogsWithDomainInfo 为日志条目添加域名信息、威胁信息和跟踪器信息
func (s *Server) enrichLogsWithDomainInfo(logs []log.QueryLog) []map[string]interface{} {
enrichedLogs := make([]map[string]interface{}, len(logs))
for i, logItem := range logs {
// 将日志条目转换为 map
logMap := make(map[string]interface{})
logMap["timestamp"] = logItem.Timestamp
logMap["clientIP"] = logItem.ClientIP
logMap["domain"] = logItem.Domain
logMap["queryType"] = logItem.QueryType
logMap["result"] = logItem.Result
logMap["responseTime"] = logItem.ResponseTime
logMap["dnsServer"] = logItem.DNSServer
logMap["answers"] = logItem.Answers
// 查询域名信息
if domainInfo := s.domainInfoManager.GetDomainInfo(logItem.Domain); domainInfo != nil {
logMap["domainInfo"] = domainInfo
}
// 查询威胁信息
if threatInfo := s.domainInfoManager.GetThreatInfo(logItem.Domain); threatInfo != nil {
logMap["threatInfo"] = threatInfo
}
// 查询跟踪器信息
if trackerInfo := s.domainInfoManager.GetTrackerInfo(logItem.Domain); trackerInfo != nil {
logMap["trackerInfo"] = trackerInfo
}
enrichedLogs[i] = logMap
}
return enrichedLogs
}
// enrichDomainInfoWithDetails 为域名查询结果添加详细信息
func (s *Server) enrichDomainInfoWithDetails(domain string, baseResult map[string]interface{}) map[string]interface{} {
// 添加域名信息
if domainInfo := s.domainInfoManager.GetDomainInfo(domain); domainInfo != nil {
baseResult["domainInfo"] = domainInfo
}
// 添加威胁信息
if threatInfo := s.domainInfoManager.GetThreatInfo(domain); threatInfo != nil {
baseResult["threatInfo"] = threatInfo
baseResult["isThreat"] = true
}
// 添加跟踪器信息
if trackerInfo := s.domainInfoManager.GetTrackerInfo(domain); trackerInfo != nil {
baseResult["trackerInfo"] = trackerInfo
baseResult["isTracker"] = true
}
return baseResult
}
+385
View File
@@ -0,0 +1,385 @@
package http
import (
"encoding/json"
"fmt"
"net/http"
"strings"
"dns-server/config"
"dns-server/logger"
"dns-server/shield"
"gopkg.in/ini.v1"
)
// handleDomainInfoUpdate 处理域名信息更新请求(更新所有类型)
func (s *Server) handleDomainInfoUpdate(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
if r.Method != http.MethodPost {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
logger.Info("收到更新所有域名信息的请求")
// 异步更新所有域名信息
go func() {
if err := s.domainInfoManager.LoadDomainInfo(); err != nil {
logger.Error("更新所有域名信息失败", "error", err)
} else {
logger.Info("更新所有域名信息成功")
}
}()
json.NewEncoder(w).Encode(map[string]string{
"status": "success",
"message": "域名信息更新任务已启动",
})
}
// handleDomainInfoUpdateByType 处理指定类型的域名信息更新请求
func (s *Server) handleDomainInfoUpdateByType(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
if r.Method != http.MethodPost {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
// 从 URL 路径中提取类型
// 路径格式:/api/domain-info/update/{type}
pathParts := strings.Split(r.URL.Path, "/")
var entryType string
for i, part := range pathParts {
if part == "update" && i+1 < len(pathParts) {
entryType = strings.TrimSpace(pathParts[i+1])
break
}
}
if entryType == "" {
json.NewEncoder(w).Encode(map[string]string{
"status": "error",
"message": "类型参数不能为空",
})
return
}
logger.Info("收到更新域名信息的请求", "type", entryType)
// 异步更新指定类型的域名信息
go func(typeToUpdate string) {
if err := s.domainInfoManager.UpdateDomainInfoList(typeToUpdate); err != nil {
logger.Error("更新域名信息失败", "type", typeToUpdate, "error", err)
} else {
logger.Info("更新域名信息成功", "type", typeToUpdate)
}
}(entryType)
json.NewEncoder(w).Encode(map[string]string{
"status": "success",
"message": "域名信息更新任务已启动",
"type": entryType,
})
}
// handleDomainInfoQuery 处理单个域名信息查询请求
func (s *Server) handleDomainInfoQuery(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
if r.Method != http.MethodGet {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
domain := r.URL.Query().Get("domain")
if domain == "" {
json.NewEncoder(w).Encode(map[string]string{
"status": "error",
"message": "domain 参数不能为空",
})
return
}
result := map[string]interface{}{
"domain": domain,
}
// 查询域名信息
if domainInfo := s.domainInfoManager.GetDomainInfo(domain); domainInfo != nil {
result["domainInfo"] = domainInfo
}
// 查询威胁信息
if threatInfo := s.domainInfoManager.GetThreatInfo(domain); threatInfo != nil {
result["threatInfo"] = threatInfo
}
// 查询跟踪器信息
if trackerInfo := s.domainInfoManager.GetTrackerInfo(domain); trackerInfo != nil {
result["trackerInfo"] = trackerInfo
}
json.NewEncoder(w).Encode(result)
}
// AddDomainInfoList 添加域名信息列表(供外部调用)
func (s *Server) AddDomainInfoList(entry config.DomainInfoEntry) error {
return s.domainInfoManager.AddDomainInfoList(entry)
}
// RemoveDomainInfoList 移除域名信息列表(供外部调用)
func (s *Server) RemoveDomainInfoList(entryType string) error {
return s.domainInfoManager.RemoveDomainInfoList(entryType)
}
// GetDomainInfoManager 获取域名信息管理器实例(供外部调用)
func (s *Server) GetDomainInfoManager() *shield.DomainInfoManager {
return s.domainInfoManager
}
// handleDomainInfoStatus 处理域名信息更新状态请求
func (s *Server) handleDomainInfoStatus(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
if r.Method != http.MethodGet {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
status := s.domainInfoManager.GetUpdateStatus()
json.NewEncoder(w).Encode(map[string]interface{}{
"status": "success",
"data": status,
})
}
// handleDomainInfoRefresh 处理域名信息缓存刷新请求
func (s *Server) handleDomainInfoRefresh(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
if r.Method != http.MethodPost {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
logger.Info("收到刷新域名信息缓存的请求")
// 异步刷新缓存
go func() {
if err := s.domainInfoManager.LoadDomainInfo(); err != nil {
logger.Error("刷新域名信息缓存失败", "error", err)
} else {
logger.Info("刷新域名信息缓存成功")
}
}()
json.NewEncoder(w).Encode(map[string]string{
"status": "success",
"message": "域名信息缓存刷新任务已启动",
})
}
// handleDomainInfoAdd 处理添加域名信息列表请求
func (s *Server) handleDomainInfoAdd(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
if r.Method != http.MethodPost {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
var entry config.DomainInfoEntry
if err := json.NewDecoder(r.Body).Decode(&entry); err != nil {
json.NewEncoder(w).Encode(map[string]string{
"status": "error",
"message": "无效的请求数据",
})
return
}
// 验证必填字段
if entry.Name == "" || entry.URL == "" || entry.Type == "" {
json.NewEncoder(w).Encode(map[string]string{
"status": "error",
"message": "名称、URL和类型不能为空",
})
return
}
logger.Info("收到添加域名信息列表的请求", "name", entry.Name, "type", entry.Type)
if err := s.domainInfoManager.AddDomainInfoList(entry); err != nil {
json.NewEncoder(w).Encode(map[string]string{
"status": "error",
"message": fmt.Sprintf("添加列表失败: %v", err),
})
return
}
// 保存配置到文件
if err := saveConfigToFile(s.globalConfig, "config.ini"); err != nil {
logger.Error("保存配置文件失败", "error", err)
json.NewEncoder(w).Encode(map[string]string{
"status": "error",
"message": "添加列表成功,但保存配置失败",
"name": entry.Name,
"type": entry.Type,
})
return
}
json.NewEncoder(w).Encode(map[string]string{
"status": "success",
"message": "域名信息列表添加成功",
"name": entry.Name,
"type": entry.Type,
})
}
// handleDomainInfoRemove 处理删除域名信息列表请求
func (s *Server) handleDomainInfoRemove(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
if r.Method != http.MethodPost {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
var request struct {
Type string `json:"type"`
}
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
json.NewEncoder(w).Encode(map[string]string{
"status": "error",
"message": "无效的请求数据",
})
return
}
if request.Type == "" {
json.NewEncoder(w).Encode(map[string]string{
"status": "error",
"message": "类型参数不能为空",
})
return
}
logger.Info("收到删除域名信息列表的请求", "type", request.Type)
if err := s.domainInfoManager.RemoveDomainInfoList(request.Type); err != nil {
json.NewEncoder(w).Encode(map[string]string{
"status": "error",
"message": fmt.Sprintf("删除列表失败: %v", err),
})
return
}
// 保存配置到文件
if err := saveConfigToFile(s.globalConfig, "config.ini"); err != nil {
logger.Error("保存配置文件失败", "error", err)
json.NewEncoder(w).Encode(map[string]string{
"status": "error",
"message": "删除列表成功,但保存配置失败",
"type": request.Type,
})
return
}
json.NewEncoder(w).Encode(map[string]string{
"status": "success",
"message": "域名信息列表删除成功",
"type": request.Type,
})
}
// saveConfigToFile 保存配置到文件
func saveConfigToFile(config *config.Config, filePath string) error {
// 创建新的INI文件
cfg := ini.Empty()
// DNS配置
dnsSection := cfg.Section("dns")
dnsSection.Key("port").SetValue(fmt.Sprintf("%d", config.DNS.Port))
dnsSection.Key("upstreamDNS").SetValue(strings.Join(config.DNS.UpstreamDNS, ", "))
dnsSection.Key("dnssecUpstreamDNS").SetValue(strings.Join(config.DNS.DNSSECUpstreamDNS, ", "))
dnsSection.Key("saveInterval").SetValue(fmt.Sprintf("%d", config.DNS.SaveInterval))
dnsSection.Key("cacheTTL").SetValue(fmt.Sprintf("%d", config.DNS.CacheTTL))
dnsSection.Key("enableDNSSEC").SetValue(fmt.Sprintf("%t", config.DNS.EnableDNSSEC))
dnsSection.Key("queryMode").SetValue(config.DNS.QueryMode)
dnsSection.Key("queryTimeout").SetValue(fmt.Sprintf("%d", config.DNS.QueryTimeout))
dnsSection.Key("enableFastReturn").SetValue(fmt.Sprintf("%t", config.DNS.EnableFastReturn))
dnsSection.Key("noDNSSECDomains").SetValue(strings.Join(config.DNS.NoDNSSECDomains, ", "))
dnsSection.Key("enableIPv6").SetValue(fmt.Sprintf("%t", config.DNS.EnableIPv6))
dnsSection.Key("cacheMode").SetValue(config.DNS.CacheMode)
dnsSection.Key("cacheSize").SetValue(fmt.Sprintf("%d", config.DNS.CacheSize))
dnsSection.Key("maxCacheTTL").SetValue(fmt.Sprintf("%d", config.DNS.MaxCacheTTL))
dnsSection.Key("minCacheTTL").SetValue(fmt.Sprintf("%d", config.DNS.MinCacheTTL))
// 域名特定DNS服务器配置
for domain, servers := range config.DNS.DomainSpecificDNS {
dnsSection.Key(fmt.Sprintf("domain_%s", domain)).SetValue(strings.Join(servers, ", "))
}
// HTTP配置
httpSection := cfg.Section("http")
httpSection.Key("port").SetValue(fmt.Sprintf("%d", config.HTTP.Port))
httpSection.Key("host").SetValue(config.HTTP.Host)
httpSection.Key("enableAPI").SetValue(fmt.Sprintf("%t", config.HTTP.EnableAPI))
httpSection.Key("username").SetValue(config.HTTP.Username)
httpSection.Key("password").SetValue(config.HTTP.Password)
// Shield配置
shieldSection := cfg.Section("shield")
shieldSection.Key("updateInterval").SetValue(fmt.Sprintf("%d", config.Shield.UpdateInterval))
shieldSection.Key("blockMethod").SetValue(config.Shield.BlockMethod)
shieldSection.Key("customBlockIP").SetValue(config.Shield.CustomBlockIP)
shieldSection.Key("statsSaveInterval").SetValue(fmt.Sprintf("%d", config.Shield.StatsSaveInterval))
// 黑名单配置
for _, bl := range config.Shield.Blacklists {
shieldSection.Key(fmt.Sprintf("blacklist_%s", bl.Name)).SetValue(fmt.Sprintf("%s,%t", bl.URL, bl.Enabled))
}
// GFWList配置
gfwListSection := cfg.Section("gfwList")
gfwListSection.Key("ip").SetValue(config.GFWList.IP)
gfwListSection.Key("content").SetValue(config.GFWList.Content)
gfwListSection.Key("enabled").SetValue(fmt.Sprintf("%t", config.GFWList.Enabled))
// Log配置
logSection := cfg.Section("log")
logSection.Key("level").SetValue(config.Log.Level)
logSection.Key("maxSize").SetValue(fmt.Sprintf("%d", config.Log.MaxSize))
logSection.Key("maxBackups").SetValue(fmt.Sprintf("%d", config.Log.MaxBackups))
logSection.Key("maxAge").SetValue(fmt.Sprintf("%d", config.Log.MaxAge))
// Threat配置
threatSection := cfg.Section("threat")
threatSection.Key("enabled").SetValue(fmt.Sprintf("%t", config.Threat.Enabled))
threatSection.Key("queryRateThreshold").SetValue(fmt.Sprintf("%d", config.Threat.QueryRateThreshold))
threatSection.Key("nxDomainThreshold").SetValue(fmt.Sprintf("%d", config.Threat.NXDomainThreshold))
threatSection.Key("maxDomainLength").SetValue(fmt.Sprintf("%d", config.Threat.MaxDomainLength))
threatSection.Key("suspiciousPatterns").SetValue(strings.Join(config.Threat.SuspiciousPatterns, ", "))
threatSection.Key("unusualQueryTypes").SetValue(strings.Join(config.Threat.UnusualQueryTypes, ", "))
threatSection.Key("alertRetentionDays").SetValue(fmt.Sprintf("%d", config.Threat.AlertRetentionDays))
threatSection.Key("threatDatabasePath").SetValue(config.Threat.ThreatDatabasePath)
// DomainInfo配置
domainInfoSection := cfg.Section("domainInfo")
domainInfoSection.Key("updateInterval").SetValue(fmt.Sprintf("%d", config.DomainInfo.UpdateInterval))
domainInfoSection.Key("enableAutoUpdate").SetValue(fmt.Sprintf("%t", config.DomainInfo.EnableAutoUpdate))
// 域名信息列表配置
for _, entry := range config.DomainInfo.DomainInfoLists {
domainInfoSection.Key(fmt.Sprintf("domainInfo_%s", entry.Name)).SetValue(fmt.Sprintf("%s,%s,%t", entry.URL, entry.Type, entry.Enabled))
}
// 保存到文件
return cfg.SaveTo(filePath)
}
+94 -155
View File
@@ -21,7 +21,6 @@ import (
"dns-server/threat"
"github.com/gorilla/websocket"
"gopkg.in/ini.v1"
)
// CacheEntry 缓存条目
@@ -313,6 +312,7 @@ type Server struct {
dnsServer *dns.Server
shieldManager *shield.ShieldManager
gfwManager *gfw.GFWListManager
domainInfoManager *shield.DomainInfoManager
server *http.Server
// 会话管理相关字段
@@ -336,12 +336,16 @@ type Server struct {
// NewServer 创建 HTTP 服务器实例
func NewServer(globalConfig *config.Config, dnsServer *dns.Server, shieldManager *shield.ShieldManager, gfwManager *gfw.GFWListManager) *Server {
// 创建域名信息管理器
domainInfoManager := shield.NewDomainInfoManager(&globalConfig.DomainInfo)
server := &Server{
globalConfig: globalConfig,
config: &globalConfig.HTTP,
dnsServer: dnsServer,
shieldManager: shieldManager,
gfwManager: gfwManager,
domainInfoManager: domainInfoManager,
upgrader: websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
@@ -363,6 +367,9 @@ func NewServer(globalConfig *config.Config, dnsServer *dns.Server, shieldManager
cacheMaxSize: 100, // 默认最大 100 条
}
// 启动域名信息管理器
domainInfoManager.Start()
// 启动广播协程
go server.startBroadcastLoop()
// 启动会话清理协程
@@ -444,6 +451,17 @@ func (s *Server) Start() error {
mux.HandleFunc("/api/logs/archive-cleanup", s.loginRequired(s.handleArchiveCleanup))
// 域名信息列表接口
mux.HandleFunc("/api/domain-info", s.loginRequired(s.handleDomainInfoList))
// 域名信息更新接口
mux.HandleFunc("/api/domain-info/update", s.loginRequired(s.handleDomainInfoUpdate))
mux.HandleFunc("/api/domain-info/update/{type}", s.loginRequired(s.handleDomainInfoUpdateByType))
// 域名信息状态接口
mux.HandleFunc("/api/domain-info/status", s.loginRequired(s.handleDomainInfoStatus))
// 域名信息缓存刷新接口
mux.HandleFunc("/api/domain-info/refresh", s.loginRequired(s.handleDomainInfoRefresh))
// 域名信息列表添加接口
mux.HandleFunc("/api/domain-info/add", s.loginRequired(s.handleDomainInfoAdd))
// 域名信息列表删除接口
mux.HandleFunc("/api/domain-info/remove", s.loginRequired(s.handleDomainInfoRemove))
// 威胁查询接口
mux.HandleFunc("/api/threat", s.loginRequired(s.handleThreatQuery))
// 威胁批量查询接口
@@ -1583,81 +1601,7 @@ func (s *Server) handleStatus(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(status)
}
// saveConfigToFile 保存配置到文件
func saveConfigToFile(config *config.Config, filePath string) error {
// 创建新的INI文件
cfg := ini.Empty()
// DNS配置
dnsSection := cfg.Section("dns")
dnsSection.Key("port").SetValue(fmt.Sprintf("%d", config.DNS.Port))
dnsSection.Key("upstreamDNS").SetValue(strings.Join(config.DNS.UpstreamDNS, ", "))
dnsSection.Key("dnssecUpstreamDNS").SetValue(strings.Join(config.DNS.DNSSECUpstreamDNS, ", "))
dnsSection.Key("saveInterval").SetValue(fmt.Sprintf("%d", config.DNS.SaveInterval))
dnsSection.Key("cacheTTL").SetValue(fmt.Sprintf("%d", config.DNS.CacheTTL))
dnsSection.Key("enableDNSSEC").SetValue(fmt.Sprintf("%t", config.DNS.EnableDNSSEC))
dnsSection.Key("queryMode").SetValue(config.DNS.QueryMode)
dnsSection.Key("queryTimeout").SetValue(fmt.Sprintf("%d", config.DNS.QueryTimeout))
dnsSection.Key("enableFastReturn").SetValue(fmt.Sprintf("%t", config.DNS.EnableFastReturn))
dnsSection.Key("noDNSSECDomains").SetValue(strings.Join(config.DNS.NoDNSSECDomains, ", "))
dnsSection.Key("enableIPv6").SetValue(fmt.Sprintf("%t", config.DNS.EnableIPv6))
dnsSection.Key("cacheMode").SetValue(config.DNS.CacheMode)
dnsSection.Key("cacheSize").SetValue(fmt.Sprintf("%d", config.DNS.CacheSize))
dnsSection.Key("maxCacheTTL").SetValue(fmt.Sprintf("%d", config.DNS.MaxCacheTTL))
dnsSection.Key("minCacheTTL").SetValue(fmt.Sprintf("%d", config.DNS.MinCacheTTL))
// 域名特定DNS服务器配置
for domain, servers := range config.DNS.DomainSpecificDNS {
dnsSection.Key(fmt.Sprintf("domain_%s", domain)).SetValue(strings.Join(servers, ", "))
}
// HTTP配置
httpSection := cfg.Section("http")
httpSection.Key("port").SetValue(fmt.Sprintf("%d", config.HTTP.Port))
httpSection.Key("host").SetValue(config.HTTP.Host)
httpSection.Key("enableAPI").SetValue(fmt.Sprintf("%t", config.HTTP.EnableAPI))
httpSection.Key("username").SetValue(config.HTTP.Username)
httpSection.Key("password").SetValue(config.HTTP.Password)
// Shield配置
shieldSection := cfg.Section("shield")
shieldSection.Key("updateInterval").SetValue(fmt.Sprintf("%d", config.Shield.UpdateInterval))
shieldSection.Key("blockMethod").SetValue(config.Shield.BlockMethod)
shieldSection.Key("customBlockIP").SetValue(config.Shield.CustomBlockIP)
shieldSection.Key("statsSaveInterval").SetValue(fmt.Sprintf("%d", config.Shield.StatsSaveInterval))
// 黑名单配置
for _, bl := range config.Shield.Blacklists {
shieldSection.Key(fmt.Sprintf("blacklist_%s", bl.Name)).SetValue(fmt.Sprintf("%s,%t", bl.URL, bl.Enabled))
}
// GFWList配置
gfwListSection := cfg.Section("gfwList")
gfwListSection.Key("ip").SetValue(config.GFWList.IP)
gfwListSection.Key("content").SetValue(config.GFWList.Content)
gfwListSection.Key("enabled").SetValue(fmt.Sprintf("%t", config.GFWList.Enabled))
// Log配置
logSection := cfg.Section("log")
logSection.Key("level").SetValue(config.Log.Level)
logSection.Key("maxSize").SetValue(fmt.Sprintf("%d", config.Log.MaxSize))
logSection.Key("maxBackups").SetValue(fmt.Sprintf("%d", config.Log.MaxBackups))
logSection.Key("maxAge").SetValue(fmt.Sprintf("%d", config.Log.MaxAge))
// Threat配置
threatSection := cfg.Section("threat")
threatSection.Key("enabled").SetValue(fmt.Sprintf("%t", config.Threat.Enabled))
threatSection.Key("queryRateThreshold").SetValue(fmt.Sprintf("%d", config.Threat.QueryRateThreshold))
threatSection.Key("nxDomainThreshold").SetValue(fmt.Sprintf("%d", config.Threat.NXDomainThreshold))
threatSection.Key("maxDomainLength").SetValue(fmt.Sprintf("%d", config.Threat.MaxDomainLength))
threatSection.Key("suspiciousPatterns").SetValue(strings.Join(config.Threat.SuspiciousPatterns, ","))
threatSection.Key("unusualQueryTypes").SetValue(strings.Join(config.Threat.UnusualQueryTypes, ","))
threatSection.Key("alertRetentionDays").SetValue(fmt.Sprintf("%d", config.Threat.AlertRetentionDays))
threatSection.Key("threatDatabasePath").SetValue(config.Threat.ThreatDatabasePath)
// 保存到文件
return cfg.SaveTo(filePath)
}
// handleConfig 处理配置请求
func (s *Server) handleConfig(w http.ResponseWriter, r *http.Request) {
@@ -2168,6 +2112,12 @@ func (s *Server) handleLogsQuery(w http.ResponseWriter, r *http.Request) {
"totalPages": totalPages,
}
// 为日志添加域名信息(只在第一页添加,减少开销)
if pageNum == 1 && len(logs) > 0 {
enrichedLogs := s.enrichLogsWithDomainInfo(logs)
response["logs"] = enrichedLogs
}
// 存入缓存(只缓存第一页,因为用户最常查看第一页)
if s.cacheEnabled && pageNum == 1 {
s.queryCache.Set(cacheKey, response)
@@ -2416,10 +2366,41 @@ func (s *Server) handleDomainInfoList(w http.ResponseWriter, r *http.Request) {
threatFilter := query.Get("threats")
handleThreatsInfo(w, threatFilter)
} else {
// 直接访问 /domain-info 不提供任何内容
http.Error(w, "No content provided", http.StatusNoContent)
// 获取所有域名信息列表
w.Header().Set("Content-Type", "application/json")
if s.domainInfoManager == nil {
json.NewEncoder(w).Encode(map[string]interface{}{
"lists": []interface{}{},
"domainInfoCount": 0,
"threatCount": 0,
"trackerCount": 0,
"lastUpdateTime": "从未更新",
})
return
}
// 使用 goroutine 和 channel 避免死锁
done := make(chan map[string]interface{}, 1)
go func() {
domainInfo := s.domainInfoManager.GetAllDomainInfo()
done <- domainInfo
}()
select {
case domainInfo := <-done:
json.NewEncoder(w).Encode(domainInfo)
case <-time.After(10 * time.Second):
// 超时,返回空响应
json.NewEncoder(w).Encode(map[string]interface{}{
"lists": []interface{}{},
"domainInfoCount": 0,
"threatCount": 0,
"trackerCount": 0,
"lastUpdateTime": "加载中...",
})
}
}
}
// isService 判断一个对象是否是服务(而不是分组)
@@ -2930,95 +2911,53 @@ func (s *Server) handleThreatQuery(w http.ResponseWriter, r *http.Request) {
return
}
// 读取威胁数据库 CSV 文件
filePath := "./static/domain-info/threats/threats-database.csv"
data, err := os.ReadFile(filePath)
if err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(map[string]string{"error": "读取威胁数据库失败"})
logger.Error(fmt.Sprintf("读取威胁数据库文件失败:%v", err))
return
// 使用域名信息管理器查询威胁信息
threatInfo := s.domainInfoManager.GetThreatInfo(domain)
result := map[string]interface{}{
"domain": domain,
}
// 解析 CSV
reader := csv.NewReader(bytes.NewReader(data))
reader.FieldsPerRecord = -1 // 允许不同长度的记录
// 读取所有记录
records, err := reader.ReadAll()
if err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(map[string]string{"error": "解析威胁数据库失败"})
logger.Error(fmt.Sprintf("解析威胁数据库文件失败:%v", err))
return
}
// 构建威胁域名映射(支持顶级域名匹配)
threatMap := make(map[string][]string)
for i, record := range records {
if i == 0 {
continue // 跳过标题行
}
if len(record) >= 4 {
threatType := record[0] // 第一列:类型
threatName := record[1] // 第二列:名称
riskLevel := record[2] // 第三列:风险等级
domain := record[3] // 第四列:域名
threatInfo := []string{threatType, threatName, riskLevel}
// 1. 完整域名匹配(所有类型都添加)
threatMap[domain] = threatInfo
// 2. 只有恶意网站类型才添加子域名匹配规则
// 类型判断:钓鱼网站、仿冒网站
// 逻辑:如果威胁数据库中有 sub.example.com,则所有子域名(a.sub.example.com)都应匹配
if threatType == "钓鱼网站" || threatType == "仿冒网站" {
// 对于恶意网站,添加子域名匹配规则
// 例如:sub.example.com -> 添加 .sub.example.com 规则
// 这样 a.sub.example.com 就会匹配
topLevelDomain := "." + domain
// 只有当该顶级域名规则不存在时才添加
if _, exists := threatMap[topLevelDomain]; !exists {
threatMap[topLevelDomain] = threatInfo
}
}
}
}
// 查询单个域名
var result string
// 1. 先检查完整匹配
if threat, exists := threatMap[domain]; exists {
result = fmt.Sprintf("%s,%s,%s,%s", threat[0], threat[1], threat[2], domain)
if threatInfo != nil {
// 从内存中的威胁数据库获取信息
result["isThreat"] = true
result["data"] = threatInfo
result["threatType"] = threatInfo["type"]
result["threatName"] = threatInfo["name"]
result["riskLevel"] = threatInfo["riskLevel"]
} else {
// 2. 检查子域名匹配(遍历顶级域名规则)
for threatDomain, threatInfo := range threatMap {
// 只检查以点开头的顶级域名规则
if strings.HasPrefix(threatDomain, ".") && strings.HasSuffix(domain, threatDomain) {
// 额外验证:确保是完整的域名部分匹配
prefix := strings.TrimSuffix(domain, threatDomain)
if len(prefix) > 0 && !strings.HasSuffix(prefix, ".") {
// 不是完整的子域名部分,跳过
// 检查子域名匹配
matched := false
// 遍历威胁数据库查找匹配的顶级域名规则
s.domainInfoManager.GetThreatInfo("") // 这个调用会触发遍历,需要重新实现
// 简单的子域名匹配逻辑
parts := strings.Split(domain, ".")
for i := range parts {
if i == 0 {
continue
}
result = fmt.Sprintf("%s,%s,%s,%s", threatInfo[0], threatInfo[1], threatInfo[2], domain)
subDomain := strings.Join(parts[i:], ".")
threatInfo = s.domainInfoManager.GetThreatInfo(subDomain)
if threatInfo != nil {
result["isThreat"] = true
result["data"] = threatInfo
result["threatType"] = threatInfo["type"]
result["threatName"] = threatInfo["name"]
result["riskLevel"] = threatInfo["riskLevel"]
result["matchedDomain"] = subDomain
matched = true
break
}
}
if !matched {
result["isThreat"] = false
}
}
w.Header().Set("Content-Type", "application/json")
if result == "" {
// 未找到匹配的威胁信息
json.NewEncoder(w).Encode(map[string]string{"message": "无"})
} else {
// 返回威胁信息
json.NewEncoder(w).Encode(map[string]string{"data": result})
}
json.NewEncoder(w).Encode(result)
}
// handleThreatBatch 批量查询威胁域名
+50 -17
View File
@@ -12,6 +12,7 @@ import (
"time"
"dns-server/logger"
_ "github.com/mattn/go-sqlite3"
)
@@ -51,24 +52,43 @@ func (aqe *ArchiveQueryEngine) QueryLogs(filter LogFilter, page PageParams) ([]Q
mainTotal = 0
}
// 2. 智能优化:如果主库数据足够且是第一页,直接返回
if page.Offset == 0 && len(mainLogs) >= page.Limit {
return mainLogs, mainTotal, nil
// 2. 智能优化:如果主库数据足够,直接返回
if len(mainLogs) > page.Offset {
// 计算主库中需要返回的数据范围
start := page.Offset
end := start + page.Limit
if end > len(mainLogs) {
end = len(mainLogs)
}
return mainLogs[start:end], mainTotal, nil
}
// 3. 查询所有归档库
archiveLogs, archiveTotal, err := aqe.queryArchives(filter, page)
// 3. 计算需要从归档中获取的数据量
// 注意:归档库查询时,offset 应该始终为 0,因为我们需要从归档的开头开始查询,然后与主库数据合并后再进行分页
remainingLimit := page.Offset + page.Limit - len(mainLogs)
if remainingLimit < 0 {
remainingLimit = 0
}
archivePage := PageParams{
Limit: remainingLimit,
Offset: 0,
SortField: page.SortField,
SortDirection: page.SortDirection,
}
// 4. 查询归档库
archiveLogs, archiveTotal, err := aqe.queryArchives(filter, archivePage)
if err != nil {
logger.Error("查询归档失败", "error", err)
archiveLogs = []QueryLog{}
archiveTotal = 0
}
// 4. 合并结果
// 5. 合并结果
allLogs := append(mainLogs, archiveLogs...)
total := mainTotal + archiveTotal
// 5. 排序(默认按时间倒序)
// 6. 排序(默认按时间倒序)
if page.SortField == "" || page.SortField == "timestamp" {
if page.SortDirection == "" || page.SortDirection == "desc" {
sort.Slice(allLogs, func(i, j int) bool {
@@ -81,13 +101,9 @@ func (aqe *ArchiveQueryEngine) QueryLogs(filter LogFilter, page PageParams) ([]Q
}
}
// 6. 分页
start := page.Offset
if start >= len(allLogs) {
return []QueryLog{}, total, nil
}
end := start + page.Limit
// 7. 分页
start := 0
end := page.Limit
if end > len(allLogs) {
end = len(allLogs)
}
@@ -101,8 +117,16 @@ func (aqe *ArchiveQueryEngine) queryMainStore(filter LogFilter, page PageParams)
return []QueryLog{}, 0, nil
}
// 注意:查询主库时,不使用 offset,只使用 limit + offset,这样可以获取足够的数据与归档库数据合并后再进行分页
mainPage := PageParams{
Limit: page.Offset + page.Limit,
Offset: 0,
SortField: page.SortField,
SortDirection: page.SortDirection,
}
// 使用 SQLiteStore 的查询方法
return aqe.mainStore.QueryLogs(filter, page)
return aqe.mainStore.QueryLogs(filter, mainPage)
}
// queryArchives 查询所有归档库
@@ -121,15 +145,24 @@ func (aqe *ArchiveQueryEngine) queryArchives(filter LogFilter, page PageParams)
var allLogs []QueryLog
var totalCount int64 = 0
// 计算需要从归档中获取的总数据量
requiredTotal := int64(page.Offset + page.Limit)
// 从新到旧遍历归档
for _, archive := range archives {
// 如果已经有足够的数据,提前退出
if int64(len(allLogs)) >= int64(page.Limit) && page.Offset == 0 {
if int64(len(allLogs)) >= requiredTotal {
break
}
// 计算当前归档需要查询的数据量
remaining := requiredTotal - int64(len(allLogs))
archivePage := page
archivePage.Limit = int(remaining)
archivePage.Offset = 0
// 查询单个归档
logs, count, err := aqe.querySingleArchive(&archive, filter, page)
logs, count, err := aqe.querySingleArchive(&archive, filter, archivePage)
if err != nil {
logger.Warn("查询归档失败", "file", archive.FilePath, "error", err)
continue
-662
View File
@@ -1,662 +0,0 @@
time="2026-04-05T02:11:56+08:00" level=debug msg="尝试加载Shield统计数据" file=/root/dnsbeta2/data/shield_stats.json
time="2026-04-05T02:11:56+08:00" level=info msg="Shield计数数据加载成功" blocked_entries=0 resolved_entries=0
time="2026-04-05T02:11:56+08:00" level=info msg="本地规则加载完成,域名规则: 0, 排除规则: 0, 正则规则: 0, hosts规则: 0"
time="2026-04-05T02:11:56+08:00" level=info msg="新日志系统初始化成功" databasePath=data/query_logs.db ringBufferSize=10000
time="2026-04-05T02:11:56+08:00" level=info msg="元数据加载完成" count=0
time="2026-04-05T02:11:56+08:00" level=info msg="归档管理器初始化成功" archiveDir=data/archive
time="2026-04-05T02:11:56+08:00" level=info msg="归档查询引擎初始化成功"
time="2026-04-05T02:11:56+08:00" level=info msg="统计数据加载成功"
time="2026-04-05T02:11:56+08:00" level=info msg="DNS服务器已启动,监听端口: 53"
time="2026-04-05T02:11:56+08:00" level=info msg="HTTP控制台已启动,监听端口: 8081"
time="2026-04-05T02:11:56+08:00" level=info msg="规则自动更新已启动" interval=3600
time="2026-04-05T02:11:56+08:00" level=info msg="开始加载威胁域名数据库" path=./static/domain-info/threats/threats-database.csv
time="2026-04-05T02:11:56+08:00" level=info msg="启动Shield计数数据自动保存功能" file=data/shield_stats.json interval=60
time="2026-04-05T02:11:56+08:00" level=info msg="Shield计数数据保存成功" blocked_entries=0 file=/root/dnsbeta2/data/shield_stats.json resolved_entries=0
time="2026-04-05T02:11:56+08:00" level=info msg="开始异步加载远程屏蔽规则"
time="2026-04-05T02:11:56+08:00" level=info msg="HTTP控制台服务器启动,监听地址: 0.0.0.0:8081"
time="2026-04-05T02:11:56+08:00" level=info msg="威胁域名数据库加载完成" count=72976
time="2026-04-05T02:11:56+08:00" level=info msg="开始监听威胁域名数据库文件" path=./static/domain-info/threats/threats-database.csv
time="2026-04-05T02:11:56+08:00" level=info msg="归档管理器监控启动"
time="2026-04-05T02:11:56+08:00" level=info msg="归档监控和清理任务已启动"
time="2026-04-05T02:11:56+08:00" level=info msg="DNS TCP服务器启动,监听端口: 53"
time="2026-04-05T02:11:56+08:00" level=info msg="DNS UDP服务器启动,监听端口: 53"
time="2026-04-05T02:11:56+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:49312" domain=www.baidu.com type=AAAA
time="2026-04-05T02:11:56+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:49312" domain=www.baidu.com type=A
time="2026-04-05T02:11:56+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=www.baidu.com
time="2026-04-05T02:11:56+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:57960" domain=edge.microsoft.com type=A
time="2026-04-05T02:11:56+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:58734" domain=wpad.amazehome.xyz type=A
time="2026-04-05T02:11:56+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:58572" domain=topdesk.com type=AAAA
time="2026-04-05T02:11:56+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=topdesk.com
time="2026-04-05T02:11:56+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:60997" domain=topdesk.com type=A
time="2026-04-05T02:11:57+08:00" level=debug msg="接收到DNS查询" client="10.35.10.29:44335" domain=time.apple.com type=AAAA
time="2026-04-05T02:11:57+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=time.apple.com
time="2026-04-05T02:11:57+08:00" level=debug msg="接收到DNS查询" client="10.35.10.29:44335" domain=time.apple.com type=A
time="2026-04-05T02:11:57+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:58126" domain=puds.ucweb.com type=A
time="2026-04-05T02:11:57+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:58555" domain=pcapp-data-collect.youku.com type=A
time="2026-04-05T02:11:57+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:50418" domain=h-adashx.ut.taobao.com type=A
time="2026-04-05T02:11:57+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:62594" domain=tpstelemetry.tencent.com type=A
time="2026-04-05T02:11:57+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:48563" domain=sonymusic.com type=A
time="2026-04-05T02:11:57+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:38934" domain=sonymusic.com type=AAAA
time="2026-04-05T02:11:57+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=sonymusic.com
time="2026-04-05T02:11:58+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:45438" domain=vsco.co type=AAAA
time="2026-04-05T02:11:58+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:47681" domain=vsco.co type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=vsco.co
time="2026-04-05T02:11:58+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:50648" domain=fossilgroup.com type=AAAA
time="2026-04-05T02:11:58+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=fossilgroup.com
time="2026-04-05T02:11:58+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:54604" domain=fossilgroup.com type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:55011" domain=time.apple.com.amazehome.xyz type=AAAA
time="2026-04-05T02:11:58+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:55011" domain=time.apple.com.amazehome.xyz type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=time.apple.com.amazehome.xyz
time="2026-04-05T02:11:58+08:00" level=info msg="规则加载完成,域名规则: 189912, 排除规则: 654, 正则规则: 12057, hosts规则: 0"
time="2026-04-05T02:11:58+08:00" level=info msg="远程屏蔽规则异步加载完成"
time="2026-04-05T02:11:58+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:58126" domain=puds.ucweb.com
time="2026-04-05T02:11:58+08:00" level=debug msg="威胁检测引擎检查域名" domain=www.baidu.com sourceIP=10.35.10.70
time="2026-04-05T02:11:58+08:00" level=debug msg="开始处理上游请求" domain=www.baidu.com type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:11:58+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=www.baidu.com. queryTimeout 配置=5
time="2026-04-05T02:11:58+08:00" level=debug msg="威胁检测引擎检查域名" domain=vsco.co sourceIP=10.35.10.70
time="2026-04-05T02:11:58+08:00" level=debug msg="开始处理上游请求" domain=vsco.co type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:11:58+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=vsco.co. queryTimeout 配置=5
time="2026-04-05T02:11:58+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:62594" domain=tpstelemetry.tencent.com
time="2026-04-05T02:11:58+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:58555" domain=pcapp-data-collect.youku.com
time="2026-04-05T02:11:58+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:50418" domain=h-adashx.ut.taobao.com
time="2026-04-05T02:11:58+08:00" level=debug msg="返回第一个成功响应" domain=www.baidu.com rtt=1.743041ms server=10.35.10.200
time="2026-04-05T02:11:58+08:00" level=debug msg="上游请求返回" domain=www.baidu.com response=true rtt=1.743041ms
time="2026-04-05T02:11:58+08:00" level=debug msg="DNS响应已缓存" dnssec=false domain=www.baidu.com ttl=30m0s type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="CNAME响应已缓存" dnssec=false domain=www.a.shifen.com. ttl=30m0s type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="准备添加查询日志" domain=www.baidu.com responseCode=0 result=allowed
time="2026-04-05T02:11:58+08:00" level=debug msg="查询日志已添加" domain=www.baidu.com
time="2026-04-05T02:11:58+08:00" level=debug msg="上游请求返回" domain=vsco.co response=false rtt=0s
time="2026-04-05T02:11:58+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=vsco.co
time="2026-04-05T02:11:58+08:00" level=debug msg="准备添加查询日志" domain=vsco.co responseCode=0 result=error
time="2026-04-05T02:11:58+08:00" level=debug msg="查询日志已添加" domain=vsco.co
time="2026-04-05T02:11:58+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:58799" domain=vsco.co type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="威胁检测引擎检查域名" domain=topdesk.com sourceIP=10.35.10.70
time="2026-04-05T02:11:58+08:00" level=debug msg="开始处理上游请求" domain=topdesk.com type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:11:58+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=topdesk.com. queryTimeout 配置=5
time="2026-04-05T02:11:58+08:00" level=debug msg="威胁检测引擎检查域名" domain=vsco.co sourceIP=10.35.10.70
time="2026-04-05T02:11:58+08:00" level=debug msg="开始处理上游请求" domain=vsco.co type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:11:58+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=vsco.co. queryTimeout 配置=5
time="2026-04-05T02:11:58+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:55673" domain=px.effirst.com type=A
time="2026-04-05T02:11:58+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:55673" domain=px.effirst.com
time="2026-04-05T02:11:58+08:00" level=debug msg="威胁检测引擎检查域名" domain=fossilgroup.com sourceIP=10.35.10.70
time="2026-04-05T02:11:58+08:00" level=debug msg="开始处理上游请求" domain=fossilgroup.com type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:11:58+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=fossilgroup.com. queryTimeout 配置=5
time="2026-04-05T02:11:58+08:00" level=debug msg="威胁检测引擎检查域名" domain=time.apple.com sourceIP=10.35.10.29
time="2026-04-05T02:11:58+08:00" level=debug msg="开始处理上游请求" domain=time.apple.com type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:11:58+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=time.apple.com. queryTimeout 配置=5
time="2026-04-05T02:11:58+08:00" level=debug msg="上游请求返回" domain=topdesk.com response=false rtt=0s
time="2026-04-05T02:11:58+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=topdesk.com
time="2026-04-05T02:11:58+08:00" level=debug msg="准备添加查询日志" domain=topdesk.com responseCode=0 result=error
time="2026-04-05T02:11:58+08:00" level=debug msg="查询日志已添加" domain=topdesk.com
time="2026-04-05T02:11:58+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:40275" domain=topdesk.com type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="上游请求返回" domain=vsco.co response=false rtt=0s
time="2026-04-05T02:11:58+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=vsco.co
time="2026-04-05T02:11:58+08:00" level=debug msg="准备添加查询日志" domain=vsco.co responseCode=0 result=error
time="2026-04-05T02:11:58+08:00" level=debug msg="查询日志已添加" domain=vsco.co
time="2026-04-05T02:11:58+08:00" level=debug msg="威胁检测引擎检查域名" domain=edge.microsoft.com sourceIP=10.35.10.78
time="2026-04-05T02:11:58+08:00" level=debug msg="开始处理上游请求" domain=edge.microsoft.com type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="域名匹配到特定DNS服务器配置" dnsServers="[10.35.10.200:53]" domain=edge.microsoft.com matchStr=microsoft.com
time="2026-04-05T02:11:58+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=edge.microsoft.com. queryTimeout 配置=5
time="2026-04-05T02:11:58+08:00" level=debug msg="威胁检测引擎检查域名" domain=wpad.amazehome.xyz sourceIP=10.35.10.78
time="2026-04-05T02:11:58+08:00" level=debug msg="开始处理上游请求" domain=wpad.amazehome.xyz type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="域名匹配到不验证DNSSEC的模式" domain=wpad.amazehome.xyz pattern=amazehome.xyz
time="2026-04-05T02:11:58+08:00" level=debug msg="域名匹配到特定DNS服务器配置" dnsServers="[10.35.10.200:53]" domain=wpad.amazehome.xyz matchStr=amazehome.xyz
time="2026-04-05T02:11:58+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=wpad.amazehome.xyz. queryTimeout 配置=5
time="2026-04-05T02:11:58+08:00" level=debug msg="所有服务器都失败,返回最后一个错误响应" domain=wpad.amazehome.xyz server="10.35.10.200:53"
time="2026-04-05T02:11:58+08:00" level=debug msg="上游请求返回" domain=wpad.amazehome.xyz response=true rtt="546.09µs"
time="2026-04-05T02:11:58+08:00" level=debug msg="上游请求返回" domain=fossilgroup.com response=false rtt=0s
time="2026-04-05T02:11:58+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=fossilgroup.com
time="2026-04-05T02:11:58+08:00" level=debug msg="上游请求返回" domain=time.apple.com response=false rtt=0s
time="2026-04-05T02:11:58+08:00" level=debug msg="准备添加查询日志" domain=fossilgroup.com responseCode=0 result=error
time="2026-04-05T02:11:58+08:00" level=debug msg="查询日志已添加" domain=fossilgroup.com
time="2026-04-05T02:11:58+08:00" level=debug msg="DNS响应已缓存" dnssec=false domain=wpad.amazehome.xyz ttl=30m0s type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="准备添加查询日志" domain=wpad.amazehome.xyz responseCode=0 result=allowed
time="2026-04-05T02:11:58+08:00" level=debug msg="查询日志已添加" domain=wpad.amazehome.xyz
time="2026-04-05T02:11:58+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=time.apple.com
time="2026-04-05T02:11:58+08:00" level=debug msg="准备添加查询日志" domain=time.apple.com responseCode=0 result=error
time="2026-04-05T02:11:58+08:00" level=debug msg="查询日志已添加" domain=time.apple.com
time="2026-04-05T02:11:58+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:59390" domain=fossilgroup.com type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="接收到DNS查询" client="10.35.10.29:50073" domain=pool.ntp.org type=AAAA
time="2026-04-05T02:11:58+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=pool.ntp.org
time="2026-04-05T02:11:58+08:00" level=debug msg="接收到DNS查询" client="10.35.10.29:50073" domain=pool.ntp.org type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="威胁检测引擎检查域名" domain=sonymusic.com sourceIP=10.35.10.70
time="2026-04-05T02:11:58+08:00" level=debug msg="开始处理上游请求" domain=sonymusic.com type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:11:58+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=sonymusic.com. queryTimeout 配置=5
time="2026-04-05T02:11:58+08:00" level=debug msg="上游请求返回" domain=edge.microsoft.com response=false rtt=0s
time="2026-04-05T02:11:58+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=edge.microsoft.com
time="2026-04-05T02:11:58+08:00" level=debug msg="准备添加查询日志" domain=edge.microsoft.com responseCode=0 result=error
time="2026-04-05T02:11:58+08:00" level=debug msg="查询日志已添加" domain=edge.microsoft.com
time="2026-04-05T02:11:58+08:00" level=debug msg="威胁检测引擎检查域名" domain=topdesk.com sourceIP=10.35.10.70
time="2026-04-05T02:11:58+08:00" level=debug msg="开始处理上游请求" domain=topdesk.com type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:11:58+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=topdesk.com. queryTimeout 配置=5
time="2026-04-05T02:11:58+08:00" level=debug msg="上游请求返回" domain=sonymusic.com response=false rtt=0s
time="2026-04-05T02:11:58+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=sonymusic.com
time="2026-04-05T02:11:58+08:00" level=debug msg="准备添加查询日志" domain=sonymusic.com responseCode=0 result=error
time="2026-04-05T02:11:58+08:00" level=debug msg="查询日志已添加" domain=sonymusic.com
time="2026-04-05T02:11:58+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:43196" domain=sonymusic.com type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="威胁检测引擎检查域名" domain=pool.ntp.org sourceIP=10.35.10.29
time="2026-04-05T02:11:58+08:00" level=debug msg="开始处理上游请求" domain=pool.ntp.org type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:11:58+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=pool.ntp.org. queryTimeout 配置=5
time="2026-04-05T02:11:58+08:00" level=debug msg="上游请求返回" domain=topdesk.com response=false rtt=0s
time="2026-04-05T02:11:58+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=topdesk.com
time="2026-04-05T02:11:58+08:00" level=debug msg="准备添加查询日志" domain=topdesk.com responseCode=0 result=error
time="2026-04-05T02:11:58+08:00" level=debug msg="查询日志已添加" domain=topdesk.com
time="2026-04-05T02:11:58+08:00" level=debug msg="威胁检测引擎检查域名" domain=time.apple.com.amazehome.xyz sourceIP=10.35.10.70
time="2026-04-05T02:11:58+08:00" level=debug msg="开始处理上游请求" domain=time.apple.com.amazehome.xyz type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="域名匹配到不验证DNSSEC的模式" domain=time.apple.com.amazehome.xyz pattern=amazehome.xyz
time="2026-04-05T02:11:58+08:00" level=debug msg="域名匹配到特定DNS服务器配置" dnsServers="[10.35.10.200:53]" domain=time.apple.com.amazehome.xyz matchStr=amazehome.xyz
time="2026-04-05T02:11:58+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=time.apple.com.amazehome.xyz. queryTimeout 配置=5
time="2026-04-05T02:11:58+08:00" level=debug msg="所有服务器都失败,返回最后一个错误响应" domain=time.apple.com.amazehome.xyz server="10.35.10.200:53"
time="2026-04-05T02:11:58+08:00" level=debug msg="上游请求返回" domain=time.apple.com.amazehome.xyz response=true rtt="664.963µs"
time="2026-04-05T02:11:58+08:00" level=debug msg="DNS响应已缓存" dnssec=false domain=time.apple.com.amazehome.xyz ttl=30m0s type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="准备添加查询日志" domain=time.apple.com.amazehome.xyz responseCode=0 result=allowed
time="2026-04-05T02:11:58+08:00" level=debug msg="查询日志已添加" domain=time.apple.com.amazehome.xyz
time="2026-04-05T02:11:58+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:55768" domain=pool.ntp.org type=AAAA
time="2026-04-05T02:11:58+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:55768" domain=pool.ntp.org type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=pool.ntp.org
time="2026-04-05T02:11:58+08:00" level=debug msg="威胁检测引擎检查域名" domain=fossilgroup.com sourceIP=10.35.10.70
time="2026-04-05T02:11:58+08:00" level=debug msg="开始处理上游请求" domain=fossilgroup.com type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:11:58+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=fossilgroup.com. queryTimeout 配置=5
time="2026-04-05T02:11:58+08:00" level=debug msg="返回第一个成功响应" domain=fossilgroup.com rtt="456.346µs" server=10.35.10.200
time="2026-04-05T02:11:58+08:00" level=debug msg="上游请求返回" domain=fossilgroup.com response=true rtt="456.346µs"
time="2026-04-05T02:11:58+08:00" level=debug msg="上游请求返回" domain=pool.ntp.org response=false rtt=0s
time="2026-04-05T02:11:58+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=pool.ntp.org
time="2026-04-05T02:11:58+08:00" level=debug msg="准备添加查询日志" domain=pool.ntp.org responseCode=0 result=error
time="2026-04-05T02:11:58+08:00" level=debug msg="查询日志已添加" domain=pool.ntp.org
time="2026-04-05T02:11:58+08:00" level=debug msg="DNS响应已缓存" dnssec=false domain=fossilgroup.com ttl=30m0s type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="准备添加查询日志" domain=fossilgroup.com responseCode=0 result=allowed
time="2026-04-05T02:11:58+08:00" level=debug msg="查询日志已添加" domain=fossilgroup.com
time="2026-04-05T02:11:58+08:00" level=debug msg="威胁检测引擎检查域名" domain=sonymusic.com sourceIP=10.35.10.70
time="2026-04-05T02:11:58+08:00" level=debug msg="开始处理上游请求" domain=sonymusic.com type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:11:58+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=sonymusic.com. queryTimeout 配置=5
time="2026-04-05T02:11:58+08:00" level=debug msg="威胁检测引擎检查域名" domain=pool.ntp.org sourceIP=10.35.10.70
time="2026-04-05T02:11:58+08:00" level=debug msg="开始处理上游请求" domain=pool.ntp.org type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:11:58+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=pool.ntp.org. queryTimeout 配置=5
time="2026-04-05T02:11:58+08:00" level=debug msg="返回第一个成功响应" domain=sonymusic.com rtt=4.027306ms server=10.35.10.200
time="2026-04-05T02:11:58+08:00" level=debug msg="上游请求返回" domain=sonymusic.com response=true rtt=4.027306ms
time="2026-04-05T02:11:58+08:00" level=debug msg="DNS响应已缓存" dnssec=false domain=sonymusic.com ttl=30m0s type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="准备添加查询日志" domain=sonymusic.com responseCode=0 result=allowed
time="2026-04-05T02:11:58+08:00" level=debug msg="查询日志已添加" domain=sonymusic.com
time="2026-04-05T02:11:58+08:00" level=debug msg="上游请求返回" domain=pool.ntp.org response=false rtt=0s
time="2026-04-05T02:11:58+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=pool.ntp.org
time="2026-04-05T02:11:58+08:00" level=debug msg="准备添加查询日志" domain=pool.ntp.org responseCode=0 result=error
time="2026-04-05T02:11:58+08:00" level=debug msg="查询日志已添加" domain=pool.ntp.org
time="2026-04-05T02:11:58+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:56074" domain=pool.ntp.org.amazehome.xyz type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:56074" domain=pool.ntp.org.amazehome.xyz type=AAAA
time="2026-04-05T02:11:58+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=pool.ntp.org.amazehome.xyz
time="2026-04-05T02:11:58+08:00" level=debug msg="威胁检测引擎检查域名" domain=pool.ntp.org.amazehome.xyz sourceIP=10.35.10.70
time="2026-04-05T02:11:58+08:00" level=debug msg="开始处理上游请求" domain=pool.ntp.org.amazehome.xyz type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="域名匹配到不验证DNSSEC的模式" domain=pool.ntp.org.amazehome.xyz pattern=amazehome.xyz
time="2026-04-05T02:11:58+08:00" level=debug msg="域名匹配到特定DNS服务器配置" dnsServers="[10.35.10.200:53]" domain=pool.ntp.org.amazehome.xyz matchStr=amazehome.xyz
time="2026-04-05T02:11:58+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=pool.ntp.org.amazehome.xyz. queryTimeout 配置=5
time="2026-04-05T02:11:58+08:00" level=debug msg="所有服务器都失败,返回最后一个错误响应" domain=pool.ntp.org.amazehome.xyz server="10.35.10.200:53"
time="2026-04-05T02:11:58+08:00" level=debug msg="上游请求返回" domain=pool.ntp.org.amazehome.xyz response=true rtt="909.456µs"
time="2026-04-05T02:11:58+08:00" level=debug msg="DNS响应已缓存" dnssec=false domain=pool.ntp.org.amazehome.xyz ttl=30m0s type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="准备添加查询日志" domain=pool.ntp.org.amazehome.xyz responseCode=0 result=allowed
time="2026-04-05T02:11:58+08:00" level=debug msg="查询日志已添加" domain=pool.ntp.org.amazehome.xyz
time="2026-04-05T02:11:58+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:57606" domain=www.baidu.com.amazehome.xyz type=AAAA
time="2026-04-05T02:11:58+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:57606" domain=www.baidu.com.amazehome.xyz type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=www.baidu.com.amazehome.xyz
time="2026-04-05T02:11:58+08:00" level=debug msg="威胁检测引擎检查域名" domain=www.baidu.com.amazehome.xyz sourceIP=10.35.10.70
time="2026-04-05T02:11:58+08:00" level=debug msg="开始处理上游请求" domain=www.baidu.com.amazehome.xyz type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="域名匹配到不验证DNSSEC的模式" domain=www.baidu.com.amazehome.xyz pattern=amazehome.xyz
time="2026-04-05T02:11:58+08:00" level=debug msg="域名匹配到特定DNS服务器配置" dnsServers="[10.35.10.200:53]" domain=www.baidu.com.amazehome.xyz matchStr=amazehome.xyz
time="2026-04-05T02:11:58+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=www.baidu.com.amazehome.xyz. queryTimeout 配置=5
time="2026-04-05T02:11:58+08:00" level=debug msg="所有服务器都失败,返回最后一个错误响应" domain=www.baidu.com.amazehome.xyz server="10.35.10.200:53"
time="2026-04-05T02:11:58+08:00" level=debug msg="上游请求返回" domain=www.baidu.com.amazehome.xyz response=true rtt="867.793µs"
time="2026-04-05T02:11:58+08:00" level=debug msg="DNS响应已缓存" dnssec=false domain=www.baidu.com.amazehome.xyz ttl=30m0s type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="准备添加查询日志" domain=www.baidu.com.amazehome.xyz responseCode=0 result=allowed
time="2026-04-05T02:11:58+08:00" level=debug msg="查询日志已添加" domain=www.baidu.com.amazehome.xyz
time="2026-04-05T02:11:58+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:55673" domain=sdkconfig.ad.xiaomi.com type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="威胁检测引擎检查域名" domain=sdkconfig.ad.xiaomi.com sourceIP=10.35.10.78
time="2026-04-05T02:11:58+08:00" level=debug msg="开始处理上游请求" domain=sdkconfig.ad.xiaomi.com type=A
time="2026-04-05T02:11:58+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:11:58+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=sdkconfig.ad.xiaomi.com. queryTimeout 配置=5
time="2026-04-05T02:11:58+08:00" level=debug msg="上游请求返回" domain=sdkconfig.ad.xiaomi.com response=false rtt=0s
time="2026-04-05T02:11:58+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=sdkconfig.ad.xiaomi.com
time="2026-04-05T02:11:58+08:00" level=debug msg="准备添加查询日志" domain=sdkconfig.ad.xiaomi.com responseCode=0 result=error
time="2026-04-05T02:11:58+08:00" level=debug msg="查询日志已添加" domain=sdkconfig.ad.xiaomi.com
time="2026-04-05T02:11:59+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:50322" domain=www.baidu.com type=AAAA
time="2026-04-05T02:11:59+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=www.baidu.com
time="2026-04-05T02:11:59+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:50322" domain=www.baidu.com type=A
time="2026-04-05T02:11:59+08:00" level=debug msg="从缓存返回DNS响应" dnssec=false domain=www.baidu.com type=A
time="2026-04-05T02:11:59+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:51927" domain=h-adashx.ut.taobao.com type=A
time="2026-04-05T02:11:59+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:51927" domain=h-adashx.ut.taobao.com
time="2026-04-05T02:11:59+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:51927" domain=pcapp-data-collect.youku.com type=A
time="2026-04-05T02:11:59+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:51927" domain=pcapp-data-collect.youku.com
time="2026-04-05T02:11:59+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:51927" domain=h-adashx.ut.taobao.com type=A
time="2026-04-05T02:11:59+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:51927" domain=h-adashx.ut.taobao.com
time="2026-04-05T02:11:59+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:51927" domain=log.zijieapi.com type=A
time="2026-04-05T02:11:59+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:51927" domain=log.zijieapi.com
time="2026-04-05T02:11:59+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:51927" domain=log.zijieapi.com type=A
time="2026-04-05T02:11:59+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:51927" domain=log.zijieapi.com
time="2026-04-05T02:11:59+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:51927" domain=log.zijieapi.com type=A
time="2026-04-05T02:11:59+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:51927" domain=log.zijieapi.com
time="2026-04-05T02:11:59+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:51927" domain=log.zijieapi.com type=A
time="2026-04-05T02:11:59+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:51927" domain=log.zijieapi.com
time="2026-04-05T02:11:59+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:51927" domain=log.zijieapi.com type=A
time="2026-04-05T02:11:59+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:51927" domain=log.zijieapi.com
time="2026-04-05T02:11:59+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:51927" domain=log.zijieapi.com type=A
time="2026-04-05T02:11:59+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:51927" domain=log.zijieapi.com
time="2026-04-05T02:11:59+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:51927" domain=log.zijieapi.com type=A
time="2026-04-05T02:11:59+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:51927" domain=log.zijieapi.com
time="2026-04-05T02:11:59+08:00" level=debug msg="接收到DNS查询" client="10.35.10.29:43377" domain=registry.cn-hangzhou.aliyuncs.com type=AAAA
time="2026-04-05T02:11:59+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=registry.cn-hangzhou.aliyuncs.com
time="2026-04-05T02:11:59+08:00" level=debug msg="接收到DNS查询" client="10.35.10.29:43377" domain=registry.cn-hangzhou.aliyuncs.com type=A
time="2026-04-05T02:11:59+08:00" level=debug msg="威胁检测引擎检查域名" domain=registry.cn-hangzhou.aliyuncs.com sourceIP=10.35.10.29
time="2026-04-05T02:11:59+08:00" level=debug msg="开始处理上游请求" domain=registry.cn-hangzhou.aliyuncs.com type=A
time="2026-04-05T02:11:59+08:00" level=debug msg="域名匹配到不验证DNSSEC的模式" domain=registry.cn-hangzhou.aliyuncs.com pattern=.cn
time="2026-04-05T02:11:59+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:11:59+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=registry.cn-hangzhou.aliyuncs.com. queryTimeout 配置=5
time="2026-04-05T02:11:59+08:00" level=debug msg="上游请求返回" domain=registry.cn-hangzhou.aliyuncs.com response=false rtt=0s
time="2026-04-05T02:11:59+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=registry.cn-hangzhou.aliyuncs.com
time="2026-04-05T02:11:59+08:00" level=debug msg="准备添加查询日志" domain=registry.cn-hangzhou.aliyuncs.com responseCode=0 result=error
time="2026-04-05T02:11:59+08:00" level=debug msg="查询日志已添加" domain=registry.cn-hangzhou.aliyuncs.com
time="2026-04-05T02:11:59+08:00" level=debug msg="接收到DNS查询" client="10.35.10.29:34218" domain=registry.cn-hangzhou.aliyuncs.com type=AAAA
time="2026-04-05T02:11:59+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=registry.cn-hangzhou.aliyuncs.com
time="2026-04-05T02:11:59+08:00" level=debug msg="接收到DNS查询" client="10.35.10.29:34218" domain=registry.cn-hangzhou.aliyuncs.com type=A
time="2026-04-05T02:12:00+08:00" level=debug msg="威胁检测引擎检查域名" domain=registry.cn-hangzhou.aliyuncs.com sourceIP=10.35.10.29
time="2026-04-05T02:12:00+08:00" level=debug msg="开始处理上游请求" domain=registry.cn-hangzhou.aliyuncs.com type=A
time="2026-04-05T02:12:00+08:00" level=debug msg="域名匹配到不验证DNSSEC的模式" domain=registry.cn-hangzhou.aliyuncs.com pattern=.cn
time="2026-04-05T02:12:00+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:12:00+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=registry.cn-hangzhou.aliyuncs.com. queryTimeout 配置=5
time="2026-04-05T02:12:00+08:00" level=debug msg="返回第一个成功响应" domain=registry.cn-hangzhou.aliyuncs.com rtt="733.909µs" server=10.35.10.200
time="2026-04-05T02:12:00+08:00" level=debug msg="上游请求返回" domain=registry.cn-hangzhou.aliyuncs.com response=true rtt="733.909µs"
time="2026-04-05T02:12:00+08:00" level=debug msg="DNS响应已缓存" dnssec=false domain=registry.cn-hangzhou.aliyuncs.com ttl=30m0s type=A
time="2026-04-05T02:12:00+08:00" level=debug msg="准备添加查询日志" domain=registry.cn-hangzhou.aliyuncs.com responseCode=0 result=allowed
time="2026-04-05T02:12:00+08:00" level=debug msg="查询日志已添加" domain=registry.cn-hangzhou.aliyuncs.com
time="2026-04-05T02:12:00+08:00" level=debug msg="接收到DNS查询" client="10.35.10.29:46141" domain=dockerauth.cn-hangzhou.aliyuncs.com type=AAAA
time="2026-04-05T02:12:00+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=dockerauth.cn-hangzhou.aliyuncs.com
time="2026-04-05T02:12:00+08:00" level=debug msg="接收到DNS查询" client="10.35.10.29:46141" domain=dockerauth.cn-hangzhou.aliyuncs.com type=A
time="2026-04-05T02:12:00+08:00" level=debug msg="威胁检测引擎检查域名" domain=dockerauth.cn-hangzhou.aliyuncs.com sourceIP=10.35.10.29
time="2026-04-05T02:12:00+08:00" level=debug msg="开始处理上游请求" domain=dockerauth.cn-hangzhou.aliyuncs.com type=A
time="2026-04-05T02:12:00+08:00" level=debug msg="域名匹配到不验证DNSSEC的模式" domain=dockerauth.cn-hangzhou.aliyuncs.com pattern=.cn
time="2026-04-05T02:12:00+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:12:00+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=dockerauth.cn-hangzhou.aliyuncs.com. queryTimeout 配置=5
time="2026-04-05T02:12:00+08:00" level=debug msg="上游请求返回" domain=dockerauth.cn-hangzhou.aliyuncs.com response=false rtt=0s
time="2026-04-05T02:12:00+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=dockerauth.cn-hangzhou.aliyuncs.com
time="2026-04-05T02:12:00+08:00" level=debug msg="准备添加查询日志" domain=dockerauth.cn-hangzhou.aliyuncs.com responseCode=0 result=error
time="2026-04-05T02:12:00+08:00" level=debug msg="查询日志已添加" domain=dockerauth.cn-hangzhou.aliyuncs.com
time="2026-04-05T02:12:00+08:00" level=debug msg="接收到DNS查询" client="10.35.10.29:52387" domain=dockerauth.cn-hangzhou.aliyuncs.com type=AAAA
time="2026-04-05T02:12:00+08:00" level=debug msg="接收到DNS查询" client="10.35.10.29:52387" domain=dockerauth.cn-hangzhou.aliyuncs.com type=A
time="2026-04-05T02:12:00+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=dockerauth.cn-hangzhou.aliyuncs.com
time="2026-04-05T02:12:00+08:00" level=debug msg="威胁检测引擎检查域名" domain=dockerauth.cn-hangzhou.aliyuncs.com sourceIP=10.35.10.29
time="2026-04-05T02:12:00+08:00" level=debug msg="开始处理上游请求" domain=dockerauth.cn-hangzhou.aliyuncs.com type=A
time="2026-04-05T02:12:00+08:00" level=debug msg="域名匹配到不验证DNSSEC的模式" domain=dockerauth.cn-hangzhou.aliyuncs.com pattern=.cn
time="2026-04-05T02:12:00+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:12:00+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=dockerauth.cn-hangzhou.aliyuncs.com. queryTimeout 配置=5
time="2026-04-05T02:12:00+08:00" level=debug msg="返回第一个成功响应" domain=dockerauth.cn-hangzhou.aliyuncs.com rtt="617.302µs" server=10.35.10.200
time="2026-04-05T02:12:00+08:00" level=debug msg="上游请求返回" domain=dockerauth.cn-hangzhou.aliyuncs.com response=true rtt="617.302µs"
time="2026-04-05T02:12:00+08:00" level=debug msg="DNS响应已缓存" dnssec=false domain=dockerauth.cn-hangzhou.aliyuncs.com ttl=30m0s type=A
time="2026-04-05T02:12:00+08:00" level=debug msg="CNAME响应已缓存" dnssec=false domain=tyjr-cn-hangzhou.aliyun.com. ttl=30m0s type=A
time="2026-04-05T02:12:00+08:00" level=debug msg="准备添加查询日志" domain=dockerauth.cn-hangzhou.aliyuncs.com responseCode=0 result=allowed
time="2026-04-05T02:12:00+08:00" level=debug msg="查询日志已添加" domain=dockerauth.cn-hangzhou.aliyuncs.com
time="2026-04-05T02:12:00+08:00" level=debug msg="接收到DNS查询" client="10.35.10.29:36552" domain=registry.cn-hangzhou.aliyuncs.com type=AAAA
time="2026-04-05T02:12:00+08:00" level=debug msg="接收到DNS查询" client="10.35.10.29:36552" domain=registry.cn-hangzhou.aliyuncs.com type=A
time="2026-04-05T02:12:00+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=registry.cn-hangzhou.aliyuncs.com
time="2026-04-05T02:12:00+08:00" level=debug msg="从缓存返回DNS响应" dnssec=false domain=registry.cn-hangzhou.aliyuncs.com type=A
time="2026-04-05T02:12:00+08:00" level=debug msg="接收到DNS查询" client="10.35.10.29:57098" domain=registry.cn-hangzhou.aliyuncs.com type=AAAA
time="2026-04-05T02:12:00+08:00" level=debug msg="接收到DNS查询" client="10.35.10.29:57098" domain=registry.cn-hangzhou.aliyuncs.com type=A
time="2026-04-05T02:12:00+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=registry.cn-hangzhou.aliyuncs.com
time="2026-04-05T02:12:00+08:00" level=debug msg="从缓存返回DNS响应" dnssec=false domain=registry.cn-hangzhou.aliyuncs.com type=A
time="2026-04-05T02:12:00+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:51927" domain=h-adashx.ut.taobao.com type=A
time="2026-04-05T02:12:00+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:51927" domain=h-adashx.ut.taobao.com
time="2026-04-05T02:12:00+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:51927" domain=pcapp-data-collect.youku.com type=A
time="2026-04-05T02:12:00+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:51927" domain=pcapp-data-collect.youku.com
time="2026-04-05T02:12:00+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:51927" domain=pcapp-data-collect.youku.com type=A
time="2026-04-05T02:12:00+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:51927" domain=pcapp-data-collect.youku.com
time="2026-04-05T02:12:00+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:51927" domain=h-adashx.ut.taobao.com type=A
time="2026-04-05T02:12:00+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:51927" domain=h-adashx.ut.taobao.com
time="2026-04-05T02:12:00+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:51927" domain=pcapp-data-collect.youku.com type=A
time="2026-04-05T02:12:00+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:51927" domain=pcapp-data-collect.youku.com
time="2026-04-05T02:12:01+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:35834" domain=o1098464.ingest.sentry.io type=A
time="2026-04-05T02:12:01+08:00" level=info msg="域名被屏蔽" client="10.35.10.70:35834" domain=o1098464.ingest.sentry.io
time="2026-04-05T02:12:01+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:58915" domain=o1098464.ingest.sentry.io type=AAAA
time="2026-04-05T02:12:01+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=o1098464.ingest.sentry.io
time="2026-04-05T02:12:01+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:60750" domain=o1098464.ingest.sentry.io type=AAAA
time="2026-04-05T02:12:01+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=o1098464.ingest.sentry.io
time="2026-04-05T02:12:01+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:54257" domain=o1098464.ingest.sentry.io type=A
time="2026-04-05T02:12:01+08:00" level=info msg="域名被屏蔽" client="10.35.10.70:54257" domain=o1098464.ingest.sentry.io
time="2026-04-05T02:12:01+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:51927" domain=pcapp-data-collect.youku.com type=A
time="2026-04-05T02:12:01+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:51927" domain=pcapp-data-collect.youku.com
time="2026-04-05T02:12:01+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:51927" domain=pcapp-data-collect.youku.com type=A
time="2026-04-05T02:12:01+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:51927" domain=pcapp-data-collect.youku.com
time="2026-04-05T02:12:02+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:51182" domain=www.baidu.com type=AAAA
time="2026-04-05T02:12:02+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=www.baidu.com
time="2026-04-05T02:12:02+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:51182" domain=www.baidu.com type=A
time="2026-04-05T02:12:02+08:00" level=debug msg="从缓存返回DNS响应" dnssec=false domain=www.baidu.com type=A
time="2026-04-05T02:12:02+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:51927" domain=pcapp-data-collect.youku.com type=A
time="2026-04-05T02:12:02+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:51927" domain=pcapp-data-collect.youku.com
time="2026-04-05T02:12:02+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:51927" domain=pcapp-data-collect.youku.com type=A
time="2026-04-05T02:12:02+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:51927" domain=pcapp-data-collect.youku.com
time="2026-04-05T02:12:05+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:41199" domain=topdesk.com type=AAAA
time="2026-04-05T02:12:05+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:52054" domain=topdesk.com type=A
time="2026-04-05T02:12:05+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=topdesk.com
time="2026-04-05T02:12:05+08:00" level=debug msg="威胁检测引擎检查域名" domain=topdesk.com sourceIP=10.35.10.70
time="2026-04-05T02:12:05+08:00" level=debug msg="开始处理上游请求" domain=topdesk.com type=A
time="2026-04-05T02:12:05+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:12:05+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=topdesk.com. queryTimeout 配置=5
time="2026-04-05T02:12:05+08:00" level=debug msg="上游请求返回" domain=topdesk.com response=false rtt=0s
time="2026-04-05T02:12:05+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=topdesk.com
time="2026-04-05T02:12:05+08:00" level=debug msg="准备添加查询日志" domain=topdesk.com responseCode=0 result=error
time="2026-04-05T02:12:05+08:00" level=debug msg="查询日志已添加" domain=topdesk.com
time="2026-04-05T02:12:05+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:37015" domain=topdesk.com type=A
time="2026-04-05T02:12:05+08:00" level=debug msg="威胁检测引擎检查域名" domain=topdesk.com sourceIP=10.35.10.70
time="2026-04-05T02:12:05+08:00" level=debug msg="开始处理上游请求" domain=topdesk.com type=A
time="2026-04-05T02:12:05+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:12:05+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=topdesk.com. queryTimeout 配置=5
time="2026-04-05T02:12:05+08:00" level=debug msg="上游请求返回" domain=topdesk.com response=false rtt=0s
time="2026-04-05T02:12:05+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=topdesk.com
time="2026-04-05T02:12:05+08:00" level=debug msg="准备添加查询日志" domain=topdesk.com responseCode=0 result=error
time="2026-04-05T02:12:05+08:00" level=debug msg="查询日志已添加" domain=topdesk.com
time="2026-04-05T02:12:05+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:35803" domain=sonymusic.com type=A
time="2026-04-05T02:12:05+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:57103" domain=sonymusic.com type=AAAA
time="2026-04-05T02:12:05+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=sonymusic.com
time="2026-04-05T02:12:05+08:00" level=debug msg="从缓存返回DNS响应" dnssec=false domain=sonymusic.com type=A
time="2026-04-05T02:12:05+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:55790" domain=vsco.co type=A
time="2026-04-05T02:12:05+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:34632" domain=vsco.co type=AAAA
time="2026-04-05T02:12:05+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=vsco.co
time="2026-04-05T02:12:05+08:00" level=debug msg="威胁检测引擎检查域名" domain=vsco.co sourceIP=10.35.10.70
time="2026-04-05T02:12:05+08:00" level=debug msg="开始处理上游请求" domain=vsco.co type=A
time="2026-04-05T02:12:05+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:12:05+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=vsco.co. queryTimeout 配置=5
time="2026-04-05T02:12:05+08:00" level=debug msg="上游请求返回" domain=vsco.co response=false rtt=0s
time="2026-04-05T02:12:05+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=vsco.co
time="2026-04-05T02:12:05+08:00" level=debug msg="准备添加查询日志" domain=vsco.co responseCode=0 result=error
time="2026-04-05T02:12:05+08:00" level=debug msg="查询日志已添加" domain=vsco.co
time="2026-04-05T02:12:05+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:47650" domain=vsco.co type=A
time="2026-04-05T02:12:05+08:00" level=debug msg="威胁检测引擎检查域名" domain=vsco.co sourceIP=10.35.10.70
time="2026-04-05T02:12:05+08:00" level=debug msg="开始处理上游请求" domain=vsco.co type=A
time="2026-04-05T02:12:05+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:12:05+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=vsco.co. queryTimeout 配置=5
time="2026-04-05T02:12:05+08:00" level=debug msg="上游请求返回" domain=vsco.co response=false rtt=0s
time="2026-04-05T02:12:05+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=vsco.co
time="2026-04-05T02:12:05+08:00" level=debug msg="准备添加查询日志" domain=vsco.co responseCode=0 result=error
time="2026-04-05T02:12:05+08:00" level=debug msg="查询日志已添加" domain=vsco.co
time="2026-04-05T02:12:05+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:41298" domain=www.baidu.com type=AAAA
time="2026-04-05T02:12:05+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:41298" domain=www.baidu.com type=A
time="2026-04-05T02:12:05+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=www.baidu.com
time="2026-04-05T02:12:05+08:00" level=debug msg="从缓存返回DNS响应" dnssec=false domain=www.baidu.com type=A
time="2026-04-05T02:12:05+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:51605" domain=ipv6.msftncsi.com type=A
time="2026-04-05T02:12:05+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:51927" domain=ipv6.msftncsi.com type=A
time="2026-04-05T02:12:05+08:00" level=debug msg="威胁检测引擎检查域名" domain=ipv6.msftncsi.com sourceIP=10.35.10.78
time="2026-04-05T02:12:05+08:00" level=debug msg="开始处理上游请求" domain=ipv6.msftncsi.com type=A
time="2026-04-05T02:12:05+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:12:05+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=ipv6.msftncsi.com. queryTimeout 配置=5
time="2026-04-05T02:12:05+08:00" level=debug msg="威胁检测引擎检查域名" domain=ipv6.msftncsi.com sourceIP=10.35.10.78
time="2026-04-05T02:12:05+08:00" level=debug msg="开始处理上游请求" domain=ipv6.msftncsi.com type=A
time="2026-04-05T02:12:05+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:12:05+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=ipv6.msftncsi.com. queryTimeout 配置=5
time="2026-04-05T02:12:05+08:00" level=debug msg="上游请求返回" domain=ipv6.msftncsi.com response=false rtt=0s
time="2026-04-05T02:12:05+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=ipv6.msftncsi.com
time="2026-04-05T02:12:05+08:00" level=debug msg="上游请求返回" domain=ipv6.msftncsi.com response=false rtt=0s
time="2026-04-05T02:12:05+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=ipv6.msftncsi.com
time="2026-04-05T02:12:05+08:00" level=debug msg="准备添加查询日志" domain=ipv6.msftncsi.com responseCode=0 result=error
time="2026-04-05T02:12:05+08:00" level=debug msg="查询日志已添加" domain=ipv6.msftncsi.com
time="2026-04-05T02:12:05+08:00" level=debug msg="准备添加查询日志" domain=ipv6.msftncsi.com responseCode=0 result=error
time="2026-04-05T02:12:05+08:00" level=debug msg="查询日志已添加" domain=ipv6.msftncsi.com
time="2026-04-05T02:12:05+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:50175" domain=pw.mediav.com type=A
time="2026-04-05T02:12:05+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:50175" domain=pw.mediav.com
time="2026-04-05T02:12:05+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:50175" domain=pw.mediav.com type=A
time="2026-04-05T02:12:05+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:50175" domain=pw.mediav.com
time="2026-04-05T02:12:06+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:50175" domain=edge.microsoft.com type=A
time="2026-04-05T02:12:06+08:00" level=debug msg="威胁检测引擎检查域名" domain=edge.microsoft.com sourceIP=10.35.10.78
time="2026-04-05T02:12:06+08:00" level=debug msg="开始处理上游请求" domain=edge.microsoft.com type=A
time="2026-04-05T02:12:06+08:00" level=debug msg="域名匹配到特定DNS服务器配置" dnsServers="[10.35.10.200:53]" domain=edge.microsoft.com matchStr=microsoft.com
time="2026-04-05T02:12:06+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=edge.microsoft.com. queryTimeout 配置=5
time="2026-04-05T02:12:06+08:00" level=debug msg="上游请求返回" domain=edge.microsoft.com response=false rtt=0s
time="2026-04-05T02:12:06+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=edge.microsoft.com
time="2026-04-05T02:12:06+08:00" level=debug msg="准备添加查询日志" domain=edge.microsoft.com responseCode=0 result=error
time="2026-04-05T02:12:06+08:00" level=debug msg="查询日志已添加" domain=edge.microsoft.com
time="2026-04-05T02:12:06+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:49006" domain=fossilgroup.com type=AAAA
time="2026-04-05T02:12:06+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:43042" domain=fossilgroup.com type=A
time="2026-04-05T02:12:06+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=fossilgroup.com
time="2026-04-05T02:12:06+08:00" level=debug msg="从缓存返回DNS响应" dnssec=false domain=fossilgroup.com type=A
time="2026-04-05T02:12:06+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:54905" domain=o1098464.ingest.sentry.io type=A
time="2026-04-05T02:12:06+08:00" level=info msg="域名被屏蔽" client="10.35.10.70:54905" domain=o1098464.ingest.sentry.io
time="2026-04-05T02:12:06+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:33302" domain=o1098464.ingest.sentry.io type=AAAA
time="2026-04-05T02:12:06+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=o1098464.ingest.sentry.io
time="2026-04-05T02:12:08+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:54859" domain=log.zijieapi.com type=A
time="2026-04-05T02:12:08+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:54859" domain=log.zijieapi.com
time="2026-04-05T02:12:08+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:54859" domain=log.zijieapi.com type=A
time="2026-04-05T02:12:08+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:54859" domain=log.zijieapi.com
time="2026-04-05T02:12:08+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:42052" domain=www.baidu.com type=AAAA
time="2026-04-05T02:12:08+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:42052" domain=www.baidu.com type=A
time="2026-04-05T02:12:08+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=www.baidu.com
time="2026-04-05T02:12:08+08:00" level=debug msg="从缓存返回DNS响应" dnssec=false domain=www.baidu.com type=A
time="2026-04-05T02:12:08+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:54859" domain=chinanorth3-0.in.applicationinsights.azure.cn type=A
time="2026-04-05T02:12:08+08:00" level=debug msg="威胁检测引擎检查域名" domain=chinanorth3-0.in.applicationinsights.azure.cn sourceIP=10.35.10.78
time="2026-04-05T02:12:08+08:00" level=debug msg="开始处理上游请求" domain=chinanorth3-0.in.applicationinsights.azure.cn type=A
time="2026-04-05T02:12:08+08:00" level=debug msg="域名匹配到不验证DNSSEC的模式" domain=chinanorth3-0.in.applicationinsights.azure.cn pattern=.cn
time="2026-04-05T02:12:08+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:12:08+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=chinanorth3-0.in.applicationinsights.azure.cn. queryTimeout 配置=5
time="2026-04-05T02:12:08+08:00" level=debug msg="上游请求返回" domain=chinanorth3-0.in.applicationinsights.azure.cn response=false rtt=0s
time="2026-04-05T02:12:08+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=chinanorth3-0.in.applicationinsights.azure.cn
time="2026-04-05T02:12:08+08:00" level=debug msg="准备添加查询日志" domain=chinanorth3-0.in.applicationinsights.azure.cn responseCode=0 result=error
time="2026-04-05T02:12:08+08:00" level=debug msg="查询日志已添加" domain=chinanorth3-0.in.applicationinsights.azure.cn
time="2026-04-05T02:12:08+08:00" level=debug msg="接收到DNS查询" client="10.35.10.39:57732" domain=horizon1.amazehome.xyz type=A
time="2026-04-05T02:12:08+08:00" level=debug msg="威胁检测引擎检查域名" domain=horizon1.amazehome.xyz sourceIP=10.35.10.39
time="2026-04-05T02:12:08+08:00" level=debug msg="开始处理上游请求" domain=horizon1.amazehome.xyz type=A
time="2026-04-05T02:12:08+08:00" level=debug msg="域名匹配到不验证DNSSEC的模式" domain=horizon1.amazehome.xyz pattern=amazehome.xyz
time="2026-04-05T02:12:08+08:00" level=debug msg="域名匹配到特定DNS服务器配置" dnsServers="[10.35.10.200:53]" domain=horizon1.amazehome.xyz matchStr=amazehome.xyz
time="2026-04-05T02:12:08+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=horizon1.amazehome.xyz. queryTimeout 配置=5
time="2026-04-05T02:12:08+08:00" level=debug msg="返回第一个成功响应" domain=horizon1.amazehome.xyz rtt="566.02µs" server="10.35.10.200:53"
time="2026-04-05T02:12:08+08:00" level=debug msg="上游请求返回" domain=horizon1.amazehome.xyz response=true rtt="566.02µs"
time="2026-04-05T02:12:08+08:00" level=debug msg="DNS响应已缓存" dnssec=false domain=horizon1.amazehome.xyz ttl=30m0s type=A
time="2026-04-05T02:12:08+08:00" level=debug msg="准备添加查询日志" domain=horizon1.amazehome.xyz responseCode=0 result=allowed
time="2026-04-05T02:12:08+08:00" level=debug msg="查询日志已添加" domain=horizon1.amazehome.xyz
time="2026-04-05T02:12:09+08:00" level=debug msg="接收到DNS查询" client="10.35.10.29:53304" domain=registry.cn-hangzhou.aliyuncs.com type=AAAA
time="2026-04-05T02:12:09+08:00" level=debug msg="接收到DNS查询" client="10.35.10.29:53304" domain=registry.cn-hangzhou.aliyuncs.com type=A
time="2026-04-05T02:12:09+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=registry.cn-hangzhou.aliyuncs.com
time="2026-04-05T02:12:09+08:00" level=debug msg="从缓存返回DNS响应" dnssec=false domain=registry.cn-hangzhou.aliyuncs.com type=A
time="2026-04-05T02:12:09+08:00" level=debug msg="接收到DNS查询" client="10.35.10.29:50420" domain=registry.cn-hangzhou.aliyuncs.com type=AAAA
time="2026-04-05T02:12:09+08:00" level=debug msg="接收到DNS查询" client="10.35.10.29:50420" domain=registry.cn-hangzhou.aliyuncs.com type=A
time="2026-04-05T02:12:09+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=registry.cn-hangzhou.aliyuncs.com
time="2026-04-05T02:12:09+08:00" level=debug msg="从缓存返回DNS响应" dnssec=false domain=registry.cn-hangzhou.aliyuncs.com type=A
time="2026-04-05T02:12:09+08:00" level=debug msg="接收到DNS查询" client="10.35.10.29:51881" domain=registry.cn-hangzhou.aliyuncs.com type=AAAA
time="2026-04-05T02:12:09+08:00" level=debug msg="接收到DNS查询" client="10.35.10.29:51881" domain=registry.cn-hangzhou.aliyuncs.com type=A
time="2026-04-05T02:12:09+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=registry.cn-hangzhou.aliyuncs.com
time="2026-04-05T02:12:09+08:00" level=debug msg="从缓存返回DNS响应" dnssec=false domain=registry.cn-hangzhou.aliyuncs.com type=A
time="2026-04-05T02:12:09+08:00" level=debug msg="接收到DNS查询" client="10.35.10.29:37858" domain=registry.cn-hangzhou.aliyuncs.com type=AAAA
time="2026-04-05T02:12:09+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=registry.cn-hangzhou.aliyuncs.com
time="2026-04-05T02:12:09+08:00" level=debug msg="接收到DNS查询" client="10.35.10.29:37858" domain=registry.cn-hangzhou.aliyuncs.com type=A
time="2026-04-05T02:12:09+08:00" level=debug msg="从缓存返回DNS响应" dnssec=false domain=registry.cn-hangzhou.aliyuncs.com type=A
time="2026-04-05T02:12:11+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:42775" domain=www.baidu.com type=AAAA
time="2026-04-05T02:12:11+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=www.baidu.com
time="2026-04-05T02:12:11+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:42775" domain=www.baidu.com type=A
time="2026-04-05T02:12:11+08:00" level=debug msg="从缓存返回DNS响应" dnssec=false domain=www.baidu.com type=A
time="2026-04-05T02:12:11+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:39920" domain=o1098464.ingest.sentry.io type=A
time="2026-04-05T02:12:11+08:00" level=info msg="域名被屏蔽" client="10.35.10.70:39920" domain=o1098464.ingest.sentry.io
time="2026-04-05T02:12:11+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:36592" domain=o1098464.ingest.sentry.io type=AAAA
time="2026-04-05T02:12:11+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=o1098464.ingest.sentry.io
time="2026-04-05T02:12:12+08:00" level=debug msg="接收到DNS查询" client="10.35.10.21:60582" domain=oth.eve.mdt.qq.com type=A
time="2026-04-05T02:12:12+08:00" level=info msg="域名被屏蔽" client="10.35.10.21:60582" domain=oth.eve.mdt.qq.com
time="2026-04-05T02:12:12+08:00" level=debug msg="接收到DNS查询" client="10.35.10.21:60582" domain=oth.eve.mdt.qq.com type=A
time="2026-04-05T02:12:12+08:00" level=info msg="域名被屏蔽" client="10.35.10.21:60582" domain=oth.eve.mdt.qq.com
time="2026-04-05T02:12:13+08:00" level=debug msg="接收到DNS查询" client="10.35.10.39:55727" domain=DC.amazehome.xyz type=A
time="2026-04-05T02:12:13+08:00" level=debug msg="威胁检测引擎检查域名" domain=DC.amazehome.xyz sourceIP=10.35.10.39
time="2026-04-05T02:12:13+08:00" level=debug msg="开始处理上游请求" domain=DC.amazehome.xyz type=A
time="2026-04-05T02:12:13+08:00" level=debug msg="域名匹配到不验证DNSSEC的模式" domain=DC.amazehome.xyz pattern=amazehome.xyz
time="2026-04-05T02:12:13+08:00" level=debug msg="域名匹配到特定DNS服务器配置" dnsServers="[10.35.10.200:53]" domain=DC.amazehome.xyz matchStr=amazehome.xyz
time="2026-04-05T02:12:13+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=DC.amazehome.xyz. queryTimeout 配置=5
time="2026-04-05T02:12:13+08:00" level=debug msg="返回第一个成功响应" domain=DC.amazehome.xyz rtt="805.167µs" server="10.35.10.200:53"
time="2026-04-05T02:12:13+08:00" level=debug msg="上游请求返回" domain=DC.amazehome.xyz response=true rtt="805.167µs"
time="2026-04-05T02:12:13+08:00" level=debug msg="DNS响应已缓存" dnssec=false domain=DC.amazehome.xyz ttl=30m0s type=A
time="2026-04-05T02:12:13+08:00" level=debug msg="准备添加查询日志" domain=DC.amazehome.xyz responseCode=0 result=allowed
time="2026-04-05T02:12:13+08:00" level=debug msg="查询日志已添加" domain=DC.amazehome.xyz
time="2026-04-05T02:12:13+08:00" level=debug msg="接收到DNS查询" client="10.35.10.39:55727" domain=DC.amazehome.xyz type=A
time="2026-04-05T02:12:13+08:00" level=debug msg="从缓存返回DNS响应" dnssec=false domain=DC.amazehome.xyz type=A
time="2026-04-05T02:12:13+08:00" level=debug msg="接收到DNS查询" client="10.35.10.39:53351" domain=amazehome.xyz type=A
time="2026-04-05T02:12:13+08:00" level=debug msg="威胁检测引擎检查域名" domain=amazehome.xyz sourceIP=10.35.10.39
time="2026-04-05T02:12:13+08:00" level=debug msg="开始处理上游请求" domain=amazehome.xyz type=A
time="2026-04-05T02:12:13+08:00" level=debug msg="域名匹配到不验证DNSSEC的模式" domain=amazehome.xyz pattern=amazehome.xyz
time="2026-04-05T02:12:13+08:00" level=debug msg="域名匹配到特定DNS服务器配置" dnsServers="[10.35.10.200:53]" domain=amazehome.xyz matchStr=amazehome.xyz
time="2026-04-05T02:12:13+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=amazehome.xyz. queryTimeout 配置=5
time="2026-04-05T02:12:13+08:00" level=debug msg="返回第一个成功响应" domain=amazehome.xyz rtt="721.515µs" server="10.35.10.200:53"
time="2026-04-05T02:12:13+08:00" level=debug msg="上游请求返回" domain=amazehome.xyz response=true rtt="721.515µs"
time="2026-04-05T02:12:13+08:00" level=debug msg="DNS响应已缓存" dnssec=false domain=amazehome.xyz ttl=30m0s type=A
time="2026-04-05T02:12:13+08:00" level=debug msg="准备添加查询日志" domain=amazehome.xyz responseCode=0 result=allowed
time="2026-04-05T02:12:13+08:00" level=debug msg="查询日志已添加" domain=amazehome.xyz
time="2026-04-05T02:12:13+08:00" level=debug msg="接收到DNS查询" client="10.35.10.39:53351" domain=amazehome.xyz type=A
time="2026-04-05T02:12:13+08:00" level=debug msg="从缓存返回DNS响应" dnssec=false domain=amazehome.xyz type=A
time="2026-04-05T02:12:14+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:59963" domain=res-honeycomb.wpscdn.cn type=A
time="2026-04-05T02:12:14+08:00" level=debug msg="威胁检测引擎检查域名" domain=res-honeycomb.wpscdn.cn sourceIP=10.35.10.78
time="2026-04-05T02:12:14+08:00" level=debug msg="开始处理上游请求" domain=res-honeycomb.wpscdn.cn type=A
time="2026-04-05T02:12:14+08:00" level=debug msg="域名匹配到不验证DNSSEC的模式" domain=res-honeycomb.wpscdn.cn pattern=.cn
time="2026-04-05T02:12:14+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:12:14+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=res-honeycomb.wpscdn.cn. queryTimeout 配置=5
time="2026-04-05T02:12:14+08:00" level=debug msg="上游请求返回" domain=res-honeycomb.wpscdn.cn response=false rtt=0s
time="2026-04-05T02:12:14+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=res-honeycomb.wpscdn.cn
time="2026-04-05T02:12:14+08:00" level=debug msg="准备添加查询日志" domain=res-honeycomb.wpscdn.cn responseCode=0 result=error
time="2026-04-05T02:12:14+08:00" level=debug msg="查询日志已添加" domain=res-honeycomb.wpscdn.cn
time="2026-04-05T02:12:14+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:36043" domain=www.baidu.com type=AAAA
time="2026-04-05T02:12:14+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=www.baidu.com
time="2026-04-05T02:12:14+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:36043" domain=www.baidu.com type=A
time="2026-04-05T02:12:14+08:00" level=debug msg="从缓存返回DNS响应" dnssec=false domain=www.baidu.com type=A
time="2026-04-05T02:12:15+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:33346" domain=topdesk.com type=A
time="2026-04-05T02:12:15+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:43044" domain=topdesk.com type=AAAA
time="2026-04-05T02:12:15+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=topdesk.com
time="2026-04-05T02:12:15+08:00" level=debug msg="威胁检测引擎检查域名" domain=topdesk.com sourceIP=10.35.10.70
time="2026-04-05T02:12:15+08:00" level=debug msg="开始处理上游请求" domain=topdesk.com type=A
time="2026-04-05T02:12:15+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:12:15+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=topdesk.com. queryTimeout 配置=5
time="2026-04-05T02:12:15+08:00" level=debug msg="上游请求返回" domain=topdesk.com response=false rtt=0s
time="2026-04-05T02:12:15+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=topdesk.com
time="2026-04-05T02:12:15+08:00" level=debug msg="准备添加查询日志" domain=topdesk.com responseCode=0 result=error
time="2026-04-05T02:12:15+08:00" level=debug msg="查询日志已添加" domain=topdesk.com
time="2026-04-05T02:12:15+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:35101" domain=topdesk.com type=A
time="2026-04-05T02:12:15+08:00" level=debug msg="威胁检测引擎检查域名" domain=topdesk.com sourceIP=10.35.10.70
time="2026-04-05T02:12:15+08:00" level=debug msg="开始处理上游请求" domain=topdesk.com type=A
time="2026-04-05T02:12:15+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:12:15+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=topdesk.com. queryTimeout 配置=5
time="2026-04-05T02:12:15+08:00" level=debug msg="返回第一个成功响应" domain=topdesk.com rtt=1.83092ms server=10.35.10.200
time="2026-04-05T02:12:15+08:00" level=debug msg="上游请求返回" domain=topdesk.com response=true rtt=1.83092ms
time="2026-04-05T02:12:15+08:00" level=debug msg="DNS响应已缓存" dnssec=false domain=topdesk.com ttl=30m0s type=A
time="2026-04-05T02:12:15+08:00" level=debug msg="准备添加查询日志" domain=topdesk.com responseCode=0 result=allowed
time="2026-04-05T02:12:15+08:00" level=debug msg="查询日志已添加" domain=topdesk.com
time="2026-04-05T02:12:15+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:50918" domain=vsco.co type=A
time="2026-04-05T02:12:15+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:37699" domain=vsco.co type=AAAA
time="2026-04-05T02:12:15+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=vsco.co
time="2026-04-05T02:12:15+08:00" level=debug msg="威胁检测引擎检查域名" domain=vsco.co sourceIP=10.35.10.70
time="2026-04-05T02:12:15+08:00" level=debug msg="开始处理上游请求" domain=vsco.co type=A
time="2026-04-05T02:12:15+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:12:15+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=vsco.co. queryTimeout 配置=5
time="2026-04-05T02:12:15+08:00" level=debug msg="上游请求返回" domain=vsco.co response=false rtt=0s
time="2026-04-05T02:12:15+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=vsco.co
time="2026-04-05T02:12:15+08:00" level=debug msg="准备添加查询日志" domain=vsco.co responseCode=0 result=error
time="2026-04-05T02:12:15+08:00" level=debug msg="查询日志已添加" domain=vsco.co
time="2026-04-05T02:12:15+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:43519" domain=vsco.co type=A
time="2026-04-05T02:12:15+08:00" level=debug msg="威胁检测引擎检查域名" domain=vsco.co sourceIP=10.35.10.70
time="2026-04-05T02:12:15+08:00" level=debug msg="开始处理上游请求" domain=vsco.co type=A
time="2026-04-05T02:12:15+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:12:15+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=vsco.co. queryTimeout 配置=5
time="2026-04-05T02:12:15+08:00" level=debug msg="上游请求返回" domain=vsco.co response=false rtt=0s
time="2026-04-05T02:12:15+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=vsco.co
time="2026-04-05T02:12:15+08:00" level=debug msg="准备添加查询日志" domain=vsco.co responseCode=0 result=error
time="2026-04-05T02:12:15+08:00" level=debug msg="查询日志已添加" domain=vsco.co
time="2026-04-05T02:12:15+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:54421" domain=fossilgroup.com type=AAAA
time="2026-04-05T02:12:15+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=fossilgroup.com
time="2026-04-05T02:12:15+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:57964" domain=fossilgroup.com type=A
time="2026-04-05T02:12:15+08:00" level=debug msg="从缓存返回DNS响应" dnssec=false domain=fossilgroup.com type=A
time="2026-04-05T02:12:15+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:8420" domain=sonymusic.com type=A
time="2026-04-05T02:12:15+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:58694" domain=sonymusic.com type=AAAA
time="2026-04-05T02:12:15+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=sonymusic.com
time="2026-04-05T02:12:15+08:00" level=debug msg="从缓存返回DNS响应" dnssec=false domain=sonymusic.com type=A
time="2026-04-05T02:12:16+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:52560" domain=ipv6.msftncsi.com type=A
time="2026-04-05T02:12:16+08:00" level=debug msg="威胁检测引擎检查域名" domain=ipv6.msftncsi.com sourceIP=10.35.10.78
time="2026-04-05T02:12:16+08:00" level=debug msg="开始处理上游请求" domain=ipv6.msftncsi.com type=A
time="2026-04-05T02:12:16+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:12:16+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=ipv6.msftncsi.com. queryTimeout 配置=5
time="2026-04-05T02:12:16+08:00" level=debug msg="上游请求返回" domain=ipv6.msftncsi.com response=false rtt=0s
time="2026-04-05T02:12:16+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=ipv6.msftncsi.com
time="2026-04-05T02:12:16+08:00" level=debug msg="准备添加查询日志" domain=ipv6.msftncsi.com responseCode=0 result=error
time="2026-04-05T02:12:16+08:00" level=debug msg="查询日志已添加" domain=ipv6.msftncsi.com
time="2026-04-05T02:12:17+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:46385" domain=o1098464.ingest.sentry.io type=A
time="2026-04-05T02:12:17+08:00" level=info msg="域名被屏蔽" client="10.35.10.70:46385" domain=o1098464.ingest.sentry.io
time="2026-04-05T02:12:17+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:39396" domain=o1098464.ingest.sentry.io type=AAAA
time="2026-04-05T02:12:17+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=o1098464.ingest.sentry.io
time="2026-04-05T02:12:17+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:35777" domain=www.baidu.com type=AAAA
time="2026-04-05T02:12:17+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:35777" domain=www.baidu.com type=A
time="2026-04-05T02:12:17+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=www.baidu.com
time="2026-04-05T02:12:17+08:00" level=debug msg="从缓存返回DNS响应" dnssec=false domain=www.baidu.com type=A
time="2026-04-05T02:12:18+08:00" level=debug msg="接收到DNS查询" client="10.35.10.21:60659" domain=oth.eve.mdt.qq.com type=A
time="2026-04-05T02:12:18+08:00" level=info msg="域名被屏蔽" client="10.35.10.21:60659" domain=oth.eve.mdt.qq.com
time="2026-04-05T02:12:18+08:00" level=debug msg="接收到DNS查询" client="10.35.10.21:60659" domain=oth.eve.mdt.qq.com type=A
time="2026-04-05T02:12:18+08:00" level=info msg="域名被屏蔽" client="10.35.10.21:60659" domain=oth.eve.mdt.qq.com
time="2026-04-05T02:12:19+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:49685" domain=time.apple.com type=AAAA
time="2026-04-05T02:12:19+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:49685" domain=time.apple.com type=A
time="2026-04-05T02:12:19+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=time.apple.com
time="2026-04-05T02:12:19+08:00" level=debug msg="威胁检测引擎检查域名" domain=time.apple.com sourceIP=10.35.10.70
time="2026-04-05T02:12:19+08:00" level=debug msg="开始处理上游请求" domain=time.apple.com type=A
time="2026-04-05T02:12:19+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:12:19+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=time.apple.com. queryTimeout 配置=5
time="2026-04-05T02:12:19+08:00" level=debug msg="上游请求返回" domain=time.apple.com response=false rtt=0s
time="2026-04-05T02:12:19+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=time.apple.com
time="2026-04-05T02:12:19+08:00" level=debug msg="准备添加查询日志" domain=time.apple.com responseCode=0 result=error
time="2026-04-05T02:12:19+08:00" level=debug msg="查询日志已添加" domain=time.apple.com
time="2026-04-05T02:12:19+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:58278" domain=time.apple.com.amazehome.xyz type=AAAA
time="2026-04-05T02:12:19+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:58278" domain=time.apple.com.amazehome.xyz type=A
time="2026-04-05T02:12:19+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=time.apple.com.amazehome.xyz
time="2026-04-05T02:12:19+08:00" level=debug msg="从缓存返回DNS响应" dnssec=false domain=time.apple.com.amazehome.xyz type=A
time="2026-04-05T02:12:19+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:33817" domain=pool.ntp.org type=AAAA
time="2026-04-05T02:12:19+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:33817" domain=pool.ntp.org type=A
time="2026-04-05T02:12:19+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=pool.ntp.org
time="2026-04-05T02:12:19+08:00" level=debug msg="威胁检测引擎检查域名" domain=pool.ntp.org sourceIP=10.35.10.70
time="2026-04-05T02:12:19+08:00" level=debug msg="开始处理上游请求" domain=pool.ntp.org type=A
time="2026-04-05T02:12:19+08:00" level=debug msg="使用用户配置的上游DNS服务器" servers="[10.35.10.200 106.14.121.141]"
time="2026-04-05T02:12:19+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=pool.ntp.org. queryTimeout 配置=5
time="2026-04-05T02:12:19+08:00" level=debug msg="上游请求返回" domain=pool.ntp.org response=false rtt=0s
time="2026-04-05T02:12:19+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=pool.ntp.org
time="2026-04-05T02:12:19+08:00" level=debug msg="准备添加查询日志" domain=pool.ntp.org responseCode=0 result=error
time="2026-04-05T02:12:19+08:00" level=debug msg="查询日志已添加" domain=pool.ntp.org
time="2026-04-05T02:12:19+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:34559" domain=pool.ntp.org.amazehome.xyz type=AAAA
time="2026-04-05T02:12:19+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:34559" domain=pool.ntp.org.amazehome.xyz type=A
time="2026-04-05T02:12:19+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=pool.ntp.org.amazehome.xyz
time="2026-04-05T02:12:19+08:00" level=debug msg="从缓存返回DNS响应" dnssec=false domain=pool.ntp.org.amazehome.xyz type=A
time="2026-04-05T02:12:19+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:64381" domain=edge.microsoft.com type=A
time="2026-04-05T02:12:19+08:00" level=debug msg="威胁检测引擎检查域名" domain=edge.microsoft.com sourceIP=10.35.10.78
time="2026-04-05T02:12:19+08:00" level=debug msg="开始处理上游请求" domain=edge.microsoft.com type=A
time="2026-04-05T02:12:19+08:00" level=debug msg="域名匹配到特定DNS服务器配置" dnsServers="[10.35.10.200:53]" domain=edge.microsoft.com matchStr=microsoft.com
time="2026-04-05T02:12:19+08:00" level=debug msg="并行查询超时设置" defaultTimeout=5ms domain=edge.microsoft.com. queryTimeout 配置=5
time="2026-04-05T02:12:19+08:00" level=debug msg="上游请求返回" domain=edge.microsoft.com response=false rtt=0s
time="2026-04-05T02:12:19+08:00" level=debug msg="上游 DNS 查询失败,返回 SERVFAIL" domain=edge.microsoft.com
time="2026-04-05T02:12:19+08:00" level=debug msg="准备添加查询日志" domain=edge.microsoft.com responseCode=0 result=error
time="2026-04-05T02:12:19+08:00" level=debug msg="查询日志已添加" domain=edge.microsoft.com
time="2026-04-05T02:12:20+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:53046" domain=log.zijieapi.com type=A
time="2026-04-05T02:12:20+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:53046" domain=log.zijieapi.com
time="2026-04-05T02:12:20+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:53046" domain=log.zijieapi.com type=A
time="2026-04-05T02:12:20+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:53046" domain=log.zijieapi.com
time="2026-04-05T02:12:20+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:41090" domain=www.baidu.com type=A
time="2026-04-05T02:12:20+08:00" level=debug msg="从缓存返回DNS响应" dnssec=false domain=www.baidu.com type=A
time="2026-04-05T02:12:20+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:41090" domain=www.baidu.com type=AAAA
time="2026-04-05T02:12:20+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=www.baidu.com
time="2026-04-05T02:12:22+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:45794" domain=o1098464.ingest.sentry.io type=AAAA
time="2026-04-05T02:12:22+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:54463" domain=o1098464.ingest.sentry.io type=A
time="2026-04-05T02:12:22+08:00" level=info msg="域名被屏蔽" client="10.35.10.70:54463" domain=o1098464.ingest.sentry.io
time="2026-04-05T02:12:22+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=o1098464.ingest.sentry.io
time="2026-04-05T02:12:23+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:56464" domain=www.baidu.com type=AAAA
time="2026-04-05T02:12:23+08:00" level=debug msg="IPv6解析已禁用,返回空的成功响应" domain=www.baidu.com
time="2026-04-05T02:12:23+08:00" level=debug msg="接收到DNS查询" client="10.35.10.70:56464" domain=www.baidu.com type=A
time="2026-04-05T02:12:23+08:00" level=debug msg="从缓存返回DNS响应" dnssec=false domain=www.baidu.com type=A
time="2026-04-05T02:12:23+08:00" level=info msg="正在关闭服务..."
time="2026-04-05T02:12:23+08:00" level=info msg="停止监听威胁域名数据库文件"
time="2026-04-05T02:12:23+08:00" level=info msg="统计数据保存成功" file=/root/dnsbeta2/data/stats.json
time="2026-04-05T02:12:23+08:00" level=info msg="DNS服务器已停止"
time="2026-04-05T02:12:23+08:00" level=error msg="HTTP控制台服务器启动失败" error="http: Server closed"
time="2026-04-05T02:12:23+08:00" level=info msg="HTTP控制台服务器已停止"
time="2026-04-05T02:12:23+08:00" level=info msg="Shield计数数据保存成功" blocked_entries=0 file=/root/dnsbeta2/data/shield_stats.json resolved_entries=0
time="2026-04-05T02:12:23+08:00" level=info msg="规则自动更新已停止"
time="2026-04-05T02:12:23+08:00" level=info msg="服务已关闭"
time="2026-04-05T02:12:23+08:00" level=warning msg="日志系统已关闭"
-23
View File
@@ -1,23 +0,0 @@
#!/bin/bash
echo "=== 域名清理进度监控 ==="
while true; do
if [ -f /root/dns/static/domain-info/threats/threats-removed.csv ]; then
removed=$(wc -l < /root/dns/static/domain-info/threats/threats-removed.csv)
removed=$((removed - 1))
else
removed=0
fi
if [ -f /root/dns/static/domain-info/threats/threats-database-cleaned.csv ]; then
kept=$(wc -l < /root/dns/static/domain-info/threats/threats-database-cleaned.csv)
kept=$((kept - 1))
else
kept=0
fi
total=$((removed + kept))
progress=$(echo "scale=2; $total * 100 / 89941" | bc)
echo "$(date '+%Y-%m-%d %H:%M:%S') - 已检查:$total/89941 ($progress%) | 移除:$removed | 保留:$kept"
sleep 60
done
+756
View File
@@ -0,0 +1,756 @@
package shield
import (
"context"
"crypto/sha256"
"encoding/csv"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"os"
"path/filepath"
"strings"
"sync"
"time"
"dns-server/config"
"dns-server/logger"
)
type DomainInfoManager struct {
config *config.DomainInfoConfig
domainInfoMap map[string]map[string]interface{}
threatDatabase map[string]map[string]string
trackerMap map[string]map[string]interface{}
mutex sync.RWMutex
updateCtx context.Context
updateCancel context.CancelFunc
updateRunning bool
updateStatus map[string]string
lastUpdateTime time.Time
updateInterval time.Duration
cacheDir string
statsFile string
}
type DomainInfo struct {
Domain string `json:"domain"`
Category string `json:"category"`
Type string `json:"type"`
RiskLevel int `json:"riskLevel"`
Info map[string]interface{} `json:"info,omitempty"`
}
type ThreatInfo struct {
Type string `json:"type"`
Name string `json:"name"`
RiskLevel int `json:"riskLevel"`
Domain string `json:"domain"`
}
type TrackerInfo struct {
Domain string `json:"domain"`
Category string `json:"category"`
Tracker string `json:"tracker"`
Info map[string]interface{} `json:"info,omitempty"`
}
func NewDomainInfoManager(config *config.DomainInfoConfig) *DomainInfoManager {
ctx, cancel := context.WithCancel(context.Background())
manager := &DomainInfoManager{
config: config,
domainInfoMap: make(map[string]map[string]interface{}),
threatDatabase: make(map[string]map[string]string),
trackerMap: make(map[string]map[string]interface{}),
updateCtx: ctx,
updateCancel: cancel,
updateRunning: false,
updateStatus: make(map[string]string),
updateInterval: time.Duration(config.UpdateInterval) * time.Second,
cacheDir: "data/domain_info_cache",
statsFile: "data/domain_info_stats.json",
}
if err := os.MkdirAll(manager.cacheDir, 0755); err != nil {
logger.Error("创建域名信息缓存目录失败", "error", err)
}
return manager
}
func (m *DomainInfoManager) Start() {
logger.Info("启动域名信息管理器")
// 异步加载缓存和初始数据
go func() {
// 先加载统计信息
if err := m.loadStats(); err != nil {
logger.Info("未找到域名信息统计文件,将使用默认值")
}
m.loadFromCache()
// 启动自动更新循环
if m.config.EnableAutoUpdate {
go m.autoUpdateLoop()
}
}()
}
func (m *DomainInfoManager) Stop() {
logger.Info("停止域名信息管理器")
m.updateCancel()
}
func (m *DomainInfoManager) autoUpdateLoop() {
ticker := time.NewTicker(m.updateInterval)
defer ticker.Stop()
for {
select {
case <-m.updateCtx.Done():
return
case <-ticker.C:
logger.Info("开始自动更新域名信息")
if err := m.LoadDomainInfo(); err != nil {
logger.Error("自动更新域名信息失败", "error", err)
}
}
}
}
func (m *DomainInfoManager) LoadDomainInfo() error {
// 检查是否有更新正在运行
m.mutex.Lock()
if m.updateRunning {
m.mutex.Unlock()
logger.Info("域名信息正在更新中,跳过")
return nil
}
m.updateRunning = true
m.updateStatus["overall"] = "running"
m.mutex.Unlock()
defer func() {
m.mutex.Lock()
m.updateRunning = false
m.updateStatus["overall"] = "completed"
m.mutex.Unlock()
}()
var wg sync.WaitGroup
errChan := make(chan error, 3)
for _, entry := range m.config.DomainInfoLists {
if !entry.Enabled {
continue
}
wg.Add(1)
go func(entry config.DomainInfoEntry) {
defer wg.Done()
// 更新状态为开始
m.mutex.Lock()
m.updateStatus[entry.Type] = "running"
m.mutex.Unlock()
var err error
switch entry.Type {
case "domain-info":
err = m.fetchRemoteDomainInfo(entry.URL)
case "threat-database":
err = m.fetchThreatDatabase(entry.URL)
case "tracker":
err = m.fetchTrackerInfo(entry.URL)
default:
logger.Warn("未知的域名信息类型", "type", entry.Type)
}
// 更新状态为完成或失败
m.mutex.Lock()
if err != nil {
m.updateStatus[entry.Type] = "failed"
errChan <- fmt.Errorf("更新 %s 失败: %v", entry.Name, err)
} else {
m.updateStatus[entry.Type] = "completed"
}
m.mutex.Unlock()
}(entry)
}
wg.Wait()
close(errChan)
var errors []string
for err := range errChan {
errors = append(errors, err.Error())
}
m.mutex.Lock()
if len(errors) > 0 {
m.lastUpdateTime = time.Now()
m.saveToCache()
m.mutex.Unlock()
return fmt.Errorf("更新过程中有错误: %s", strings.Join(errors, "; "))
}
m.lastUpdateTime = time.Now()
m.saveToCache()
m.mutex.Unlock()
logger.Info("域名信息更新完成",
"domainInfoCount", len(m.domainInfoMap),
"threatCount", len(m.threatDatabase),
"trackerCount", len(m.trackerMap))
return nil
}
func (m *DomainInfoManager) fetchRemoteDomainInfo(url string) error {
data, err := m.fetchRemoteData(url)
if err != nil {
return err
}
var domainInfoData map[string]interface{}
if err := json.Unmarshal(data, &domainInfoData); err != nil {
return fmt.Errorf("解析域名信息 JSON 失败: %v", err)
}
m.mutex.Lock()
defer m.mutex.Unlock()
// 清空现有数据
m.domainInfoMap = make(map[string]map[string]interface{})
// 处理嵌套的domains结构
if domains, ok := domainInfoData["domains"].(map[string]interface{}); ok {
for company, services := range domains {
if servicesMap, ok := services.(map[string]interface{}); ok {
for serviceName, serviceInfo := range servicesMap {
if infoMap, ok := serviceInfo.(map[string]interface{}); ok {
// 提取域名信息
if urlStr, ok := infoMap["url"].(string); ok {
// 从URL中提取域名
domain := m.extractDomainFromURL(urlStr)
if domain != "" {
// 添加公司和服务信息
infoMap["company"] = company
infoMap["service"] = serviceName
m.domainInfoMap[domain] = infoMap
}
}
}
}
}
}
}
logger.Info("加载域名信息", "count", len(m.domainInfoMap), "url", url)
return nil
}
func (m *DomainInfoManager) fetchThreatDatabase(url string) error {
data, err := m.fetchRemoteData(url)
if err != nil {
return err
}
reader := csv.NewReader(strings.NewReader(string(data)))
records, err := reader.ReadAll()
if err != nil {
return fmt.Errorf("解析威胁数据库 CSV 失败: %v", err)
}
m.mutex.Lock()
defer m.mutex.Unlock()
for i, record := range records {
if i == 0 || len(record) < 4 {
continue
}
domain := strings.TrimSpace(record[3])
if domain == "" {
continue
}
m.threatDatabase[domain] = map[string]string{
"type": strings.TrimSpace(record[0]),
"name": strings.TrimSpace(record[1]),
"riskLevel": strings.TrimSpace(record[2]),
"domain": domain,
}
}
logger.Info("加载威胁数据库", "count", len(m.threatDatabase), "url", url)
return nil
}
func (m *DomainInfoManager) fetchTrackerInfo(url string) error {
data, err := m.fetchRemoteData(url)
if err != nil {
return err
}
var trackerData map[string]interface{}
if err := json.Unmarshal(data, &trackerData); err != nil {
return fmt.Errorf("解析跟踪器信息 JSON 失败: %v", err)
}
m.mutex.Lock()
defer m.mutex.Unlock()
// 清空现有数据
m.trackerMap = make(map[string]map[string]interface{})
// 处理trackers字段
if trackers, ok := trackerData["trackers"].(map[string]interface{}); ok {
for domain, info := range trackers {
if infoMap, ok := info.(map[string]interface{}); ok {
m.trackerMap[domain] = infoMap
}
}
}
// 处理trackerDomains字段
if trackerDomains, ok := trackerData["trackerDomains"].(map[string]interface{}); ok {
for trackerName, domains := range trackerDomains {
if domainsList, ok := domains.([]interface{}); ok {
for _, domain := range domainsList {
if domainStr, ok := domain.(string); ok {
// 为每个域名创建跟踪器信息
if _, exists := m.trackerMap[domainStr]; !exists {
m.trackerMap[domainStr] = map[string]interface{}{
"tracker": trackerName,
"domain": domainStr,
}
}
}
}
}
}
}
logger.Info("加载跟踪器信息", "count", len(m.trackerMap), "url", url)
return nil
}
func (m *DomainInfoManager) fetchRemoteData(url string) ([]byte, error) {
cacheFile := m.getCacheFilePath(url)
if m.shouldUpdateCache(cacheFile) {
resp, err := http.Get(url)
if err != nil {
logger.Warn("从远程获取数据失败,尝试使用缓存", "url", url, "error", err)
return m.loadFromCacheFile(cacheFile)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("HTTP 状态码: %d", resp.StatusCode)
}
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("读取响应失败: %v", err)
}
if err := ioutil.WriteFile(cacheFile, data, 0644); err != nil {
logger.Warn("保存缓存文件失败", "error", err)
}
return data, nil
}
return m.loadFromCacheFile(cacheFile)
}
func (m *DomainInfoManager) getCacheFilePath(url string) string {
hash := fmt.Sprintf("%x", sha256.Sum256([]byte(url)))
return filepath.Join(m.cacheDir, hash+".cache")
}
func (m *DomainInfoManager) shouldUpdateCache(cacheFile string) bool {
if _, err := os.Stat(cacheFile); os.IsNotExist(err) {
return true
}
fileInfo, err := os.Stat(cacheFile)
if err != nil {
return true
}
return time.Since(fileInfo.ModTime()) > m.updateInterval
}
func (m *DomainInfoManager) loadFromCacheFile(cacheFile string) ([]byte, error) {
data, err := ioutil.ReadFile(cacheFile)
if err != nil {
return nil, err
}
return data, nil
}
func (m *DomainInfoManager) saveToCache() {
data := map[string]interface{}{
"domainInfoMap": m.domainInfoMap,
"threatDatabase": m.threatDatabase,
"trackerMap": m.trackerMap,
"lastUpdateTime": m.lastUpdateTime,
}
jsonData, err := json.Marshal(data)
if err != nil {
logger.Error("序列化域名信息缓存失败", "error", err)
return
}
cacheFile := filepath.Join(m.cacheDir, "all_domain_info.json")
if err := ioutil.WriteFile(cacheFile, jsonData, 0644); err != nil {
logger.Error("保存域名信息缓存失败", "error", err)
}
// 同时保存统计信息
m.saveStats()
}
func (m *DomainInfoManager) loadFromCache() {
cacheFile := filepath.Join(m.cacheDir, "all_domain_info.json")
data, err := ioutil.ReadFile(cacheFile)
if err != nil {
logger.Info("未找到域名信息缓存,将从远程加载")
if err := m.LoadDomainInfo(); err != nil {
logger.Error("初始加载域名信息失败", "error", err)
}
return
}
var cacheData map[string]interface{}
if err := json.Unmarshal(data, &cacheData); err != nil {
logger.Error("解析域名信息缓存失败", "error", err)
return
}
if domainInfoMap, ok := cacheData["domainInfoMap"].(map[string]interface{}); ok {
for k, v := range domainInfoMap {
if vm, ok := v.(map[string]interface{}); ok {
m.domainInfoMap[k] = vm
}
}
}
if threatDatabase, ok := cacheData["threatDatabase"].(map[string]interface{}); ok {
for k, v := range threatDatabase {
if vm, ok := v.(map[string]interface{}); ok {
strMap := make(map[string]string)
for kk, vv := range vm {
if vs, ok := vv.(string); ok {
strMap[kk] = vs
}
}
m.threatDatabase[k] = strMap
}
}
}
if trackerMap, ok := cacheData["trackerMap"].(map[string]interface{}); ok {
for k, v := range trackerMap {
if vm, ok := v.(map[string]interface{}); ok {
m.trackerMap[k] = vm
}
}
}
logger.Info("从缓存加载域名信息完成",
"domainInfoCount", len(m.domainInfoMap),
"threatCount", len(m.threatDatabase),
"trackerCount", len(m.trackerMap))
// 从缓存加载后也保存统计信息
m.saveStats()
}
func (m *DomainInfoManager) GetDomainInfo(domain string) map[string]interface{} {
m.mutex.RLock()
defer m.mutex.RUnlock()
if info, ok := m.domainInfoMap[domain]; ok {
return info
}
return nil
}
func (m *DomainInfoManager) GetThreatInfo(domain string) map[string]string {
m.mutex.RLock()
defer m.mutex.RUnlock()
if info, ok := m.threatDatabase[domain]; ok {
return info
}
return nil
}
func (m *DomainInfoManager) GetTrackerInfo(domain string) map[string]interface{} {
m.mutex.RLock()
defer m.mutex.RUnlock()
if info, ok := m.trackerMap[domain]; ok {
return info
}
return nil
}
// extractDomainFromURL 从URL中提取域名
func (m *DomainInfoManager) extractDomainFromURL(urlStr string) string {
// 解析URL
parsedURL, err := url.Parse(urlStr)
if err != nil {
return ""
}
// 返回主机名
return parsedURL.Hostname()
}
func (m *DomainInfoManager) GetAllDomainInfo() map[string]interface{} {
// 获取当前统计(只读锁)
m.mutex.RLock()
domainInfoCount := len(m.domainInfoMap)
threatCount := len(m.threatDatabase)
trackerCount := len(m.trackerMap)
lastUpdateTime := m.lastUpdateTime
m.mutex.RUnlock()
lastUpdateTimeStr := "从未更新"
if !lastUpdateTime.IsZero() {
lastUpdateTimeStr = lastUpdateTime.Format(time.RFC3339)
}
// 直接返回配置中的列表,并添加统计信息
var lists []config.DomainInfoEntry
if m.config != nil {
lists = make([]config.DomainInfoEntry, len(m.config.DomainInfoLists))
copy(lists, m.config.DomainInfoLists)
// 为每个列表添加规则数量
for i := range lists {
switch lists[i].Type {
case "domain-info":
lists[i].RuleCount = domainInfoCount
case "threat-database":
lists[i].RuleCount = threatCount
case "tracker":
lists[i].RuleCount = trackerCount
}
if !lastUpdateTime.IsZero() {
lists[i].LastUpdateTime = lastUpdateTimeStr
}
}
} else {
lists = []config.DomainInfoEntry{}
}
return map[string]interface{}{
"lists": lists,
"domainInfoCount": domainInfoCount,
"threatCount": threatCount,
"trackerCount": trackerCount,
"lastUpdateTime": lastUpdateTimeStr,
}
}
func (m *DomainInfoManager) getRuleCount(entryType string) int {
switch entryType {
case "domain-info":
return len(m.domainInfoMap)
case "threat-database":
return len(m.threatDatabase)
case "tracker":
return len(m.trackerMap)
}
return 0
}
func (m *DomainInfoManager) UpdateDomainInfoList(entryType string) error {
for _, entry := range m.config.DomainInfoLists {
if entry.Type != entryType {
continue
}
m.mutex.Lock()
switch entryType {
case "domain-info":
m.domainInfoMap = make(map[string]map[string]interface{})
case "threat-database":
m.threatDatabase = make(map[string]map[string]string)
case "tracker":
m.trackerMap = make(map[string]map[string]interface{})
}
m.mutex.Unlock()
switch entryType {
case "domain-info":
return m.fetchRemoteDomainInfo(entry.URL)
case "threat-database":
return m.fetchThreatDatabase(entry.URL)
case "tracker":
return m.fetchTrackerInfo(entry.URL)
}
}
return fmt.Errorf("未找到类型为 %s 的域名信息配置", entryType)
}
func (m *DomainInfoManager) AddDomainInfoList(entry config.DomainInfoEntry) error {
m.config.DomainInfoLists = append(m.config.DomainInfoLists, entry)
return nil
}
func (m *DomainInfoManager) RemoveDomainInfoList(entryType string) error {
var newLists []config.DomainInfoEntry
for _, entry := range m.config.DomainInfoLists {
if entry.Type != entryType {
newLists = append(newLists, entry)
}
}
m.config.DomainInfoLists = newLists
m.mutex.Lock()
switch entryType {
case "domain-info":
m.domainInfoMap = make(map[string]map[string]interface{})
case "threat-database":
m.threatDatabase = make(map[string]map[string]string)
case "tracker":
m.trackerMap = make(map[string]map[string]interface{})
}
m.mutex.Unlock()
m.saveToCache()
return nil
}
// GetUpdateStatus 获取更新状态
func (m *DomainInfoManager) GetUpdateStatus() map[string]string {
m.mutex.RLock()
defer m.mutex.RUnlock()
// 复制状态以避免并发修改
status := make(map[string]string)
for k, v := range m.updateStatus {
status[k] = v
}
return status
}
// DomainInfoStats 域名信息统计
type DomainInfoStats struct {
DomainInfoCount int `json:"domainInfoCount"`
ThreatCount int `json:"threatCount"`
TrackerCount int `json:"trackerCount"`
LastUpdateTime string `json:"lastUpdateTime"`
Lists []struct {
Name string `json:"name"`
Type string `json:"type"`
URL string `json:"url"`
Enabled bool `json:"enabled"`
RuleCount int `json:"ruleCount"`
LastUpdateTime string `json:"lastUpdateTime"`
} `json:"lists"`
}
// saveStats 保存统计信息到文件
func (m *DomainInfoManager) saveStats() {
m.mutex.RLock()
defer m.mutex.RUnlock()
stats := DomainInfoStats{
DomainInfoCount: len(m.domainInfoMap),
ThreatCount: len(m.threatDatabase),
TrackerCount: len(m.trackerMap),
}
if !m.lastUpdateTime.IsZero() {
stats.LastUpdateTime = m.lastUpdateTime.Format(time.RFC3339)
}
for _, entry := range m.config.DomainInfoLists {
listStat := struct {
Name string `json:"name"`
Type string `json:"type"`
URL string `json:"url"`
Enabled bool `json:"enabled"`
RuleCount int `json:"ruleCount"`
LastUpdateTime string `json:"lastUpdateTime"`
}{
Name: entry.Name,
Type: entry.Type,
URL: entry.URL,
Enabled: entry.Enabled,
}
switch entry.Type {
case "domain-info":
listStat.RuleCount = len(m.domainInfoMap)
case "threat-database":
listStat.RuleCount = len(m.threatDatabase)
case "tracker":
listStat.RuleCount = len(m.trackerMap)
}
if !m.lastUpdateTime.IsZero() {
listStat.LastUpdateTime = m.lastUpdateTime.Format(time.RFC3339)
}
stats.Lists = append(stats.Lists, listStat)
}
jsonData, err := json.MarshalIndent(stats, "", " ")
if err != nil {
logger.Error("序列化域名信息统计失败", "error", err)
return
}
if err := ioutil.WriteFile(m.statsFile, jsonData, 0644); err != nil {
logger.Error("保存域名信息统计失败", "error", err)
}
}
// loadStats 从文件加载统计信息
func (m *DomainInfoManager) loadStats() error {
data, err := ioutil.ReadFile(m.statsFile)
if err != nil {
return err
}
var stats DomainInfoStats
if err := json.Unmarshal(data, &stats); err != nil {
return err
}
// 更新配置中的统计信息
for i := range m.config.DomainInfoLists {
for _, listStat := range stats.Lists {
if m.config.DomainInfoLists[i].Type == listStat.Type {
m.config.DomainInfoLists[i].RuleCount = listStat.RuleCount
m.config.DomainInfoLists[i].LastUpdateTime = listStat.LastUpdateTime
break
}
}
}
return nil
}
-176
View File
@@ -1,176 +0,0 @@
#!/bin/bash
# 启动/停止/重启脚本
# ===================== 配置区 =====================
# 程序路径
AGENT_PATH="./dns-server"
# 日志文件路径
LOG_FILE="./server.log"
# PID文件路径(记录进程ID
PID_FILE="./server.pid"
# 启动参数(根据实际需求调整)
START_ARGS=""
# 工作目录
WORK_DIR="."
# ==================== 配置区结束 ====================
# 检查程序文件是否存在
check_agent_exists() {
if [ ! -f "${AGENT_PATH}" ]; then
echo "错误:程序文件 ${AGENT_PATH} 不存在!"
exit 1
fi
if [ ! -x "${AGENT_PATH}" ]; then
echo "错误:程序文件 ${AGENT_PATH} 没有执行权限,正在尝试添加..."
chmod +x "${AGENT_PATH}"
if [ $? -ne 0 ]; then
echo "错误:添加执行权限失败,请手动执行 chmod +x ${AGENT_PATH}"
exit 1
fi
fi
}
# 检查进程是否运行
check_running() {
if [ -f "${PID_FILE}" ]; then
PID=$(cat "${PID_FILE}")
if ps -p "${PID}" > /dev/null 2>&1; then
return 0 # 运行中
else
rm -f "${PID_FILE}" # PID文件存在但进程已死,清理PID文件
fi
fi
return 1 # 未运行
}
# 启动程序
start_agent() {
if check_running; then
echo "✅ dns-server 已在运行(PID: $(cat ${PID_FILE})"
return 0
fi
echo "🚀 正在启动 dns-server(工作目录:${WORK_DIR}..."
# 新增:检查并切换工作目录
if [ ! -d "${WORK_DIR}" ]; then
echo "⚠️ 工作目录 ${WORK_DIR} 不存在,正在创建..."
mkdir -p "${WORK_DIR}"
if [ $? -ne 0 ]; then
echo "❌ 创建工作目录 ${WORK_DIR} 失败!"
exit 1
fi
fi
# 切换到工作目录(关键:程序将在此目录下运行)
cd "${WORK_DIR}" || {
echo "❌ 切换到工作目录 ${WORK_DIR} 失败!"
exit 1
}
# 创建日志目录
mkdir -p "$(dirname ${LOG_FILE})"
# 后台启动程序(注意:cd仅影响当前子进程,需在同一行执行)
nohup "${AGENT_PATH}" ${START_ARGS} > "${LOG_FILE}" 2>&1 &
AGENT_PID=$!
echo "${AGENT_PID}" > "${PID_FILE}"
# 等待检查启动状态
sleep 2
if check_running; then
echo "✅ dns-server 启动成功(PID: ${AGENT_PID},工作目录:${WORK_DIR}"
echo "日志文件:${LOG_FILE}"
else
echo "❌ dns-server 启动失败!请查看日志:${LOG_FILE}"
rm -f "${PID_FILE}"
exit 1
fi
}
# 停止程序
stop_agent() {
if ! check_running; then
echo "️ dns-server 未运行"
return 0
fi
PID=$(cat "${PID_FILE}")
echo "🛑 正在停止 dns-serverPID: ${PID}..."
# 优雅停止(先尝试TERM信号,失败则强制KILL)
kill "${PID}" > /dev/null 2>&1
sleep 3
if ps -p "${PID}" > /dev/null 2>&1; then
echo "⚠️ 优雅停止失败,强制杀死进程..."
kill -9 "${PID}" > /dev/null 2>&1
sleep 1
fi
# 清理PID文件
rm -f "${PID_FILE}"
echo "✅ dns-server 已停止"
}
# 查看状态
status_agent() {
if check_running; then
echo "✅ dns-server 运行中(PID: $(cat ${PID_FILE})"
else
echo "️ dns-server 未运行"
fi
}
# 重启程序
restart_agent() {
echo "🔄 正在重启 dns-server..."
stop_agent
sleep 2
start_agent
}
# 帮助信息
show_help() {
echo "使用方法:$0 [start|stop|restart|status|help]"
echo " start - 启动 dns-server"
echo " stop - 停止 dns-server"
echo " restart - 重启 dns-server"
echo " status - 查看 dns-server 运行状态"
echo " help - 显示帮助信息"
}
# 主逻辑
main() {
# 检查是否为root用户(可选,根据需求调整)
if [ "$(id -u)" -ne 0 ]; then
echo "警告:建议使用root用户运行此脚本(当前用户:$(whoami)"
# exit 1 # 如果强制要求root,取消注释
fi
check_agent_exists
case "$1" in
start)
start_agent
;;
stop)
stop_agent
;;
restart)
restart_agent
;;
status)
status_agent
;;
help|--help|-h)
show_help
;;
*)
echo "错误:无效参数 '$1'"
show_help
exit 1
;;
esac
}
# 执行主逻辑
main "$@"
+103
View File
@@ -0,0 +1,103 @@
[dns]
port = 53
upstreamDNS = 10.35.10.200
dnssecUpstreamDNS = 208.67.220.220, 208.67.222.222
saveInterval = 10
cacheTTL = 10
enableDNSSEC = false
queryMode = parallel
queryTimeout = 5000
enableFastReturn = true
noDNSSECDomains = amazehome.cn, addr.arpa, amazehome.xyz, .cn
enableIPv6 = false
cacheMode = file
cacheSize = 100
maxCacheTTL = 30
minCacheTTL = 5
domain_akamai = 10.35.10.200:53
domain_amazehome.cn = 10.35.10.200:53
domain_amazehome.xyz = 10.35.10.200:53
domain_microsoft.com = 10.35.10.200:53
domain_addr.arpa = 10.35.10.200:53
domain_akadns = 10.35.10.200:53
[http]
port = 8081
host = 0.0.0.0
enableAPI = true
username = admin
password = admin
[shield]
updateInterval = 3600
blockMethod = NXDOMAIN
customBlockIP = 0.0.0.2
statsSaveInterval = 60
blacklist_AdGuard_DNS_filter = https://gitea.amazehome.xyz/AMAZEHOME/hosts-and-filters/raw/branch/main/filter.txt,true
blacklist_Adaway_Default_Blocklist = https://gitea.amazehome.xyz/AMAZEHOME/hosts-and-Filters/raw/branch/main/hosts/adaway.txt,true
blacklist_CHN_anti_AD = https://gitea.amazehome.xyz/AMAZEHOME/hosts-and-Filters/raw/branch/main/list/easylist.txt,true
blacklist_My_GitHub_Rules = https://gitea.amazehome.xyz/AMAZEHOME/hosts-and-filters/raw/branch/main/rules/costomize.txt,true
blacklist_CNList = https://gitea.amazehome.xyz/AMAZEHOME/hosts-and-filters/raw/branch/main/list/china.list,false
blacklist_大圣净化 = http://gitea.amazehome.xyz/AMAZEHOME/hosts-and-Filters/raw/branch/main/hosts/dsjh.txt,true
blacklist_Hate_and_Junk = http://gitea.amazehome.xyz/AMAZEHOME/hosts-and-filters/raw/branch/main/hate-and-junk-extended.txt,true
blacklist_My_Gitlab_Hosts = http://gitea.amazehome.xyz/AMAZEHOME/hosts-and-filters/raw/branch/main/hosts/costomize.txt,true
blacklist_Anti_Remote_Requests = http://gitea.amazehome.xyz/AMAZEHOME/hosts-and-filters/raw/branch/main/hosts/anti-remoterequests.txt,true
blacklist_URL_Based = http://gitea.amazehome.xyz/AMAZEHOME/hosts-and-filters/raw/branch/main/rules/url-based-adguard.txt,true
blacklist_My_Gitlab_A_T_Rules = http://gitea.amazehome.xyz/AMAZEHOME/hosts-and-filters/raw/branch/main/rules/ads-and-trackers.txt,true
blacklist_My_Gitlab_Malware_List = http://gitea.amazehome.xyz/AMAZEHOME/hosts-and-filters/raw/branch/main/rules/malware.txt,true
blacklist_hosts = http://gitea.amazehome.xyz/AMAZEHOME/hosts-and-Filters/raw/branch/main/hosts/costomize.txt,true
blacklist_AWAvenue_Ads_Rule = http://gitea.amazehome.xyz/AMAZEHOME/hosts-and-Filters/raw/branch/main/rules/AWAvenue-Ads-Rule.txt,true
blacklist_诈骗域名 = https://gitea.amazehome.xyz/AMAZEHOME/hosts-and-filters/raw/branch/main/rules/cheat.txt,true
[domainInfo]
updateInterval = 3600
enableAutoUpdate = true
domainInfo_域名信息列表 = https://gitea.amazehome.xyz/AMAZEHOME/domain-info/raw/branch/main/domains/domain-info.json,domain-info,true
domainInfo_威胁数据库 = https://gitea.amazehome.xyz/AMAZEHOME/domain-info/src/branch/main/threats/threats-database.csv,threat-database,true
domainInfo_跟踪器列表 = https://gitea.amazehome.xyz/AMAZEHOME/domain-info/raw/branch/main/tracker/trackers.json,tracker,true
[gfwList]
ip = 127.0.0.1
content =
enabled = false
[log]
level = debug
maxSize = 100
maxBackups = 10
maxAge = 30
[queryLog]
# 基本配置
enabled = true
ringBufferSize = 10000
# SQLite 主库配置
databasePath = data/query_logs.db
maxDatabaseSizeMB = 1024
enableWAL = true
# 归档配置
archiveEnabled = true
archiveDir = data/archive
archivePrefix = querylog
compressionLevel = 6
# 清理配置
retentionDays = 0
retentionMonths = 0
# 查询配置
queryTimeout = 5
enableCache = true
cacheTTL = 300
[threat]
enabled = true
queryRateThreshold = 0
nxDomainThreshold = 0
maxDomainLength = 0
suspiciousPatterns = malware,phishing,trojan,virus,ransomware
unusualQueryTypes = TXT,SRV,MX
alertRetentionDays = 0
threatDatabasePath = ./static/domain-info/threats/threats-database.csv
BIN
View File
Binary file not shown.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+173 -4
View File
@@ -47,6 +47,13 @@
<span>屏蔽管理</span>
</a>
</li>
<li>
<a href="#domain-info"
class="flex items-center px-4 py-3 text-gray-700 hover:bg-gray-100 rounded-md transition-all">
<i class="fa fa-database mr-3 text-lg"></i>
<span>域名信息管理</span>
</a>
</li>
<li>
<a href="#hosts"
class="flex items-center px-4 py-3 text-gray-700 hover:bg-gray-100 rounded-md transition-all">
@@ -146,6 +153,13 @@
<span>屏蔽管理</span>
</a>
</li>
<li>
<a href="#domain-info"
class="flex items-center px-4 py-3 text-gray-700 hover:bg-gray-100 rounded-md transition-all">
<i class="fa fa-database mr-3 text-lg"></i>
<span>域名信息管理</span>
</a>
</li>
<li>
<a href="#hosts"
class="flex items-center px-4 py-3 text-gray-700 hover:bg-gray-100 rounded-md transition-all">
@@ -730,6 +744,164 @@
<!-- 添加域名信息列表模态框 -->
<div id="add-domain-info-modal" class="fixed inset-0 bg-black/50 flex items-center justify-center z-50 hidden">
<div class="bg-white rounded-lg w-full max-w-md p-6">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-semibold">添加域名信息列表</h3>
<button onclick="window.domainInfo.hideAddListModal()"
class="p-2 rounded-full hover:bg-gray-100 transition-colors">
<i class="fa fa-times"></i>
</button>
</div>
<form id="add-domain-info-form">
<div class="space-y-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">名称</label>
<input type="text" id="list-name" required
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">URL</label>
<input type="url" id="list-url" required
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">类型</label>
<select id="list-type" required
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent">
<option value="domain-info">域名信息</option>
<option value="threat-database">威胁数据库</option>
<option value="tracker">跟踪器</option>
</select>
</div>
<div>
<label class="flex items-center space-x-2">
<input type="checkbox" id="list-enabled" checked
class="rounded border-gray-300 text-primary focus:ring-primary">
<span class="text-sm text-gray-700">启用</span>
</label>
</div>
</div>
<div class="mt-6 flex space-x-3">
<button type="button" onclick="window.domainInfo.hideAddListModal()"
class="px-4 py-2 border border-gray-300 rounded-md hover:bg-gray-50 transition-colors text-sm flex-1">
取消
</button>
<button type="submit"
class="px-4 py-2 bg-primary text-white rounded-md hover:bg-primary/90 transition-colors text-sm flex-1">
添加
</button>
</div>
</form>
</div>
</div>
<!-- 域名信息管理页面内容(初始隐藏) -->
<div id="domain-info-content" class="hidden space-y-6">
<!-- 域名信息统计卡片 -->
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4 sm:gap-6">
<!-- 域名信息数量卡片 -->
<div class="bg-blue-50 rounded-lg p-3 sm:p-4 card-shadow relative overflow-hidden transition-all hover:shadow-md">
<div class="absolute -bottom-6 -right-6 w-20 h-20 sm:w-24 sm:h-24 rounded-full bg-primary opacity-10"></div>
<div class="relative z-10">
<div class="flex items-center justify-between mb-3 sm:mb-4">
<h3 class="text-xs sm:text-sm text-gray-500 font-medium">域名信息数量</h3>
<div class="p-1.5 sm:p-2 rounded-full bg-primary/10 text-primary">
<i class="fa fa-database text-xs sm:text-sm"></i>
</div>
</div>
<div class="mb-2">
<div class="flex items-end justify-between">
<p class="text-2xl sm:text-3xl font-bold" id="domain-info-count">0</p>
</div>
</div>
</div>
</div>
<!-- 威胁域名数量卡片 -->
<div class="bg-red-50 rounded-lg p-3 sm:p-4 card-shadow relative overflow-hidden transition-all hover:shadow-md">
<div class="absolute -bottom-6 -right-6 w-20 h-20 sm:w-24 sm:h-24 rounded-full bg-danger opacity-10"></div>
<div class="relative z-10">
<div class="flex items-center justify-between mb-3 sm:mb-4">
<h3 class="text-xs sm:text-sm text-gray-500 font-medium">威胁域名数量</h3>
<div class="p-1.5 sm:p-2 rounded-full bg-danger/10 text-danger">
<i class="fa fa-exclamation-triangle text-xs sm:text-sm"></i>
</div>
</div>
<div class="mb-2">
<div class="flex items-end justify-between">
<p class="text-2xl sm:text-3xl font-bold" id="threat-count">0</p>
</div>
</div>
</div>
</div>
<!-- 跟踪器数量卡片 -->
<div class="bg-purple-50 rounded-lg p-3 sm:p-4 card-shadow relative overflow-hidden transition-all hover:shadow-md">
<div class="absolute -bottom-6 -right-6 w-20 h-20 sm:w-24 sm:h-24 rounded-full bg-purple-500 opacity-10"></div>
<div class="relative z-10">
<div class="flex items-center justify-between mb-3 sm:mb-4">
<h3 class="text-xs sm:text-sm text-gray-500 font-medium">跟踪器数量</h3>
<div class="p-1.5 sm:p-2 rounded-full bg-purple-500/10 text-purple-500">
<i class="fa fa-bullseye text-xs sm:text-sm"></i>
</div>
</div>
<div class="mb-2">
<div class="flex items-end justify-between">
<p class="text-2xl sm:text-3xl font-bold" id="tracker-count">0</p>
</div>
</div>
</div>
</div>
</div>
<!-- 域名信息列表管理 -->
<div class="bg-white rounded-lg p-4 sm:p-6 card-shadow">
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between mb-4 sm:mb-6">
<h3 class="text-base sm:text-lg font-semibold mb-3 sm:mb-0">远程域名信息列表</h3>
<div class="flex space-x-2 sm:space-x-3">
<button onclick="window.domainInfo.updateAllDomainInfo()"
class="px-3 sm:px-4 py-2 bg-primary text-white rounded-md hover:bg-primary/90 transition-colors text-sm flex items-center">
<i class="fa fa-refresh mr-2"></i>
更新所有列表
</button>
<button onclick="window.domainInfo.showAddListModal()"
class="px-3 sm:px-4 py-2 bg-green-500 text-white rounded-md hover:bg-green-600 transition-colors text-sm flex items-center">
<i class="fa fa-plus mr-2"></i>
添加列表
</button>
</div>
</div>
<!-- 最后更新时间 -->
<div class="mb-4 text-sm text-gray-500">
<i class="fa fa-clock-o mr-2"></i>
最后更新时间:<span id="last-update-time">从未更新</span>
</div>
<!-- 域名信息列表表格 -->
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th class="px-3 sm:px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">名称</th>
<th class="px-3 sm:px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">状态</th>
<th class="px-3 sm:px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">类型</th>
<th class="px-3 sm:px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">规则数量</th>
<th class="px-3 sm:px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">最后更新</th>
<th class="px-3 sm:px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">操作</th>
</tr>
</thead>
<tbody id="domain-info-lists-table-body" class="bg-white divide-y divide-gray-200">
<!-- 动态生成 -->
</tbody>
</table>
</div>
</div>
</div>
<!-- 威胁告警页面内容(初始隐藏) -->
<div id="threats-content" class="hidden space-y-6">
<!-- 威胁统计卡片 -->
@@ -2219,16 +2391,13 @@
<script src="js/api.js"></script>
<script src="js/dashboard.js"></script>
<script src="js/shield.js"></script>
<script src="js/modules/domain-info.js"></script>
<script src="js/hosts.js"></script>
<script src="js/query.js"></script>
<script src="js/logs.js"></script>
<script src="js/config.js"></script>
<script src="js/about.js"></script>
<!-- 直接渲染滚动列表的静态HTML内容 -->
<script src="js/whois.js"></script>
<!-- 威胁告警页面脚本 -->
<script src="js/threats.js"></script>
</body>
+374
View File
@@ -0,0 +1,374 @@
// 域名信息管理模块
// 用于管理远程域名信息列表的加载、更新和显示
(function() {
'use strict';
// 域名信息列表缓存
let domainInfoCache = null;
let cacheTimestamp = 0;
const CACHE_DURATION = 5 * 60 * 1000; // 5 分钟缓存
/**
* 加载域名信息列表
*/
function loadDomainInfoLists() {
const tbody = document.getElementById('domain-info-lists-table-body');
if (!tbody) {
console.warn('未找到域名信息列表表格元素');
return;
}
showLoading(tbody);
// 检查缓存
if (domainInfoCache && (Date.now() - cacheTimestamp) < CACHE_DURATION) {
console.log('使用缓存的域名信息列表');
renderDomainInfoLists(domainInfoCache);
return;
}
apiRequest('/api/domain-info')
.then(data => {
domainInfoCache = data;
cacheTimestamp = Date.now();
renderDomainInfoLists(data);
})
.catch(error => {
console.error('获取域名信息列表失败:', error);
showError(tbody, '获取域名信息列表失败');
window.showNotification('获取域名信息列表失败', 'error');
});
}
/**
* 渲染域名信息列表
*/
function renderDomainInfoLists(data) {
const tbody = document.getElementById('domain-info-lists-table-body');
if (!tbody) return;
tbody.innerHTML = '';
if (!data || !data.lists || data.lists.length === 0) {
const emptyRow = document.createElement('tr');
emptyRow.innerHTML = '<td colspan="6" class="py-4 text-center text-gray-500">暂无域名信息列表</td>';
tbody.appendChild(emptyRow);
return;
}
const fragment = document.createDocumentFragment();
data.lists.forEach((list, index) => {
const tr = document.createElement('tr');
tr.className = 'border-b border-gray-200 hover:bg-gray-50';
const typeLabel = getTypeLabel(list.type);
const statusClass = list.enabled ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-800';
const statusText = list.enabled ? '启用' : '禁用';
tr.innerHTML = `
<td class="py-3 px-4 font-medium">${escapeHtml(list.name)}</td>
<td class="py-3 px-4">
<span class="px-2 py-1 rounded-full text-xs font-medium ${statusClass}">${statusText}</span>
</td>
<td class="py-3 px-4">
<span class="px-2 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800">${typeLabel}</span>
</td>
<td class="py-3 px-4 text-center">${list.ruleCount || 0}</td>
<td class="py-3 px-4 text-sm text-gray-600">${formatLastUpdateTime(list.lastUpdateTime)}</td>
<td class="py-3 px-4 text-center">
<div class="flex space-x-2 justify-center">
<button onclick="window.domainInfo.updateDomainInfo('${list.type}')"
class="px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600 text-sm"
title="更新此列表">
更新
</button>
<button onclick="window.domainInfo.removeDomainInfo('${list.type}')"
class="px-3 py-1 bg-red-500 text-white rounded hover:bg-red-600 text-sm"
title="删除此列表">
删除
</button>
</div>
</td>
`;
fragment.appendChild(tr);
});
tbody.appendChild(fragment);
// 更新统计信息
updateDomainInfoStats(data);
}
/**
* 更新域名信息统计
*/
function updateDomainInfoStats(data) {
if (document.getElementById('domain-info-count')) {
document.getElementById('domain-info-count').textContent = data.domainInfoCount || 0;
}
if (document.getElementById('threat-count')) {
document.getElementById('threat-count').textContent = data.threatCount || 0;
}
if (document.getElementById('tracker-count')) {
document.getElementById('tracker-count').textContent = data.trackerCount || 0;
}
if (document.getElementById('last-update-time')) {
document.getElementById('last-update-time').textContent = formatLastUpdateTime(data.lastUpdateTime);
}
}
/**
* 更新域名信息
*/
function updateDomainInfo(type) {
const url = `/api/domain-info/update/${encodeURIComponent(type)}`;
apiRequest(url, 'POST')
.then(data => {
if (data.status === 'success') {
window.showNotification(`域名信息更新任务已启动:${getTypeLabel(type)}`, 'success');
// 延迟刷新列表
setTimeout(() => {
loadDomainInfoLists();
}, 2000);
} else {
window.showNotification(`更新失败:${data.message || '未知错误'}`, 'error');
}
})
.catch(error => {
console.error('更新域名信息失败:', error);
window.showNotification('更新域名信息失败', 'error');
});
}
/**
* 更新所有域名信息
*/
function updateAllDomainInfo() {
if (!confirm('确定要更新所有域名信息吗?这可能需要一些时间。')) {
return;
}
apiRequest('/api/domain-info/update', 'POST')
.then(data => {
if (data.status === 'success') {
window.showNotification('所有域名信息更新任务已启动', 'success');
setTimeout(() => {
loadDomainInfoLists();
}, 2000);
} else {
window.showNotification(`更新失败:${data.message || '未知错误'}`, 'error');
}
})
.catch(error => {
console.error('更新所有域名信息失败:', error);
window.showNotification('更新所有域名信息失败', 'error');
});
}
/**
* 获取类型标签
*/
function getTypeLabel(type) {
const labels = {
'domain-info': '域名信息',
'threat-database': '威胁数据库',
'tracker': '跟踪器'
};
return labels[type] || type;
}
/**
* 格式化最后更新时间
*/
function formatLastUpdateTime(timeStr) {
if (!timeStr) return '从未更新';
const date = new Date(timeStr);
const now = new Date();
const diff = now - date;
const minutes = Math.floor(diff / 60000);
const hours = Math.floor(diff / 3600000);
const days = Math.floor(diff / 86400000);
if (minutes < 1) return '刚刚';
if (minutes < 60) return `${minutes}分钟前`;
if (hours < 24) return `${hours}小时前`;
if (days < 30) return `${days}天前`;
return date.toLocaleDateString('zh-CN');
}
/**
* 显示加载状态
*/
function showLoading(container) {
container.innerHTML = `
<tr>
<td colspan="6" class="py-8 text-center">
<div class="flex items-center justify-center">
<div class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500"></div>
<span class="ml-3 text-gray-600">加载中...</span>
</div>
</td>
</tr>
`;
}
/**
* 显示错误状态
*/
function showError(container, message) {
container.innerHTML = `
<tr>
<td colspan="6" class="py-8 text-center text-red-500">
<svg class="w-12 h-12 mx-auto mb-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
${escapeHtml(message)}
</td>
</tr>
`;
}
/**
* HTML 转义
*/
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
/**
* API 请求封装
*/
function apiRequest(url, method = 'GET', data = null) {
const options = {
method: method,
headers: {
'Content-Type': 'application/json'
},
credentials: 'same-origin' // 添加认证信息
};
if (data && method !== 'GET') {
options.body = JSON.stringify(data);
}
return fetch(url, options)
.then(response => {
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return response.json();
});
}
/**
* 显示添加列表模态框
*/
function showAddListModal() {
const modal = document.getElementById('add-domain-info-modal');
if (modal) {
modal.classList.remove('hidden');
}
}
/**
* 隐藏添加列表模态框
*/
function hideAddListModal() {
const modal = document.getElementById('add-domain-info-modal');
if (modal) {
modal.classList.add('hidden');
// 重置表单
document.getElementById('add-domain-info-form').reset();
}
}
/**
* 添加域名信息列表
*/
function addDomainInfo(e) {
e.preventDefault();
const name = document.getElementById('list-name').value.trim();
const url = document.getElementById('list-url').value.trim();
const type = document.getElementById('list-type').value;
const enabled = document.getElementById('list-enabled').checked;
if (!name || !url) {
window.showNotification('请填写名称和URL', 'error');
return;
}
const data = {
name: name,
url: url,
type: type,
enabled: enabled
};
apiRequest('/api/domain-info/add', 'POST', data)
.then(response => {
if (response.status === 'success') {
window.showNotification('域名信息列表添加成功', 'success');
hideAddListModal();
loadDomainInfoLists();
} else {
window.showNotification(`添加失败:${response.message || '未知错误'}`, 'error');
}
})
.catch(error => {
console.error('添加域名信息列表失败:', error);
window.showNotification('添加域名信息列表失败', 'error');
});
}
/**
* 删除域名信息列表
*/
function removeDomainInfo(type) {
if (!confirm('确定要删除此域名信息列表吗?此操作不可恢复。')) {
return;
}
apiRequest(`/api/domain-info/remove/${encodeURIComponent(type)}`, 'POST')
.then(response => {
if (response.status === 'success') {
window.showNotification('域名信息列表删除成功', 'success');
loadDomainInfoLists();
} else {
window.showNotification(`删除失败:${response.message || '未知错误'}`, 'error');
}
})
.catch(error => {
console.error('删除域名信息列表失败:', error);
window.showNotification('删除域名信息列表失败', 'error');
});
}
// 绑定添加列表表单提交事件
document.addEventListener('DOMContentLoaded', function() {
const form = document.getElementById('add-domain-info-form');
if (form) {
form.addEventListener('submit', addDomainInfo);
}
});
// 暴露到全局命名空间
window.domainInfo = {
loadDomainInfoLists,
updateDomainInfo,
updateAllDomainInfo,
renderDomainInfoLists,
showAddListModal,
hideAddListModal,
removeDomainInfo
};
})();
+149
View File
@@ -1481,3 +1481,152 @@ document.addEventListener('DOMContentLoaded', () => {
}
});
});
// ========== 域名信息管理相关功能 ==========
// 加载远程域名信息列表
async function loadRemoteDomainInfoLists() {
// 检查是否有有效的缓存数据
const cachedDomainInfo = window.pageDataCache && window.pageDataCache.getCache('domain_info_lists');
if (cachedDomainInfo) {
console.log('使用缓存的域名信息列表');
updateDomainInfoListsTable(cachedDomainInfo);
return;
}
try {
const response = await fetch('/api/domain-info');
if (!response.ok) {
throw new Error(`加载失败:${response.status}`);
}
const domainInfo = await response.json();
// 更新域名信息列表 UI
updateDomainInfoListsTable(domainInfo);
// 存储数据到缓存
if (window.pageDataCache) {
window.pageDataCache.setCache('domain_info_lists', domainInfo);
}
} catch (error) {
console.error('加载域名信息列表失败:', error);
showNotification('加载域名信息列表失败', 'error');
}
}
// 更新域名信息列表表格
function updateDomainInfoListsTable(data) {
if (!data) return;
// 更新统计信息
if (document.getElementById('domain-info-count')) {
document.getElementById('domain-info-count').textContent = data.domainInfoCount || 0;
}
if (document.getElementById('threat-count')) {
document.getElementById('threat-count').textContent = data.threatCount || 0;
}
if (document.getElementById('tracker-count')) {
document.getElementById('tracker-count').textContent = data.trackerCount || 0;
}
// 渲染列表(如果页面有表格元素)
if (window.domainInfo && typeof window.domainInfo.renderDomainInfoLists === 'function') {
window.domainInfo.renderDomainInfoLists(data);
}
}
// 更新所有域名信息
async function updateAllDomainInfo() {
if (!confirm('确定要更新所有域名信息吗?这可能需要一些时间。')) {
return;
}
try {
const response = await fetch('/api/domain-info/update', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
});
if (!response.ok) {
throw new Error(`更新失败:${response.status}`);
}
const result = await response.json();
if (result.status === 'success') {
showNotification('所有域名信息更新任务已启动', 'success');
// 清除缓存
if (window.pageDataCache) {
window.pageDataCache.clearCache('domain_info_lists');
}
// 延迟刷新
setTimeout(() => {
loadRemoteDomainInfoLists();
}, 2000);
} else {
showNotification(`更新失败:${result.message || '未知错误'}`, 'error');
}
} catch (error) {
console.error('更新所有域名信息失败:', error);
showNotification('更新所有域名信息失败', 'error');
}
}
// 更新指定类型的域名信息
async function updateDomainInfoByType(type) {
const typeLabels = {
'domain-info': '域名信息',
'threat-database': '威胁数据库',
'tracker': '跟踪器'
};
const typeName = typeLabels[type] || type;
try {
const response = await fetch(`/api/domain-info/update/${encodeURIComponent(type)}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
});
if (!response.ok) {
throw new Error(`更新失败:${response.status}`);
}
const result = await response.json();
if (result.status === 'success') {
showNotification(`${typeName}更新任务已启动`, 'success');
// 清除缓存
if (window.pageDataCache) {
window.pageDataCache.clearCache('domain_info_lists');
}
// 延迟刷新
setTimeout(() => {
loadRemoteDomainInfoLists();
}, 2000);
} else {
showNotification(`更新失败:${result.message || '未知错误'}`, 'error');
}
} catch (error) {
console.error(`更新${typeName}失败:`, error);
showNotification(`更新${typeName}失败`, 'error');
}
}
// 在 initShieldPage 中添加域名信息列表加载(如果页面存在相关元素)
const originalInitShieldPage = window.initShieldPage;
window.initShieldPage = async function() {
if (originalInitShieldPage) {
await originalInitShieldPage();
}
// 如果页面有域名信息管理相关元素,则加载
if (document.getElementById('domain-info-lists-table-body')) {
await loadRemoteDomainInfoLists();
}
};
-25333
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff