更新Web文件
This commit is contained in:
BIN
dns-server
BIN
dns-server
Binary file not shown.
@@ -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"
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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 },
|
|
||||||
{ domain: 'github.com', count: 654 },
|
|
||||||
{ domain: 'gitee.com', count: 521 },
|
|
||||||
{ domain: 'bing.com', count: 489 },
|
|
||||||
{ domain: 'sohu.com', count: 398 },
|
|
||||||
{ domain: 'jd.com', count: 345 },
|
|
||||||
{ domain: 'taobao.com', count: 298 }
|
|
||||||
];
|
|
||||||
|
|
||||||
const container = document.getElementById('top-resolved-domains');
|
if (!data || data.length === 0) {
|
||||||
container.innerHTML = '';
|
container.innerHTML = '<div class="empty-state"><i class="fas fa-info-circle"></i><p>暂无解析域名统计</p></div>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mockResolvedDomains.forEach((item, index) => {
|
data.forEach((item, index) => {
|
||||||
const listItem = document.createElement('div');
|
const listItem = document.createElement('div');
|
||||||
listItem.className = 'list-item';
|
listItem.className = 'list-item';
|
||||||
listItem.innerHTML = `
|
listItem.innerHTML = `
|
||||||
<div class="list-content">
|
<div class="list-content">
|
||||||
<div class="list-title">${index + 1}. ${item.domain}</div>
|
<div class="list-title">${index + 1}. ${item.domain}</div>
|
||||||
<div class="list-description">解析次数: ${item.count}</div>
|
<div class="list-description">解析次数: ${item.count}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="list-actions">
|
<div class="list-actions">
|
||||||
<span class="badge badge-success">解析</span>
|
<span class="badge badge-success">解析</span>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
container.appendChild(listItem);
|
container.appendChild(listItem);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('加载TOP解析域名失败:', error);
|
||||||
|
document.getElementById('top-resolved-domains').innerHTML = '<div class="empty-state"><i class="fas fa-exclamation-circle"></i><p>加载失败</p></div>';
|
||||||
});
|
});
|
||||||
}, 500);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化页面
|
// 初始化页面
|
||||||
|
|||||||
Reference in New Issue
Block a user