351 lines
15 KiB
Go
351 lines
15 KiB
Go
package config
|
|
|
|
import (
|
|
"io/ioutil"
|
|
"strings"
|
|
|
|
"gopkg.in/ini.v1"
|
|
)
|
|
|
|
// DomainSpecificDNS 域名特定 DNS 服务器配置
|
|
// INI 格式:domain_域名匹配字符串 = DNS 服务器 1, DNS 服务器 2
|
|
// 例如:domain_google.com = 8.8.8.8:53, 8.8.4.4:53
|
|
|
|
type DomainSpecificDNS map[string][]string
|
|
|
|
// DNSConfig DNS 配置
|
|
type DNSConfig struct {
|
|
Port int `json:"port"`
|
|
UpstreamDNS []string `json:"upstreamDNS"`
|
|
DNSSECUpstreamDNS []string `json:"dnssecUpstreamDNS"` // 用于 DNSSEC 查询的专用服务器
|
|
SaveInterval int `json:"saveInterval"` // 数据保存间隔(秒)
|
|
CacheTTL int `json:"cacheTTL"` // DNS 缓存过期时间(分钟)
|
|
EnableDNSSEC bool `json:"enableDNSSEC"` // 是否启用 DNSSEC 支持
|
|
QueryMode string `json:"queryMode"` // 查询模式:"parallel"(并行请求)、"fastest-ip"(最快的 IP 地址)
|
|
QueryTimeout int `json:"queryTimeout"` // 查询超时时间(毫秒)
|
|
EnableFastReturn bool `json:"enableFastReturn"` // 是否启用快速返回机制
|
|
DomainSpecificDNS DomainSpecificDNS `json:"domainSpecificDNS"` // 域名特定 DNS 服务器配置
|
|
NoDNSSECDomains []string `json:"noDNSSECDomains"` // 不验证 DNSSEC 的域名模式列表
|
|
EnableIPv6 bool `json:"enableIPv6"` // 是否启用 IPv6 解析(AAAA 记录)
|
|
CacheMode string `json:"cacheMode"` // 缓存模式:"memory"(内存缓存)、"file"(文件缓存)
|
|
CacheSize int `json:"cacheSize"` // 缓存大小限制(MB),0 表示不缓存
|
|
MaxCacheTTL int `json:"maxCacheTTL"` // 最大缓存 TTL(分钟)
|
|
MinCacheTTL int `json:"minCacheTTL"` // 最小缓存 TTL(分钟)
|
|
CacheFilePath string `json:"cacheFilePath"` // 缓存文件路径
|
|
}
|
|
|
|
// HTTPConfig HTTP 控制台配置
|
|
type HTTPConfig struct {
|
|
Port int `json:"port"`
|
|
Host string `json:"host"`
|
|
EnableAPI bool `json:"enableAPI"`
|
|
Username string `json:"username"` // 登录用户名
|
|
Password string `json:"password"` // 登录密码
|
|
}
|
|
|
|
// BlacklistEntry 黑名单条目
|
|
type BlacklistEntry struct {
|
|
Name string `json:"name"`
|
|
URL string `json:"url"`
|
|
Enabled bool `json:"enabled"`
|
|
RuleCount int `json:"ruleCount,omitempty"`
|
|
LastUpdateTime string `json:"lastUpdateTime,omitempty"`
|
|
}
|
|
|
|
// DomainInfoEntry 域名信息条目
|
|
type DomainInfoEntry struct {
|
|
Name string `json:"name"`
|
|
URL string `json:"url"`
|
|
Enabled bool `json:"enabled"`
|
|
Type string `json:"type"` // domain-info, threat-database, tracker
|
|
RuleCount int `json:"ruleCount,omitempty"`
|
|
LastUpdateTime string `json:"lastUpdateTime,omitempty"`
|
|
}
|
|
|
|
// DomainInfoConfig 域名信息配置
|
|
type DomainInfoConfig struct {
|
|
DomainInfoLists []DomainInfoEntry `json:"domainInfoLists"`
|
|
UpdateInterval int `json:"updateInterval"` // 更新间隔(秒)
|
|
EnableAutoUpdate bool `json:"enableAutoUpdate"` // 是否启用自动更新
|
|
}
|
|
|
|
// ShieldConfig 屏蔽规则配置
|
|
type ShieldConfig struct {
|
|
Blacklists []BlacklistEntry `json:"blacklists"`
|
|
UpdateInterval int `json:"updateInterval"`
|
|
BlockMethod string `json:"blockMethod"` // 屏蔽方法:"NXDOMAIN", "refused", "emptyIP", "customIP"
|
|
CustomBlockIP string `json:"customBlockIP"` // 自定义屏蔽 IP,当 BlockMethod 为"customIP"时使用
|
|
StatsSaveInterval int `json:"statsSaveInterval"` // 计数数据保存间隔(秒)
|
|
}
|
|
|
|
// GFWListConfig GFWList 配置
|
|
type GFWListConfig struct {
|
|
IP string `json:"ip"` // GFWList 域名解析的目标 IP 地址
|
|
Content string `json:"content"` // GFWList 规则文件路径
|
|
Enabled bool `json:"enabled"` // 是否启用 GFWList 功能
|
|
}
|
|
|
|
// LogConfig 日志配置
|
|
type LogConfig struct {
|
|
Level string `json:"level"`
|
|
MaxSize int `json:"maxSize"`
|
|
MaxBackups int `json:"maxBackups"`
|
|
MaxAge int `json:"maxAge"`
|
|
}
|
|
|
|
// QueryLogConfig 查询日志配置
|
|
type QueryLogConfig struct {
|
|
Enabled bool `json:"enabled"`
|
|
RingBufferSize int `json:"ringBufferSize"`
|
|
DatabasePath string `json:"databasePath"`
|
|
MaxDatabaseSizeMB int `json:"maxDatabaseSizeMB"`
|
|
EnableWAL bool `json:"enableWAL"`
|
|
|
|
// 归档配置
|
|
ArchiveEnabled bool `json:"archiveEnabled"`
|
|
ArchiveDir string `json:"archiveDir"`
|
|
ArchivePrefix string `json:"archivePrefix"`
|
|
CompressionLevel int `json:"compressionLevel"`
|
|
|
|
// 清理配置
|
|
RetentionDays int `json:"retentionDays"`
|
|
RetentionMonths int `json:"retentionMonths"`
|
|
|
|
// 查询配置
|
|
QueryTimeout int `json:"queryTimeout"`
|
|
EnableCache bool `json:"enableCache"`
|
|
CacheTTL int `json:"cacheTTL"`
|
|
}
|
|
|
|
// Config 整体配置
|
|
type Config struct {
|
|
DNS DNSConfig `json:"dns"`
|
|
HTTP HTTPConfig `json:"http"`
|
|
Shield ShieldConfig `json:"shield"`
|
|
GFWList GFWListConfig `json:"gfwList"` // GFWList 配置
|
|
Threat ThreatConfig `json:"threat"` // 威胁检测配置
|
|
Log LogConfig `json:"log"`
|
|
QueryLog QueryLogConfig `json:"queryLog"` // 查询日志配置
|
|
DomainInfo DomainInfoConfig `json:"domainInfo"` // 域名信息配置
|
|
}
|
|
|
|
// ThreatConfig 威胁检测配置
|
|
type ThreatConfig struct {
|
|
Enabled bool `json:"enabled"`
|
|
QueryRateThreshold int `json:"queryRateThreshold"` // 每分钟查询阈值,0 表示不限制
|
|
NXDomainThreshold int `json:"nxDomainThreshold"` // 每分钟 NXDOMAIN 阈值,0 表示不限制
|
|
MaxDomainLength int `json:"maxDomainLength"` // 最大域名长度,0 表示不限制
|
|
SuspiciousPatterns []string `json:"suspiciousPatterns"` // 可疑域名模式
|
|
UnusualQueryTypes []string `json:"unusualQueryTypes"` // 不常见的查询类型
|
|
AlertRetentionDays int `json:"alertRetentionDays"` // 告警保留天数,0 表示一直保存
|
|
ThreatDatabasePath string `json:"threatDatabasePath"` // 威胁域名数据库路径
|
|
}
|
|
|
|
// LoadConfig 加载配置文件
|
|
func LoadConfig(path string) (*Config, error) {
|
|
// 读取配置文件
|
|
data, err := ioutil.ReadFile(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// 解析 INI 文件
|
|
cfg, err := ini.Load(data)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// 初始化配置
|
|
config := &Config{
|
|
DNS: DNSConfig{
|
|
Port: cfg.Section("dns").Key("port").MustInt(53),
|
|
SaveInterval: cfg.Section("dns").Key("saveInterval").MustInt(300),
|
|
CacheTTL: cfg.Section("dns").Key("cacheTTL").MustInt(30),
|
|
EnableDNSSEC: cfg.Section("dns").Key("enableDNSSEC").MustBool(true),
|
|
QueryMode: cfg.Section("dns").Key("queryMode").MustString("parallel"),
|
|
QueryTimeout: cfg.Section("dns").Key("queryTimeout").MustInt(500),
|
|
EnableFastReturn: cfg.Section("dns").Key("enableFastReturn").MustBool(true),
|
|
EnableIPv6: cfg.Section("dns").Key("enableIPv6").MustBool(false),
|
|
CacheMode: cfg.Section("dns").Key("cacheMode").MustString("memory"),
|
|
CacheSize: cfg.Section("dns").Key("cacheSize").MustInt(100),
|
|
MaxCacheTTL: cfg.Section("dns").Key("maxCacheTTL").MustInt(120),
|
|
MinCacheTTL: cfg.Section("dns").Key("minCacheTTL").MustInt(5),
|
|
CacheFilePath: "data/cache.json", // 固定路径
|
|
UpstreamDNS: parseStringList(cfg.Section("dns").Key("upstreamDNS").MustString("223.5.5.5:53,223.6.6.6:53")),
|
|
DNSSECUpstreamDNS: parseStringList(cfg.Section("dns").Key("dnssecUpstreamDNS").MustString("8.8.8.8:53,1.1.1.1:53")),
|
|
NoDNSSECDomains: parseStringList(cfg.Section("dns").Key("noDNSSECDomains").MustString("")),
|
|
DomainSpecificDNS: parseDomainSpecificDNS(cfg.Section("dns")),
|
|
},
|
|
HTTP: HTTPConfig{
|
|
Port: cfg.Section("http").Key("port").MustInt(8081),
|
|
Host: cfg.Section("http").Key("host").MustString("0.0.0.0"),
|
|
EnableAPI: cfg.Section("http").Key("enableAPI").MustBool(true),
|
|
Username: cfg.Section("http").Key("username").MustString("admin"),
|
|
Password: cfg.Section("http").Key("password").MustString("admin"),
|
|
},
|
|
Shield: ShieldConfig{
|
|
UpdateInterval: cfg.Section("shield").Key("updateInterval").MustInt(3600),
|
|
BlockMethod: cfg.Section("shield").Key("blockMethod").MustString("NXDOMAIN"),
|
|
CustomBlockIP: cfg.Section("shield").Key("customBlockIP").MustString(""),
|
|
StatsSaveInterval: cfg.Section("shield").Key("statsSaveInterval").MustInt(300),
|
|
Blacklists: parseBlacklists(cfg.Section("shield")),
|
|
},
|
|
GFWList: GFWListConfig{
|
|
IP: cfg.Section("gfwList").Key("ip").MustString("127.0.0.1"),
|
|
Content: cfg.Section("gfwList").Key("content").MustString(""),
|
|
Enabled: cfg.Section("gfwList").Key("enabled").MustBool(false),
|
|
},
|
|
Log: LogConfig{
|
|
Level: cfg.Section("log").Key("level").MustString("info"),
|
|
MaxSize: cfg.Section("log").Key("maxSize").MustInt(100),
|
|
MaxBackups: cfg.Section("log").Key("maxBackups").MustInt(10),
|
|
MaxAge: cfg.Section("log").Key("maxAge").MustInt(30),
|
|
},
|
|
QueryLog: QueryLogConfig{
|
|
Enabled: cfg.Section("queryLog").Key("enabled").MustBool(true),
|
|
RingBufferSize: cfg.Section("queryLog").Key("ringBufferSize").MustInt(10000),
|
|
DatabasePath: cfg.Section("queryLog").Key("databasePath").MustString("data/query_logs.db"),
|
|
MaxDatabaseSizeMB: cfg.Section("queryLog").Key("maxDatabaseSizeMB").MustInt(1024),
|
|
EnableWAL: cfg.Section("queryLog").Key("enableWAL").MustBool(true),
|
|
ArchiveEnabled: cfg.Section("queryLog").Key("archiveEnabled").MustBool(true),
|
|
ArchiveDir: cfg.Section("queryLog").Key("archiveDir").MustString("data/archive"),
|
|
ArchivePrefix: cfg.Section("queryLog").Key("archivePrefix").MustString("querylog"),
|
|
CompressionLevel: cfg.Section("queryLog").Key("compressionLevel").MustInt(6),
|
|
RetentionDays: cfg.Section("queryLog").Key("retentionDays").MustInt(0),
|
|
RetentionMonths: cfg.Section("queryLog").Key("retentionMonths").MustInt(0),
|
|
QueryTimeout: cfg.Section("queryLog").Key("queryTimeout").MustInt(5),
|
|
EnableCache: cfg.Section("queryLog").Key("enableCache").MustBool(true),
|
|
CacheTTL: cfg.Section("queryLog").Key("cacheTTL").MustInt(300),
|
|
},
|
|
Threat: ThreatConfig{
|
|
Enabled: cfg.Section("threat").Key("enabled").MustBool(true),
|
|
QueryRateThreshold: cfg.Section("threat").Key("queryRateThreshold").MustInt(0),
|
|
NXDomainThreshold: cfg.Section("threat").Key("nxDomainThreshold").MustInt(0),
|
|
MaxDomainLength: cfg.Section("threat").Key("maxDomainLength").MustInt(0),
|
|
SuspiciousPatterns: parseStringList(cfg.Section("threat").Key("suspiciousPatterns").MustString("malware,phishing,trojan,virus,ransomware")),
|
|
UnusualQueryTypes: parseStringList(cfg.Section("threat").Key("unusualQueryTypes").MustString("TXT,SRV,MX")),
|
|
AlertRetentionDays: cfg.Section("threat").Key("alertRetentionDays").MustInt(0),
|
|
ThreatDatabasePath: cfg.Section("threat").Key("threatDatabasePath").MustString("./static/domain-info/threats/threats-database.csv"),
|
|
},
|
|
DomainInfo: DomainInfoConfig{
|
|
UpdateInterval: cfg.Section("domainInfo").Key("updateInterval").MustInt(3600),
|
|
EnableAutoUpdate: cfg.Section("domainInfo").Key("enableAutoUpdate").MustBool(true),
|
|
DomainInfoLists: parseDomainInfoLists(cfg.Section("domainInfo")),
|
|
},
|
|
}
|
|
|
|
// 如果黑名单列表为空,添加一些默认的黑名单
|
|
if len(config.Shield.Blacklists) == 0 {
|
|
config.Shield.Blacklists = []BlacklistEntry{
|
|
{Name: "AdGuard DNS filter", URL: "https://gitea.amazehome.xyz/AMAZEHOME/hosts-and-filters/raw/branch/main/filter.txt", Enabled: true},
|
|
{Name: "Adaway Default Blocklist", URL: "https://gitea.amazehome.xyz/AMAZEHOME/hosts-and-Filters/raw/branch/main/hosts/adaway.txt", Enabled: true},
|
|
{Name: "CHN-anti-AD", URL: "https://gitea.amazehome.xyz/AMAZEHOME/hosts-and-Filters/raw/branch/main/list/easylist.txt", Enabled: true},
|
|
{Name: "My GitHub Rules", URL: "https://gitea.amazehome.xyz/AMAZEHOME/hosts-and-filters/raw/branch/main/rules/costomize.txt", Enabled: true},
|
|
}
|
|
}
|
|
|
|
// 如果域名信息列表为空,添加默认的域名信息列表
|
|
if len(config.DomainInfo.DomainInfoLists) == 0 {
|
|
config.DomainInfo.DomainInfoLists = []DomainInfoEntry{
|
|
{Name: "域名信息列表", URL: "https://gitea.amazehome.xyz/AMAZEHOME/domain-info/raw/branch/main/domains/domain-info.json", Enabled: true, Type: "domain-info"},
|
|
{Name: "威胁数据库", URL: "https://gitea.amazehome.xyz/AMAZEHOME/domain-info/raw/branch/main/threats/threats-database.csv", Enabled: true, Type: "threat-database"},
|
|
{Name: "跟踪器列表", URL: "https://gitea.amazehome.xyz/AMAZEHOME/domain-info/raw/branch/main/tracker/trackers.json", Enabled: true, Type: "tracker"},
|
|
}
|
|
}
|
|
|
|
return config, nil
|
|
}
|
|
|
|
// parseStringList 解析逗号分隔的字符串列表
|
|
func parseStringList(s string) []string {
|
|
if s == "" {
|
|
return []string{}
|
|
}
|
|
|
|
// 分割字符串
|
|
parts := []string{}
|
|
for _, part := range strings.Split(s, ",") {
|
|
part = strings.TrimSpace(part)
|
|
if part != "" {
|
|
parts = append(parts, part)
|
|
}
|
|
}
|
|
return parts
|
|
}
|
|
|
|
// parseDomainSpecificDNS 解析域名特定 DNS 服务器配置
|
|
func parseDomainSpecificDNS(section *ini.Section) DomainSpecificDNS {
|
|
domainDNS := make(DomainSpecificDNS)
|
|
|
|
// 遍历所有键,查找以"domain_"开头的键
|
|
for _, key := range section.Keys() {
|
|
if strings.HasPrefix(key.Name(), "domain_") {
|
|
domain := strings.TrimPrefix(key.Name(), "domain_")
|
|
dnsServers := parseStringList(key.String())
|
|
if len(dnsServers) > 0 {
|
|
domainDNS[domain] = dnsServers
|
|
}
|
|
}
|
|
}
|
|
|
|
return domainDNS
|
|
}
|
|
|
|
// parseBlacklists 解析黑名单配置
|
|
func parseBlacklists(section *ini.Section) []BlacklistEntry {
|
|
blacklists := []BlacklistEntry{}
|
|
|
|
// 遍历所有键,查找以"blacklist_"开头的键
|
|
for _, key := range section.Keys() {
|
|
if strings.HasPrefix(key.Name(), "blacklist_") {
|
|
// 提取黑名单名称和属性
|
|
name := strings.TrimPrefix(key.Name(), "blacklist_")
|
|
value := key.String()
|
|
|
|
// 解析黑名单 URL 和启用状态,格式:url,enabled
|
|
parts := strings.Split(value, ",")
|
|
if len(parts) >= 2 {
|
|
url := strings.TrimSpace(parts[0])
|
|
enabled := strings.TrimSpace(parts[1]) == "true"
|
|
blacklists = append(blacklists, BlacklistEntry{
|
|
Name: name,
|
|
URL: url,
|
|
Enabled: enabled,
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
return blacklists
|
|
}
|
|
|
|
// parseDomainInfoLists 解析域名信息列表配置
|
|
func parseDomainInfoLists(section *ini.Section) []DomainInfoEntry {
|
|
domainInfoLists := []DomainInfoEntry{}
|
|
|
|
// 遍历所有键,查找以"domainInfo_"开头的键
|
|
for _, key := range section.Keys() {
|
|
if strings.HasPrefix(key.Name(), "domainInfo_") {
|
|
// 提取域名信息名称和属性
|
|
name := strings.TrimPrefix(key.Name(), "domainInfo_")
|
|
value := key.String()
|
|
|
|
// 解析域名信息 URL 和启用状态,格式:url,type,enabled
|
|
parts := strings.Split(value, ",")
|
|
if len(parts) >= 3 {
|
|
url := strings.TrimSpace(parts[0])
|
|
entryType := strings.TrimSpace(parts[1])
|
|
enabled := strings.TrimSpace(parts[2]) == "true"
|
|
domainInfoLists = append(domainInfoLists, DomainInfoEntry{
|
|
Name: name,
|
|
URL: url,
|
|
Type: entryType,
|
|
Enabled: enabled,
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
return domainInfoLists
|
|
}
|