修复了规则更新后没有生效的问题

This commit is contained in:
Alex Yang
2025-11-28 18:52:22 +08:00
parent ee148fe6c3
commit 16bc615a52
3 changed files with 134 additions and 0 deletions

View File

@@ -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服务器使用最新的规则进行域名屏蔽
- 本地规则文件被正确更新,添加和删除的规则都能正确反映在文件中

View File

@@ -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 {

49
test_remove_rule.go Normal file
View File

@@ -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))
}