更新Web文件

This commit is contained in:
Alex Yang
2025-11-23 18:37:24 +08:00
parent 0072e8a5c2
commit 15c87a9d94
6 changed files with 331 additions and 48 deletions

Binary file not shown.

View File

@@ -131,3 +131,102 @@ time="2025-11-23T18:08:48+08:00" level=debug msg="接收到DNS查询" client="10
time="2025-11-23T18:08:48+08:00" level=debug msg="DNS查询成功" domain=h5hosting.dbankcdn.com rtt=7.025853ms server="223.5.5.5:53" time="2025-11-23T18:08:48+08:00" level=debug msg="DNS查询成功" domain=h5hosting.dbankcdn.com rtt=7.025853ms server="223.5.5.5:53"
time="2025-11-23T18:08:48+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:12618" domain=metrics1.data.hicloud.com type=1 time="2025-11-23T18:08:48+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:12618" domain=metrics1.data.hicloud.com type=1
time="2025-11-23T18:08:48+08:00" level=debug msg="DNS查询成功" domain=metrics1.data.hicloud.com rtt=5.85395ms server="223.5.5.5:53" time="2025-11-23T18:08:48+08:00" level=debug msg="DNS查询成功" domain=metrics1.data.hicloud.com rtt=5.85395ms server="223.5.5.5:53"
time="2025-11-23T18:14:50+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:18455" domain=dns.weixin.qq.com.cn type=1
time="2025-11-23T18:14:50+08:00" level=debug msg="DNS查询成功" domain=dns.weixin.qq.com.cn rtt=5.279561ms server="223.5.5.5:53"
time="2025-11-23T18:15:31+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:51626" domain=tvax4.sinaimg.cn type=1
time="2025-11-23T18:15:31+08:00" level=debug msg="DNS查询成功" domain=tvax4.sinaimg.cn rtt=5.918625ms server="223.5.5.5:53"
time="2025-11-23T18:15:57+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:5242" domain=tsms-drcn.security.dbankcloud.cn type=1
time="2025-11-23T18:15:57+08:00" level=debug msg="DNS查询成功" domain=tsms-drcn.security.dbankcloud.cn rtt=6.292185ms server="223.5.5.5:53"
time="2025-11-23T18:17:24+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:3812" domain=login.microsoftonline.com type=1
time="2025-11-23T18:17:24+08:00" level=debug msg="DNS查询成功" domain=login.microsoftonline.com rtt=8.062737ms server="223.5.5.5:53"
time="2025-11-23T18:20:29+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:24579" domain=apd-pcdnwxlogin.teg.tencent-cloud.net type=1
time="2025-11-23T18:20:29+08:00" level=debug msg="DNS查询成功" domain=apd-pcdnwxlogin.teg.tencent-cloud.net rtt=6.721482ms server="223.5.5.5:53"
time="2025-11-23T18:22:01+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:46378" domain=nearby-find-api-drcn.hms.dbankcloud.com type=1
time="2025-11-23T18:22:01+08:00" level=debug msg="DNS查询成功" domain=nearby-find-api-drcn.hms.dbankcloud.com rtt=5.399528ms server="223.5.5.5:53"
time="2025-11-23T18:22:37+08:00" level=info msg="正在关闭服务..."
time="2025-11-23T18:22:37+08:00" level=info msg="DNS服务器已停止"
time="2025-11-23T18:22:37+08:00" level=error msg="HTTP控制台服务器启动失败" error="http: Server closed"
time="2025-11-23T18:22:37+08:00" level=info msg="HTTP控制台服务器已停止"
time="2025-11-23T18:22:37+08:00" level=info msg="所有服务已关闭"
time="2025-11-23T18:22:37+08:00" level=warning msg="日志系统已关闭"
time="2025-11-23T18:28:33+08:00" level=error msg="获取远程规则失败" error="远程服务器返回错误状态码: 404" url="https://example.com/rules.txt"
time="2025-11-23T18:28:33+08:00" level=info msg="规则加载完成,域名规则: 2, 排除规则: 0, 正则规则: 2, hosts规则: 3"
time="2025-11-23T18:28:33+08:00" level=info msg="DNS服务器已启动监听端口: 53"
time="2025-11-23T18:28:33+08:00" level=info msg="HTTP控制台已启动监听端口: 8080"
time="2025-11-23T18:28:33+08:00" level=info msg="DNS TCP服务器启动监听端口: 53"
time="2025-11-23T18:28:33+08:00" level=info msg="DNS UDP服务器启动监听端口: 53"
time="2025-11-23T18:28:33+08:00" level=info msg="HTTP控制台服务器启动监听地址: 0.0.0.0:8080"
time="2025-11-23T18:28:41+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:55569" domain=adjust.net.amazehome.xyz type=1
time="2025-11-23T18:28:41+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:55569" domain=adjust.net.amazehome.xyz
time="2025-11-23T18:28:41+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:55570" domain=adjust.net.amazehome.xyz type=28
time="2025-11-23T18:28:41+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:55570" domain=adjust.net.amazehome.xyz
time="2025-11-23T18:28:41+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:55571" domain=adjust.net type=1
time="2025-11-23T18:28:41+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:55571" domain=adjust.net
time="2025-11-23T18:28:41+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:55572" domain=adjust.net type=28
time="2025-11-23T18:28:41+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:55572" domain=adjust.net
time="2025-11-23T18:30:14+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:62375" domain=adjust.net.amazehome.xyz type=1
time="2025-11-23T18:30:14+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:62375" domain=adjust.net.amazehome.xyz
time="2025-11-23T18:30:14+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:62376" domain=adjust.net.amazehome.xyz type=28
time="2025-11-23T18:30:14+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:62376" domain=adjust.net.amazehome.xyz
time="2025-11-23T18:30:14+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:62377" domain=adjust.net type=1
time="2025-11-23T18:30:14+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:62377" domain=adjust.net
time="2025-11-23T18:30:14+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:62378" domain=adjust.net type=28
time="2025-11-23T18:30:14+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:62378" domain=adjust.net
time="2025-11-23T18:30:16+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:55979" domain=adjust.net.amazehome.xyz type=1
time="2025-11-23T18:30:16+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:55979" domain=adjust.net.amazehome.xyz
time="2025-11-23T18:30:16+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:55980" domain=adjust.net.amazehome.xyz type=28
time="2025-11-23T18:30:16+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:55980" domain=adjust.net.amazehome.xyz
time="2025-11-23T18:30:16+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:55981" domain=adjust.net type=1
time="2025-11-23T18:30:16+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:55981" domain=adjust.net
time="2025-11-23T18:30:16+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:55982" domain=adjust.net type=28
time="2025-11-23T18:30:16+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:55982" domain=adjust.net
time="2025-11-23T18:30:17+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:56717" domain=adjust.net.amazehome.xyz type=1
time="2025-11-23T18:30:17+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:56717" domain=adjust.net.amazehome.xyz
time="2025-11-23T18:30:17+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:56718" domain=adjust.net.amazehome.xyz type=28
time="2025-11-23T18:30:17+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:56718" domain=adjust.net.amazehome.xyz
time="2025-11-23T18:30:17+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:56719" domain=adjust.net type=1
time="2025-11-23T18:30:17+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:56719" domain=adjust.net
time="2025-11-23T18:30:17+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:56720" domain=adjust.net type=28
time="2025-11-23T18:30:17+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:56720" domain=adjust.net
time="2025-11-23T18:30:43+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:64531" domain=so.com.amazehome.xyz type=1
time="2025-11-23T18:30:43+08:00" level=debug msg="DNS查询成功" domain=so.com.amazehome.xyz rtt=28.942261ms server="223.5.5.5:53"
time="2025-11-23T18:30:43+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:64532" domain=so.com.amazehome.xyz type=28
time="2025-11-23T18:30:43+08:00" level=debug msg="DNS查询成功" domain=so.com.amazehome.xyz rtt=66.744527ms server="223.5.5.5:53"
time="2025-11-23T18:30:43+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:64533" domain=so.com type=1
time="2025-11-23T18:30:43+08:00" level=debug msg="DNS查询成功" domain=so.com rtt=6.238678ms server="223.5.5.5:53"
time="2025-11-23T18:30:43+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:64534" domain=so.com type=28
time="2025-11-23T18:30:43+08:00" level=debug msg="DNS查询成功" domain=so.com rtt=76.33228ms server="223.5.5.5:53"
time="2025-11-23T18:30:43+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:64535" domain=so.com.amazehome.xyz type=1
time="2025-11-23T18:30:43+08:00" level=debug msg="DNS查询成功" domain=so.com.amazehome.xyz rtt=65.586366ms server="223.5.5.5:53"
time="2025-11-23T18:30:43+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:55838" domain=so.com.amazehome.xyz type=28
time="2025-11-23T18:30:43+08:00" level=debug msg="DNS查询成功" domain=so.com.amazehome.xyz rtt=66.617532ms server="223.5.5.5:53"
time="2025-11-23T18:30:43+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:55839" domain=so.com type=1
time="2025-11-23T18:30:43+08:00" level=debug msg="DNS查询成功" domain=so.com rtt=3.690694ms server="223.5.5.5:53"
time="2025-11-23T18:30:43+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:55840" domain=so.com type=28
time="2025-11-23T18:30:44+08:00" level=debug msg="DNS查询成功" domain=so.com rtt=24.691944ms server="223.5.5.5:53"
time="2025-11-23T18:30:44+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:52832" domain=so.com.amazehome.xyz type=1
time="2025-11-23T18:30:44+08:00" level=debug msg="DNS查询成功" domain=so.com.amazehome.xyz rtt=67.631415ms server="223.5.5.5:53"
time="2025-11-23T18:30:44+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:52833" domain=so.com.amazehome.xyz type=28
time="2025-11-23T18:30:44+08:00" level=debug msg="DNS查询成功" domain=so.com.amazehome.xyz rtt=67.775451ms server="223.5.5.5:53"
time="2025-11-23T18:30:44+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:52834" domain=so.com type=1
time="2025-11-23T18:30:44+08:00" level=debug msg="DNS查询成功" domain=so.com rtt=6.394435ms server="223.5.5.5:53"
time="2025-11-23T18:30:44+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:52835" domain=so.com type=28
time="2025-11-23T18:30:44+08:00" level=debug msg="DNS查询成功" domain=so.com rtt=41.126372ms server="223.5.5.5:53"
time="2025-11-23T18:30:46+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:49722" domain=tracking.ad.qq.com.amazehome.xyz type=1
time="2025-11-23T18:30:46+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:49722" domain=tracking.ad.qq.com.amazehome.xyz
time="2025-11-23T18:30:46+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:49723" domain=tracking.ad.qq.com.amazehome.xyz type=28
time="2025-11-23T18:30:46+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:49723" domain=tracking.ad.qq.com.amazehome.xyz
time="2025-11-23T18:30:46+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:49724" domain=tracking.ad.qq.com type=1
time="2025-11-23T18:30:46+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:49724" domain=tracking.ad.qq.com
time="2025-11-23T18:30:46+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:49725" domain=tracking.ad.qq.com type=28
time="2025-11-23T18:30:46+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:49725" domain=tracking.ad.qq.com
time="2025-11-23T18:30:48+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:64389" domain=ads.qq.com.amazehome.xyz type=1
time="2025-11-23T18:30:48+08:00" level=debug msg="DNS查询成功" domain=ads.qq.com.amazehome.xyz rtt=23.436825ms server="223.5.5.5:53"
time="2025-11-23T18:30:48+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:64390" domain=ads.qq.com.amazehome.xyz type=28
time="2025-11-23T18:30:48+08:00" level=debug msg="DNS查询成功" domain=ads.qq.com.amazehome.xyz rtt=26.677483ms server="223.5.5.5:53"
time="2025-11-23T18:30:48+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:64391" domain=ads.qq.com type=1
time="2025-11-23T18:30:48+08:00" level=error msg="DNS查询失败" domain=ads.qq.com
time="2025-11-23T18:30:48+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:64392" domain=ads.qq.com type=28
time="2025-11-23T18:30:48+08:00" level=error msg="DNS查询失败" domain=ads.qq.com
time="2025-11-23T18:31:49+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:8360" domain=self.events.data.microsoft.com type=65
time="2025-11-23T18:31:49+08:00" level=debug msg="DNS查询成功" domain=self.events.data.microsoft.com rtt=14.34768ms server="223.5.5.5:53"

View File

@@ -25,19 +25,21 @@ type BlockedDomain struct {
// Server DNS服务器 // Server DNS服务器
type Server struct { type Server struct {
config *config.DNSConfig config *config.DNSConfig
shieldConfig *config.ShieldConfig shieldConfig *config.ShieldConfig
shieldManager *shield.ShieldManager shieldManager *shield.ShieldManager
server *dns.Server server *dns.Server
resolver *dns.Client resolver *dns.Client
ctx context.Context ctx context.Context
cancel context.CancelFunc cancel context.CancelFunc
statsMutex sync.Mutex statsMutex sync.Mutex
stats *Stats stats *Stats
blockedDomainsMutex sync.RWMutex blockedDomainsMutex sync.RWMutex
blockedDomains map[string]*BlockedDomain blockedDomains map[string]*BlockedDomain
hourlyStatsMutex sync.RWMutex resolvedDomainsMutex sync.RWMutex
hourlyStats map[string]int64 // 按小时统计屏蔽数量 resolvedDomains map[string]*BlockedDomain // 用于记录解析的域名
hourlyStatsMutex sync.RWMutex
hourlyStats map[string]int64 // 按小时统计屏蔽数量
} }
// Stats DNS服务器统计信息 // Stats DNS服务器统计信息
@@ -68,8 +70,9 @@ func NewServer(config *config.DNSConfig, shieldConfig *config.ShieldConfig, shie
Allowed: 0, Allowed: 0,
Errors: 0, Errors: 0,
}, },
blockedDomains: make(map[string]*BlockedDomain), blockedDomains: make(map[string]*BlockedDomain),
hourlyStats: make(map[string]int64), resolvedDomains: make(map[string]*BlockedDomain),
hourlyStats: make(map[string]int64),
} }
} }
@@ -184,6 +187,16 @@ func (s *Server) handleHostsResponse(w dns.ResponseWriter, r *dns.Msg, ip string
response.Answer = append(response.Answer, answer) response.Answer = append(response.Answer, answer)
} }
// 记录解析域名统计
domain := ""
if len(r.Question) > 0 {
domain = r.Question[0].Name
if len(domain) > 0 && domain[len(domain)-1] == '.' {
domain = domain[:len(domain)-1]
}
s.updateResolvedDomainStats(domain)
}
w.WriteMsg(response) w.WriteMsg(response)
s.updateStats(func(stats *Stats) { s.updateStats(func(stats *Stats) {
stats.Allowed++ stats.Allowed++
@@ -272,6 +285,9 @@ func (s *Server) forwardDNSRequest(w dns.ResponseWriter, r *dns.Msg, domain stri
w.WriteMsg(response) w.WriteMsg(response)
logger.Debug("DNS查询成功", "domain", domain, "rtt", rtt, "server", upstream) logger.Debug("DNS查询成功", "domain", domain, "rtt", rtt, "server", upstream)
// 记录解析域名统计
s.updateResolvedDomainStats(domain)
s.updateStats(func(stats *Stats) { s.updateStats(func(stats *Stats) {
stats.Allowed++ stats.Allowed++
}) })
@@ -311,7 +327,26 @@ func (s *Server) updateBlockedDomainStats(domain string) {
// 更新小时统计 // 更新小时统计
hourKey := time.Now().Format("2006-01-02-15") hourKey := time.Now().Format("2006-01-02-15")
s.hourlyStatsMutex.Lock()
s.hourlyStats[hourKey]++ s.hourlyStats[hourKey]++
s.hourlyStatsMutex.Unlock()
}
// updateResolvedDomainStats 更新解析域名统计
func (s *Server) updateResolvedDomainStats(domain string) {
s.resolvedDomainsMutex.Lock()
defer s.resolvedDomainsMutex.Unlock()
if entry, exists := s.resolvedDomains[domain]; exists {
entry.Count++
entry.LastSeen = time.Now()
} else {
s.resolvedDomains[domain] = &BlockedDomain{
Domain: domain,
Count: 1,
LastSeen: time.Now(),
}
}
} }
// updateStats 更新统计信息 // updateStats 更新统计信息
@@ -359,6 +394,29 @@ func (s *Server) GetTopBlockedDomains(limit int) []BlockedDomain {
return domains return domains
} }
// GetTopResolvedDomains 获取TOP解析域名
func (s *Server) GetTopResolvedDomains(limit int) []BlockedDomain {
s.resolvedDomainsMutex.RLock()
defer s.resolvedDomainsMutex.RUnlock()
// 转换为切片
domains := make([]BlockedDomain, 0, len(s.resolvedDomains))
for _, entry := range s.resolvedDomains {
domains = append(domains, *entry)
}
// 按数量排序
sort.Slice(domains, func(i, j int) bool {
return domains[i].Count > domains[j].Count
})
// 返回限制数量
if len(domains) > limit {
return domains[:limit]
}
return domains
}
// GetRecentBlockedDomains 获取最近屏蔽的域名列表 // GetRecentBlockedDomains 获取最近屏蔽的域名列表
func (s *Server) GetRecentBlockedDomains(limit int) []BlockedDomain { func (s *Server) GetRecentBlockedDomains(limit int) []BlockedDomain {
s.blockedDomainsMutex.RLock() s.blockedDomainsMutex.RLock()

View File

@@ -46,6 +46,7 @@ func (s *Server) Start() error {
mux.HandleFunc("/api/config", s.handleConfig) mux.HandleFunc("/api/config", s.handleConfig)
// 添加统计相关接口 // 添加统计相关接口
mux.HandleFunc("/api/top-blocked", s.handleTopBlockedDomains) mux.HandleFunc("/api/top-blocked", s.handleTopBlockedDomains)
mux.HandleFunc("/api/top-resolved", s.handleTopResolvedDomains)
mux.HandleFunc("/api/recent-blocked", s.handleRecentBlockedDomains) mux.HandleFunc("/api/recent-blocked", s.handleRecentBlockedDomains)
mux.HandleFunc("/api/hourly-stats", s.handleHourlyStats) mux.HandleFunc("/api/hourly-stats", s.handleHourlyStats)
} }
@@ -114,6 +115,28 @@ func (s *Server) handleTopBlockedDomains(w http.ResponseWriter, r *http.Request)
json.NewEncoder(w).Encode(result) json.NewEncoder(w).Encode(result)
} }
// handleTopResolvedDomains 处理获取最常解析的域名请求
func (s *Server) handleTopResolvedDomains(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
domains := s.dnsServer.GetTopResolvedDomains(10)
// 转换为前端需要的格式
result := make([]map[string]interface{}, len(domains))
for i, domain := range domains {
result[i] = map[string]interface{}{
"domain": domain.Domain,
"count": domain.Count,
}
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(result)
}
// handleRecentBlockedDomains 处理最近屏蔽域名请求 // handleRecentBlockedDomains 处理最近屏蔽域名请求
func (s *Server) handleRecentBlockedDomains(w http.ResponseWriter, r *http.Request) { func (s *Server) handleRecentBlockedDomains(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet { if r.Method != http.MethodGet {

View File

@@ -8,6 +8,7 @@ import (
"net/http" "net/http"
"os" "os"
"regexp" "regexp"
"sort"
"strings" "strings"
"sync" "sync"
"time" "time"
@@ -30,6 +31,8 @@ type ShieldManager struct {
regexRules []regexRule regexRules []regexRule
regexExceptions []regexRule regexExceptions []regexRule
hostsMap map[string]string hostsMap map[string]string
blockedDomainsCount map[string]int
resolvedDomainsCount map[string]int
rulesMutex sync.RWMutex rulesMutex sync.RWMutex
updateCtx context.Context updateCtx context.Context
updateCancel context.CancelFunc updateCancel context.CancelFunc
@@ -46,6 +49,8 @@ func NewShieldManager(config *config.ShieldConfig) *ShieldManager {
regexRules: []regexRule{}, regexRules: []regexRule{},
regexExceptions: []regexRule{}, regexExceptions: []regexRule{},
hostsMap: make(map[string]string), hostsMap: make(map[string]string),
blockedDomainsCount: make(map[string]int),
resolvedDomainsCount: make(map[string]int),
updateCtx: ctx, updateCtx: ctx,
updateCancel: cancel, updateCancel: cancel,
} }
@@ -62,6 +67,7 @@ func (m *ShieldManager) LoadRules() error {
m.regexRules = []regexRule{} m.regexRules = []regexRule{}
m.regexExceptions = []regexRule{} m.regexExceptions = []regexRule{}
m.hostsMap = make(map[string]string) m.hostsMap = make(map[string]string)
// 保留计数数据,不随规则重新加载而清空
// 加载本地规则文件 // 加载本地规则文件
if err := m.loadLocalRules(); err != nil { if err := m.loadLocalRules(); err != nil {
@@ -380,6 +386,106 @@ func (m *ShieldManager) IsBlocked(domain string) bool {
return false return false
} }
// RecordBlockedDomain 记录被屏蔽的域名
func (m *ShieldManager) RecordBlockedDomain(domain string) {
m.rulesMutex.Lock()
defer m.rulesMutex.Unlock()
m.blockedDomainsCount[domain]++
}
// RecordResolvedDomain 记录被解析的域名
func (m *ShieldManager) RecordResolvedDomain(domain string) {
m.rulesMutex.Lock()
defer m.rulesMutex.Unlock()
m.resolvedDomainsCount[domain]++
}
// GetTopBlockedDomains 获取最常被屏蔽的域名
func (m *ShieldManager) GetTopBlockedDomains(limit int) []map[string]interface{} {
m.rulesMutex.RLock()
defer m.rulesMutex.RUnlock()
// 如果没有数据,返回空数组
if len(m.blockedDomainsCount) == 0 {
return []map[string]interface{}{}
}
// 转换为切片以便排序
type domainCount struct {
Domain string
Count int
}
var domains []domainCount
for domain, count := range m.blockedDomainsCount {
domains = append(domains, domainCount{Domain: domain, Count: count})
}
// 按计数降序排序
sort.Slice(domains, func(i, j int) bool {
return domains[i].Count > domains[j].Count
})
// 限制返回数量
if len(domains) > limit {
domains = domains[:limit]
}
// 转换为API响应格式
result := make([]map[string]interface{}, len(domains))
for i, item := range domains {
result[i] = map[string]interface{}{
"domain": item.Domain,
"count": item.Count,
}
}
return result
}
// GetTopResolvedDomains 获取最常被解析的域名
func (m *ShieldManager) GetTopResolvedDomains(limit int) []map[string]interface{} {
m.rulesMutex.RLock()
defer m.rulesMutex.RUnlock()
// 如果没有数据,返回空数组
if len(m.resolvedDomainsCount) == 0 {
return []map[string]interface{}{}
}
// 转换为切片以便排序
type domainCount struct {
Domain string
Count int
}
var domains []domainCount
for domain, count := range m.resolvedDomainsCount {
domains = append(domains, domainCount{Domain: domain, Count: count})
}
// 按计数降序排序
sort.Slice(domains, func(i, j int) bool {
return domains[i].Count > domains[j].Count
})
// 限制返回数量
if len(domains) > limit {
domains = domains[:limit]
}
// 转换为API响应格式
result := make([]map[string]interface{}, len(domains))
for i, item := range domains {
result[i] = map[string]interface{}{
"domain": item.Domain,
"count": item.Count,
}
}
return result
}
// GetHostsIP 获取hosts文件中的IP映射 // GetHostsIP 获取hosts文件中的IP映射
func (m *ShieldManager) GetHostsIP(domain string) (string, bool) { func (m *ShieldManager) GetHostsIP(domain string) (string, bool) {
m.rulesMutex.RLock() m.rulesMutex.RLock()

View File

@@ -1567,40 +1567,37 @@ function loadRules() {
document.getElementById('top-blocked-domains').innerHTML = '<div class="empty-state"><i class="fas fa-exclamation-circle"></i><p>加载失败</p></div>'; document.getElementById('top-blocked-domains').innerHTML = '<div class="empty-state"><i class="fas fa-exclamation-circle"></i><p>加载失败</p></div>';
}); });
// 加载TOP解析域名由于没有直接的API这里使用模拟数据 // 加载TOP解析域名
// 实际使用时应该调用后端提供的相关API fetch('/api/top-resolved')
setTimeout(() => { .then(response => response.json())
const mockResolvedDomains = [ .then(data => {
{ domain: 'baidu.com', count: 1532 }, const container = document.getElementById('top-resolved-domains');
{ domain: 'sina.com.cn', count: 987 }, container.innerHTML = '';
{ domain: 'qq.com', count: 845 },
{ domain: 'aliyun.com', count: 732 }, if (!data || data.length === 0) {
{ domain: 'github.com', count: 654 }, container.innerHTML = '<div class="empty-state"><i class="fas fa-info-circle"></i><p>暂无解析域名统计</p></div>';
{ domain: 'gitee.com', count: 521 }, return;
{ domain: 'bing.com', count: 489 }, }
{ domain: 'sohu.com', count: 398 },
{ domain: 'jd.com', count: 345 }, data.forEach((item, index) => {
{ domain: 'taobao.com', count: 298 } const listItem = document.createElement('div');
]; listItem.className = 'list-item';
listItem.innerHTML = `
const container = document.getElementById('top-resolved-domains'); <div class="list-content">
container.innerHTML = ''; <div class="list-title">${index + 1}. ${item.domain}</div>
<div class="list-description">解析次数: ${item.count}</div>
mockResolvedDomains.forEach((item, index) => { </div>
const listItem = document.createElement('div'); <div class="list-actions">
listItem.className = 'list-item'; <span class="badge badge-success">解析</span>
listItem.innerHTML = ` </div>
<div class="list-content"> `;
<div class="list-title">${index + 1}. ${item.domain}</div> container.appendChild(listItem);
<div class="list-description">解析次数: ${item.count}</div> });
</div> })
<div class="list-actions"> .catch(error => {
<span class="badge badge-success">解析</span> console.error('加载TOP解析域名失败:', error);
</div> document.getElementById('top-resolved-domains').innerHTML = '<div class="empty-state"><i class="fas fa-exclamation-circle"></i><p>加载失败</p></div>';
`;
container.appendChild(listItem);
}); });
}, 500);
} }
// 初始化页面 // 初始化页面