Files
dns-server/config/config.go
T
Alex Yang f627244b8f 更新
2026-03-30 01:04:46 +08:00

225 lines
9.0 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"`
}
// 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配置
Log LogConfig `json:"log"`
}
// 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),
},
}
// 如果黑名单列表为空,添加一些默认的黑名单
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
}