// DNS Server API // @title DNS Server API // @version 1.0 // @description DNS服务器API文档 // @termsOfService http://swagger.io/terms/ // @contact.name API Support // @contact.email support@example.com // @license.name Apache 2.0 // @license.url http://www.apache.org/licenses/LICENSE-2.0.html // @host localhost:8080 // @BasePath /api package main import ( "flag" "fmt" "log" "os" "os/signal" "path/filepath" "syscall" "dns-server/config" "dns-server/dns" "dns-server/gfw" "dns-server/http" "dns-server/logger" "dns-server/shield" ) // createDefaultConfig 创建默认配置文件 func createDefaultConfig(configFile string) error { // 默认配置内容 defaultConfig := `# DNS服务器配置文件 # 格式:INI格式,使用#注释 [dns] # DNS服务器监听端口 port = 53 # 上游DNS服务器列表,逗号分隔 upstreamDNS = 223.5.5.5:53, 223.6.6.6:53 # DNSSEC专用服务器列表,逗号分隔 dnssecUpstreamDNS = 8.8.8.8:53, 1.1.1.1:53 # 数据保存间隔(秒) saveInterval = 300 # DNS缓存过期时间(分钟) cacheTTL = 30 # 是否启用DNSSEC支持 enableDNSSEC = true # 查询模式:parallel(并行请求)、fastest-ip(最快的IP地址) queryMode = parallel # 查询超时时间(毫秒) queryTimeout = 5000 # 是否启用快速返回机制 enableFastReturn = true # 不验证DNSSEC的域名模式列表,逗号分隔 noDNSSECDomains = # 是否启用IPv6解析(AAAA记录) enableIPv6 = false # 缓存模式:memory(内存缓存)、file(文件缓存) cacheMode = memory # 缓存大小限制(MB) cacheSize = 100 # 最大缓存TTL(分钟) maxCacheTTL = 120 # 最小缓存TTL(分钟) minCacheTTL = 5 [http] # HTTP控制台监听端口 port = 8080 # HTTP控制台监听地址 host = 0.0.0.0 # 是否启用API enableAPI = true # 登录用户名 username = admin # 登录密码 password = admin [shield] # 屏蔽规则更新间隔(秒) updateInterval = 3600 # 屏蔽方法: NXDOMAIN, refused, emptyIP, customIP blockMethod = NXDOMAIN # 自定义屏蔽IP,当BlockMethod为"customIP"时使用 customBlockIP = # 计数数据保存间隔(秒) statsSaveInterval = 60 # 黑名单配置 # 格式:blacklist_名称 = URL,enabled blacklist_AdGuard_DNS_filter = https://gitea.amazehome.xyz/AMAZEHOME/hosts-and-filters/raw/branch/main/filter.txt,true blacklist_Adaway_Default_Blocklist = https://gitea.amazehome.xyz/AMAZEHOME/hosts-and-Filters/raw/branch/main/hosts/adaway.txt,true blacklist_CHN_anti_AD = https://gitea.amazehome.xyz/AMAZEHOME/hosts-and-Filters/raw/branch/main/list/easylist.txt,true blacklist_My_GitHub_Rules = https://gitea.amazehome.xyz/AMAZEHOME/hosts-and-filters/raw/branch/main/rules/costomize.txt,true [gfwList] # GFWList域名解析的目标IP地址 ip = 127.0.0.1 # GFWList规则文件路径 content = ./data/gfwlist.txt # 是否启用GFWList功能 enabled = true [log] # 日志级别:debug, info, warn, error level = debug # 日志文件最大大小(MB) maxSize = 100 # 日志文件最大备份数 maxBackups = 10 # 日志文件最大保留天数 maxAge = 30 ` // 写入默认配置到文件 return os.WriteFile(configFile, []byte(defaultConfig), 0644) } // createRequiredFiles 创建所需的文件和文件夹 func createRequiredFiles(cfg *config.Config) error { // 创建数据文件夹 dataDir := "./data" if err := os.MkdirAll(dataDir, 0755); err != nil { return fmt.Errorf("创建数据文件夹失败: %w", err) } // 创建远程规则缓存文件夹 if err := os.MkdirAll("data/remote_rules", 0755); err != nil { return fmt.Errorf("创建远程规则缓存文件夹失败: %w", err) } // 创建日志文件夹 logDir := filepath.Dir("logs/dns-server.log") if logDir != "." { if err := os.MkdirAll(logDir, 0755); err != nil { return fmt.Errorf("创建日志文件夹失败: %w", err) } } // 创建自定义规则文件 if _, err := os.Stat("data/rules.txt"); os.IsNotExist(err) { if err := os.WriteFile("data/rules.txt", []byte("# 自定义规则文件\n# 格式:域名\n# 例如:example.com\n"), 0644); err != nil { return fmt.Errorf("创建自定义规则文件失败: %w", err) } } // 创建Hosts文件 if _, err := os.Stat("data/hosts.txt"); os.IsNotExist(err) { if err := os.WriteFile("data/hosts.txt", []byte("# Hosts文件\n# 格式:IP 域名\n# 例如:127.0.0.1 localhost\n"), 0644); err != nil { return fmt.Errorf("创建Hosts文件失败: %w", err) } } // 创建GFWList文件 if _, err := os.Stat("data/gfwlist.txt"); os.IsNotExist(err) { if err := os.WriteFile("data/gfwlist.txt", []byte("# GFWList规则文件\n# 格式:每行一条规则\n# 例如:www.google.com\n"), 0644); err != nil { return fmt.Errorf("创建GFWList文件失败: %w", err) } } // 创建统计数据文件 if _, err := os.Stat("data/stats.json"); os.IsNotExist(err) { if err := os.WriteFile("data/stats.json", []byte("{}"), 0644); err != nil { return fmt.Errorf("创建统计数据文件失败: %w", err) } } // 创建Shield统计数据文件 if _, err := os.Stat("data/shield_stats.json"); os.IsNotExist(err) { if err := os.WriteFile("data/shield_stats.json", []byte("{}"), 0644); err != nil { return fmt.Errorf("创建Shield统计数据文件失败: %w", err) } } return nil } func main() { // 命令行参数解析 var configFile string flag.StringVar(&configFile, "config", "config.ini", "配置文件路径") flag.Parse() // 检查配置文件是否存在,如果不存在则创建默认配置文件 if _, err := os.Stat(configFile); os.IsNotExist(err) { log.Printf("配置文件 %s 不存在,正在创建默认配置文件...", configFile) if err := createDefaultConfig(configFile); err != nil { log.Fatalf("创建默认配置文件失败: %v", err) } log.Printf("默认配置文件 %s 创建成功", configFile) } // 初始化配置 var cfg *config.Config var err error cfg, err = config.LoadConfig(configFile) if err != nil { log.Fatalf("加载配置失败: %v", err) } // 创建所需的文件和文件夹 log.Println("正在创建所需的文件和文件夹...") if err := createRequiredFiles(cfg); err != nil { log.Fatalf("创建所需文件和文件夹失败: %v", err) } log.Println("所需文件和文件夹创建成功") // 初始化日志系统 if err := logger.InitLogger("logs/dns-server.log", cfg.Log.Level, 0, 0, 0, false); err != nil { log.Fatalf("初始化日志系统失败: %v", err) } defer logger.Close() // 初始化屏蔽管理系统 shieldManager := shield.NewShieldManager(&cfg.Shield) if err := shieldManager.LoadLocalRulesOnly(); err != nil { logger.Error("加载本地屏蔽规则失败", "error", err) } // 初始化GFWList管理系统 gfwManager := gfw.NewGFWListManager(&cfg.GFWList) if err := gfwManager.LoadRules(); err != nil { logger.Error("加载GFWList规则失败", "error", err) } // 启动DNS服务器 dnsServer := dns.NewServer(cfg, shieldManager, gfwManager) go func() { if err := dnsServer.Start(); err != nil { logger.Error("DNS服务器启动失败", "error", err) os.Exit(1) } }() // 启动HTTP控制台服务器 httpServer := http.NewServer(cfg, dnsServer, shieldManager, gfwManager) go func() { if err := httpServer.Start(); err != nil { logger.Error("HTTP控制台服务器启动失败", "error", err) } }() // 异步加载远程规则 go func() { logger.Info("开始异步加载远程屏蔽规则") if err := shieldManager.LoadRules(); err != nil { logger.Error("异步加载远程屏蔽规则失败", "error", err) } else { logger.Info("远程屏蔽规则异步加载完成") } }() // 启动定时更新任务 go shieldManager.StartAutoUpdate() logger.Info(fmt.Sprintf("DNS服务器已启动,监听端口: %d", cfg.DNS.Port)) logger.Info(fmt.Sprintf("HTTP控制台已启动,监听端口: %d", cfg.HTTP.Port)) // 监听信号 sigCh := make(chan os.Signal, 1) signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) <-sigCh // 清理资源 logger.Info("正在关闭服务...") dnsServer.Stop() httpServer.Stop() shieldManager.StopAutoUpdate() logger.Info("服务已关闭") }