This commit is contained in:
Alex Yang
2025-12-16 00:11:42 +08:00
parent ba26e2b647
commit 11d39d6b76
35 changed files with 12378 additions and 1157 deletions

View File

@@ -36,48 +36,50 @@ type regexRule struct {
// ShieldManager 屏蔽管理器
type ShieldManager struct {
config *config.ShieldConfig
domainRules map[string]bool
domainExceptions map[string]bool
domainRulesIsLocal map[string]bool // 标记域名规则是否为本地规则
domainExceptionsIsLocal map[string]bool // 标记域名排除规则是否为本地规则
domainRulesSource map[string]string // 标记域名规则来源
domainExceptionsSource map[string]string // 标记域名排除规则来源
regexRules []regexRule
regexExceptions []regexRule
hostsMap map[string]string
blockedDomainsCount map[string]int
resolvedDomainsCount map[string]int
rulesMutex sync.RWMutex
updateCtx context.Context
updateCancel context.CancelFunc
updateRunning bool
localRulesCount int // 本地规则数量
remoteRulesCount int // 远程规则数量
urlToBlacklistName map[string]string // URL到黑名单名称的映射
config *config.ShieldConfig
domainRules map[string]bool
domainExceptions map[string]bool
domainRulesIsLocal map[string]bool // 标记域名规则是否为本地规则
domainExceptionsIsLocal map[string]bool // 标记域名排除规则是否为本地规则
domainRulesSource map[string]string // 标记域名规则来源
domainExceptionsSource map[string]string // 标记域名排除规则来源
domainRulesOriginal map[string]string // 存储域名规则的原始字符串
domainExceptionsOriginal map[string]string // 存储域名排除规则的原始字符串
regexRules []regexRule
regexExceptions []regexRule
hostsMap map[string]string
blockedDomainsCount map[string]int
resolvedDomainsCount map[string]int
rulesMutex sync.RWMutex
updateCtx context.Context
updateCancel context.CancelFunc
updateRunning bool
localRulesCount int // 本地规则数量
remoteRulesCount int // 远程规则数量
}
// NewShieldManager 创建屏蔽管理器实例
func NewShieldManager(config *config.ShieldConfig) *ShieldManager {
ctx, cancel := context.WithCancel(context.Background())
manager := &ShieldManager{
config: config,
domainRules: make(map[string]bool),
domainExceptions: make(map[string]bool),
domainRulesIsLocal: make(map[string]bool),
domainExceptionsIsLocal: make(map[string]bool),
domainRulesSource: make(map[string]string),
domainExceptionsSource: make(map[string]string),
regexRules: []regexRule{},
regexExceptions: []regexRule{},
hostsMap: make(map[string]string),
blockedDomainsCount: make(map[string]int),
resolvedDomainsCount: make(map[string]int),
updateCtx: ctx,
updateCancel: cancel,
localRulesCount: 0,
remoteRulesCount: 0,
urlToBlacklistName: make(map[string]string),
config: config,
domainRules: make(map[string]bool),
domainExceptions: make(map[string]bool),
domainRulesIsLocal: make(map[string]bool),
domainExceptionsIsLocal: make(map[string]bool),
domainRulesSource: make(map[string]string),
domainExceptionsSource: make(map[string]string),
domainRulesOriginal: make(map[string]string),
domainExceptionsOriginal: make(map[string]string),
regexRules: []regexRule{},
regexExceptions: []regexRule{},
hostsMap: make(map[string]string),
blockedDomainsCount: make(map[string]int),
resolvedDomainsCount: make(map[string]int),
updateCtx: ctx,
updateCancel: cancel,
localRulesCount: 0,
remoteRulesCount: 0,
}
// 加载已保存的计数数据
@@ -98,6 +100,8 @@ func (m *ShieldManager) LoadRules() error {
m.domainExceptionsIsLocal = make(map[string]bool)
m.domainRulesSource = make(map[string]string)
m.domainExceptionsSource = make(map[string]string)
m.domainRulesOriginal = make(map[string]string)
m.domainExceptionsOriginal = make(map[string]string)
m.regexRules = []regexRule{}
m.regexExceptions = []regexRule{}
m.hostsMap = make(map[string]string)
@@ -161,13 +165,7 @@ func (m *ShieldManager) loadLocalRules() error {
// loadRemoteRules 加载远程规则
func (m *ShieldManager) loadRemoteRules() error {
// 清空URL到黑名单名称的映射
m.urlToBlacklistName = make(map[string]string)
// 构建URL到黑名单名称的映射
for _, blacklist := range m.config.Blacklists {
m.urlToBlacklistName[blacklist.URL] = blacklist.Name
if blacklist.Enabled {
if err := m.fetchRemoteRules(blacklist.URL); err != nil {
logger.Error("获取远程规则失败", "url", blacklist.URL, "error", err)
@@ -341,6 +339,9 @@ func (m *ShieldManager) loadHosts() error {
// parseRule 解析规则行
func (m *ShieldManager) parseRule(line string, isLocal bool, source string) {
// 保存原始规则用于后续使用
originalLine := line
// 处理注释
if strings.HasPrefix(line, "!") || strings.HasPrefix(line, "#") || line == "" {
return
@@ -365,12 +366,12 @@ func (m *ShieldManager) parseRule(line string, isLocal bool, source string) {
case strings.HasPrefix(line, "||") && strings.HasSuffix(line, "^"):
// AdGuardHome域名规则格式: ||example.com^
domain := strings.TrimSuffix(strings.TrimPrefix(line, "||"), "^")
m.addDomainRule(domain, !isException, isLocal, source)
m.addDomainRule(domain, !isException, isLocal, source, originalLine)
case strings.HasPrefix(line, "||"):
// 精确域名匹配规则
domain := strings.TrimPrefix(line, "||")
m.addDomainRule(domain, !isException, isLocal, source)
m.addDomainRule(domain, !isException, isLocal, source, originalLine)
case strings.HasPrefix(line, "*"):
// 通配符规则,转换为正则表达式
@@ -378,7 +379,7 @@ func (m *ShieldManager) parseRule(line string, isLocal bool, source string) {
pattern = "^" + pattern + "$"
if re, err := regexp.Compile(pattern); err == nil {
// 保存原始规则字符串
m.addRegexRule(re, line, !isException, isLocal, source)
m.addRegexRule(re, originalLine, !isException, isLocal, source)
}
case strings.HasPrefix(line, "/") && strings.HasSuffix(line, "/"):
@@ -388,7 +389,7 @@ func (m *ShieldManager) parseRule(line string, isLocal bool, source string) {
// 对于像 /domain/ 这样的规则,应该匹配包含 domain 字符串的任何域名
if re, err := regexp.Compile("(?i).*" + regexp.QuoteMeta(pattern) + ".*"); err == nil {
// 保存原始规则字符串
m.addRegexRule(re, line, !isException, isLocal, source)
m.addRegexRule(re, originalLine, !isException, isLocal, source)
}
case strings.HasPrefix(line, "|") && strings.HasSuffix(line, "|"):
@@ -397,7 +398,7 @@ func (m *ShieldManager) parseRule(line string, isLocal bool, source string) {
// 将URL模式转换为正则表达式
pattern := "^" + regexp.QuoteMeta(urlPattern) + "$"
if re, err := regexp.Compile(pattern); err == nil {
m.addRegexRule(re, line, !isException, isLocal, source)
m.addRegexRule(re, originalLine, !isException, isLocal, source)
}
case strings.HasPrefix(line, "|"):
@@ -405,7 +406,7 @@ func (m *ShieldManager) parseRule(line string, isLocal bool, source string) {
urlPattern := strings.TrimPrefix(line, "|")
pattern := "^" + regexp.QuoteMeta(urlPattern)
if re, err := regexp.Compile(pattern); err == nil {
m.addRegexRule(re, line, !isException, isLocal, source)
m.addRegexRule(re, originalLine, !isException, isLocal, source)
}
case strings.HasSuffix(line, "|"):
@@ -413,12 +414,12 @@ func (m *ShieldManager) parseRule(line string, isLocal bool, source string) {
urlPattern := strings.TrimSuffix(line, "|")
pattern := regexp.QuoteMeta(urlPattern) + "$"
if re, err := regexp.Compile(pattern); err == nil {
m.addRegexRule(re, line, !isException, isLocal, source)
m.addRegexRule(re, originalLine, !isException, isLocal, source)
}
default:
// 默认作为普通域名规则
m.addDomainRule(line, !isException, isLocal, source)
m.addDomainRule(line, !isException, isLocal, source, originalLine)
}
}
@@ -442,7 +443,7 @@ func (m *ShieldManager) parseRuleOptions(optionsStr string) map[string]string {
}
// addDomainRule 添加域名规则,支持是否为阻止规则
func (m *ShieldManager) addDomainRule(domain string, block bool, isLocal bool, source string) {
func (m *ShieldManager) addDomainRule(domain string, block bool, isLocal bool, source string, original string) {
if block {
// 如果是远程规则,检查是否已经存在本地规则,如果存在则不覆盖
if !isLocal {
@@ -454,6 +455,7 @@ func (m *ShieldManager) addDomainRule(domain string, block bool, isLocal bool, s
m.domainRules[domain] = true
m.domainRulesIsLocal[domain] = isLocal
m.domainRulesSource[domain] = source
m.domainRulesOriginal[domain] = original
} else {
// 添加到排除规则
// 如果是远程规则,检查是否已经存在本地规则,如果存在则不覆盖
@@ -466,6 +468,7 @@ func (m *ShieldManager) addDomainRule(domain string, block bool, isLocal bool, s
m.domainExceptions[domain] = true
m.domainExceptionsIsLocal[domain] = isLocal
m.domainExceptionsSource[domain] = source
m.domainExceptionsOriginal[domain] = original
}
}
@@ -521,7 +524,6 @@ func (m *ShieldManager) CheckDomainBlockDetails(domain string) map[string]interf
"blockRule": "",
"blockRuleType": "",
"blocksource": "",
"blacklistName": "",
"excluded": false,
"excludeRule": "",
"excludeRuleType": "",
@@ -537,49 +539,67 @@ func (m *ShieldManager) CheckDomainBlockDetails(domain string) map[string]interf
// 检查排除规则(优先级最高)
// 检查域名排除规则
if m.domainExceptions[domain] {
source := m.domainExceptionsSource[domain]
result["excluded"] = true
result["excludeRule"] = domain
result["excludeRule"] = m.domainExceptionsOriginal[domain]
result["excludeRuleType"] = "exact_domain"
result["blocksource"] = source
result["blacklistName"] = m.getBlacklistNameByURL(source)
result["blocksource"] = m.domainExceptionsSource[domain]
return result
}
// 检查子域名排除规则
parts := strings.Split(domain, ".")
for i := 0; i < len(parts)-1; i++ {
subdomain := strings.Join(parts[i:], ".")
if m.domainExceptions[subdomain] {
result["excluded"] = true
result["excludeRule"] = m.domainExceptionsOriginal[subdomain]
result["excludeRuleType"] = "subdomain"
result["blocksource"] = m.domainExceptionsSource[subdomain]
return result
}
}
// 检查正则表达式排除规则
for _, re := range m.regexExceptions {
if re.pattern.MatchString(domain) {
source := re.source
result["excluded"] = true
result["excludeRule"] = re.original
result["excludeRuleType"] = "regex"
result["blocksource"] = source
result["blacklistName"] = m.getBlacklistNameByURL(source)
result["blocksource"] = re.source
return result
}
}
// 检查阻止规则
// 检查阻止规则 - 先检查精确域名匹配,再检查子域名匹配
// 检查精确域名匹配
if m.domainRules[domain] {
source := m.domainRulesSource[domain]
result["blocked"] = true
result["blockRule"] = domain
result["blockRule"] = m.domainRulesOriginal[domain]
result["blockRuleType"] = "exact_domain"
result["blocksource"] = source
result["blacklistName"] = m.getBlacklistNameByURL(source)
result["blocksource"] = m.domainRulesSource[domain]
return result
}
// 检查子域名匹配AdGuardHome风格
// 从最长的子域名开始匹配,确保优先级正确
for i := 0; i < len(parts)-1; i++ {
subdomain := strings.Join(parts[i:], ".")
if m.domainRules[subdomain] {
result["blocked"] = true
result["blockRule"] = m.domainRulesOriginal[subdomain]
result["blockRuleType"] = "subdomain"
result["blocksource"] = m.domainRulesSource[subdomain]
return result
}
}
// 检查正则表达式匹配
for _, re := range m.regexRules {
if re.pattern.MatchString(domain) {
source := re.source
result["blocked"] = true
result["blockRule"] = re.original
result["blockRuleType"] = "regex"
result["blocksource"] = source
result["blacklistName"] = m.getBlacklistNameByURL(source)
result["blocksource"] = re.source
return result
}
}
@@ -1251,14 +1271,6 @@ func (m *ShieldManager) UpdateBlacklist(blacklists []config.BlacklistEntry) {
m.config.Blacklists = blacklists
}
// getBlacklistNameByURL 根据URL获取黑名单名称如果没有找到则返回URL本身
func (m *ShieldManager) getBlacklistNameByURL(url string) string {
if name, exists := m.urlToBlacklistName[url]; exists {
return name
}
return url
}
// GetAllHosts 获取所有hosts条目
func (m *ShieldManager) GetAllHosts() map[string]string {
m.rulesMutex.RLock()