feat: add support for specifying real-ip-filter in DNS

This commit is contained in:
David Xiang 2024-09-28 02:31:25 +08:00
parent 264713571d
commit 4dcf4a381d
3 changed files with 57 additions and 22 deletions

View File

@ -29,16 +29,17 @@ type store interface {
// Pool is an implementation about fake ip generator without storage
type Pool struct {
gateway netip.Addr
first netip.Addr
last netip.Addr
offset netip.Addr
cycle bool
mux sync.Mutex
host []C.DomainMatcher
mode C.FilterMode
ipnet netip.Prefix
store store
gateway netip.Addr
first netip.Addr
last netip.Addr
offset netip.Addr
cycle bool
mux sync.Mutex
host []C.DomainMatcher
realhost []C.DomainMatcher
mode C.FilterMode
ipnet netip.Prefix
store store
}
// Lookup return a fake ip with host
@ -75,12 +76,22 @@ func (p *Pool) ShouldSkipped(domain string) bool {
}
func (p *Pool) shouldSkipped(domain string) bool {
// When both fake-ip-filter and real-ip-filter match, the fake-ip-filter takes precedence.
// If neither filter matches, fake-ip is returned.
// For example:
// If an ad domain (www.ad.com) matches both fake-ip-filter:AD and real-ip-filter:cn, fake-ip will be returned.
// If a blocked domain (wiki.metacubex.one) does not match either filter, fake-ip will be returned by default.
for _, matcher := range p.host {
if matcher.MatchDomain(domain) {
return true
}
}
return false
for _, matcher := range p.realhost {
if matcher.MatchDomain(domain) {
return false
}
}
return true
}
// Exist returns if given ip exists in fake-ip pool
@ -164,9 +175,10 @@ func (p *Pool) restoreState() {
}
type Options struct {
IPNet netip.Prefix
Host []C.DomainMatcher
Mode C.FilterMode
IPNet netip.Prefix
Host []C.DomainMatcher
RealHost []C.DomainMatcher
Mode C.FilterMode
// Size sets the maximum number of entries in memory
// and does not work if Persistence is true
@ -191,14 +203,15 @@ func New(options Options) (*Pool, error) {
}
pool := &Pool{
gateway: gateway,
first: first,
last: last,
offset: first.Prev(),
cycle: false,
host: options.Host,
mode: options.Mode,
ipnet: options.IPNet,
gateway: gateway,
first: first,
last: last,
offset: first.Prev(),
cycle: false,
host: options.Host,
realhost: options.RealHost,
mode: options.Mode,
ipnet: options.IPNet,
}
if options.Persistence {
pool.store = newCachefileStore(cachefile.Cache())

View File

@ -206,6 +206,7 @@ type RawDNS struct {
EnhancedMode C.DNSMode `yaml:"enhanced-mode" json:"enhanced-mode"`
FakeIPRange string `yaml:"fake-ip-range" json:"fake-ip-range"`
FakeIPFilter []string `yaml:"fake-ip-filter" json:"fake-ip-filter"`
RealIPFilter []string `yaml:"real-ip-filter" json:"real-ip-filter"`
FakeIPFilterMode C.FilterMode `yaml:"fake-ip-filter-mode" json:"fake-ip-filter-mode"`
DefaultNameserver []string `yaml:"default-nameserver" json:"default-nameserver"`
CacheAlgorithm string `yaml:"cache-algorithm" json:"cache-algorithm"`
@ -1449,10 +1450,17 @@ func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie[resolver.HostValue], rul
return nil, err
}
// real ip via host rule
realHost, err := parseDomain(cfg.RealIPFilter, fakeIPTrie, "dns.real-ip-filter", ruleProviders)
if err != nil {
return nil, err
}
pool, err := fakeip.New(fakeip.Options{
IPNet: fakeIPRange,
Size: 1000,
Host: host,
RealHost: realHost,
Mode: cfg.FakeIPFilterMode,
Persistence: rawCfg.Profile.StoreFakeIP,
})

View File

@ -257,6 +257,20 @@ dns:
# 可设置为whitelist即只有匹配成功才返回fake-ip
fake-ip-filter-mode: blacklist
# fake-ip 白名单模式
# 当 fake-ip-filter 和 real-ip-filter 同时匹配时fake-ip-filter 优先级更高。
# 如果都没有匹配到规则,则返回 fake-ip。
# 例如:
# 如果广告域名 (www.ad.com) 同时满足 fake-ip-filter:AD 和 real-ip-filter:cn则返回 fake-ip。
# 如果被墙域名 (wiki.metacubex.one) 都没匹配到,默认返回 fake-ip。
# fake-ip-filter-mode: whitelist
# fake-ip-filter:
# - rule-set:anti-AD
# - geosite:gfw
# real-ip-filter:
# - geosite:cn
# - rule-set:douyin
# use-hosts: true # 查询 hosts
# 配置后面的nameserver、fallback和nameserver-policy向dns服务器的连接过程是否遵守遵守rules规则