Skip to content

Commit

Permalink
feat: add support for specifying real-ip-filter in DNS
Browse files Browse the repository at this point in the history
  • Loading branch information
HEUDavid committed Sep 27, 2024
1 parent 2647135 commit 4dcf4a3
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 22 deletions.
57 changes: 35 additions & 22 deletions component/fakeip/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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())
Expand Down
8 changes: 8 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand Down Expand Up @@ -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,
})
Expand Down
14 changes: 14 additions & 0 deletions docs/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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规则
Expand Down

0 comments on commit 4dcf4a3

Please sign in to comment.