增加数据持久化功能
This commit is contained in:
@@ -5,11 +5,13 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DNSConfig DNS服务器配置
|
// DNSConfig DNS配置
|
||||||
type DNSConfig struct {
|
type DNSConfig struct {
|
||||||
Port int `json:"port"`
|
Port int `json:"port"`
|
||||||
UpstreamDNS []string `json:"upstreamDNS"`
|
UpstreamDNS []string `json:"upstreamDNS"`
|
||||||
Timeout int `json:"timeout"`
|
Timeout int `json:"timeout"`
|
||||||
|
StatsFile string `json:"statsFile"` // 统计数据持久化文件
|
||||||
|
SaveInterval int `json:"saveInterval"` // 数据保存间隔(秒)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTTPConfig HTTP控制台配置
|
// HTTPConfig HTTP控制台配置
|
||||||
@@ -21,12 +23,14 @@ type HTTPConfig struct {
|
|||||||
|
|
||||||
// ShieldConfig 屏蔽规则配置
|
// ShieldConfig 屏蔽规则配置
|
||||||
type ShieldConfig struct {
|
type ShieldConfig struct {
|
||||||
LocalRulesFile string `json:"localRulesFile"`
|
LocalRulesFile string `json:"localRulesFile"`
|
||||||
RemoteRules []string `json:"remoteRules"`
|
RemoteRules []string `json:"remoteRules"`
|
||||||
UpdateInterval int `json:"updateInterval"`
|
UpdateInterval int `json:"updateInterval"`
|
||||||
HostsFile string `json:"hostsFile"`
|
HostsFile string `json:"hostsFile"`
|
||||||
BlockMethod string `json:"blockMethod"` // 屏蔽方法: "NXDOMAIN", "refused", "emptyIP", "customIP"
|
BlockMethod string `json:"blockMethod"` // 屏蔽方法: "NXDOMAIN", "refused", "emptyIP", "customIP"
|
||||||
CustomBlockIP string `json:"customBlockIP"` // 自定义屏蔽IP,当BlockMethod为"customIP"时使用
|
CustomBlockIP string `json:"customBlockIP"` // 自定义屏蔽IP,当BlockMethod为"customIP"时使用
|
||||||
|
StatsFile string `json:"statsFile"` // 计数数据持久化文件
|
||||||
|
StatsSaveInterval int `json:"statsSaveInterval"` // 计数数据保存间隔(秒)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LogConfig 日志配置
|
// LogConfig 日志配置
|
||||||
@@ -64,7 +68,13 @@ func LoadConfig(path string) (*Config, error) {
|
|||||||
config.DNS.Port = 53
|
config.DNS.Port = 53
|
||||||
}
|
}
|
||||||
if len(config.DNS.UpstreamDNS) == 0 {
|
if len(config.DNS.UpstreamDNS) == 0 {
|
||||||
config.DNS.UpstreamDNS = []string{"8.8.8.8:53", "1.1.1.1:53"}
|
config.DNS.UpstreamDNS = []string{"223.5.5.5:53", "223.6.6.6:53"}
|
||||||
|
}
|
||||||
|
if config.DNS.StatsFile == "" {
|
||||||
|
config.DNS.StatsFile = "./data/stats.json" // 默认统计数据文件路径
|
||||||
|
}
|
||||||
|
if config.DNS.SaveInterval == 0 {
|
||||||
|
config.DNS.SaveInterval = 300 // 默认5分钟保存一次
|
||||||
}
|
}
|
||||||
if config.HTTP.Port == 0 {
|
if config.HTTP.Port == 0 {
|
||||||
config.HTTP.Port = 8080
|
config.HTTP.Port = 8080
|
||||||
@@ -78,6 +88,12 @@ func LoadConfig(path string) (*Config, error) {
|
|||||||
if config.Shield.BlockMethod == "" {
|
if config.Shield.BlockMethod == "" {
|
||||||
config.Shield.BlockMethod = "NXDOMAIN" // 默认屏蔽方法为NXDOMAIN
|
config.Shield.BlockMethod = "NXDOMAIN" // 默认屏蔽方法为NXDOMAIN
|
||||||
}
|
}
|
||||||
|
if config.Shield.StatsFile == "" {
|
||||||
|
config.Shield.StatsFile = "./data/shield_stats.json" // 默认Shield统计数据文件路径
|
||||||
|
}
|
||||||
|
if config.Shield.StatsSaveInterval == 0 {
|
||||||
|
config.Shield.StatsSaveInterval = 300 // 默认5分钟保存一次
|
||||||
|
}
|
||||||
if config.Log.Level == "" {
|
if config.Log.Level == "" {
|
||||||
config.Log.Level = "info"
|
config.Log.Level = "info"
|
||||||
}
|
}
|
||||||
|
|||||||
0
data/shield_stats.json
Normal file
0
data/shield_stats.json
Normal file
42
data/stats.json
Normal file
42
data/stats.json
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
"stats": {
|
||||||
|
"Queries": 33,
|
||||||
|
"Blocked": 24,
|
||||||
|
"Allowed": 19,
|
||||||
|
"Errors": 2,
|
||||||
|
"LastQuery": "2025-11-23T19:06:10.694259822+08:00"
|
||||||
|
},
|
||||||
|
"blockedDomains": {
|
||||||
|
"ad.qq.com": {
|
||||||
|
"Domain": "ad.qq.com",
|
||||||
|
"Count": 6,
|
||||||
|
"LastSeen": "2025-11-23T19:06:10.694532789+08:00"
|
||||||
|
},
|
||||||
|
"ad.qq.com.amazehome.xyz": {
|
||||||
|
"Domain": "ad.qq.com.amazehome.xyz",
|
||||||
|
"Count": 6,
|
||||||
|
"LastSeen": "2025-11-23T19:06:10.691565251+08:00"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"resolvedDomains": {
|
||||||
|
"ad.qq.com": {
|
||||||
|
"Domain": "ad.qq.com",
|
||||||
|
"Count": 10,
|
||||||
|
"LastSeen": "2025-11-23T19:05:54.429002187+08:00"
|
||||||
|
},
|
||||||
|
"ad.qq.com.amazehome.xyz": {
|
||||||
|
"Domain": "ad.qq.com.amazehome.xyz",
|
||||||
|
"Count": 8,
|
||||||
|
"LastSeen": "2025-11-23T19:05:54.356216418+08:00"
|
||||||
|
},
|
||||||
|
"apd-pcdnwxstat.teg.tencent-cloud.net": {
|
||||||
|
"Domain": "apd-pcdnwxstat.teg.tencent-cloud.net",
|
||||||
|
"Count": 1,
|
||||||
|
"LastSeen": "2025-11-23T19:05:56.842653777+08:00"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"hourlyStats": {
|
||||||
|
"2025-11-23-19": 12
|
||||||
|
},
|
||||||
|
"lastSaved": "2025-11-23T19:06:21.194988376+08:00"
|
||||||
|
}
|
||||||
BIN
dns-server
BIN
dns-server
Binary file not shown.
149
dns-server.log
149
dns-server.log
@@ -230,3 +230,152 @@ time="2025-11-23T18:30:48+08:00" level=debug msg="接收到DNS查询" client="10
|
|||||||
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=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查询" 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"
|
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"
|
||||||
|
time="2025-11-23T18:35:09+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:34681" domain=apd-pcdnwxstat.teg.tencent-cloud.net type=1
|
||||||
|
time="2025-11-23T18:35:09+08:00" level=debug msg="DNS查询成功" domain=apd-pcdnwxstat.teg.tencent-cloud.net rtt=5.914665ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:37:26+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:8652" domain=apd-pcdnwxstat.teg.tencent-cloud.net type=1
|
||||||
|
time="2025-11-23T18:37:26+08:00" level=debug msg="DNS查询成功" domain=apd-pcdnwxstat.teg.tencent-cloud.net rtt=5.903025ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:39:07+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:15083" domain=metrics1-drcn.dt.dbankcloud.cn type=1
|
||||||
|
time="2025-11-23T18:39:07+08:00" level=debug msg="DNS查询成功" domain=metrics1-drcn.dt.dbankcloud.cn rtt=5.213232ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:39:09+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:61317" domain=appdl-1-drcn.dbankcdn.com type=1
|
||||||
|
time="2025-11-23T18:39:09+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:4656" domain=appdl-drcn.dbankcdn.com type=1
|
||||||
|
time="2025-11-23T18:39:09+08:00" level=debug msg="DNS查询成功" domain=appdl-1-drcn.dbankcdn.com rtt=4.647968ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:39:09+08:00" level=debug msg="DNS查询成功" domain=appdl-drcn.dbankcdn.com rtt=4.474298ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:39:09+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:47439" domain=appoptimize-drcn.dbankcdn.cn type=1
|
||||||
|
time="2025-11-23T18:39:09+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:50747" domain=appimg-drcn.dbankcdn.com type=1
|
||||||
|
time="2025-11-23T18:39:09+08:00" level=debug msg="DNS查询成功" domain=appoptimize-drcn.dbankcdn.cn rtt=4.028323ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:39:09+08:00" level=debug msg="DNS查询成功" domain=appimg-drcn.dbankcdn.com rtt=4.806171ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:39:09+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:58085" domain=store-drcn.hispace.dbankcloud.com type=1
|
||||||
|
time="2025-11-23T18:39:09+08:00" level=debug msg="DNS查询成功" domain=store-drcn.hispace.dbankcloud.com rtt=4.298717ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:39:09+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:65072" domain=contentcenter-drcn.dbankcdn.cn type=1
|
||||||
|
time="2025-11-23T18:39:09+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:9115" domain=api-drcn.theme.dbankcloud.cn type=1
|
||||||
|
time="2025-11-23T18:39:09+08:00" level=debug msg="DNS查询成功" domain=contentcenter-drcn.dbankcdn.cn rtt=5.394543ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:39:09+08:00" level=debug msg="DNS查询成功" domain=api-drcn.theme.dbankcloud.cn rtt=5.24299ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:39:09+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:58544" domain=magazine-drcn.theme.dbankcloud.cn type=1
|
||||||
|
time="2025-11-23T18:39:09+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:22253" domain=magazine-drcn.theme.dbankcloud.cn type=1
|
||||||
|
time="2025-11-23T18:39:09+08:00" level=debug msg="DNS查询成功" domain=magazine-drcn.theme.dbankcloud.cn rtt=5.682249ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:39:09+08:00" level=debug msg="DNS查询成功" domain=magazine-drcn.theme.dbankcloud.cn rtt=5.599705ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:39:09+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:32221" domain=agpicnsp-drcn.dbankcdn.com type=1
|
||||||
|
time="2025-11-23T18:39:09+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:3445" domain=appimg.dbankcdn.com type=1
|
||||||
|
time="2025-11-23T18:39:09+08:00" level=debug msg="DNS查询成功" domain=agpicnsp-drcn.dbankcdn.com rtt=5.96018ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:39:09+08:00" level=debug msg="DNS查询成功" domain=appimg.dbankcdn.com rtt=13.633739ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:39:09+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:16444" domain=f00b1b869deb32d2ad60ba514bb876ea.b.hon.cc.cdnhwc8.com type=1
|
||||||
|
time="2025-11-23T18:39:09+08:00" level=debug msg="DNS查询成功" domain=f00b1b869deb32d2ad60ba514bb876ea.b.hon.cc.cdnhwc8.com rtt=15.020117ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:39:09+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:43083" domain=appdl-2-drcn.dbankcdn.com type=1
|
||||||
|
time="2025-11-23T18:39:09+08:00" level=debug msg="DNS查询成功" domain=appdl-2-drcn.dbankcdn.com rtt=4.087138ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:39:10+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:41949" domain=grs.dbankcloud.com type=1
|
||||||
|
time="2025-11-23T18:39:10+08:00" level=debug msg="DNS查询成功" domain=grs.dbankcloud.com rtt=6.434814ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:39:10+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:18043" domain=sdkserver.op.hicloud.com type=1
|
||||||
|
time="2025-11-23T18:39:10+08:00" level=debug msg="DNS查询成功" domain=sdkserver.op.hicloud.com rtt=6.663746ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:39:10+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:27296" domain=events.op.hicloud.com type=1
|
||||||
|
time="2025-11-23T18:39:10+08:00" level=debug msg="DNS查询成功" domain=events.op.hicloud.com rtt=4.076785ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:39:10+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:20705" domain=acd.op.hicloud.com type=1
|
||||||
|
time="2025-11-23T18:39:10+08:00" level=debug msg="DNS查询成功" domain=acd.op.hicloud.com rtt=5.188271ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:39:10+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:11580" domain=api.cloud.huawei.com type=1
|
||||||
|
time="2025-11-23T18:39:11+08:00" level=debug msg="DNS查询成功" domain=api.cloud.huawei.com rtt=5.414894ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:39:11+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:16274" domain=sdkserver-drcn.op.dbankcloud.cn type=1
|
||||||
|
time="2025-11-23T18:39:11+08:00" level=debug msg="DNS查询成功" domain=sdkserver-drcn.op.dbankcloud.cn rtt=5.745651ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:39:12+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:54852" domain=tsms-drcn.security.dbankcloud.cn type=1
|
||||||
|
time="2025-11-23T18:39:12+08:00" level=debug msg="DNS查询成功" domain=tsms-drcn.security.dbankcloud.cn rtt=5.889368ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:39:18+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:56128" domain=store-drcn.hispace.dbankcloud.com type=1
|
||||||
|
time="2025-11-23T18:39:18+08:00" level=debug msg="DNS查询成功" domain=store-drcn.hispace.dbankcloud.com rtt=5.222492ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:41:22+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:6990" domain=dldir1v6.qq.com type=1
|
||||||
|
time="2025-11-23T18:41:22+08:00" level=debug msg="DNS查询成功" domain=dldir1v6.qq.com rtt=5.968557ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:48:02+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:20065" domain=dns.weixin.qq.com.cn type=1
|
||||||
|
time="2025-11-23T18:48:02+08:00" level=debug msg="DNS查询成功" domain=dns.weixin.qq.com.cn rtt=5.24456ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:52:01+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:2060" domain=apd-pcdnwxlogin.teg.tencent-cloud.net type=1
|
||||||
|
time="2025-11-23T18:52:01+08:00" level=debug msg="DNS查询成功" domain=apd-pcdnwxlogin.teg.tencent-cloud.net rtt=6.190907ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:55:03+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:12293" domain=apd-pcdnwxnat.teg.tencent-cloud.net type=1
|
||||||
|
time="2025-11-23T18:55:03+08:00" level=debug msg="DNS查询成功" domain=apd-pcdnwxnat.teg.tencent-cloud.net rtt=5.919306ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:55:34+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:27926" domain=aeventlog.beacon.qq.com type=1
|
||||||
|
time="2025-11-23T18:55:34+08:00" level=debug msg="DNS查询成功" domain=aeventlog.beacon.qq.com rtt=6.692955ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T18:57:28+08:00" level=info msg="正在关闭服务..."
|
||||||
|
time="2025-11-23T18:57:28+08:00" level=info msg="DNS服务器已停止"
|
||||||
|
time="2025-11-23T18:57:28+08:00" level=error msg="HTTP控制台服务器启动失败" error="http: Server closed"
|
||||||
|
time="2025-11-23T18:57:28+08:00" level=info msg="HTTP控制台服务器已停止"
|
||||||
|
time="2025-11-23T18:57:28+08:00" level=info msg="所有服务已关闭"
|
||||||
|
time="2025-11-23T18:57:28+08:00" level=warning msg="日志系统已关闭"
|
||||||
|
time="2025-11-23T19:05:40+08:00" level=error msg="获取远程规则失败" error="远程服务器返回错误状态码: 404" url="https://example.com/rules.txt"
|
||||||
|
time="2025-11-23T19:05:40+08:00" level=info msg="规则加载完成,域名规则: 2, 排除规则: 0, 正则规则: 2, hosts规则: 3"
|
||||||
|
time="2025-11-23T19:05:40+08:00" level=info msg="DNS服务器已启动,监听端口: 53"
|
||||||
|
time="2025-11-23T19:05:40+08:00" level=info msg="HTTP控制台已启动,监听端口: 8080"
|
||||||
|
time="2025-11-23T19:05:40+08:00" level=info msg="HTTP控制台服务器启动,监听地址: 0.0.0.0:8080"
|
||||||
|
time="2025-11-23T19:05:40+08:00" level=info msg="DNS TCP服务器启动,监听端口: 53"
|
||||||
|
time="2025-11-23T19:05:40+08:00" level=info msg="规则自动更新已启动" interval=3600
|
||||||
|
time="2025-11-23T19:05:40+08:00" level=info msg="启动Shield计数数据自动保存功能" file=./data/shield_stats.json interval=300
|
||||||
|
time="2025-11-23T19:05:40+08:00" level=info msg="DNS UDP服务器启动,监听端口: 53"
|
||||||
|
time="2025-11-23T19:05:40+08:00" level=info msg="Shield计数数据保存成功"
|
||||||
|
time="2025-11-23T19:05:51+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:63504" domain=ad.qq.com.amazehome.xyz type=1
|
||||||
|
time="2025-11-23T19:05:52+08:00" level=debug msg="DNS查询成功" domain=ad.qq.com.amazehome.xyz rtt=68.496416ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T19:05:52+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:63505" domain=ad.qq.com.amazehome.xyz type=28
|
||||||
|
time="2025-11-23T19:05:52+08:00" level=debug msg="DNS查询成功" domain=ad.qq.com.amazehome.xyz rtt=22.855544ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T19:05:52+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:63506" domain=ad.qq.com type=1
|
||||||
|
time="2025-11-23T19:05:52+08:00" level=debug msg="DNS查询成功" domain=ad.qq.com rtt=23.728363ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T19:05:52+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:62552" domain=ad.qq.com type=28
|
||||||
|
time="2025-11-23T19:05:52+08:00" level=debug msg="DNS查询成功" domain=ad.qq.com rtt=27.123116ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T19:05:52+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:62553" domain=ad.qq.com.amazehome.xyz type=1
|
||||||
|
time="2025-11-23T19:05:52+08:00" level=debug msg="DNS查询成功" domain=ad.qq.com.amazehome.xyz rtt=5.560802ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T19:05:52+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:62554" domain=ad.qq.com.amazehome.xyz type=28
|
||||||
|
time="2025-11-23T19:05:52+08:00" level=debug msg="DNS查询成功" domain=ad.qq.com.amazehome.xyz rtt=4.628616ms server="223.6.6.6:53"
|
||||||
|
time="2025-11-23T19:05:52+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:62555" domain=ad.qq.com type=1
|
||||||
|
time="2025-11-23T19:05:52+08:00" level=debug msg="DNS查询成功" domain=ad.qq.com rtt=32.441875ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T19:05:52+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:62556" domain=ad.qq.com type=28
|
||||||
|
time="2025-11-23T19:05:52+08:00" level=debug msg="DNS查询成功" domain=ad.qq.com rtt=16.630593ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T19:05:53+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:62557" domain=ad.qq.com.amazehome.xyz type=1
|
||||||
|
time="2025-11-23T19:05:53+08:00" level=debug msg="DNS查询成功" domain=ad.qq.com.amazehome.xyz rtt=37.27035ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T19:05:53+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:62558" domain=ad.qq.com.amazehome.xyz type=28
|
||||||
|
time="2025-11-23T19:05:53+08:00" level=error msg="DNS查询失败" domain=ad.qq.com.amazehome.xyz
|
||||||
|
time="2025-11-23T19:05:53+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:62559" domain=ad.qq.com type=1
|
||||||
|
time="2025-11-23T19:05:53+08:00" level=debug msg="DNS查询成功" domain=ad.qq.com rtt=14.2654ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T19:05:53+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:62560" domain=ad.qq.com type=28
|
||||||
|
time="2025-11-23T19:05:53+08:00" level=debug msg="DNS查询成功" domain=ad.qq.com rtt=6.551795ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T19:05:53+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:52135" domain=ad.qq.com.amazehome.xyz type=1
|
||||||
|
time="2025-11-23T19:05:53+08:00" level=debug msg="DNS查询成功" domain=ad.qq.com.amazehome.xyz rtt=31.31022ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T19:05:53+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:52136" domain=ad.qq.com.amazehome.xyz type=28
|
||||||
|
time="2025-11-23T19:05:53+08:00" level=debug msg="DNS查询成功" domain=ad.qq.com.amazehome.xyz rtt=30.611352ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T19:05:53+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:52137" domain=ad.qq.com type=1
|
||||||
|
time="2025-11-23T19:05:53+08:00" level=debug msg="DNS查询成功" domain=ad.qq.com rtt=43.032729ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T19:05:53+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:52138" domain=ad.qq.com type=28
|
||||||
|
time="2025-11-23T19:05:53+08:00" level=debug msg="DNS查询成功" domain=ad.qq.com rtt=27.754923ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T19:05:54+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:52139" domain=ad.qq.com.amazehome.xyz type=1
|
||||||
|
time="2025-11-23T19:05:54+08:00" level=debug msg="DNS查询成功" domain=ad.qq.com.amazehome.xyz rtt=5.00309ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T19:05:54+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:52140" domain=ad.qq.com.amazehome.xyz type=28
|
||||||
|
time="2025-11-23T19:05:54+08:00" level=error msg="DNS查询失败" domain=ad.qq.com.amazehome.xyz
|
||||||
|
time="2025-11-23T19:05:54+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:52141" domain=ad.qq.com type=1
|
||||||
|
time="2025-11-23T19:05:54+08:00" level=debug msg="DNS查询成功" domain=ad.qq.com rtt=18.018889ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T19:05:54+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:52142" domain=ad.qq.com type=28
|
||||||
|
time="2025-11-23T19:05:54+08:00" level=debug msg="DNS查询成功" domain=ad.qq.com rtt=32.759047ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T19:05:56+08:00" level=debug msg="接收到DNS查询" client="10.35.10.11:32332" domain=apd-pcdnwxstat.teg.tencent-cloud.net type=1
|
||||||
|
time="2025-11-23T19:05:56+08:00" level=debug msg="DNS查询成功" domain=apd-pcdnwxstat.teg.tencent-cloud.net rtt=6.574939ms server="223.5.5.5:53"
|
||||||
|
time="2025-11-23T19:06:09+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:49579" domain=ad.qq.com.amazehome.xyz type=1
|
||||||
|
time="2025-11-23T19:06:09+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:49579" domain=ad.qq.com.amazehome.xyz
|
||||||
|
time="2025-11-23T19:06:09+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:49580" domain=ad.qq.com.amazehome.xyz type=28
|
||||||
|
time="2025-11-23T19:06:09+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:49580" domain=ad.qq.com.amazehome.xyz
|
||||||
|
time="2025-11-23T19:06:09+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:49581" domain=ad.qq.com type=1
|
||||||
|
time="2025-11-23T19:06:09+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:49581" domain=ad.qq.com
|
||||||
|
time="2025-11-23T19:06:09+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:49582" domain=ad.qq.com type=28
|
||||||
|
time="2025-11-23T19:06:09+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:49582" domain=ad.qq.com
|
||||||
|
time="2025-11-23T19:06:10+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:49583" domain=ad.qq.com.amazehome.xyz type=1
|
||||||
|
time="2025-11-23T19:06:10+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:49583" domain=ad.qq.com.amazehome.xyz
|
||||||
|
time="2025-11-23T19:06:10+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:49584" domain=ad.qq.com.amazehome.xyz type=28
|
||||||
|
time="2025-11-23T19:06:10+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:49584" domain=ad.qq.com.amazehome.xyz
|
||||||
|
time="2025-11-23T19:06:10+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:49585" domain=ad.qq.com type=1
|
||||||
|
time="2025-11-23T19:06:10+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:49585" domain=ad.qq.com
|
||||||
|
time="2025-11-23T19:06:10+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:49586" domain=ad.qq.com type=28
|
||||||
|
time="2025-11-23T19:06:10+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:49586" domain=ad.qq.com
|
||||||
|
time="2025-11-23T19:06:10+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:64329" domain=ad.qq.com.amazehome.xyz type=1
|
||||||
|
time="2025-11-23T19:06:10+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:64329" domain=ad.qq.com.amazehome.xyz
|
||||||
|
time="2025-11-23T19:06:10+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:64330" domain=ad.qq.com.amazehome.xyz type=28
|
||||||
|
time="2025-11-23T19:06:10+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:64330" domain=ad.qq.com.amazehome.xyz
|
||||||
|
time="2025-11-23T19:06:10+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:64331" domain=ad.qq.com type=1
|
||||||
|
time="2025-11-23T19:06:10+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:64331" domain=ad.qq.com
|
||||||
|
time="2025-11-23T19:06:10+08:00" level=debug msg="接收到DNS查询" client="10.35.10.78:64332" domain=ad.qq.com type=28
|
||||||
|
time="2025-11-23T19:06:10+08:00" level=info msg="域名被屏蔽" client="10.35.10.78:64332" domain=ad.qq.com
|
||||||
|
time="2025-11-23T19:06:21+08:00" level=info msg="正在关闭服务..."
|
||||||
|
time="2025-11-23T19:06:21+08:00" level=info msg="统计数据保存成功"
|
||||||
|
time="2025-11-23T19:06:21+08:00" level=info msg="DNS服务器已停止"
|
||||||
|
time="2025-11-23T19:06:21+08:00" level=error msg="HTTP控制台服务器启动失败" error="http: Server closed"
|
||||||
|
time="2025-11-23T19:06:21+08:00" level=info msg="HTTP控制台服务器已停止"
|
||||||
|
time="2025-11-23T19:06:21+08:00" level=info msg="Shield计数数据保存成功"
|
||||||
|
time="2025-11-23T19:06:21+08:00" level=info msg="规则自动更新已停止"
|
||||||
|
time="2025-11-23T19:06:21+08:00" level=info msg="所有服务已关闭"
|
||||||
|
time="2025-11-23T19:06:21+08:00" level=warning msg="日志系统已关闭"
|
||||||
|
|||||||
165
dns/server.go
165
dns/server.go
@@ -2,8 +2,12 @@ package dns
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -23,6 +27,15 @@ type BlockedDomain struct {
|
|||||||
LastSeen time.Time
|
LastSeen time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StatsData 用于持久化的统计数据结构
|
||||||
|
type StatsData struct {
|
||||||
|
Stats *Stats `json:"stats"`
|
||||||
|
BlockedDomains map[string]*BlockedDomain `json:"blockedDomains"`
|
||||||
|
ResolvedDomains map[string]*BlockedDomain `json:"resolvedDomains"`
|
||||||
|
HourlyStats map[string]int64 `json:"hourlyStats"`
|
||||||
|
LastSaved time.Time `json:"lastSaved"`
|
||||||
|
}
|
||||||
|
|
||||||
// Server DNS服务器
|
// Server DNS服务器
|
||||||
type Server struct {
|
type Server struct {
|
||||||
config *config.DNSConfig
|
config *config.DNSConfig
|
||||||
@@ -40,6 +53,8 @@ type Server struct {
|
|||||||
resolvedDomains map[string]*BlockedDomain // 用于记录解析的域名
|
resolvedDomains map[string]*BlockedDomain // 用于记录解析的域名
|
||||||
hourlyStatsMutex sync.RWMutex
|
hourlyStatsMutex sync.RWMutex
|
||||||
hourlyStats map[string]int64 // 按小时统计屏蔽数量
|
hourlyStats map[string]int64 // 按小时统计屏蔽数量
|
||||||
|
saveTicker *time.Ticker // 用于定时保存数据
|
||||||
|
saveDone chan struct{} // 用于通知保存协程停止
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stats DNS服务器统计信息
|
// Stats DNS服务器统计信息
|
||||||
@@ -54,7 +69,7 @@ type Stats struct {
|
|||||||
// NewServer 创建DNS服务器实例
|
// NewServer 创建DNS服务器实例
|
||||||
func NewServer(config *config.DNSConfig, shieldConfig *config.ShieldConfig, shieldManager *shield.ShieldManager) *Server {
|
func NewServer(config *config.DNSConfig, shieldConfig *config.ShieldConfig, shieldManager *shield.ShieldManager) *Server {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
return &Server{
|
server := &Server{
|
||||||
config: config,
|
config: config,
|
||||||
shieldConfig: shieldConfig,
|
shieldConfig: shieldConfig,
|
||||||
shieldManager: shieldManager,
|
shieldManager: shieldManager,
|
||||||
@@ -73,7 +88,14 @@ func NewServer(config *config.DNSConfig, shieldConfig *config.ShieldConfig, shie
|
|||||||
blockedDomains: make(map[string]*BlockedDomain),
|
blockedDomains: make(map[string]*BlockedDomain),
|
||||||
resolvedDomains: make(map[string]*BlockedDomain),
|
resolvedDomains: make(map[string]*BlockedDomain),
|
||||||
hourlyStats: make(map[string]int64),
|
hourlyStats: make(map[string]int64),
|
||||||
|
saveDone: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 加载已保存的统计数据
|
||||||
|
server.loadStatsData()
|
||||||
|
|
||||||
|
return server
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start 启动DNS服务器
|
// Start 启动DNS服务器
|
||||||
@@ -116,10 +138,17 @@ func (s *Server) Start() error {
|
|||||||
|
|
||||||
// Stop 停止DNS服务器
|
// Stop 停止DNS服务器
|
||||||
func (s *Server) Stop() {
|
func (s *Server) Stop() {
|
||||||
|
// 发送停止信号给保存协程
|
||||||
|
close(s.saveDone)
|
||||||
|
|
||||||
|
// 最后保存一次数据
|
||||||
|
s.saveStatsData()
|
||||||
|
|
||||||
|
// 停止服务器
|
||||||
|
s.cancel()
|
||||||
if s.server != nil {
|
if s.server != nil {
|
||||||
s.server.Shutdown()
|
s.server.Shutdown()
|
||||||
}
|
}
|
||||||
s.cancel()
|
|
||||||
logger.Info("DNS服务器已停止")
|
logger.Info("DNS服务器已停止")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,3 +481,135 @@ func (s *Server) GetHourlyStats() map[string]int64 {
|
|||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// loadStatsData 从文件加载统计数据
|
||||||
|
func (s *Server) loadStatsData() {
|
||||||
|
if s.config.StatsFile == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查文件是否存在
|
||||||
|
data, err := ioutil.ReadFile(s.config.StatsFile)
|
||||||
|
if err != nil {
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
logger.Error("读取统计数据文件失败", "error", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var statsData StatsData
|
||||||
|
err = json.Unmarshal(data, &statsData)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("解析统计数据失败", "error", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 恢复统计数据
|
||||||
|
s.statsMutex.Lock()
|
||||||
|
if statsData.Stats != nil {
|
||||||
|
s.stats = statsData.Stats
|
||||||
|
}
|
||||||
|
s.statsMutex.Unlock()
|
||||||
|
|
||||||
|
s.blockedDomainsMutex.Lock()
|
||||||
|
if statsData.BlockedDomains != nil {
|
||||||
|
s.blockedDomains = statsData.BlockedDomains
|
||||||
|
}
|
||||||
|
s.blockedDomainsMutex.Unlock()
|
||||||
|
|
||||||
|
s.resolvedDomainsMutex.Lock()
|
||||||
|
if statsData.ResolvedDomains != nil {
|
||||||
|
s.resolvedDomains = statsData.ResolvedDomains
|
||||||
|
}
|
||||||
|
s.resolvedDomainsMutex.Unlock()
|
||||||
|
|
||||||
|
s.hourlyStatsMutex.Lock()
|
||||||
|
if statsData.HourlyStats != nil {
|
||||||
|
s.hourlyStats = statsData.HourlyStats
|
||||||
|
}
|
||||||
|
s.hourlyStatsMutex.Unlock()
|
||||||
|
|
||||||
|
logger.Info("统计数据加载成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// saveStatsData 保存统计数据到文件
|
||||||
|
func (s *Server) saveStatsData() {
|
||||||
|
if s.config.StatsFile == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建数据目录
|
||||||
|
statsDir := filepath.Dir(s.config.StatsFile)
|
||||||
|
err := os.MkdirAll(statsDir, 0755)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("创建统计数据目录失败", "error", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 收集所有统计数据
|
||||||
|
statsData := &StatsData{
|
||||||
|
Stats: s.GetStats(),
|
||||||
|
LastSaved: time.Now(),
|
||||||
|
}
|
||||||
|
|
||||||
|
// 复制域名数据
|
||||||
|
s.blockedDomainsMutex.RLock()
|
||||||
|
statsData.BlockedDomains = make(map[string]*BlockedDomain)
|
||||||
|
for k, v := range s.blockedDomains {
|
||||||
|
statsData.BlockedDomains[k] = v
|
||||||
|
}
|
||||||
|
s.blockedDomainsMutex.RUnlock()
|
||||||
|
|
||||||
|
s.resolvedDomainsMutex.RLock()
|
||||||
|
statsData.ResolvedDomains = make(map[string]*BlockedDomain)
|
||||||
|
for k, v := range s.resolvedDomains {
|
||||||
|
statsData.ResolvedDomains[k] = v
|
||||||
|
}
|
||||||
|
s.resolvedDomainsMutex.RUnlock()
|
||||||
|
|
||||||
|
s.hourlyStatsMutex.RLock()
|
||||||
|
statsData.HourlyStats = make(map[string]int64)
|
||||||
|
for k, v := range s.hourlyStats {
|
||||||
|
statsData.HourlyStats[k] = v
|
||||||
|
}
|
||||||
|
s.hourlyStatsMutex.RUnlock()
|
||||||
|
|
||||||
|
// 序列化数据
|
||||||
|
jsonData, err := json.MarshalIndent(statsData, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("序列化统计数据失败", "error", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写入文件
|
||||||
|
err = ioutil.WriteFile(s.config.StatsFile, jsonData, 0644)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("保存统计数据到文件失败", "error", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("统计数据保存成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// startAutoSave 启动自动保存功能
|
||||||
|
func (s *Server) startAutoSave() {
|
||||||
|
if s.config.StatsFile == "" || s.config.SaveInterval <= 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置定时器
|
||||||
|
s.saveTicker = time.NewTicker(time.Duration(s.config.SaveInterval) * time.Second)
|
||||||
|
defer s.saveTicker.Stop()
|
||||||
|
|
||||||
|
logger.Info("启动统计数据自动保存功能", "interval", s.config.SaveInterval, "file", s.config.StatsFile)
|
||||||
|
|
||||||
|
// 定期保存数据
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-s.saveTicker.C:
|
||||||
|
s.saveStatsData()
|
||||||
|
case <-s.saveDone:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
||hm.baidu.com
|
||hm.baidu.com
|
||||||
|
||baidu.com
|
||||||
/.*tracking.*/
|
/.*tracking.*/
|
||||||
/adjust.net/
|
/adjust.net/
|
||||||
|
/ad./
|
||||||
@@ -3,10 +3,12 @@ package shield
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -23,6 +25,13 @@ type regexRule struct {
|
|||||||
original string
|
original string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ShieldStatsData 用于持久化的Shield统计数据
|
||||||
|
type ShieldStatsData struct {
|
||||||
|
BlockedDomainsCount map[string]int `json:"blockedDomainsCount"`
|
||||||
|
ResolvedDomainsCount map[string]int `json:"resolvedDomainsCount"`
|
||||||
|
LastSaved time.Time `json:"lastSaved"`
|
||||||
|
}
|
||||||
|
|
||||||
// ShieldManager 屏蔽管理器
|
// ShieldManager 屏蔽管理器
|
||||||
type ShieldManager struct {
|
type ShieldManager struct {
|
||||||
config *config.ShieldConfig
|
config *config.ShieldConfig
|
||||||
@@ -42,7 +51,7 @@ type ShieldManager struct {
|
|||||||
// NewShieldManager 创建屏蔽管理器实例
|
// NewShieldManager 创建屏蔽管理器实例
|
||||||
func NewShieldManager(config *config.ShieldConfig) *ShieldManager {
|
func NewShieldManager(config *config.ShieldConfig) *ShieldManager {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
return &ShieldManager{
|
manager := &ShieldManager{
|
||||||
config: config,
|
config: config,
|
||||||
domainRules: make(map[string]bool),
|
domainRules: make(map[string]bool),
|
||||||
domainExceptions: make(map[string]bool),
|
domainExceptions: make(map[string]bool),
|
||||||
@@ -54,6 +63,11 @@ func NewShieldManager(config *config.ShieldConfig) *ShieldManager {
|
|||||||
updateCtx: ctx,
|
updateCtx: ctx,
|
||||||
updateCancel: cancel,
|
updateCancel: cancel,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 加载已保存的计数数据
|
||||||
|
manager.loadStatsData()
|
||||||
|
|
||||||
|
return manager
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadRules 加载屏蔽规则
|
// LoadRules 加载屏蔽规则
|
||||||
@@ -651,6 +665,9 @@ func (m *ShieldManager) StartAutoUpdate() {
|
|||||||
ticker := time.NewTicker(time.Duration(m.config.UpdateInterval) * time.Second)
|
ticker := time.NewTicker(time.Duration(m.config.UpdateInterval) * time.Second)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
|
|
||||||
|
// 启动自动保存计数数据
|
||||||
|
go m.startAutoSaveStats()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
@@ -661,16 +678,27 @@ func (m *ShieldManager) StartAutoUpdate() {
|
|||||||
logger.Info("自动更新规则成功")
|
logger.Info("自动更新规则成功")
|
||||||
}
|
}
|
||||||
case <-m.updateCtx.Done():
|
case <-m.updateCtx.Done():
|
||||||
|
// 保存计数数据
|
||||||
|
m.saveStatsData()
|
||||||
m.updateRunning = false
|
m.updateRunning = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
logger.Info("规则自动更新已启动", "interval", m.config.UpdateInterval)
|
||||||
|
|
||||||
|
// 如果是首次启动,先保存一次数据确保目录存在
|
||||||
|
go m.saveStatsData()
|
||||||
}
|
}
|
||||||
|
|
||||||
// StopAutoUpdate 停止自动更新
|
// StopAutoUpdate 停止自动更新
|
||||||
func (m *ShieldManager) StopAutoUpdate() {
|
func (m *ShieldManager) StopAutoUpdate() {
|
||||||
|
m.updateRunning = false
|
||||||
m.updateCancel()
|
m.updateCancel()
|
||||||
|
// 保存计数数据
|
||||||
|
m.saveStatsData()
|
||||||
|
logger.Info("规则自动更新已停止")
|
||||||
}
|
}
|
||||||
|
|
||||||
// saveRulesToFile 保存规则到文件
|
// saveRulesToFile 保存规则到文件
|
||||||
@@ -781,7 +809,112 @@ func (m *ShieldManager) GetStats() map[string]interface{} {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRules 获取所有规则的详细列表
|
// loadStatsData 从文件加载计数数据
|
||||||
|
func (m *ShieldManager) loadStatsData() {
|
||||||
|
if m.config.StatsFile == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查文件是否存在
|
||||||
|
data, err := ioutil.ReadFile(m.config.StatsFile)
|
||||||
|
if err != nil {
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
logger.Error("读取Shield计数数据文件失败", "error", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var statsData ShieldStatsData
|
||||||
|
err = json.Unmarshal(data, &statsData)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("解析Shield计数数据失败", "error", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 恢复计数数据
|
||||||
|
m.rulesMutex.Lock()
|
||||||
|
if statsData.BlockedDomainsCount != nil {
|
||||||
|
m.blockedDomainsCount = statsData.BlockedDomainsCount
|
||||||
|
}
|
||||||
|
if statsData.ResolvedDomainsCount != nil {
|
||||||
|
m.resolvedDomainsCount = statsData.ResolvedDomainsCount
|
||||||
|
}
|
||||||
|
m.rulesMutex.Unlock()
|
||||||
|
|
||||||
|
logger.Info("Shield计数数据加载成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// saveStatsData 保存计数数据到文件
|
||||||
|
func (m *ShieldManager) saveStatsData() {
|
||||||
|
if m.config.StatsFile == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建数据目录
|
||||||
|
statsDir := filepath.Dir(m.config.StatsFile)
|
||||||
|
err := os.MkdirAll(statsDir, 0755)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("创建Shield统计数据目录失败", "error", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 收集计数数据
|
||||||
|
m.rulesMutex.RLock()
|
||||||
|
statsData := &ShieldStatsData{
|
||||||
|
BlockedDomainsCount: make(map[string]int),
|
||||||
|
ResolvedDomainsCount: make(map[string]int),
|
||||||
|
LastSaved: time.Now(),
|
||||||
|
}
|
||||||
|
|
||||||
|
// 复制数据
|
||||||
|
for k, v := range m.blockedDomainsCount {
|
||||||
|
statsData.BlockedDomainsCount[k] = v
|
||||||
|
}
|
||||||
|
for k, v := range m.resolvedDomainsCount {
|
||||||
|
statsData.ResolvedDomainsCount[k] = v
|
||||||
|
}
|
||||||
|
m.rulesMutex.RUnlock()
|
||||||
|
|
||||||
|
// 序列化数据
|
||||||
|
jsonData, err := json.MarshalIndent(statsData, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("序列化Shield计数数据失败", "error", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写入文件
|
||||||
|
err = ioutil.WriteFile(m.config.StatsFile, jsonData, 0644)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("保存Shield计数数据到文件失败", "error", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("Shield计数数据保存成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// startAutoSaveStats 启动计数数据自动保存功能
|
||||||
|
func (m *ShieldManager) startAutoSaveStats() {
|
||||||
|
if m.config.StatsFile == "" || m.config.StatsSaveInterval <= 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ticker := time.NewTicker(time.Duration(m.config.StatsSaveInterval) * time.Second)
|
||||||
|
defer ticker.Stop()
|
||||||
|
|
||||||
|
logger.Info("启动Shield计数数据自动保存功能", "interval", m.config.StatsSaveInterval, "file", m.config.StatsFile)
|
||||||
|
|
||||||
|
// 定期保存数据
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ticker.C:
|
||||||
|
m.saveStatsData()
|
||||||
|
case <-m.updateCtx.Done():
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRules 获取所有规则
|
||||||
func (m *ShieldManager) GetRules() map[string]interface{} {
|
func (m *ShieldManager) GetRules() map[string]interface{} {
|
||||||
m.rulesMutex.RLock()
|
m.rulesMutex.RLock()
|
||||||
defer m.rulesMutex.RUnlock()
|
defer m.rulesMutex.RUnlock()
|
||||||
|
|||||||
Reference in New Issue
Block a user