增加数据持久化功能
This commit is contained in:
@@ -5,11 +5,13 @@ import (
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
// DNSConfig DNS服务器配置
|
||||
// DNSConfig DNS配置
|
||||
type DNSConfig struct {
|
||||
Port int `json:"port"`
|
||||
UpstreamDNS []string `json:"upstreamDNS"`
|
||||
Timeout int `json:"timeout"`
|
||||
Port int `json:"port"`
|
||||
UpstreamDNS []string `json:"upstreamDNS"`
|
||||
Timeout int `json:"timeout"`
|
||||
StatsFile string `json:"statsFile"` // 统计数据持久化文件
|
||||
SaveInterval int `json:"saveInterval"` // 数据保存间隔(秒)
|
||||
}
|
||||
|
||||
// HTTPConfig HTTP控制台配置
|
||||
@@ -21,12 +23,14 @@ type HTTPConfig struct {
|
||||
|
||||
// ShieldConfig 屏蔽规则配置
|
||||
type ShieldConfig struct {
|
||||
LocalRulesFile string `json:"localRulesFile"`
|
||||
RemoteRules []string `json:"remoteRules"`
|
||||
UpdateInterval int `json:"updateInterval"`
|
||||
HostsFile string `json:"hostsFile"`
|
||||
BlockMethod string `json:"blockMethod"` // 屏蔽方法: "NXDOMAIN", "refused", "emptyIP", "customIP"
|
||||
CustomBlockIP string `json:"customBlockIP"` // 自定义屏蔽IP,当BlockMethod为"customIP"时使用
|
||||
LocalRulesFile string `json:"localRulesFile"`
|
||||
RemoteRules []string `json:"remoteRules"`
|
||||
UpdateInterval int `json:"updateInterval"`
|
||||
HostsFile string `json:"hostsFile"`
|
||||
BlockMethod string `json:"blockMethod"` // 屏蔽方法: "NXDOMAIN", "refused", "emptyIP", "customIP"
|
||||
CustomBlockIP string `json:"customBlockIP"` // 自定义屏蔽IP,当BlockMethod为"customIP"时使用
|
||||
StatsFile string `json:"statsFile"` // 计数数据持久化文件
|
||||
StatsSaveInterval int `json:"statsSaveInterval"` // 计数数据保存间隔(秒)
|
||||
}
|
||||
|
||||
// LogConfig 日志配置
|
||||
@@ -64,7 +68,13 @@ func LoadConfig(path string) (*Config, error) {
|
||||
config.DNS.Port = 53
|
||||
}
|
||||
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 {
|
||||
config.HTTP.Port = 8080
|
||||
@@ -78,6 +88,12 @@ func LoadConfig(path string) (*Config, error) {
|
||||
if config.Shield.BlockMethod == "" {
|
||||
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 == "" {
|
||||
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: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: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 (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -23,6 +27,15 @@ type BlockedDomain struct {
|
||||
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服务器
|
||||
type Server struct {
|
||||
config *config.DNSConfig
|
||||
@@ -40,6 +53,8 @@ type Server struct {
|
||||
resolvedDomains map[string]*BlockedDomain // 用于记录解析的域名
|
||||
hourlyStatsMutex sync.RWMutex
|
||||
hourlyStats map[string]int64 // 按小时统计屏蔽数量
|
||||
saveTicker *time.Ticker // 用于定时保存数据
|
||||
saveDone chan struct{} // 用于通知保存协程停止
|
||||
}
|
||||
|
||||
// Stats DNS服务器统计信息
|
||||
@@ -54,7 +69,7 @@ type Stats struct {
|
||||
// NewServer 创建DNS服务器实例
|
||||
func NewServer(config *config.DNSConfig, shieldConfig *config.ShieldConfig, shieldManager *shield.ShieldManager) *Server {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
return &Server{
|
||||
server := &Server{
|
||||
config: config,
|
||||
shieldConfig: shieldConfig,
|
||||
shieldManager: shieldManager,
|
||||
@@ -73,7 +88,14 @@ func NewServer(config *config.DNSConfig, shieldConfig *config.ShieldConfig, shie
|
||||
blockedDomains: make(map[string]*BlockedDomain),
|
||||
resolvedDomains: make(map[string]*BlockedDomain),
|
||||
hourlyStats: make(map[string]int64),
|
||||
saveDone: make(chan struct{}),
|
||||
}
|
||||
|
||||
// 加载已保存的统计数据
|
||||
server.loadStatsData()
|
||||
|
||||
return server
|
||||
|
||||
}
|
||||
|
||||
// Start 启动DNS服务器
|
||||
@@ -116,10 +138,17 @@ func (s *Server) Start() error {
|
||||
|
||||
// Stop 停止DNS服务器
|
||||
func (s *Server) Stop() {
|
||||
// 发送停止信号给保存协程
|
||||
close(s.saveDone)
|
||||
|
||||
// 最后保存一次数据
|
||||
s.saveStatsData()
|
||||
|
||||
// 停止服务器
|
||||
s.cancel()
|
||||
if s.server != nil {
|
||||
s.server.Shutdown()
|
||||
}
|
||||
s.cancel()
|
||||
logger.Info("DNS服务器已停止")
|
||||
}
|
||||
|
||||
@@ -452,3 +481,135 @@ func (s *Server) GetHourlyStats() map[string]int64 {
|
||||
}
|
||||
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
|
||||
||baidu.com
|
||||
/.*tracking.*/
|
||||
/adjust.net/
|
||||
/adjust.net/
|
||||
/ad./
|
||||
@@ -3,10 +3,12 @@ package shield
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
@@ -23,6 +25,13 @@ type regexRule struct {
|
||||
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 屏蔽管理器
|
||||
type ShieldManager struct {
|
||||
config *config.ShieldConfig
|
||||
@@ -42,7 +51,7 @@ type ShieldManager struct {
|
||||
// NewShieldManager 创建屏蔽管理器实例
|
||||
func NewShieldManager(config *config.ShieldConfig) *ShieldManager {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
return &ShieldManager{
|
||||
manager := &ShieldManager{
|
||||
config: config,
|
||||
domainRules: make(map[string]bool),
|
||||
domainExceptions: make(map[string]bool),
|
||||
@@ -54,6 +63,11 @@ func NewShieldManager(config *config.ShieldConfig) *ShieldManager {
|
||||
updateCtx: ctx,
|
||||
updateCancel: cancel,
|
||||
}
|
||||
|
||||
// 加载已保存的计数数据
|
||||
manager.loadStatsData()
|
||||
|
||||
return manager
|
||||
}
|
||||
|
||||
// LoadRules 加载屏蔽规则
|
||||
@@ -651,6 +665,9 @@ func (m *ShieldManager) StartAutoUpdate() {
|
||||
ticker := time.NewTicker(time.Duration(m.config.UpdateInterval) * time.Second)
|
||||
defer ticker.Stop()
|
||||
|
||||
// 启动自动保存计数数据
|
||||
go m.startAutoSaveStats()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
@@ -661,16 +678,27 @@ func (m *ShieldManager) StartAutoUpdate() {
|
||||
logger.Info("自动更新规则成功")
|
||||
}
|
||||
case <-m.updateCtx.Done():
|
||||
// 保存计数数据
|
||||
m.saveStatsData()
|
||||
m.updateRunning = false
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
logger.Info("规则自动更新已启动", "interval", m.config.UpdateInterval)
|
||||
|
||||
// 如果是首次启动,先保存一次数据确保目录存在
|
||||
go m.saveStatsData()
|
||||
}
|
||||
|
||||
// StopAutoUpdate 停止自动更新
|
||||
func (m *ShieldManager) StopAutoUpdate() {
|
||||
m.updateRunning = false
|
||||
m.updateCancel()
|
||||
// 保存计数数据
|
||||
m.saveStatsData()
|
||||
logger.Info("规则自动更新已停止")
|
||||
}
|
||||
|
||||
// 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{} {
|
||||
m.rulesMutex.RLock()
|
||||
defer m.rulesMutex.RUnlock()
|
||||
|
||||
Reference in New Issue
Block a user