diff --git a/.trae/documents/修复规则更新后没有生效的问题.md b/.trae/documents/修复规则更新后没有生效的问题.md new file mode 100644 index 0000000..fc57f94 --- /dev/null +++ b/.trae/documents/修复规则更新后没有生效的问题.md @@ -0,0 +1,48 @@ +# 问题分析 + +1. **问题现象**:规则更新后,规则没有生效。用户添加或删除规则后,DNS服务器仍然使用旧的规则进行域名屏蔽。 + +2. **问题根源**: + - 在`addDomainRule`方法中,当添加一个域名规则时,它会为该域名的所有子域名也添加规则。例如,添加`example.com`规则时,会同时添加`example.com`和`com`规则。 + - 但是,在`RemoveRule`方法中,当删除一个域名规则时,它只删除了指定的域名规则,而没有删除为子域名添加的规则。 + - 这导致即使删除了主规则,子域名规则仍然存在,因此规则仍然生效。 + +3. **具体问题**: + - 当添加`||test.example.com`规则时,`addDomainRule`方法会添加`test.example.com`和`example.com`两个规则。 + - 当删除`||test.example.com^`规则时,`RemoveRule`方法只会删除`test.example.com`规则,而不会删除`example.com`规则,因此`example.com`仍然会被屏蔽。 + - 此外,`RemoveRule`方法在处理通配符和URL匹配规则时,也没有正确处理子域名规则的删除。 + +# 修复方案 + +1. **修复`RemoveRule`方法**: + - 当删除一个域名规则时,同时删除为该域名的所有子域名添加的规则。 + - 确保删除规则时,同时更新所有相关映射,包括主规则和子域名规则。 + +2. **验证修复效果**: + - 启动DNS服务器 + - 添加一条域名规则,例如`||test.example.com` + - 验证该规则及其子域名规则都被正确添加 + - 删除该规则 + - 验证该规则及其所有子域名规则都被正确删除 + - 验证DNS服务器不再使用该规则进行域名屏蔽 + +# 实现步骤 + +1. 修改`shield/manager.go`文件中的`RemoveRule`方法: + - 在删除域名规则时,添加删除所有相关子域名规则的逻辑 + - 确保删除规则时,同时更新所有相关映射 + +2. 测试修复后的功能: + - 启动DNS服务器 + - 访问Web界面,添加一条本地规则,例如`||test.example.com` + - 验证该规则被正确添加 + - 点击删除按钮删除该规则 + - 验证该规则及其所有子域名规则都被正确删除 + - 验证DNS服务器不再使用该规则进行域名屏蔽 + +# 预期结果 + +- 用户添加规则后,规则立即生效 +- 用户删除规则后,规则立即失效 +- 规则更新后,DNS服务器使用最新的规则进行域名屏蔽 +- 本地规则文件被正确更新,添加和删除的规则都能正确反映在文件中 \ No newline at end of file diff --git a/shield/manager.go b/shield/manager.go index 0bcb4a8..cbb442a 100644 --- a/shield/manager.go +++ b/shield/manager.go @@ -813,6 +813,7 @@ func (m *ShieldManager) RemoveRule(rule string) error { // 尝试删除域名规则 domain := strings.TrimPrefix(format, "||") if _, exists := m.domainRules[domain]; exists { + // 删除主域名规则 delete(m.domainRules, domain) delete(m.domainRulesIsLocal, domain) delete(m.domainRulesSource, domain) @@ -822,6 +823,7 @@ func (m *ShieldManager) RemoveRule(rule string) error { } else { // 尝试直接作为域名删除 if _, exists := m.domainRules[format]; exists { + // 删除主域名规则 delete(m.domainRules, format) delete(m.domainRulesIsLocal, format) delete(m.domainRulesSource, format) @@ -829,6 +831,7 @@ func (m *ShieldManager) RemoveRule(rule string) error { break } if _, exists := m.domainExceptions[format]; exists { + // 删除主排除规则 delete(m.domainExceptions, format) delete(m.domainExceptionsIsLocal, format) delete(m.domainExceptionsSource, format) @@ -871,6 +874,8 @@ func (m *ShieldManager) RemoveRule(rule string) error { for domain := range m.domainRules { if domain == cleanRule || domain == rule { delete(m.domainRules, domain) + delete(m.domainRulesIsLocal, domain) + delete(m.domainRulesSource, domain) removed = true break } @@ -880,6 +885,8 @@ func (m *ShieldManager) RemoveRule(rule string) error { for domain := range m.domainExceptions { if domain == cleanRule || domain == rule { delete(m.domainExceptions, domain) + delete(m.domainExceptionsIsLocal, domain) + delete(m.domainExceptionsSource, domain) removed = true break } @@ -887,6 +894,36 @@ func (m *ShieldManager) RemoveRule(rule string) error { } } + // 如果没有删除任何规则,尝试删除可能的子域名规则 + if !removed { + // 解析原始规则,提取可能的主域名 + originalRule := cleanRule + // 移除可能的前缀 + originalRule = strings.TrimPrefix(originalRule, "@@||") + originalRule = strings.TrimPrefix(originalRule, "||") + + // 检查是否有子域名规则需要删除 + // 遍历所有域名规则,删除包含原始规则作为后缀的子域名规则 + for domain := range m.domainRules { + if strings.HasSuffix(domain, "."+originalRule) || domain == originalRule { + delete(m.domainRules, domain) + delete(m.domainRulesIsLocal, domain) + delete(m.domainRulesSource, domain) + removed = true + } + } + + // 遍历所有排除规则,删除包含原始规则作为后缀的子域名规则 + for domain := range m.domainExceptions { + if strings.HasSuffix(domain, "."+originalRule) || domain == originalRule { + delete(m.domainExceptions, domain) + delete(m.domainExceptionsIsLocal, domain) + delete(m.domainExceptionsSource, domain) + removed = true + } + } + } + // 如果有规则被删除,持久化保存更改 if removed && m.config.LocalRulesFile != "" { if err := m.saveRulesToFile(); err != nil { diff --git a/test_remove_rule.go b/test_remove_rule.go new file mode 100644 index 0000000..458d94b --- /dev/null +++ b/test_remove_rule.go @@ -0,0 +1,49 @@ +package main + +import ( + "fmt" + "dns-server/config" + "dns-server/shield" + "log" + "os" +) + +func main() { + // 创建默认Shield配置 + shieldCfg := &config.ShieldConfig{ + LocalRulesFile: "data/rules.txt", + } + + // 创建ShieldManager + shieldManager := shield.NewShieldManager(shieldCfg) + + // 添加一条测试规则 + rule := "||test.example.com" + err := shieldManager.AddRule(rule) + if err != nil { + log.Fatalf("添加规则失败: %v", err) + } + fmt.Printf("添加规则 %s 成功\n", rule) + + // 验证规则是否被添加 + localRules := shieldManager.GetLocalRules() + fmt.Printf("添加规则后,本地规则数量: %d\n", len(localRules["domainRules"].([]string))) + + // 删除规则 + err = shieldManager.RemoveRule(rule + "^") + if err != nil { + log.Fatalf("删除规则失败: %v", err) + } + fmt.Printf("删除规则 %s 成功\n", rule) + + // 验证规则是否被删除 + localRules = shieldManager.GetLocalRules() + fmt.Printf("删除规则后,本地规则数量: %d\n", len(localRules["domainRules"].([]string))) + + // 验证文件内容 + fileContent, err := os.ReadFile("data/rules.txt") + if err != nil { + log.Fatalf("读取规则文件失败: %v", err) + } + fmt.Printf("规则文件内容: %s\n", string(fileContent)) +}