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"` } // 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"` } // 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"` } // 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(8080), 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), }, 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"), }, } // 如果黑名单列表为空,添加一些默认的黑名单 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}, } } 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 }